Skip to content

Commit cccc137

Browse files
committed
Auto merge of #25675 - bluss:rustdoc-assoc-types-index, r=alexcrichton
rustdoc: Associated type fixes The first commit fixes a bug with "dud" items in the search index from misrepresented `type` items in trait impl blocks. 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. The second commit fixes a bug that made signatures and where bounds using associated types (if they were not on `Self`) incorrect. The third commit fixes so that where clauses in type alias definititons are shown. Fixes #22442 Fixes #24417 Fixes #25769
2 parents 1742a01 + 06304ed commit cccc137

File tree

7 files changed

+83
-28
lines changed

7 files changed

+83
-28
lines changed

src/librustdoc/clean/inline.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ fn build_type(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEn
217217
clean::TypedefItem(clean::Typedef {
218218
type_: t.ty.clean(cx),
219219
generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx),
220-
})
220+
}, false)
221221
}
222222

223223
pub fn build_impls(cx: &DocContext, tcx: &ty::ctxt,
@@ -370,7 +370,7 @@ pub fn build_impl(cx: &DocContext,
370370
subst::ParamSpace::TypeSpace).clean(cx);
371371
Some(clean::Item {
372372
name: Some(assoc_ty.name.clean(cx)),
373-
inner: clean::TypedefItem(typedef),
373+
inner: clean::TypedefItem(typedef, true),
374374
source: clean::Span::empty(),
375375
attrs: vec![],
376376
visibility: None,

src/librustdoc/clean/mod.rs

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ pub enum ItemEnum {
343343
EnumItem(Enum),
344344
FunctionItem(Function),
345345
ModuleItem(Module),
346-
TypedefItem(Typedef),
346+
TypedefItem(Typedef, bool /* is associated type */),
347347
StaticItem(Static),
348348
ConstantItem(Constant),
349349
TraitItem(Trait),
@@ -664,6 +664,7 @@ impl Clean<TyParamBound> for ty::BuiltinBound {
664664
path: path,
665665
typarams: None,
666666
did: did,
667+
is_generic: false,
667668
},
668669
lifetimes: vec![]
669670
}, ast::TraitBoundModifier::None)
@@ -706,7 +707,12 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
706707
}
707708

708709
TraitBound(PolyTrait {
709-
trait_: ResolvedPath { path: path, typarams: None, did: self.def_id, },
710+
trait_: ResolvedPath {
711+
path: path,
712+
typarams: None,
713+
did: self.def_id,
714+
is_generic: false,
715+
},
710716
lifetimes: late_bounds
711717
}, ast::TraitBoundModifier::None)
712718
}
@@ -1286,7 +1292,7 @@ impl Clean<Item> for ast::ImplItem {
12861292
type_params: Vec::new(),
12871293
where_predicates: Vec::new()
12881294
},
1289-
}),
1295+
}, true),
12901296
ast::MacImplItem(_) => {
12911297
MacroItem(Macro {
12921298
source: self.span.to_src(cx),
@@ -1401,11 +1407,13 @@ pub struct PolyTrait {
14011407
/// it does not preserve mutability or boxes.
14021408
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
14031409
pub enum Type {
1404-
/// structs/enums/traits (anything that'd be an ast::TyPath)
1410+
/// structs/enums/traits (most that'd be an ast::TyPath)
14051411
ResolvedPath {
14061412
path: Path,
14071413
typarams: Option<Vec<TyParamBound>>,
14081414
did: ast::DefId,
1415+
/// true if is a `T::Name` path for associated types
1416+
is_generic: bool,
14091417
},
14101418
/// For parameterized types, so the consumer of the JSON don't go
14111419
/// looking for types which don't exist anywhere.
@@ -1594,8 +1602,13 @@ impl Clean<Type> for ast::Ty {
15941602
TyObjectSum(ref lhs, ref bounds) => {
15951603
let lhs_ty = lhs.clean(cx);
15961604
match lhs_ty {
1597-
ResolvedPath { path, typarams: None, did } => {
1598-
ResolvedPath { path: path, typarams: Some(bounds.clean(cx)), did: did}
1605+
ResolvedPath { path, typarams: None, did, is_generic } => {
1606+
ResolvedPath {
1607+
path: path,
1608+
typarams: Some(bounds.clean(cx)),
1609+
did: did,
1610+
is_generic: is_generic,
1611+
}
15991612
}
16001613
_ => {
16011614
lhs_ty // shouldn't happen
@@ -1675,6 +1688,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
16751688
path: path,
16761689
typarams: None,
16771690
did: did,
1691+
is_generic: false,
16781692
}
16791693
}
16801694
ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => {
@@ -1689,6 +1703,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
16891703
path: path,
16901704
typarams: Some(typarams),
16911705
did: did,
1706+
is_generic: false,
16921707
}
16931708
}
16941709
ty::ty_tup(ref t) => Tuple(t.clean(cx)),
@@ -2085,7 +2100,7 @@ impl Clean<Item> for doctree::Typedef {
20852100
inner: TypedefItem(Typedef {
20862101
type_: self.ty.clean(cx),
20872102
generics: self.gen.clean(cx),
2088-
}),
2103+
}, false),
20892104
}
20902105
}
20912106
}
@@ -2255,7 +2270,7 @@ fn build_deref_target_impls(cx: &DocContext,
22552270

22562271
for item in items {
22572272
let target = match item.inner {
2258-
TypedefItem(ref t) => &t.type_,
2273+
TypedefItem(ref t, true) => &t.type_,
22592274
_ => continue,
22602275
};
22612276
let primitive = match *target {
@@ -2580,10 +2595,7 @@ fn resolve_type(cx: &DocContext,
25802595
None => panic!("unresolved id not in defmap")
25812596
};
25822597

2583-
match def {
2584-
def::DefSelfTy(..) if path.segments.len() == 1 => {
2585-
return Generic(token::get_name(special_idents::type_self.name).to_string());
2586-
}
2598+
let is_generic = match def {
25872599
def::DefPrimTy(p) => match p {
25882600
ast::TyStr => return Primitive(Str),
25892601
ast::TyBool => return Primitive(Bool),
@@ -2601,13 +2613,14 @@ fn resolve_type(cx: &DocContext,
26012613
ast::TyFloat(ast::TyF32) => return Primitive(F32),
26022614
ast::TyFloat(ast::TyF64) => return Primitive(F64),
26032615
},
2604-
def::DefTyParam(_, _, _, n) => {
2605-
return Generic(token::get_name(n).to_string())
2616+
def::DefSelfTy(..) if path.segments.len() == 1 => {
2617+
return Generic(token::get_name(special_idents::type_self.name).to_string());
26062618
}
2607-
_ => {}
2619+
def::DefSelfTy(..) | def::DefTyParam(..) => true,
2620+
_ => false,
26082621
};
26092622
let did = register_def(&*cx, def);
2610-
ResolvedPath { path: path, typarams: None, did: did }
2623+
ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
26112624
}
26122625

26132626
fn register_def(cx: &DocContext, def: def::Def) -> ast::DefId {
@@ -2821,6 +2834,7 @@ fn lang_struct(cx: &DocContext, did: Option<ast::DefId>,
28212834
}
28222835
}],
28232836
},
2837+
is_generic: false,
28242838
}
28252839
}
28262840

src/librustdoc/html/format.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -437,9 +437,9 @@ impl fmt::Display for clean::Type {
437437
clean::Generic(ref name) => {
438438
f.write_str(name)
439439
}
440-
clean::ResolvedPath{ did, ref typarams, ref path } => {
441-
// Paths like Self::Output should be rendered with all segments
442-
try!(resolved_path(f, did, path, path.segments[0].name == "Self"));
440+
clean::ResolvedPath{ did, ref typarams, ref path, is_generic } => {
441+
// Paths like T::Output and Self::Output should be rendered with all segments
442+
try!(resolved_path(f, did, path, is_generic));
443443
tybounds(f, typarams)
444444
}
445445
clean::Infer => write!(f, "_"),

src/librustdoc/html/render.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,7 @@ impl DocFolder for Cache {
865865
clean::StructItem(ref s) => self.generics(&s.generics),
866866
clean::EnumItem(ref e) => self.generics(&e.generics),
867867
clean::FunctionItem(ref f) => self.generics(&f.generics),
868-
clean::TypedefItem(ref t) => self.generics(&t.generics),
868+
clean::TypedefItem(ref t, _) => self.generics(&t.generics),
869869
clean::TraitItem(ref t) => self.generics(&t.generics),
870870
clean::ImplItem(ref i) => self.generics(&i.generics),
871871
clean::TyMethodItem(ref i) => self.generics(&i.generics),
@@ -931,6 +931,10 @@ impl DocFolder for Cache {
931931
((Some(*last), path), true)
932932
}
933933
}
934+
clean::TypedefItem(_, true) => {
935+
// skip associated types in impls
936+
((None, None), false)
937+
}
934938
_ => ((None, Some(&*self.stack)), false)
935939
};
936940
let hidden_field = match item.inner {
@@ -1492,7 +1496,7 @@ impl<'a> fmt::Display for Item<'a> {
14921496
clean::TraitItem(ref t) => item_trait(fmt, self.cx, self.item, t),
14931497
clean::StructItem(ref s) => item_struct(fmt, self.item, s),
14941498
clean::EnumItem(ref e) => item_enum(fmt, self.item, e),
1495-
clean::TypedefItem(ref t) => item_typedef(fmt, self.item, t),
1499+
clean::TypedefItem(ref t, _) => item_typedef(fmt, self.item, t),
14961500
clean::MacroItem(ref m) => item_macro(fmt, self.item, m),
14971501
clean::PrimitiveItem(ref p) => item_primitive(fmt, self.item, p),
14981502
clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) =>
@@ -2304,10 +2308,10 @@ fn render_deref_methods(w: &mut fmt::Formatter, impl_: &Impl) -> fmt::Result {
23042308
let deref_type = impl_.impl_.trait_.as_ref().unwrap();
23052309
let target = impl_.impl_.items.iter().filter_map(|item| {
23062310
match item.inner {
2307-
clean::TypedefItem(ref t) => Some(&t.type_),
2311+
clean::TypedefItem(ref t, true) => Some(&t.type_),
23082312
_ => None,
23092313
}
2310-
}).next().unwrap();
2314+
}).next().expect("Expected associated type binding");
23112315
let what = AssocItemRender::DerefFor { trait_: deref_type, type_: target };
23122316
match *target {
23132317
clean::ResolvedPath { did, .. } => render_assoc_items(w, did, what),
@@ -2357,7 +2361,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink,
23572361
try!(write!(w, "</code></h4>\n"));
23582362
}
23592363
}
2360-
clean::TypedefItem(ref tydef) => {
2364+
clean::TypedefItem(ref tydef, _) => {
23612365
let name = item.name.as_ref().unwrap();
23622366
try!(write!(w, "<h4 id='assoc_type.{}' class='{}'><code>",
23632367
*name,
@@ -2447,10 +2451,11 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink,
24472451

24482452
fn item_typedef(w: &mut fmt::Formatter, it: &clean::Item,
24492453
t: &clean::Typedef) -> fmt::Result {
2450-
try!(write!(w, "<pre class='rust typedef'>type {}{} = {};</pre>",
2454+
try!(write!(w, "<pre class='rust typedef'>type {}{}{where_clause} = {type_};</pre>",
24512455
it.name.as_ref().unwrap(),
24522456
t.generics,
2453-
t.type_));
2457+
where_clause = WhereClause(&t.generics),
2458+
type_ = t.type_));
24542459

24552460
document(w, it)
24562461
}

src/test/rustdoc/assoc-types.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,25 @@ pub trait Index<I: ?Sized> {
1818
// "fn index<'a>(&'a self, index: I) -> &'a Self::Output"
1919
fn index<'a>(&'a self, index: I) -> &'a Self::Output;
2020
}
21+
22+
// @has assoc_types/fn.use_output.html
23+
// @has - '//*[@class="rust fn"]' '-> &T::Output'
24+
pub fn use_output<T: Index<usize>>(obj: &T, index: usize) -> &T::Output {
25+
obj.index(index)
26+
}
27+
28+
pub trait Feed {
29+
type Input;
30+
}
31+
32+
// @has assoc_types/fn.use_input.html
33+
// @has - '//*[@class="rust fn"]' 'T::Input'
34+
pub fn use_input<T: Feed>(_feed: &T, _element: T::Input) { }
35+
36+
// @has assoc_types/fn.cmp_input.html
37+
// @has - '//*[@class="rust fn"]' 'where T::Input: PartialEq<U::Input>'
38+
pub fn cmp_input<T: Feed, U: Feed>(a: &T::Input, b: &U::Input) -> bool
39+
where T::Input: PartialEq<U::Input>
40+
{
41+
a == b
42+
}

src/test/rustdoc/search-index.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
#![crate_name = "rustdoc_test"]
1212

13+
use std::ops::Deref;
14+
1315
// @has search-index.js Foo
1416
pub use private::Foo;
1517

@@ -24,3 +26,11 @@ mod private {
2426
fn trait_method(&self) {} // @!has - priv_method
2527
}
2628
}
29+
30+
pub struct Bar;
31+
32+
impl Deref for Bar {
33+
// @!has search-index.js Target
34+
type Target = Bar;
35+
fn deref(&self) -> &Bar { self }
36+
}

src/test/rustdoc/where.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,7 @@ pub enum Foxtrot<F> { Foxtrot1(F) }
4242
// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//code' \
4343
// "impl<F> MyTrait for Foxtrot<F> where F: MyTrait"
4444
impl<F> MyTrait for Foxtrot<F> where F: MyTrait {}
45+
46+
// @has foo/type.Golf.html '//pre[@class="rust typedef"]' \
47+
// "type Golf<T> where T: Clone = (T, T)"
48+
pub type Golf<T> where T: Clone = (T, T);

0 commit comments

Comments
 (0)