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: disambiguate Implementors when the type name is not unique #38414

Merged
merged 5 commits into from Jan 4, 2017

Conversation

estebank
Copy link
Contributor

Presentation goes from:

to:

on cases where there're multiple implementors with the same name.

Fixes #37762.

@rust-highfive
Copy link
Collaborator

r? @steveklabnik

(rust_highfive has picked a reviewer for you, use r? to override)

@bluss
Copy link
Member

bluss commented Dec 16, 2016

Ignore-whitespace diff: https://github.com/rust-lang/rust/pull/38414/files?w=1

// full path, for example in `std::iter::ExactSizeIterator`
let mut dissambiguate = false;
for l in implementors.iter() {
match (k.impl_.for_.clone(), l.impl_.for_.clone()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two .clone() can be removed, just use match (&k.impl_.for_, &l....) if not rewriting the loop entirely due to the other comment.

match (k.impl_.for_.clone(), l.impl_.for_.clone()) {
(clean::Type::ResolvedPath {path: path_a, ..},
clean::Type::ResolvedPath {path: path_b, ..}) => {
if k.def_id != l.def_id && path_a.last_name() == path_b.last_name() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed (not in this patch) that last_name creates a String where it could just be a &str, too.

}
}
_ => (),
}
Copy link
Member

@bluss bluss Dec 16, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The loops are quadratic (complexity) in the number of implementors, I don't think we can afford that. A trait like Clone only lists ~480 impls, but still.

Copy link
Member

@bluss bluss Dec 16, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless I'm missing something, you can change last_name() to return &str and create a HashMap<&str, usize> or something to count everything's duplicitly here.

@@ -2110,24 +2110,27 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
<h2 id='implementors'>Implementors</h2>
<ul class='item-list' id='implementors-list'>
")?;
let mut implementor_count: FxHashMap<String, usize> = FxHashMap();
for (_, implementors) in cache.implementors.iter() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's counting far too many.. all implementors instead of just the ones for this trait(!). I tested a fix.

@bluss
Copy link
Member

bluss commented Dec 19, 2016

Can you apply this diff? Then it uses &str instead, and counts the right implementors. I wrote this up to make sure that it was possible (to not make suggestions that can't be).

diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 28ca92f..a99d4dd 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2205,8 +2205,8 @@ impl Path {
         }
     }
 
-    pub fn last_name(&self) -> String {
-        self.segments.last().unwrap().name.clone()
+    pub fn last_name(&self) -> &str {
+        &self.segments.last().unwrap().name
     }
 }
 
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 846c072..5839c46 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -2110,23 +2110,22 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         <h2 id='implementors'>Implementors</h2>
         <ul class='item-list' id='implementors-list'>
     ")?;
-    let mut implementor_count: FxHashMap<String, usize> = FxHashMap();
-    for (_, implementors) in cache.implementors.iter() {
+    if let Some(implementors) = cache.implementors.get(&it.def_id) {
+        let mut implementor_count: FxHashMap<&str, usize> = FxHashMap();
         for implementor in implementors {
             if let clean::Type::ResolvedPath {ref path, ..} = implementor.impl_.for_ {
                 *implementor_count.entry(path.last_name()).or_insert(0) += 1;
             }
         }
-    }
-    if let Some(implementors) = cache.implementors.get(&it.def_id) {
-        for implementor in implementors.iter() {
+
+        for implementor in implementors {
             write!(w, "<li><code>")?;
             // If there's already another implementor that has the same abbridged name, use the
             // full path, for example in `std::iter::ExactSizeIterator`
             let dissambiguate = if let clean::Type::ResolvedPath {
                 ref path, ..
             } = implementor.impl_.for_ {
-                *implementor_count.get(&path.last_name()).unwrap_or(&0) > 1
+                implementor_count[path.last_name()] > 1
             } else {
                 false
             };

@estebank
Copy link
Contributor Author

@bluss applied 👍

Copy link
Member

@bluss bluss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, we can integrate, let's just clean up that bool parameter's name to be consistent across the patch.

@@ -433,7 +433,7 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec<String>)> {
/// Used when rendering a `ResolvedPath` structure. This invokes the `path`
/// rendering function with the necessary arguments for linking to a local path.
fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path,
print_all: bool) -> fmt::Result {
print_all: bool, use_absolute: bool) -> fmt::Result {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you go through the patch and use the same name for this parameter everywhere (the use_absolute here)? That's one step that makes a bool parameter more bearable.

// Paths like T::Output and Self::Output should be rendered with all segments
resolved_path(f, did, path, is_generic)?;
tybounds(f, typarams)
fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, full_path: bool) -> fmt::Result {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This parameter is the same (full_path), so this and in other places.

fmt_impl_for_trait_page(&i.impl_, w)?;
// If there's already another implementor that has the same abbridged name, use the
// full path, for example in `std::iter::ExactSizeIterator`
let dissambiguate = if let clean::Type::ResolvedPath {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra s in the spelling here. It's another of the ones that should have the same name across the patch, though.

@steveklabnik
Copy link
Member

/cc @rust-lang/tools

@steveklabnik
Copy link
Member

@bors: r+

thanks!

@GuillaumeGomez
Copy link
Member

Excellent, thanks a lot for this!

@japaric
Copy link
Member

japaric commented Jan 4, 2017

@bors r=steveklabnik

@bors
Copy link
Contributor

bors commented Jan 4, 2017

📌 Commit 346a442 has been approved by steveklabnik

@bluss
Copy link
Member

bluss commented Jan 4, 2017

@bors r=steveklabnik

@bors
Copy link
Contributor

bors commented Jan 4, 2017

💡 This pull request was already approved, no need to approve it again.

@bors
Copy link
Contributor

bors commented Jan 4, 2017

📌 Commit 346a442 has been approved by steveklabnik

@bors
Copy link
Contributor

bors commented Jan 4, 2017

⌛ Testing commit 346a442 with merge 05f4a75...

bors added a commit that referenced this pull request Jan 4, 2017
Rustdoc: disambiguate Implementors when the type name is not unique

Presentation [goes from](https://doc.rust-lang.org/stable/std/iter/trait.ExactSizeIterator.html#implementors):

<img width="492" alt="" src="https://cloud.githubusercontent.com/assets/1606434/21276752/b2b50474-c387-11e6-96e1-9766851da269.png">

to:

<img width="787" alt="" src="https://cloud.githubusercontent.com/assets/1606434/21276763/bb37f6b0-c387-11e6-8596-9163cb254674.png">

on cases where there're multiple implementors with the same name.

Fixes #37762.
@bors
Copy link
Contributor

bors commented Jan 4, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: steveklabnik
Pushing 05f4a75 to master...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants