Skip to content

Commit 174c619

Browse files
author
Ulrik Sverdrup
committed
rustdoc: Fix associated types in signatures
Functions such as `fn foo<I: Iterator>(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 rust-lang#24417
1 parent 093e18d commit 174c619

File tree

3 files changed

+50
-17
lines changed

3 files changed

+50
-17
lines changed

src/librustdoc/clean/mod.rs

+25-14
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use syntax::attr;
3232
use syntax::attr::{AttributeMethods, AttrMetaMethods};
3333
use syntax::codemap;
3434
use syntax::codemap::{DUMMY_SP, Pos, Spanned};
35-
use syntax::parse::token::{self, InternedString, special_idents};
35+
use syntax::parse::token::{self, InternedString};
3636
use syntax::ptr::P;
3737

3838
use rustc_trans::back::link;
@@ -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
}
@@ -1394,11 +1400,13 @@ pub struct PolyTrait {
13941400
/// it does not preserve mutability or boxes.
13951401
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
13961402
pub enum Type {
1397-
/// structs/enums/traits (anything that'd be an ast::TyPath)
1403+
/// structs/enums/traits (most that'd be an ast::TyPath)
13981404
ResolvedPath {
13991405
path: Path,
14001406
typarams: Option<Vec<TyParamBound>>,
14011407
did: ast::DefId,
1408+
/// true if is a `T::Name` path for associated types
1409+
is_generic: bool,
14021410
},
14031411
/// For parameterized types, so the consumer of the JSON don't go
14041412
/// looking for types which don't exist anywhere.
@@ -1587,8 +1595,13 @@ impl Clean<Type> for ast::Ty {
15871595
TyObjectSum(ref lhs, ref bounds) => {
15881596
let lhs_ty = lhs.clean(cx);
15891597
match lhs_ty {
1590-
ResolvedPath { path, typarams: None, did } => {
1591-
ResolvedPath { path: path, typarams: Some(bounds.clean(cx)), did: did}
1598+
ResolvedPath { path, typarams: None, did, is_generic } => {
1599+
ResolvedPath {
1600+
path: path,
1601+
typarams: Some(bounds.clean(cx)),
1602+
did: did,
1603+
is_generic: is_generic,
1604+
}
15921605
}
15931606
_ => {
15941607
lhs_ty // shouldn't happen
@@ -1668,6 +1681,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
16681681
path: path,
16691682
typarams: None,
16701683
did: did,
1684+
is_generic: false,
16711685
}
16721686
}
16731687
ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => {
@@ -1682,6 +1696,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
16821696
path: path,
16831697
typarams: Some(typarams),
16841698
did: did,
1699+
is_generic: false,
16851700
}
16861701
}
16871702
ty::ty_tup(ref t) => Tuple(t.clean(cx)),
@@ -2572,10 +2587,7 @@ fn resolve_type(cx: &DocContext,
25722587
None => panic!("unresolved id not in defmap")
25732588
};
25742589

2575-
match def {
2576-
def::DefSelfTy(..) if path.segments.len() == 1 => {
2577-
return Generic(token::get_name(special_idents::type_self.name).to_string());
2578-
}
2590+
let is_generic = match def {
25792591
def::DefPrimTy(p) => match p {
25802592
ast::TyStr => return Primitive(Str),
25812593
ast::TyBool => return Primitive(Bool),
@@ -2593,13 +2605,11 @@ fn resolve_type(cx: &DocContext,
25932605
ast::TyFloat(ast::TyF32) => return Primitive(F32),
25942606
ast::TyFloat(ast::TyF64) => return Primitive(F64),
25952607
},
2596-
def::DefTyParam(_, _, _, n) => {
2597-
return Generic(token::get_name(n).to_string())
2598-
}
2599-
_ => {}
2608+
def::DefTyParam(..) | def::DefSelfTy(..) => true,
2609+
_ => false,
26002610
};
26012611
let did = register_def(&*cx, def);
2602-
ResolvedPath { path: path, typarams: None, did: did }
2612+
ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
26032613
}
26042614

26052615
fn register_def(cx: &DocContext, def: def::Def) -> ast::DefId {
@@ -2798,6 +2808,7 @@ fn lang_struct(cx: &DocContext, did: Option<ast::DefId>,
27982808
}
27992809
}],
28002810
},
2811+
is_generic: false,
28012812
}
28022813
}
28032814

src/librustdoc/html/format.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -427,9 +427,9 @@ impl fmt::Display for clean::Type {
427427
clean::Generic(ref name) => {
428428
f.write_str(name)
429429
}
430-
clean::ResolvedPath{ did, ref typarams, ref path } => {
431-
// Paths like Self::Output should be rendered with all segments
432-
try!(resolved_path(f, did, path, path.segments[0].name == "Self"));
430+
clean::ResolvedPath{ did, ref typarams, ref path, is_generic } => {
431+
// Paths like T::Output and Self::Output should be rendered with all segments
432+
try!(resolved_path(f, did, path, is_generic));
433433
tybounds(f, typarams)
434434
}
435435
clean::Infer => write!(f, "_"),

src/test/rustdoc/assoc-types.rs

+22
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+
}

0 commit comments

Comments
 (0)