Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustdoc: Add more semantic information to impl IDs #98939

Merged
merged 4 commits into from
Jul 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions library/core/src/char/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ impl const From<char> for u128 {
/// Map `char` with code point in U+0000..=U+00FF to byte in 0x00..=0xFF with same value, failing
/// if the code point is greater than U+00FF.
///
/// See [`impl From<u8> for char`](char#impl-From<u8>) for details on the encoding.
/// See [`impl From<u8> for char`](char#impl-From<u8>-for-char) for details on the encoding.
#[stable(feature = "u8_from_char", since = "1.59.0")]
impl TryFrom<char> for u8 {
type Error = TryFromCharError;
Expand Down Expand Up @@ -229,7 +229,7 @@ impl TryFrom<u32> for char {

/// The error type returned when a conversion from [`prim@u32`] to [`prim@char`] fails.
///
/// This `struct` is created by the [`char::try_from<u32>`](char#impl-TryFrom<u32>) method.
/// This `struct` is created by the [`char::try_from<u32>`](char#impl-TryFrom<u32>-for-char) method.
/// See its documentation for more.
#[stable(feature = "try_from", since = "1.34.0")]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/hash/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ mod sip;
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
/// [`HashSet`]: ../../std/collections/struct.HashSet.html
/// [`hash`]: Hash::hash
/// [impl]: ../../std/primitive.str.html#impl-Hash
/// [impl]: ../../std/primitive.str.html#impl-Hash-for-str
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "Hash"]
pub trait Hash {
Expand Down
6 changes: 3 additions & 3 deletions library/core/src/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@
//! [`Option`] of a collection of each contained value of the original
//! [`Option`] values, or [`None`] if any of the elements was [`None`].
//!
//! [impl-FromIterator]: Option#impl-FromIterator%3COption%3CA%3E%3E
//! [impl-FromIterator]: Option#impl-FromIterator%3COption%3CA%3E%3E-for-Option%3CV%3E
//!
//! ```
//! let v = [Some(2), Some(4), None, Some(8)];
Expand All @@ -405,8 +405,8 @@
//! to provide the [`product`][Iterator::product] and
//! [`sum`][Iterator::sum] methods.
//!
//! [impl-Product]: Option#impl-Product%3COption%3CU%3E%3E
//! [impl-Sum]: Option#impl-Sum%3COption%3CU%3E%3E
//! [impl-Product]: Option#impl-Product%3COption%3CU%3E%3E-for-Option%3CT%3E
//! [impl-Sum]: Option#impl-Sum%3COption%3CU%3E%3E-for-Option%3CT%3E
//!
//! ```
//! let v = [None, Some(1), Some(2), Some(3)];
Expand Down
6 changes: 3 additions & 3 deletions library/core/src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@
//! [`Result`] of a collection of each contained value of the original
//! [`Result`] values, or [`Err`] if any of the elements was [`Err`].
//!
//! [impl-FromIterator]: Result#impl-FromIterator%3CResult%3CA%2C%20E%3E%3E
//! [impl-FromIterator]: Result#impl-FromIterator%3CResult%3CA%2C%20E%3E%3E-for-Result%3CV%2C%20E%3E
//!
//! ```
//! let v = [Ok(2), Ok(4), Err("err!"), Ok(8)];
Expand All @@ -475,8 +475,8 @@
//! to provide the [`product`][Iterator::product] and
//! [`sum`][Iterator::sum] methods.
//!
//! [impl-Product]: Result#impl-Product%3CResult%3CU%2C%20E%3E%3E
//! [impl-Sum]: Result#impl-Sum%3CResult%3CU%2C%20E%3E%3E
//! [impl-Product]: Result#impl-Product%3CResult%3CU%2C%20E%3E%3E-for-Result%3CT%2C%20E%3E
//! [impl-Sum]: Result#impl-Sum%3CResult%3CU%2C%20E%3E%3E-for-Result%3CT%2C%20E%3E
//!
//! ```
//! let v = [Err("error!"), Ok(1), Ok(2), Ok(3), Err("foo")];
Expand Down
60 changes: 20 additions & 40 deletions src/librustdoc/html/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,6 @@ fn render_impls(
&[],
ImplRenderingParameters {
show_def_docs: true,
is_on_foreign_type: false,
show_default_items: true,
show_non_assoc_items: true,
toggle_open_by_default,
Expand Down Expand Up @@ -1071,7 +1070,6 @@ fn render_assoc_items_inner(
&[],
ImplRenderingParameters {
show_def_docs: true,
is_on_foreign_type: false,
show_default_items: true,
show_non_assoc_items: true,
toggle_open_by_default: true,
Expand Down Expand Up @@ -1287,7 +1285,6 @@ fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String {
#[derive(Clone, Copy, Debug)]
struct ImplRenderingParameters {
show_def_docs: bool,
is_on_foreign_type: bool,
show_default_items: bool,
/// Whether or not to show methods.
show_non_assoc_items: bool,
Expand Down Expand Up @@ -1603,7 +1600,6 @@ fn render_impl(
parent,
rendering_params.show_def_docs,
use_absolute,
rendering_params.is_on_foreign_type,
aliases,
);
if toggled {
Expand Down Expand Up @@ -1688,21 +1684,12 @@ pub(crate) fn render_impl_summary(
containing_item: &clean::Item,
show_def_docs: bool,
use_absolute: Option<bool>,
is_on_foreign_type: bool,
// This argument is used to reference same type with different paths to avoid duplication
// in documentation pages for trait with automatic implementations like "Send" and "Sync".
aliases: &[String],
) {
let id = cx.derive_id(match i.inner_impl().trait_ {
Some(ref t) => {
if is_on_foreign_type {
get_id_for_impl_on_foreign_type(&i.inner_impl().for_, t, cx)
} else {
format!("impl-{}", small_url_encode(format!("{:#}", t.print(cx))))
}
}
None => "impl".to_string(),
});
let id =
cx.derive_id(get_id_for_impl(&i.inner_impl().for_, i.inner_impl().trait_.as_ref(), cx));
let aliases = if aliases.is_empty() {
String::new()
} else {
Expand Down Expand Up @@ -1986,21 +1973,18 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
let mut ret = impls
.iter()
.filter_map(|it| {
if let Some(ref i) = it.inner_impl().trait_ {
let i_display = format!("{:#}", i.print(cx));
let out = Escape(&i_display);
let encoded =
id_map.derive(small_url_encode(format!("impl-{:#}", i.print(cx))));
let prefix = match it.inner_impl().polarity {
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
ty::ImplPolarity::Negative => "!",
};
let generated =
format!("<a href=\"#{}\">{}{}</a>", encoded, prefix, out);
if links.insert(generated.clone()) { Some(generated) } else { None }
} else {
None
}
let trait_ = it.inner_impl().trait_.as_ref()?;
let encoded =
id_map.derive(get_id_for_impl(&it.inner_impl().for_, Some(trait_), cx));

let i_display = format!("{:#}", trait_.print(cx));
let out = Escape(&i_display);
let prefix = match it.inner_impl().polarity {
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
ty::ImplPolarity::Negative => "!",
};
let generated = format!("<a href=\"#{}\">{}{}</a>", encoded, prefix, out);
if links.insert(generated.clone()) { Some(generated) } else { None }
})
.collect::<Vec<String>>();
ret.sort();
Expand Down Expand Up @@ -2147,12 +2131,11 @@ fn sidebar_struct(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, s: &clea
}
}

fn get_id_for_impl_on_foreign_type(
for_: &clean::Type,
trait_: &clean::Path,
cx: &Context<'_>,
) -> String {
small_url_encode(format!("impl-{:#}-for-{:#}", trait_.print(cx), for_.print(cx)))
fn get_id_for_impl(for_: &clean::Type, trait_: Option<&clean::Path>, cx: &Context<'_>) -> String {
match trait_ {
Some(t) => small_url_encode(format!("impl-{:#}-for-{:#}", t.print(cx), for_.print(cx))),
None => small_url_encode(format!("impl-{:#}", for_.print(cx))),
}
}

fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String, String)> {
Expand All @@ -2161,10 +2144,7 @@ fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String
i.trait_.as_ref().map(|trait_| {
// Alternative format produces no URLs,
// so this parameter does nothing.
(
format!("{:#}", i.for_.print(cx)),
get_id_for_impl_on_foreign_type(&i.for_, trait_, cx),
)
(format!("{:#}", i.for_.print(cx)), get_id_for_impl(&i.for_, Some(trait_), cx))
})
}
_ => None,
Expand Down
2 changes: 0 additions & 2 deletions src/librustdoc/html/render/print_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -853,7 +853,6 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
&[],
ImplRenderingParameters {
show_def_docs: false,
is_on_foreign_type: true,
show_default_items: false,
show_non_assoc_items: true,
toggle_open_by_default: false,
Expand Down Expand Up @@ -1627,7 +1626,6 @@ fn render_implementor(
aliases,
ImplRenderingParameters {
show_def_docs: false,
is_on_foreign_type: false,
show_default_items: false,
show_non_assoc_items: false,
toggle_open_by_default: false,
Expand Down
4 changes: 2 additions & 2 deletions src/test/rustdoc-gui/anchors.goml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ move-cursor-to: "h2#implementations"
assert-css: ("h2#implementations a.anchor", {"color": "rgb(0, 0, 0)"})

// Same thing with the impl block title.
move-cursor-to: "#impl"
assert-css: ("#impl a.anchor", {"color": "rgb(0, 0, 0)"})
move-cursor-to: "#impl-HeavilyDocumentedStruct"
assert-css: ("#impl-HeavilyDocumentedStruct a.anchor", {"color": "rgb(0, 0, 0)"})

assert-css: ("#title-for-struct-impl-item-doc", {"margin-left": "0px"})
12 changes: 6 additions & 6 deletions src/test/rustdoc-gui/headers-color.goml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ assert-css: (
ALL,
)

goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl
goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl-Foo
assert-css: (
"#impl",
"#impl-Foo",
{"color": "rgb(197, 197, 197)", "background-color": "rgba(255, 236, 164, 0.06)"},
)

Expand Down Expand Up @@ -62,9 +62,9 @@ assert-css: (
ALL,
)

goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl
goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl-Foo
assert-css: (
"#impl",
"#impl-Foo",
{"color": "rgb(221, 221, 221)", "background-color": "rgb(73, 74, 61)"},
)

Expand Down Expand Up @@ -99,8 +99,8 @@ assert-css: (
ALL,
)

goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl
assert-css: ("#impl", {"color": "rgb(0, 0, 0)", "background-color": "rgb(253, 255, 211)"})
goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl-Foo
assert-css: ("#impl-Foo", {"color": "rgb(0, 0, 0)", "background-color": "rgb(253, 255, 211)"})

goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use
assert-css: (
Expand Down
12 changes: 6 additions & 6 deletions src/test/rustdoc-gui/headings.goml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ assert-css: ("h4#sub-heading-for-field", {"border-bottom-width": "0px"})
assert-css: ("h2#implementations", {"font-size": "22px"})
assert-css: ("h2#implementations", {"border-bottom-width": "1px"})

assert-css: ("#impl > h3.code-header", {"font-size": "18px"})
assert-css: ("#impl > h3.code-header", {"border-bottom-width": "0px"})
assert-css: ("#impl-HeavilyDocumentedStruct > h3.code-header", {"font-size": "18px"})
assert-css: ("#impl-HeavilyDocumentedStruct > h3.code-header", {"border-bottom-width": "0px"})
assert-css: ("#method\.do_nothing > h4.code-header", {"font-size": "16px"})
assert-css: ("#method\.do_nothing > h4.code-header", {"border-bottom-width": "0px"})

Expand Down Expand Up @@ -87,8 +87,8 @@ assert-css: ("h6#structy-prose-sub-heading", {"border-bottom-width": "0px"})
assert-css: ("h2#implementations", {"font-size": "22px"})
assert-css: ("h2#implementations", {"border-bottom-width": "1px"})

assert-css: ("#impl > h3.code-header", {"font-size": "18px"})
assert-css: ("#impl > h3.code-header", {"border-bottom-width": "0px"})
assert-css: ("#impl-HeavilyDocumentedEnum > h3.code-header", {"font-size": "18px"})
assert-css: ("#impl-HeavilyDocumentedEnum > h3.code-header", {"border-bottom-width": "0px"})
assert-css: ("#method\.do_nothing > h4.code-header", {"font-size": "16px"})
assert-css: ("#method\.do_nothing > h4.code-header", {"border-bottom-width": "0px"})

Expand Down Expand Up @@ -129,8 +129,8 @@ assert-css: ("h4#sub-heading-for-union-variant", {"border-bottom-width": "0px"})
assert-css: ("h2#implementations", {"font-size": "22px"})
assert-css: ("h2#implementations", {"border-bottom-width": "1px"})

assert-css: ("#impl > h3.code-header", {"font-size": "18px"})
assert-css: ("#impl > h3.code-header", {"border-bottom-width": "0px"})
assert-css: ("#impl-HeavilyDocumentedUnion > h3.code-header", {"font-size": "18px"})
assert-css: ("#impl-HeavilyDocumentedUnion > h3.code-header", {"border-bottom-width": "0px"})
assert-css: ("h4#title-for-union-impl-doc", {"font-size": "16px"})
assert-css: ("h4#title-for-union-impl-doc", {"border-bottom-width": "0px"})
assert-css: ("h5#sub-heading-for-union-impl-doc", {"font-size": "16px"})
Expand Down
16 changes: 12 additions & 4 deletions src/test/rustdoc-gui/implementors.goml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ assert: "#implementors-list"
assert-count: ("#implementors-list .impl", 2)
// Now we check that both implementors have an anchor, an ID and a similar DOM.
assert: ("#implementors-list .impl:nth-child(1) > a.anchor")
assert-attribute: ("#implementors-list .impl:nth-child(1)", {"id": "impl-Whatever"})
assert-attribute: ("#implementors-list .impl:nth-child(1) > a.anchor", {"href": "#impl-Whatever"})
assert-attribute: ("#implementors-list .impl:nth-child(1)", {"id": "impl-Whatever-for-Struct"})
assert-attribute: ("#implementors-list .impl:nth-child(1) > a.anchor", {"href": "#impl-Whatever-for-Struct"})
assert: "#implementors-list .impl:nth-child(1) > .code-header.in-band"

assert: ("#implementors-list .impl:nth-child(2) > a.anchor")
Expand All @@ -16,8 +16,16 @@ assert-attribute: ("#implementors-list .impl:nth-child(2) > a.anchor", {"href":
assert: "#implementors-list .impl:nth-child(2) > .code-header.in-band"

goto: file://|DOC_PATH|/test_docs/struct.HasEmptyTraits.html
compare-elements-position-near-false: ("#impl-EmptyTrait1", "#impl-EmptyTrait2", {"y": 30})
compare-elements-position-near: ("#impl-EmptyTrait3 h3", "#impl-EmptyTrait3 .item-info", {"y": 30})
compare-elements-position-near-false: (
"#impl-EmptyTrait1-for-HasEmptyTraits",
"#impl-EmptyTrait2-for-HasEmptyTraits",
{"y": 30},
)
compare-elements-position-near: (
"#impl-EmptyTrait3-for-HasEmptyTraits h3",
"#impl-EmptyTrait3-for-HasEmptyTraits .item-info",
{"y": 30},
)

// Now check that re-exports work correctly.
// There should be exactly one impl shown on both of these pages.
Expand Down
11 changes: 7 additions & 4 deletions src/test/rustdoc-gui/item-info-overflow.goml
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@ assert-text: (
// Checking the "item-info" on an impl block as well:
goto: file://|DOC_PATH|/lib2/struct.LongItemInfo2.html
compare-elements-property: (
"#impl-SimpleTrait .item-info",
"#impl-SimpleTrait + .docblock",
"#impl-SimpleTrait-for-LongItemInfo2 .item-info",
"#impl-SimpleTrait-for-LongItemInfo2 + .docblock",
["scrollWidth"],
)
assert-property: ("#impl-SimpleTrait .item-info", {"scrollWidth": "866"})
assert-property: (
"#impl-SimpleTrait-for-LongItemInfo2 .item-info",
{"scrollWidth": "866"},
)
// Just to be sure we're comparing the correct "item-info":
assert-text: (
"#impl-SimpleTrait .item-info",
"#impl-SimpleTrait-for-LongItemInfo2 .item-info",
"Available on Android or Linux or Emscripten or DragonFly BSD",
STARTS_WITH,
)
2 changes: 1 addition & 1 deletion src/test/rustdoc-gui/toggle-click-deadspace.goml
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ click: ".impl-items .rustdoc-toggle summary::before" // This is the position of
assert-attribute-false: (".impl-items .rustdoc-toggle", {"open": ""})

// Click the "Trait" part of "impl Trait" and verify it navigates.
click: "#impl-Trait h3 a:first-of-type"
click: "#impl-Trait-for-Foo h3 a:first-of-type"
assert-text: (".fqn .in-band", "Trait lib2::Trait")
4 changes: 2 additions & 2 deletions src/test/rustdoc/auto-trait-not-send.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#![crate_name = "foo"]

// @has 'foo/struct.Foo.html'
// @has - '//*[@id="impl-Send"]' 'impl !Send for Foo'
// @has - '//*[@id="impl-Sync"]' 'impl !Sync for Foo'
// @has - '//*[@id="impl-Send-for-Foo"]' 'impl !Send for Foo'
// @has - '//*[@id="impl-Sync-for-Foo"]' 'impl !Sync for Foo'
pub struct Foo(*const i8);
pub trait Whatever: Send {}
impl<T: Send + ?Sized> Whatever for T {}
2 changes: 1 addition & 1 deletion src/test/rustdoc/blanket-reexport-item.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![crate_name = "foo"]

// @has foo/struct.S.html '//*[@id="impl-Into%3CU%3E"]//h3[@class="code-header in-band"]' 'impl<T, U> Into<U> for T'
// @has foo/struct.S.html '//*[@id="impl-Into%3CU%3E-for-S"]//h3[@class="code-header in-band"]' 'impl<T, U> Into<U> for T'
pub struct S2 {}
mod m {
pub struct S {}
Expand Down
4 changes: 2 additions & 2 deletions src/test/rustdoc/const-generics/const-generics-docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub struct Foo<const N: usize> where u8: Trait<N>;
// @has foo/struct.Bar.html '//pre[@class="rust struct"]' 'pub struct Bar<T, const N: usize>(_)'
pub struct Bar<T, const N: usize>([T; N]);

// @has foo/struct.Foo.html '//*[@id="impl"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Foo<M> where u8: Trait<M>'
// @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Foo<M> where u8: Trait<M>'
impl<const M: usize> Foo<M> where u8: Trait<M> {
// @has - '//*[@id="associatedconstant.FOO_ASSOC"]' 'pub const FOO_ASSOC: usize'
pub const FOO_ASSOC: usize = M + 13;
Expand All @@ -47,7 +47,7 @@ impl<const M: usize> Foo<M> where u8: Trait<M> {
}
}

// @has foo/struct.Bar.html '//*[@id="impl"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Bar<u8, M>'
// @has foo/struct.Bar.html '//*[@id="impl-Bar%3Cu8%2C%20M%3E"]/h3[@class="code-header in-band"]' 'impl<const M: usize> Bar<u8, M>'
impl<const M: usize> Bar<u8, M> {
// @has - '//*[@id="method.hey"]' \
// 'pub fn hey<const N: usize>(&self) -> Foo<N> where u8: Trait<N>'
Expand Down
Loading