From 59d13820c45ba86da1b45cfb6e41dadaeed2f07d Mon Sep 17 00:00:00 2001 From: Tom Jakubowski Date: Mon, 24 Nov 2014 10:14:46 -0800 Subject: [PATCH] rustdoc: Render Sized? on traits and generics Both `trait Foo for Sized?` and `` are handled correctly. Fix #18515 --- src/librustdoc/clean/inline.rs | 3 ++- src/librustdoc/clean/mod.rs | 37 ++++++++++++++++++++++++++-------- src/librustdoc/doctree.rs | 1 + src/librustdoc/html/format.rs | 3 +++ src/librustdoc/html/render.rs | 6 ++++++ src/librustdoc/visit_ast.rs | 3 ++- 6 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 16edccd15430..c671e8dcaf80 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -159,11 +159,12 @@ pub fn build_external_trait(cx: &DocContext, tcx: &ty::ctxt, } }); let trait_def = ty::lookup_trait_def(tcx, did); - let bounds = trait_def.bounds.clean(cx); + let (bounds, default_unbound) = trait_def.bounds.clean(cx); clean::Trait { generics: (&def.generics, subst::TypeSpace).clean(cx), items: items.collect(), bounds: bounds, + default_unbound: default_unbound } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5985516a559f..db23ec07a84e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -464,7 +464,9 @@ pub struct TyParam { pub name: String, pub did: ast::DefId, pub bounds: Vec, - pub default: Option + pub default: Option, + /// An optional default bound on the parameter which is unbound, like `Sized?` + pub default_unbound: Option } impl Clean for ast::TyParam { @@ -473,7 +475,8 @@ impl Clean for ast::TyParam { name: self.ident.clean(cx), did: ast::DefId { krate: ast::LOCAL_CRATE, node: self.id }, bounds: self.bounds.clean(cx), - default: self.default.clean(cx) + default: self.default.clean(cx), + default_unbound: self.unbound.clean(cx) } } } @@ -482,11 +485,13 @@ impl<'tcx> Clean for ty::TypeParameterDef<'tcx> { fn clean(&self, cx: &DocContext) -> TyParam { cx.external_typarams.borrow_mut().as_mut().unwrap() .insert(self.def_id, self.name.clean(cx)); + let (bounds, default_unbound) = self.bounds.clean(cx); TyParam { name: self.name.clean(cx), did: self.def_id, - bounds: self.bounds.clean(cx), - default: self.default.clean(cx) + bounds: bounds, + default: self.default.clean(cx), + default_unbound: default_unbound } } } @@ -588,12 +593,16 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { } } -impl<'tcx> Clean> for ty::ParamBounds<'tcx> { - fn clean(&self, cx: &DocContext) -> Vec { +// Returns (bounds, default_unbound) +impl<'tcx> Clean<(Vec, Option)> for ty::ParamBounds<'tcx> { + fn clean(&self, cx: &DocContext) -> (Vec, Option) { let mut v = Vec::new(); + let mut has_sized_bound = false; for b in self.builtin_bounds.iter() { if b != ty::BoundSized { v.push(b.clean(cx)); + } else { + has_sized_bound = true; } } for t in self.trait_bounds.iter() { @@ -602,7 +611,15 @@ impl<'tcx> Clean> for ty::ParamBounds<'tcx> { for r in self.region_bounds.iter().filter_map(|r| r.clean(cx)) { v.push(RegionBound(r)); } - return v; + if has_sized_bound { + (v, None) + } else { + let ty = match ty::BoundSized.clean(cx) { + TraitBound(ty) => ty, + _ => unreachable!() + }; + (v, Some(ty)) + } } } @@ -950,6 +967,8 @@ pub struct Trait { pub items: Vec, pub generics: Generics, pub bounds: Vec, + /// An optional default bound not required for `Self`, like `Sized?` + pub default_unbound: Option } impl Clean for doctree::Trait { @@ -965,6 +984,7 @@ impl Clean for doctree::Trait { items: self.items.clean(cx), generics: self.generics.clean(cx), bounds: self.bounds.clean(cx), + default_unbound: self.default_unbound.clean(cx) }), } } @@ -2258,7 +2278,8 @@ impl Clean for ty::AssociatedType { node: ast::DUMMY_NODE_ID }, bounds: vec![], - default: None + default: None, + default_unbound: None }), visibility: None, def_id: self.def_id, diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index b78ce21eb06e..adfd9aa82132 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -177,6 +177,7 @@ pub struct Trait { pub whence: Span, pub vis: ast::Visibility, pub stab: Option, + pub default_unbound: Option // FIXME(tomjakubowski) } pub struct Impl { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 43aef11ce5c2..4d1270137900 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -94,6 +94,9 @@ impl fmt::Show for clean::Generics { if i > 0 { try!(f.write(", ".as_bytes())) } + if let Some(ref unbound) = tp.default_unbound { + try!(write!(f, "{}? ", unbound)); + }; try!(f.write(tp.name.as_bytes())); if tp.bounds.len() > 0 { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 24b5904b6d3b..3fbb2a8749f9 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1670,7 +1670,13 @@ fn item_function(w: &mut fmt::Formatter, it: &clean::Item, fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, t: &clean::Trait) -> fmt::Result { let mut bounds = String::new(); + if let Some(ref ty) = t.default_unbound { + bounds.push_str(format!(" for {}?", ty).as_slice()); + } if t.bounds.len() > 0 { + if bounds.len() > 0 { + bounds.push(' '); + } bounds.push_str(": "); for (i, p) in t.bounds.iter().enumerate() { if i > 0 { bounds.push_str(" + "); } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 8f0f19fe16d0..b5b34ef6efe6 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -322,7 +322,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { }; om.constants.push(s); }, - ast::ItemTrait(ref gen, _, ref b, ref items) => { + ast::ItemTrait(ref gen, ref def_ub, ref b, ref items) => { let t = Trait { name: name, items: items.clone(), @@ -333,6 +333,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { whence: item.span, vis: item.vis, stab: self.stability(item.id), + default_unbound: def_ub.clone() }; om.traits.push(t); },