From 093e18d18465364ef96495ab662fb4325595bead Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Thu, 21 May 2015 14:17:37 +0200 Subject: [PATCH 1/3] rustdoc: Skip types in impls in search index For a trait *implementation* there are typedefs which are the types for that particular trait and implementor. Skip these in the search index. There were lots of dud items in the search index due to this (search for Item, Iterator's associated type). Add a boolean to clean::TypedefItem so that it tracks whether the it is a type alias on its own, or if it's a `type` item in a trait impl. Fixes #22442 --- src/librustdoc/clean/inline.rs | 4 ++-- src/librustdoc/clean/mod.rs | 8 ++++---- src/librustdoc/html/render.rs | 14 +++++++++----- src/test/rustdoc/search-index.rs | 10 ++++++++++ 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 3ce8835b1a8d..c5c0f4dd8db1 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -216,7 +216,7 @@ fn build_type(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEn clean::TypedefItem(clean::Typedef { type_: t.ty.clean(cx), generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx), - }) + }, false) } pub fn build_impls(cx: &DocContext, tcx: &ty::ctxt, @@ -368,7 +368,7 @@ pub fn build_impl(cx: &DocContext, subst::ParamSpace::TypeSpace).clean(cx); Some(clean::Item { name: Some(assoc_ty.name.clean(cx)), - inner: clean::TypedefItem(typedef), + inner: clean::TypedefItem(typedef, true), source: clean::Span::empty(), attrs: vec![], visibility: None, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4c2357f8a8f0..d985fa4c8cc6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -343,7 +343,7 @@ pub enum ItemEnum { EnumItem(Enum), FunctionItem(Function), ModuleItem(Module), - TypedefItem(Typedef), + TypedefItem(Typedef, bool /* is associated type */), StaticItem(Static), ConstantItem(Constant), TraitItem(Trait), @@ -1282,7 +1282,7 @@ impl Clean for ast::ImplItem { type_params: Vec::new(), where_predicates: Vec::new() }, - }), + }, true), ast::MacImplItem(_) => { MacroItem(Macro { source: self.span.to_src(cx), @@ -2078,7 +2078,7 @@ impl Clean for doctree::Typedef { inner: TypedefItem(Typedef { type_: self.ty.clean(cx), generics: self.gen.clean(cx), - }), + }, false), } } } @@ -2248,7 +2248,7 @@ fn build_deref_target_impls(cx: &DocContext, for item in items { let target = match item.inner { - TypedefItem(ref t) => &t.type_, + TypedefItem(ref t, true) => &t.type_, _ => continue, }; let primitive = match *target { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 36cf650d54e9..d82602c9bd07 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -870,7 +870,7 @@ impl DocFolder for Cache { clean::StructItem(ref s) => self.generics(&s.generics), clean::EnumItem(ref e) => self.generics(&e.generics), clean::FunctionItem(ref f) => self.generics(&f.generics), - clean::TypedefItem(ref t) => self.generics(&t.generics), + clean::TypedefItem(ref t, _) => self.generics(&t.generics), clean::TraitItem(ref t) => self.generics(&t.generics), clean::ImplItem(ref i) => self.generics(&i.generics), clean::TyMethodItem(ref i) => self.generics(&i.generics), @@ -936,6 +936,10 @@ impl DocFolder for Cache { ((Some(*last), path), true) } } + clean::TypedefItem(_, true) => { + // skip associated types in impls + ((None, None), false) + } _ => ((None, Some(&*self.stack)), false) }; let hidden_field = match item.inner { @@ -1497,7 +1501,7 @@ impl<'a> fmt::Display for Item<'a> { clean::TraitItem(ref t) => item_trait(fmt, self.cx, self.item, t), clean::StructItem(ref s) => item_struct(fmt, self.item, s), clean::EnumItem(ref e) => item_enum(fmt, self.item, e), - clean::TypedefItem(ref t) => item_typedef(fmt, self.item, t), + clean::TypedefItem(ref t, _) => item_typedef(fmt, self.item, t), clean::MacroItem(ref m) => item_macro(fmt, self.item, m), clean::PrimitiveItem(ref p) => item_primitive(fmt, self.item, p), clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => @@ -2303,10 +2307,10 @@ fn render_deref_methods(w: &mut fmt::Formatter, impl_: &Impl) -> fmt::Result { let deref_type = impl_.impl_.trait_.as_ref().unwrap(); let target = impl_.impl_.items.iter().filter_map(|item| { match item.inner { - clean::TypedefItem(ref t) => Some(&t.type_), + clean::TypedefItem(ref t, true) => Some(&t.type_), _ => None, } - }).next().unwrap(); + }).next().expect("Expected associated type binding"); let what = AssocItemRender::DerefFor { trait_: deref_type, type_: target }; match *target { clean::ResolvedPath { did, .. } => render_assoc_items(w, did, what), @@ -2350,7 +2354,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink, try!(render_assoc_item(w, item, link)); try!(write!(w, "\n")); } - clean::TypedefItem(ref tydef) => { + clean::TypedefItem(ref tydef, _) => { let name = item.name.as_ref().unwrap(); try!(write!(w, "

", *name, diff --git a/src/test/rustdoc/search-index.rs b/src/test/rustdoc/search-index.rs index 42469a21f22d..70b77f6760d8 100644 --- a/src/test/rustdoc/search-index.rs +++ b/src/test/rustdoc/search-index.rs @@ -10,6 +10,8 @@ #![crate_name = "rustdoc_test"] +use std::ops::Deref; + // @has search-index.js Foo pub use private::Foo; @@ -24,3 +26,11 @@ mod private { fn trait_method(&self) {} // @!has - priv_method } } + +pub struct Bar; + +impl Deref for Bar { + // @!has search-index.js Target + type Target = Bar; + fn deref(&self) -> &Bar { self } +} From d1cd689b4867e915e42264175d54c45f22180206 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Mon, 25 May 2015 15:06:38 +0200 Subject: [PATCH 2/3] rustdoc: Fix associated types in signatures Functions such as `fn foo(x: I::Item)` would not render correctly and displayed `I` instead of `I::Item`. Same thing with `I::Item` appearing in where bounds. This fixes the bug by using paths for generics. Fixes #24417 --- src/librustdoc/clean/mod.rs | 38 ++++++++++++++++++++++----------- src/librustdoc/html/format.rs | 6 +++--- src/test/rustdoc/assoc-types.rs | 22 +++++++++++++++++++ 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d985fa4c8cc6..701e99a6e3bf 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -664,6 +664,7 @@ impl Clean for ty::BuiltinBound { path: path, typarams: None, did: did, + is_generic: false, }, lifetimes: vec![] }, ast::TraitBoundModifier::None) @@ -706,7 +707,12 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { } TraitBound(PolyTrait { - trait_: ResolvedPath { path: path, typarams: None, did: self.def_id, }, + trait_: ResolvedPath { + path: path, + typarams: None, + did: self.def_id, + is_generic: false, + }, lifetimes: late_bounds }, ast::TraitBoundModifier::None) } @@ -1394,11 +1400,13 @@ pub struct PolyTrait { /// it does not preserve mutability or boxes. #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] pub enum Type { - /// structs/enums/traits (anything that'd be an ast::TyPath) + /// structs/enums/traits (most that'd be an ast::TyPath) ResolvedPath { path: Path, typarams: Option>, did: ast::DefId, + /// true if is a `T::Name` path for associated types + is_generic: bool, }, /// For parameterized types, so the consumer of the JSON don't go /// looking for types which don't exist anywhere. @@ -1587,8 +1595,13 @@ impl Clean for ast::Ty { TyObjectSum(ref lhs, ref bounds) => { let lhs_ty = lhs.clean(cx); match lhs_ty { - ResolvedPath { path, typarams: None, did } => { - ResolvedPath { path: path, typarams: Some(bounds.clean(cx)), did: did} + ResolvedPath { path, typarams: None, did, is_generic } => { + ResolvedPath { + path: path, + typarams: Some(bounds.clean(cx)), + did: did, + is_generic: is_generic, + } } _ => { lhs_ty // shouldn't happen @@ -1668,6 +1681,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { path: path, typarams: None, did: did, + is_generic: false, } } ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => { @@ -1682,6 +1696,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { path: path, typarams: Some(typarams), did: did, + is_generic: false, } } ty::ty_tup(ref t) => Tuple(t.clean(cx)), @@ -2572,10 +2587,7 @@ fn resolve_type(cx: &DocContext, None => panic!("unresolved id not in defmap") }; - match def { - def::DefSelfTy(..) if path.segments.len() == 1 => { - return Generic(token::get_name(special_idents::type_self.name).to_string()); - } + let is_generic = match def { def::DefPrimTy(p) => match p { ast::TyStr => return Primitive(Str), ast::TyBool => return Primitive(Bool), @@ -2593,13 +2605,14 @@ fn resolve_type(cx: &DocContext, ast::TyFloat(ast::TyF32) => return Primitive(F32), ast::TyFloat(ast::TyF64) => return Primitive(F64), }, - def::DefTyParam(_, _, _, n) => { - return Generic(token::get_name(n).to_string()) + def::DefSelfTy(..) if path.segments.len() == 1 => { + return Generic(token::get_name(special_idents::type_self.name).to_string()); } - _ => {} + def::DefSelfTy(..) | def::DefTyParam(..) => true, + _ => false, }; let did = register_def(&*cx, def); - ResolvedPath { path: path, typarams: None, did: did } + ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic } } fn register_def(cx: &DocContext, def: def::Def) -> ast::DefId { @@ -2798,6 +2811,7 @@ fn lang_struct(cx: &DocContext, did: Option, } }], }, + is_generic: false, } } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index bb53d532f52f..e899f668e402 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -427,9 +427,9 @@ impl fmt::Display for clean::Type { clean::Generic(ref name) => { f.write_str(name) } - clean::ResolvedPath{ did, ref typarams, ref path } => { - // Paths like Self::Output should be rendered with all segments - try!(resolved_path(f, did, path, path.segments[0].name == "Self")); + clean::ResolvedPath{ did, ref typarams, ref path, is_generic } => { + // Paths like T::Output and Self::Output should be rendered with all segments + try!(resolved_path(f, did, path, is_generic)); tybounds(f, typarams) } clean::Infer => write!(f, "_"), diff --git a/src/test/rustdoc/assoc-types.rs b/src/test/rustdoc/assoc-types.rs index 20076a764943..d5047ade062d 100644 --- a/src/test/rustdoc/assoc-types.rs +++ b/src/test/rustdoc/assoc-types.rs @@ -18,3 +18,25 @@ pub trait Index { // "fn index<'a>(&'a self, index: I) -> &'a Self::Output" fn index<'a>(&'a self, index: I) -> &'a Self::Output; } + +// @has assoc_types/fn.use_output.html +// @has - '//*[@class="rust fn"]' '-> &T::Output' +pub fn use_output>(obj: &T, index: usize) -> &T::Output { + obj.index(index) +} + +pub trait Feed { + type Input; +} + +// @has assoc_types/fn.use_input.html +// @has - '//*[@class="rust fn"]' 'T::Input' +pub fn use_input(_feed: &T, _element: T::Input) { } + +// @has assoc_types/fn.cmp_input.html +// @has - '//*[@class="rust fn"]' 'where T::Input: PartialEq' +pub fn cmp_input(a: &T::Input, b: &U::Input) -> bool + where T::Input: PartialEq +{ + a == b +} From 06304ed52201ea0cae7a09f2546123c78a60a193 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Mon, 25 May 2015 23:05:35 +0200 Subject: [PATCH 3/3] rustdoc: Show where clauses in type aliases Yes, it's allowed. Example: type MapFn where I: Iterator = Map B>; Fixes #25769 --- src/librustdoc/html/render.rs | 5 +++-- src/test/rustdoc/where.rs | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index d82602c9bd07..65652a4d9c36 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2429,10 +2429,11 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink, fn item_typedef(w: &mut fmt::Formatter, it: &clean::Item, t: &clean::Typedef) -> fmt::Result { - try!(write!(w, "
type {}{} = {};
", + try!(write!(w, "
type {}{}{where_clause} = {type_};
", it.name.as_ref().unwrap(), t.generics, - t.type_)); + where_clause = WhereClause(&t.generics), + type_ = t.type_)); document(w, it) } diff --git a/src/test/rustdoc/where.rs b/src/test/rustdoc/where.rs index 3ce91d633000..91ec69d9a3cb 100644 --- a/src/test/rustdoc/where.rs +++ b/src/test/rustdoc/where.rs @@ -42,3 +42,7 @@ pub enum Foxtrot { Foxtrot1(F) } // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//code' \ // "impl MyTrait for Foxtrot where F: MyTrait" impl MyTrait for Foxtrot where F: MyTrait {} + +// @has foo/type.Golf.html '//pre[@class="rust typedef"]' \ +// "type Golf where T: Clone = (T, T)" +pub type Golf where T: Clone = (T, T);