diff options
| -rw-r--r-- | src/librustdoc/clean/auto_trait.rs | 10 | ||||
| -rw-r--r-- | src/librustdoc/clean/mod.rs | 84 | ||||
| -rw-r--r-- | src/librustdoc/clean/types.rs | 8 | ||||
| -rw-r--r-- | src/librustdoc/clean/utils.rs | 18 | ||||
| -rw-r--r-- | src/librustdoc/formats/cache.rs | 15 | ||||
| -rw-r--r-- | src/librustdoc/html/format.rs | 60 | ||||
| -rw-r--r-- | src/librustdoc/html/render/cache.rs | 1 | ||||
| -rw-r--r-- | src/librustdoc/json/conversions.rs | 29 | ||||
| -rw-r--r-- | src/test/rustdoc/higher-ranked-trait-bounds.rs | 8 |
9 files changed, 117 insertions, 116 deletions
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 0828f0b3e51..ebab3add6c5 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -353,12 +353,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { let (poly_trait, output) = (data.0.as_ref().expect("as_ref failed").clone(), data.1.as_ref().cloned()); let new_ty = match poly_trait.trait_ { - Type::ResolvedPath { - ref path, - ref param_names, - ref did, - ref is_generic, - } => { + Type::ResolvedPath { ref path, ref did, ref is_generic } => { let mut new_path = path.clone(); let last_segment = new_path.segments.pop().expect("segments were empty"); @@ -395,7 +390,6 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { Type::ResolvedPath { path: new_path, - param_names: param_names.clone(), did: *did, is_generic: *is_generic, } @@ -570,7 +564,6 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { match **trait_ { Type::ResolvedPath { path: ref trait_path, - ref param_names, ref did, ref is_generic, } => { @@ -617,7 +610,6 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { PolyTrait { trait_: Type::ResolvedPath { path: new_trait_path, - param_names: param_names.clone(), did: *did, is_generic: *is_generic, }, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 889e645309c..fea09b383c0 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -180,7 +180,7 @@ impl Clean<Type> for (ty::TraitRef<'_>, &[TypeBinding]) { debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs); - ResolvedPath { path, param_names: None, did: trait_ref.def_id, is_generic: false } + ResolvedPath { path, did: trait_ref.def_id, is_generic: false } } } @@ -1378,30 +1378,9 @@ impl Clean<Type> for hir::Ty<'_> { } TyKind::Path(_) => clean_qpath(&self, cx), TyKind::TraitObject(ref bounds, ref lifetime, _) => { - let cleaned = bounds[0].clean(cx); - match cleaned.trait_ { - ResolvedPath { path, param_names: None, did, is_generic, .. } => { - let mut bounds: Vec<self::GenericBound> = bounds[1..] - .iter() - .map(|bound| { - self::GenericBound::TraitBound( - bound.clean(cx), - hir::TraitBoundModifier::None, - ) - }) - .collect(); - if !lifetime.is_elided() { - bounds.push(self::GenericBound::Outlives(lifetime.clean(cx))); - } - ResolvedPath { - path, - param_names: Some((bounds, cleaned.generic_params)), - did, - is_generic, - } - } - _ => Infer, // shouldn't happen - } + let bounds = bounds.iter().map(|bound| bound.clean(cx)).collect(); + let lifetime = if !lifetime.is_elided() { Some(lifetime.clean(cx)) } else { None }; + DynTrait(bounds, lifetime) } TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)), TyKind::Infer | TyKind::Err => Infer, @@ -1484,7 +1463,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> { }; inline::record_extern_fqn(cx, did, kind); let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], substs); - ResolvedPath { path, param_names: None, did, is_generic: false } + ResolvedPath { path, did, is_generic: false } } ty::Foreign(did) => { inline::record_extern_fqn(cx, did, ItemType::ForeignType); @@ -1496,7 +1475,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> { vec![], InternalSubsts::empty(), ); - ResolvedPath { path, param_names: None, did, is_generic: false } + ResolvedPath { path, did, is_generic: false } } ty::Dynamic(ref obj, ref reg) => { // HACK: pick the first `did` as the `did` of the trait object. Someone @@ -1514,28 +1493,19 @@ impl<'tcx> Clean<Type> for Ty<'tcx> { inline::record_extern_fqn(cx, did, ItemType::Trait); - let mut param_names = vec![]; - if let Some(b) = reg.clean(cx) { - param_names.push(GenericBound::Outlives(b)); - } + let lifetime = reg.clean(cx); + let mut bounds = vec![]; + for did in dids { let empty = cx.tcx.intern_substs(&[]); let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty); inline::record_extern_fqn(cx, did, ItemType::Trait); - let bound = GenericBound::TraitBound( - PolyTrait { - trait_: ResolvedPath { - path, - param_names: None, - did, - is_generic: false, - }, - generic_params: Vec::new(), - }, - hir::TraitBoundModifier::None, - ); - param_names.push(bound); + let bound = PolyTrait { + trait_: ResolvedPath { path, did, is_generic: false }, + generic_params: Vec::new(), + }; + bounds.push(bound); } let mut bindings = vec![]; @@ -1548,12 +1518,15 @@ impl<'tcx> Clean<Type> for Ty<'tcx> { let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, bindings, substs); - ResolvedPath { - path, - param_names: Some((param_names, vec![])), - did, - is_generic: false, - } + bounds.insert( + 0, + PolyTrait { + trait_: ResolvedPath { path, did, is_generic: false }, + generic_params: Vec::new(), + }, + ); + + DynTrait(bounds, lifetime) } ty::Tuple(ref t) => { Tuple(t.iter().map(|t| t.expect_ty()).collect::<Vec<_>>().clean(cx)) @@ -2257,14 +2230,9 @@ impl From<GenericBound> for SimpleBound { match bound.clone() { GenericBound::Outlives(l) => SimpleBound::Outlives(l), GenericBound::TraitBound(t, mod_) => match t.trait_ { - Type::ResolvedPath { path, param_names, .. } => SimpleBound::TraitBound( - path.segments, - param_names.map_or_else(Vec::new, |(v, _)| { - v.iter().map(|p| SimpleBound::from(p.clone())).collect() - }), - t.generic_params, - mod_, - ), + Type::ResolvedPath { path, .. } => { + SimpleBound::TraitBound(path.segments, Vec::new(), t.generic_params, mod_) + } _ => panic!("Unexpected bound {:?}", bound), }, } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 4c94501b80b..b78cabddef6 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1141,7 +1141,7 @@ impl GenericBound { inline::record_extern_fqn(cx, did, ItemType::Trait); GenericBound::TraitBound( PolyTrait { - trait_: ResolvedPath { path, param_names: None, did, is_generic: false }, + trait_: ResolvedPath { path, did, is_generic: false }, generic_params: Vec::new(), }, hir::TraitBoundModifier::Maybe, @@ -1407,13 +1407,12 @@ crate enum Type { /// Structs/enums/traits (most that would be an `hir::TyKind::Path`). ResolvedPath { path: Path, - /// If `param_names` is `Some`, this path is a trait object and the Vecs repsresent - /// `(generic bounds, generic parameters)` - param_names: Option<(Vec<GenericBound>, Vec<GenericParamDef>)>, did: DefId, /// `true` if is a `T::Name` path for associated types. is_generic: bool, }, + /// `dyn for<'a> Trait<'a> + Send + 'static` + DynTrait(Vec<PolyTrait>, Option<Lifetime>), /// For parameterized types, so the consumer of the JSON don't go /// looking for types which don't exist anywhere. Generic(Symbol), @@ -1600,6 +1599,7 @@ impl Type { fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> { let t: PrimitiveType = match *self { ResolvedPath { did, .. } => return Some(did.into()), + DynTrait(ref bounds, _) => return bounds[0].trait_.inner_def_id(cache), Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()), BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference, BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache), diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 706a56fbcbf..3d056979780 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -2,7 +2,7 @@ use crate::clean::auto_trait::AutoTraitFinder; use crate::clean::blanket_impl::BlanketImplFinder; use crate::clean::{ inline, Clean, Crate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime, - Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding, + Path, PathSegment, PolyTrait, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding, }; use crate::core::DocContext; use crate::formats::item_type::ItemType; @@ -163,8 +163,18 @@ pub(super) fn external_path( crate fn strip_type(ty: Type) -> Type { match ty { - Type::ResolvedPath { path, param_names, did, is_generic } => { - Type::ResolvedPath { path: strip_path(&path), param_names, did, is_generic } + Type::ResolvedPath { path, did, is_generic } => { + Type::ResolvedPath { path: strip_path(&path), did, is_generic } + } + Type::DynTrait(mut bounds, lt) => { + let first = bounds.remove(0); + let stripped_trait = strip_type(first.trait_); + + bounds.insert( + 0, + PolyTrait { trait_: stripped_trait, generic_params: first.generic_params }, + ); + Type::DynTrait(bounds, lt) } Type::Tuple(inner_tys) => { Type::Tuple(inner_tys.iter().map(|t| strip_type(t.clone())).collect()) @@ -431,7 +441,7 @@ crate fn resolve_type(cx: &mut DocContext<'_>, path: Path, id: hir::HirId) -> Ty _ => false, }; let did = register_res(cx, path.res); - ResolvedPath { path, param_names: None, did, is_generic } + ResolvedPath { path, did, is_generic } } crate fn get_auto_trait_and_blanket_impls( diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 5734a4a98e2..fb6ecca4c89 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -402,6 +402,15 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { self.cache.parent_stack.push(did); true } + clean::DynTrait(ref bounds, _) + | clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => { + if let Some(did) = bounds[0].trait_.def_id() { + self.cache.parent_stack.push(did); + true + } else { + false + } + } ref t => { let prim_did = t .primitive_type() @@ -432,6 +441,12 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> { | clean::BorrowedRef { type_: box clean::ResolvedPath { did, .. }, .. } => { dids.insert(did); } + clean::DynTrait(ref bounds, _) + | clean::BorrowedRef { type_: box clean::DynTrait(ref bounds, _), .. } => { + if let Some(did) = bounds[0].trait_.def_id() { + dids.insert(did); + } + } ref t => { let did = t .primitive_type() diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index e4fb7384aff..404af8f1aed 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -646,18 +646,24 @@ fn primitive_link( /// Helper to render type parameters fn tybounds<'a, 'tcx: 'a>( - param_names: Option<&'a Vec<clean::GenericBound>>, + bounds: &'a Vec<clean::PolyTrait>, + lt: &'a Option<clean::Lifetime>, cx: &'a Context<'tcx>, ) -> impl fmt::Display + 'a + Captures<'tcx> { - display_fn(move |f| match param_names { - Some(params) => { - for param in params { + display_fn(move |f| { + for (i, bound) in bounds.iter().enumerate() { + if i > 0 { write!(f, " + ")?; - fmt::Display::fmt(¶m.print(cx), f)?; } - Ok(()) + + fmt::Display::fmt(&bound.print(cx), f)?; } - None => Ok(()), + + if let Some(lt) = lt { + write!(f, " + ")?; + fmt::Display::fmt(<.print(), f)?; + } + Ok(()) }) } @@ -694,32 +700,13 @@ fn fmt_type<'cx>( match *t { clean::Generic(name) => write!(f, "{}", name), - clean::ResolvedPath { did, ref param_names, ref path, is_generic } => { - let generic_params = param_names.as_ref().map(|(_, x)| x); - let param_names = param_names.as_ref().map(|(x, _)| x); - - if let Some(generic_params) = generic_params { - f.write_str("dyn ")?; - - if !generic_params.is_empty() { - if f.alternate() { - write!( - f, - "for<{:#}> ", - comma_sep(generic_params.iter().map(|g| g.print(cx))) - )?; - } else { - write!( - f, - "for<{}> ", - comma_sep(generic_params.iter().map(|g| g.print(cx))) - )?; - } - } - } + clean::ResolvedPath { did, ref path, is_generic } => { // Paths like `T::Output` and `Self::Output` should be rendered with all segments. - resolved_path(f, did, path, is_generic, use_absolute, cx)?; - fmt::Display::fmt(&tybounds(param_names, cx), f) + resolved_path(f, did, path, is_generic, use_absolute, cx) + } + clean::DynTrait(ref bounds, ref lt) => { + f.write_str("dyn ")?; + fmt::Display::fmt(&tybounds(bounds, lt, cx), f) } clean::Infer => write!(f, "_"), clean::Primitive(prim) => primitive_link(f, prim, &*prim.as_sym().as_str(), cx), @@ -854,7 +841,9 @@ fn fmt_type<'cx>( } } } - clean::ResolvedPath { param_names: Some((ref v, _)), .. } if !v.is_empty() => { + clean::DynTrait(ref bounds, ref trait_lt) + if bounds.len() > 1 || trait_lt.is_some() => + { write!(f, "{}{}{}(", amp, lt, m)?; fmt_type(&ty, f, use_absolute, cx)?; write!(f, ")") @@ -915,7 +904,7 @@ fn fmt_type<'cx>( // the ugliness comes from inlining across crates where // everything comes in as a fully resolved QPath (hard to // look at). - box clean::ResolvedPath { did, ref param_names, .. } => { + box clean::ResolvedPath { did, .. } => { match href(did.into(), cx) { Some((ref url, _, ref path)) if !f.alternate() => { write!( @@ -930,9 +919,6 @@ fn fmt_type<'cx>( } _ => write!(f, "{}", name)?, } - - // FIXME: `param_names` are not rendered, and this seems bad? - drop(param_names); Ok(()) } _ => write!(f, "{}", name), diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 3e056c4b67a..78b2f1e2513 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -233,6 +233,7 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option }); Some(path_segment.name) } + clean::DynTrait(ref bounds, _) => get_index_type_name(&bounds[0].trait_, accept_generic), clean::Generic(s) if accept_generic => Some(s), clean::Primitive(ref p) => Some(p.as_sym()), clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_, accept_generic), diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 643c0f82ae9..b89a266a695 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -373,14 +373,35 @@ impl FromWithTcx<clean::Type> for Type { fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self { use clean::Type::*; match ty { - ResolvedPath { path, param_names, did, is_generic: _ } => Type::ResolvedPath { + ResolvedPath { path, did, is_generic: _ } => Type::ResolvedPath { name: path.whole_name(), id: from_def_id(did.into()), args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))), - param_names: param_names - .map(|(v, _)| v.into_iter().map(|x| x.into_tcx(tcx)).collect()) - .unwrap_or_default(), + param_names: Vec::new(), }, + DynTrait(mut bounds, lt) => { + let (path, id) = match bounds.remove(0).trait_ { + ResolvedPath { path, did, .. } => (path, did), + _ => unreachable!(), + }; + + Type::ResolvedPath { + name: path.whole_name(), + id: from_def_id(id.into()), + args: path + .segments + .last() + .map(|args| Box::new(args.clone().args.into_tcx(tcx))), + param_names: bounds + .into_iter() + .map(|t| { + clean::GenericBound::TraitBound(t, rustc_hir::TraitBoundModifier::None) + }) + .chain(lt.into_iter().map(|lt| clean::GenericBound::Outlives(lt))) + .map(|bound| bound.into_tcx(tcx)) + .collect(), + } + } Generic(s) => Type::Generic(s.to_string()), Primitive(p) => Type::Primitive(p.as_sym().to_string()), BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))), diff --git a/src/test/rustdoc/higher-ranked-trait-bounds.rs b/src/test/rustdoc/higher-ranked-trait-bounds.rs index 492a743fbf2..41940b0884e 100644 --- a/src/test/rustdoc/higher-ranked-trait-bounds.rs +++ b/src/test/rustdoc/higher-ranked-trait-bounds.rs @@ -51,3 +51,11 @@ pub trait B<'x> {} // @has - '//code[@class="in-band"]' "impl<'a> B<'a> for dyn for<'b> Trait<'b>" impl<'a> B<'a> for dyn for<'b> Trait<'b> {} + +// @has foo/struct.Bar.html +// @has - '//span[@id="structfield.bar"]' "bar: &'a (dyn for<'b> Trait<'b> + Unpin)" +// @has - '//span[@id="structfield.baz"]' "baz: &'a (dyn Unpin + for<'b> Trait<'b>)" +pub struct Bar<'a> { + pub bar: &'a (dyn for<'b> Trait<'b> + Unpin), + pub baz: &'a (dyn Unpin + for<'b> Trait<'b>), +} |
