diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 9c64b7b4ab6..de978971bbe 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -217,7 +217,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, @@ -370,7 +370,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 95444bb9158..e366caf92f7 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), @@ -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) } @@ -1286,7 +1292,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), @@ -1401,11 +1407,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. @@ -1594,8 +1602,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 @@ -1675,6 +1688,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 }) => { @@ -1689,6 +1703,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)), @@ -2085,7 +2100,7 @@ impl Clean for doctree::Typedef { inner: TypedefItem(Typedef { type_: self.ty.clean(cx), generics: self.gen.clean(cx), - }), + }, false), } } } @@ -2255,7 +2270,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 { @@ -2580,10 +2595,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), @@ -2601,13 +2613,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 { @@ -2821,6 +2834,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 6e70b3711e4..3929630267a 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -437,9 +437,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/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index ef733a80466..c4f2c7207ac 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -865,7 +865,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), @@ -931,6 +931,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 { @@ -1492,7 +1496,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) => @@ -2304,10 +2308,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), @@ -2357,7 +2361,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink, try!(write!(w, "\n")); } } - clean::TypedefItem(ref tydef) => { + clean::TypedefItem(ref tydef, _) => { let name = item.name.as_ref().unwrap(); try!(write!(w, "

", *name, @@ -2447,10 +2451,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/assoc-types.rs b/src/test/rustdoc/assoc-types.rs index 20076a76494..d5047ade062 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 +} diff --git a/src/test/rustdoc/search-index.rs b/src/test/rustdoc/search-index.rs index 42469a21f22..70b77f6760d 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 } +} diff --git a/src/test/rustdoc/where.rs b/src/test/rustdoc/where.rs index 3ce91d63300..91ec69d9a3c 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);