Skip to content

Properly render HRTBs #84814

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 7 additions & 11 deletions src/librustdoc/clean/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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,
}
Expand All @@ -414,7 +408,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
let mut bounds_vec = bounds.into_iter().collect();
self.sort_where_bounds(&mut bounds_vec);

Some(WherePredicate::BoundPredicate { ty, bounds: bounds_vec })
Some(WherePredicate::BoundPredicate {
ty,
bounds: bounds_vec,
bound_params: Vec::new(),
})
})
.chain(
lifetime_to_bounds.into_iter().filter(|&(_, ref bounds)| !bounds.is_empty()).map(
Expand Down Expand Up @@ -492,7 +490,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
}
let p = p.unwrap();
match p {
WherePredicate::BoundPredicate { ty, mut bounds } => {
WherePredicate::BoundPredicate { ty, mut bounds, .. } => {
// Writing a projection trait bound of the form
// <T as Trait>::Name : ?Sized
// is illegal, because ?Sized bounds can only
Expand Down Expand Up @@ -566,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,
} => {
Expand Down Expand Up @@ -613,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,
},
Expand Down
11 changes: 7 additions & 4 deletions src/librustdoc/clean/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,9 +566,11 @@ fn build_macro(cx: &mut DocContext<'_>, did: DefId, name: Symbol) -> clean::Item
fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean::Generics {
for pred in &mut g.where_predicates {
match *pred {
clean::WherePredicate::BoundPredicate { ty: clean::Generic(ref s), ref mut bounds }
if *s == kw::SelfUpper =>
{
clean::WherePredicate::BoundPredicate {
ty: clean::Generic(ref s),
ref mut bounds,
..
} if *s == kw::SelfUpper => {
bounds.retain(|bound| match *bound {
clean::GenericBound::TraitBound(
clean::PolyTrait { trait_: clean::ResolvedPath { did, .. }, .. },
Expand All @@ -591,6 +593,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
..
},
ref bounds,
..
} => !(bounds.is_empty() || *s == kw::SelfUpper && did == trait_did),
_ => true,
});
Expand All @@ -605,7 +608,7 @@ fn separate_supertrait_bounds(
) -> (clean::Generics, Vec<clean::GenericBound>) {
let mut ty_bounds = Vec::new();
g.where_predicates.retain(|pred| match *pred {
clean::WherePredicate::BoundPredicate { ty: clean::Generic(ref s), ref bounds }
clean::WherePredicate::BoundPredicate { ty: clean::Generic(ref s), ref bounds, .. }
if *s == kw::SelfUpper =>
{
ty_bounds.extend(bounds.iter().cloned());
Expand Down
84 changes: 35 additions & 49 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
}
}

Expand Down Expand Up @@ -330,6 +330,7 @@ impl Clean<WherePredicate> for hir::WherePredicate<'_> {
hir::WherePredicate::BoundPredicate(ref wbp) => WherePredicate::BoundPredicate {
ty: wbp.bounded_ty.clean(cx),
bounds: wbp.bounds.clean(cx),
bound_params: wbp.bound_generic_params.into_iter().map(|x| x.clean(cx)).collect(),
},

hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
Expand Down Expand Up @@ -370,6 +371,7 @@ impl<'a> Clean<WherePredicate> for ty::PolyTraitPredicate<'a> {
WherePredicate::BoundPredicate {
ty: poly_trait_ref.skip_binder().self_ty().clean(cx),
bounds: vec![poly_trait_ref.clean(cx)],
bound_params: Vec::new(),
}
}
}
Expand Down Expand Up @@ -402,6 +404,7 @@ impl<'tcx> Clean<Option<WherePredicate>> for ty::OutlivesPredicate<Ty<'tcx>, ty:
Some(WherePredicate::BoundPredicate {
ty: ty.clean(cx),
bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))],
bound_params: Vec::new(),
})
}
}
Expand Down Expand Up @@ -567,7 +570,9 @@ impl Clean<Generics> for hir::Generics<'_> {
// to where predicates when such cases occur.
for where_pred in &mut generics.where_predicates {
match *where_pred {
WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
WherePredicate::BoundPredicate {
ty: Generic(ref name), ref mut bounds, ..
} => {
if bounds.is_empty() {
for param in &mut generics.params {
match param.kind {
Expand Down Expand Up @@ -721,7 +726,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
// handled in cleaning associated types
let mut sized_params = FxHashSet::default();
where_predicates.retain(|pred| match *pred {
WP::BoundPredicate { ty: Generic(ref g), ref bounds } => {
WP::BoundPredicate { ty: Generic(ref g), ref bounds, .. } => {
if bounds.iter().any(|b| b.is_sized_bound(cx)) {
sized_params.insert(*g);
false
Expand All @@ -741,6 +746,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
where_predicates.push(WP::BoundPredicate {
ty: Type::Generic(tp.name),
bounds: vec![GenericBound::maybe_sized(cx)],
bound_params: Vec::new(),
})
}
}
Expand Down Expand Up @@ -1117,6 +1123,7 @@ impl Clean<Item> for ty::AssocItem {
WherePredicate::BoundPredicate {
ty: QPath { ref name, ref self_type, ref trait_, .. },
ref bounds,
..
} => (name, self_type, trait_, bounds),
_ => return None,
};
Expand Down Expand Up @@ -1371,24 +1378,9 @@ impl Clean<Type> for hir::Ty<'_> {
}
TyKind::Path(_) => clean_qpath(&self, cx),
TyKind::TraitObject(ref bounds, ref lifetime, _) => {
match bounds[0].clean(cx).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), 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,
Expand Down Expand Up @@ -1471,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);
Expand All @@ -1483,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
Expand All @@ -1501,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![];
Expand All @@ -1535,7 +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), 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))
Expand Down Expand Up @@ -2239,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),
},
}
Expand Down
28 changes: 19 additions & 9 deletions src/librustdoc/clean/simplify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,20 @@ use crate::core::DocContext;

crate fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
// First, partition the where clause into its separate components
let mut params: BTreeMap<_, Vec<_>> = BTreeMap::new();
let mut params: BTreeMap<_, (Vec<_>, Vec<_>)> = BTreeMap::new();
let mut lifetimes = Vec::new();
let mut equalities = Vec::new();
let mut tybounds = Vec::new();

for clause in clauses {
match clause {
WP::BoundPredicate { ty, bounds } => match ty {
clean::Generic(s) => params.entry(s).or_default().extend(bounds),
t => tybounds.push((t, bounds)),
WP::BoundPredicate { ty, bounds, bound_params } => match ty {
clean::Generic(s) => {
let (b, p) = params.entry(s).or_default();
b.extend(bounds);
p.extend(bound_params);
}
t => tybounds.push((t, (bounds, bound_params))),
},
WP::RegionPredicate { lifetime, bounds } => {
lifetimes.push((lifetime, bounds));
Expand All @@ -54,7 +58,7 @@ crate fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
clean::Generic(s) => s,
_ => return true,
};
let bounds = match params.get_mut(generic) {
let (bounds, _) = match params.get_mut(generic) {
Some(bound) => bound,
None => return true,
};
Expand All @@ -67,10 +71,16 @@ crate fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
clauses.extend(
lifetimes.into_iter().map(|(lt, bounds)| WP::RegionPredicate { lifetime: lt, bounds }),
);
clauses.extend(
params.into_iter().map(|(k, v)| WP::BoundPredicate { ty: clean::Generic(k), bounds: v }),
);
clauses.extend(tybounds.into_iter().map(|(ty, bounds)| WP::BoundPredicate { ty, bounds }));
clauses.extend(params.into_iter().map(|(k, (bounds, params))| WP::BoundPredicate {
ty: clean::Generic(k),
bounds,
bound_params: params,
}));
clauses.extend(tybounds.into_iter().map(|(ty, (bounds, bound_params))| WP::BoundPredicate {
ty,
bounds,
bound_params,
}));
clauses.extend(equalities.into_iter().map(|(lhs, rhs)| WP::EqPredicate { lhs, rhs }));
clauses
}
Expand Down
8 changes: 5 additions & 3 deletions src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -1193,7 +1193,7 @@ impl Lifetime {

#[derive(Clone, Debug)]
crate enum WherePredicate {
BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<Lifetime> },
RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
EqPredicate { lhs: Type, rhs: Type },
}
Expand Down Expand Up @@ -1407,11 +1407,12 @@ crate enum Type {
/// Structs/enums/traits (most that would be an `hir::TyKind::Path`).
ResolvedPath {
path: Path,
param_names: Option<Vec<GenericBound>>,
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),
Expand Down Expand Up @@ -1598,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),
Expand Down
Loading