Rustdoc: disambiguate Implementors when the type name is not unique
This commit is contained in:
parent
6483bdd860
commit
2841bf3bc7
2 changed files with 201 additions and 171 deletions
|
@ -433,7 +433,7 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec<String>)> {
|
||||||
/// Used when rendering a `ResolvedPath` structure. This invokes the `path`
|
/// Used when rendering a `ResolvedPath` structure. This invokes the `path`
|
||||||
/// rendering function with the necessary arguments for linking to a local 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,
|
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 {
|
||||||
let last = path.segments.last().unwrap();
|
let last = path.segments.last().unwrap();
|
||||||
let rel_root = match &*path.segments[0].name {
|
let rel_root = match &*path.segments[0].name {
|
||||||
"self" => Some("./".to_string()),
|
"self" => Some("./".to_string()),
|
||||||
|
@ -467,7 +467,17 @@ fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path,
|
||||||
if w.alternate() {
|
if w.alternate() {
|
||||||
write!(w, "{:#}{:#}", HRef::new(did, &last.name), last.params)?;
|
write!(w, "{:#}{:#}", HRef::new(did, &last.name), last.params)?;
|
||||||
} else {
|
} else {
|
||||||
write!(w, "{}{}", HRef::new(did, &last.name), last.params)?;
|
let path = if use_absolute {
|
||||||
|
match href(did) {
|
||||||
|
Some((_, _, fqp)) => format!("{}::{}",
|
||||||
|
fqp[..fqp.len()-1].join("::"),
|
||||||
|
HRef::new(did, fqp.last().unwrap())),
|
||||||
|
None => format!("{}", HRef::new(did, &last.name)),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
format!("{}", HRef::new(did, &last.name))
|
||||||
|
};
|
||||||
|
write!(w, "{}{}", path, last.params)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -551,15 +561,14 @@ impl<'a> fmt::Display for HRef<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for clean::Type {
|
fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, full_path: bool) -> fmt::Result {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
match *t {
|
||||||
match *self {
|
|
||||||
clean::Generic(ref name) => {
|
clean::Generic(ref name) => {
|
||||||
f.write_str(name)
|
f.write_str(name)
|
||||||
}
|
}
|
||||||
clean::ResolvedPath{ did, ref typarams, ref path, is_generic } => {
|
clean::ResolvedPath{ did, ref typarams, ref path, is_generic } => {
|
||||||
// Paths like T::Output and Self::Output should be rendered with all segments
|
// Paths like T::Output and Self::Output should be rendered with all segments
|
||||||
resolved_path(f, did, path, is_generic)?;
|
resolved_path(f, did, path, is_generic, full_path)?;
|
||||||
tybounds(f, typarams)
|
tybounds(f, typarams)
|
||||||
}
|
}
|
||||||
clean::Infer => write!(f, "_"),
|
clean::Infer => write!(f, "_"),
|
||||||
|
@ -718,7 +727,7 @@ impl fmt::Display for clean::Type {
|
||||||
write!(f, "{}::", self_type)?;
|
write!(f, "{}::", self_type)?;
|
||||||
}
|
}
|
||||||
let path = clean::Path::singleton(name.clone());
|
let path = clean::Path::singleton(name.clone());
|
||||||
resolved_path(f, did, &path, false)?;
|
resolved_path(f, did, &path, true, full_path)?;
|
||||||
|
|
||||||
// FIXME: `typarams` are not rendered, and this seems bad?
|
// FIXME: `typarams` are not rendered, and this seems bad?
|
||||||
drop(typarams);
|
drop(typarams);
|
||||||
|
@ -736,9 +745,14 @@ impl fmt::Display for clean::Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for clean::Type {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
fmt_type(self, f, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fmt_impl(i: &clean::Impl, f: &mut fmt::Formatter, link_trait: bool) -> fmt::Result {
|
fn fmt_impl(i: &clean::Impl, f: &mut fmt::Formatter, link_trait: bool, full: bool) -> fmt::Result {
|
||||||
let mut plain = String::new();
|
let mut plain = String::new();
|
||||||
|
|
||||||
if f.alternate() {
|
if f.alternate() {
|
||||||
|
@ -772,7 +786,7 @@ fn fmt_impl(i: &clean::Impl, f: &mut fmt::Formatter, link_trait: bool) -> fmt::R
|
||||||
plain.push_str(" for ");
|
plain.push_str(" for ");
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt::Display::fmt(&i.for_, f)?;
|
fmt_type(&i.for_, f, full)?;
|
||||||
plain.push_str(&format!("{:#}", i.for_));
|
plain.push_str(&format!("{:#}", i.for_));
|
||||||
|
|
||||||
fmt::Display::fmt(&WhereClause(&i.generics, plain.len() + 1), f)?;
|
fmt::Display::fmt(&WhereClause(&i.generics, plain.len() + 1), f)?;
|
||||||
|
@ -781,13 +795,15 @@ fn fmt_impl(i: &clean::Impl, f: &mut fmt::Formatter, link_trait: bool) -> fmt::R
|
||||||
|
|
||||||
impl fmt::Display for clean::Impl {
|
impl fmt::Display for clean::Impl {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt_impl(self, f, true)
|
fmt_impl(self, f, true, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The difference from above is that trait is not hyperlinked.
|
// The difference from above is that trait is not hyperlinked.
|
||||||
pub fn fmt_impl_for_trait_page(i: &clean::Impl, f: &mut fmt::Formatter) -> fmt::Result {
|
pub fn fmt_impl_for_trait_page(i: &clean::Impl,
|
||||||
fmt_impl(i, f, false)
|
f: &mut fmt::Formatter,
|
||||||
|
disambiguate: bool) -> fmt::Result {
|
||||||
|
fmt_impl(i, f, false, disambiguate)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for clean::Arguments {
|
impl fmt::Display for clean::Arguments {
|
||||||
|
@ -978,7 +994,7 @@ impl fmt::Display for clean::Import {
|
||||||
impl fmt::Display for clean::ImportSource {
|
impl fmt::Display for clean::ImportSource {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self.did {
|
match self.did {
|
||||||
Some(did) => resolved_path(f, did, &self.path, true),
|
Some(did) => resolved_path(f, did, &self.path, true, false),
|
||||||
_ => {
|
_ => {
|
||||||
for (i, seg) in self.path.segments.iter().enumerate() {
|
for (i, seg) in self.path.segments.iter().enumerate() {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
|
|
|
@ -2111,9 +2111,23 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
||||||
<ul class='item-list' id='implementors-list'>
|
<ul class='item-list' id='implementors-list'>
|
||||||
")?;
|
")?;
|
||||||
if let Some(implementors) = cache.implementors.get(&it.def_id) {
|
if let Some(implementors) = cache.implementors.get(&it.def_id) {
|
||||||
for i in implementors {
|
for k in implementors.iter() {
|
||||||
write!(w, "<li><code>")?;
|
write!(w, "<li><code>")?;
|
||||||
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 mut dissambiguate = false;
|
||||||
|
for l in implementors.iter() {
|
||||||
|
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() {
|
||||||
|
dissambiguate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt_impl_for_trait_page(&k.impl_, w, dissambiguate)?;
|
||||||
writeln!(w, "</code></li>")?;
|
writeln!(w, "</code></li>")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue