Skip to content

Commit 3722528

Browse files
committed
rustdoc: render higher-rank trait bounds
Fix #19915
1 parent b39e99c commit 3722528

File tree

3 files changed

+78
-26
lines changed

3 files changed

+78
-26
lines changed

src/librustdoc/clean/inline.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt,
328328
derived: clean::detect_derived(attrs.as_slice()),
329329
trait_: associated_trait.clean(cx).map(|bound| {
330330
match bound {
331-
clean::TraitBound(ty) => ty,
331+
clean::TraitBound(polyt) => polyt.trait_,
332332
clean::RegionBound(..) => unreachable!(),
333333
}
334334
}),

src/librustdoc/clean/mod.rs

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ use rustc::metadata::cstore;
4343
use rustc::metadata::csearch;
4444
use rustc::metadata::decoder;
4545
use rustc::middle::def;
46-
use rustc::middle::subst;
47-
use rustc::middle::subst::VecPerParamSpace;
46+
use rustc::middle::subst::{mod, ParamSpace, VecPerParamSpace};
4847
use rustc::middle::ty;
4948
use rustc::middle::stability;
5049
use rustc::session::config;
@@ -493,7 +492,7 @@ impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
493492
#[deriving(Clone, RustcEncodable, RustcDecodable, PartialEq)]
494493
pub enum TyParamBound {
495494
RegionBound(Lifetime),
496-
TraitBound(Type)
495+
TraitBound(PolyTrait)
497496
}
498497

499498
impl Clean<TyParamBound> for ast::TyParamBound {
@@ -558,10 +557,13 @@ impl Clean<TyParamBound> for ty::BuiltinBound {
558557
let fqn = fqn.into_iter().map(|i| i.to_string()).collect();
559558
cx.external_paths.borrow_mut().as_mut().unwrap().insert(did,
560559
(fqn, TypeTrait));
561-
TraitBound(ResolvedPath {
562-
path: path,
563-
typarams: None,
564-
did: did,
560+
TraitBound(PolyTrait {
561+
trait_: ResolvedPath {
562+
path: path,
563+
typarams: None,
564+
did: did,
565+
},
566+
lifetimes: vec![]
565567
})
566568
}
567569
}
@@ -585,10 +587,31 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
585587
&self.substs);
586588
cx.external_paths.borrow_mut().as_mut().unwrap().insert(self.def_id,
587589
(fqn, TypeTrait));
588-
TraitBound(ResolvedPath {
589-
path: path,
590-
typarams: None,
591-
did: self.def_id,
590+
591+
debug!("ty::TraitRef\n substs.types(TypeSpace): {}\n",
592+
self.substs.types.get_slice(ParamSpace::TypeSpace));
593+
594+
// collect any late bound regions
595+
let mut late_bounds = vec![];
596+
for &ty_s in self.substs.types.get_slice(ParamSpace::TypeSpace).iter() {
597+
use rustc::middle::ty::{Region, sty};
598+
if let sty::ty_tup(ref ts) = ty_s.sty {
599+
for &ty_s in ts.iter() {
600+
if let sty::ty_rptr(ref reg, _) = ty_s.sty {
601+
if let &Region::ReLateBound(_, _) = reg {
602+
debug!(" hit an ReLateBound {}", reg);
603+
if let Some(lt) = reg.clean(cx) {
604+
late_bounds.push(lt)
605+
}
606+
}
607+
}
608+
}
609+
}
610+
}
611+
612+
TraitBound(PolyTrait {
613+
trait_: ResolvedPath { path: path, typarams: None, did: self.def_id, },
614+
lifetimes: late_bounds
592615
})
593616
}
594617
}
@@ -615,7 +638,7 @@ impl<'tcx> Clean<(Vec<TyParamBound>, Option<Type>)> for ty::ParamBounds<'tcx> {
615638
(v, None)
616639
} else {
617640
let ty = match ty::BoundSized.clean(cx) {
618-
TraitBound(ty) => ty,
641+
TraitBound(polyt) => polyt.trait_,
619642
_ => unreachable!()
620643
};
621644
(v, Some(ty))
@@ -627,7 +650,10 @@ impl<'tcx> Clean<Option<Vec<TyParamBound>>> for subst::Substs<'tcx> {
627650
fn clean(&self, cx: &DocContext) -> Option<Vec<TyParamBound>> {
628651
let mut v = Vec::new();
629652
v.extend(self.regions().iter().filter_map(|r| r.clean(cx)).map(RegionBound));
630-
v.extend(self.types.iter().map(|t| TraitBound(t.clean(cx))));
653+
v.extend(self.types.iter().map(|t| TraitBound(PolyTrait {
654+
trait_: t.clean(cx),
655+
lifetimes: vec![]
656+
})));
631657
if v.len() > 0 {Some(v)} else {None}
632658
}
633659
}
@@ -1006,9 +1032,12 @@ impl Clean<Type> for ast::TraitRef {
10061032
}
10071033
}
10081034

1009-
impl Clean<Type> for ast::PolyTraitRef {
1010-
fn clean(&self, cx: &DocContext) -> Type {
1011-
self.trait_ref.clean(cx)
1035+
impl Clean<PolyTrait> for ast::PolyTraitRef {
1036+
fn clean(&self, cx: &DocContext) -> PolyTrait {
1037+
PolyTrait {
1038+
trait_: self.trait_ref.clean(cx),
1039+
lifetimes: self.bound_lifetimes.clean(cx)
1040+
}
10121041
}
10131042
}
10141043

@@ -1129,6 +1158,13 @@ impl<'tcx> Clean<Item> for ty::ImplOrTraitItem<'tcx> {
11291158
}
11301159
}
11311160

1161+
/// A trait reference, which may have higher ranked lifetimes.
1162+
#[deriving(Clone, RustcEncodable, RustcDecodable, PartialEq)]
1163+
pub struct PolyTrait {
1164+
pub trait_: Type,
1165+
pub lifetimes: Vec<Lifetime>
1166+
}
1167+
11321168
/// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
11331169
/// type out of the AST/ty::ctxt given one of these, if more information is needed. Most importantly
11341170
/// it does not preserve mutability or boxes.

src/librustdoc/html/format.rs

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,22 @@ impl fmt::Show for clean::Lifetime {
142142
}
143143
}
144144

145+
impl fmt::Show for clean::PolyTrait {
146+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
147+
if self.lifetimes.len() > 0 {
148+
try!(f.write("for&lt;".as_bytes()));
149+
for (i, lt) in self.lifetimes.iter().enumerate() {
150+
if i > 0 {
151+
try!(f.write(", ".as_bytes()));
152+
}
153+
try!(write!(f, "{}", lt));
154+
}
155+
try!(f.write("&gt; ".as_bytes()));
156+
}
157+
write!(f, "{}", self.trait_)
158+
}
159+
}
160+
145161
impl fmt::Show for clean::TyParamBound {
146162
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
147163
match *self {
@@ -389,15 +405,6 @@ impl fmt::Show for clean::Type {
389405
try!(resolved_path(f, did, path, false));
390406
tybounds(f, typarams)
391407
}
392-
clean::PolyTraitRef(ref bounds) => {
393-
for (i, bound) in bounds.iter().enumerate() {
394-
if i != 0 {
395-
try!(write!(f, " + "));
396-
}
397-
try!(write!(f, "{}", *bound));
398-
}
399-
Ok(())
400-
}
401408
clean::Infer => write!(f, "_"),
402409
clean::Self(..) => f.write("Self".as_bytes()),
403410
clean::Primitive(prim) => primitive_link(f, prim, prim.to_string()),
@@ -505,6 +512,15 @@ impl fmt::Show for clean::Type {
505512
}
506513
}
507514
}
515+
clean::PolyTraitRef(ref bounds) => {
516+
for (i, bound) in bounds.iter().enumerate() {
517+
if i != 0 {
518+
try!(write!(f, " + "));
519+
}
520+
try!(write!(f, "{}", *bound));
521+
}
522+
Ok(())
523+
}
508524
clean::QPath { ref name, ref self_type, ref trait_ } => {
509525
write!(f, "&lt;{} as {}&gt;::{}", self_type, trait_, name)
510526
}

0 commit comments

Comments
 (0)