Skip to content

Commit 825939e

Browse files
committed
Compute implied_bounds for generic types, assoc types, TAITs etc.
1 parent ec818fd commit 825939e

43 files changed

Lines changed: 2476 additions & 200 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/librustdoc/clean/mod.rs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ pub(crate) fn clean_trait_ref_with_constraints<'tcx>(
264264
path
265265
}
266266

267-
fn clean_poly_trait_ref_with_constraints<'tcx>(
267+
pub(crate) fn clean_poly_trait_ref_with_constraints<'tcx>(
268268
cx: &mut DocContext<'tcx>,
269269
poly_trait_ref: ty::PolyTraitRef<'tcx>,
270270
constraints: ThinVec<AssocItemConstraint>,
@@ -458,7 +458,7 @@ fn clean_type_outlives_predicate<'tcx>(
458458
}
459459
}
460460

461-
fn clean_middle_term<'tcx>(
461+
pub(crate) fn clean_middle_term<'tcx>(
462462
term: ty::Binder<'tcx, ty::Term<'tcx>>,
463463
cx: &mut DocContext<'tcx>,
464464
) -> Term {
@@ -526,7 +526,7 @@ fn should_fully_qualify_path(self_def_id: Option<DefId>, trait_: &Path, self_typ
526526
.map_or(!self_type.is_self_type(), |(id, trait_)| id != trait_)
527527
}
528528

529-
fn projection_to_path_segment<'tcx>(
529+
pub(crate) fn projection_to_path_segment<'tcx>(
530530
proj: ty::Binder<'tcx, ty::AliasTerm<'tcx>>,
531531
cx: &mut DocContext<'tcx>,
532532
) -> PathSegment {
@@ -698,8 +698,13 @@ pub(crate) fn clean_generics<'tcx>(
698698
let param = clean_generic_param(cx, Some(gens), param);
699699
match param.kind {
700700
GenericParamDefKind::Lifetime { .. } => unreachable!(),
701-
GenericParamDefKind::Type { ref bounds, .. } => {
702-
cx.impl_trait_bounds.insert(param.def_id.into(), bounds.to_vec());
701+
GenericParamDefKind::Type { ref bounds, ref synthetic, .. } => {
702+
debug_assert!(*synthetic, "non-synthetic generic for impl trait: {param:?}");
703+
let param_def_id = param.def_id;
704+
cx.impl_trait_bounds.insert(
705+
param_def_id.into(),
706+
(bounds.to_vec(), ImplTraitOrigin::Param { def_id: param_def_id }),
707+
);
703708
}
704709
GenericParamDefKind::Const { .. } => unreachable!(),
705710
}
@@ -819,7 +824,7 @@ fn clean_ty_generics_inner<'tcx>(
819824
) -> Generics {
820825
// Don't populate `cx.impl_trait_bounds` before cleaning where clauses,
821826
// since `clean_predicate` would consume them.
822-
let mut impl_trait = BTreeMap::<u32, Vec<GenericBound>>::default();
827+
let mut impl_trait = BTreeMap::<u32, (DefId, Vec<GenericBound>)>::default();
823828

824829
let params: ThinVec<_> = gens
825830
.own_params
@@ -832,7 +837,7 @@ fn clean_ty_generics_inner<'tcx>(
832837
return false;
833838
}
834839
if synthetic {
835-
impl_trait.insert(param.index, vec![]);
840+
impl_trait.insert(param.index, (param.def_id, vec![]));
836841
return false;
837842
}
838843
true
@@ -873,7 +878,7 @@ fn clean_ty_generics_inner<'tcx>(
873878
};
874879

875880
if let Some(param_idx) = param_idx
876-
&& let Some(bounds) = impl_trait.get_mut(&param_idx)
881+
&& let Some((_, bounds)) = impl_trait.get_mut(&param_idx)
877882
{
878883
let pred = clean_predicate(*pred, cx)?;
879884

@@ -895,7 +900,7 @@ fn clean_ty_generics_inner<'tcx>(
895900
})
896901
.collect::<Vec<_>>();
897902

898-
for (idx, mut bounds) in impl_trait {
903+
for (idx, (param_def_id, mut bounds)) in impl_trait {
899904
let mut has_sized = false;
900905
bounds.retain(|b| {
901906
if b.is_sized_bound(cx) {
@@ -929,7 +934,8 @@ fn clean_ty_generics_inner<'tcx>(
929934
}
930935
}
931936

932-
cx.impl_trait_bounds.insert(idx.into(), bounds);
937+
cx.impl_trait_bounds
938+
.insert(idx.into(), (bounds, ImplTraitOrigin::Param { def_id: param_def_id }));
933939
}
934940

935941
// Now that `cx.impl_trait_bounds` is populated, we can process
@@ -1156,7 +1162,7 @@ fn clean_poly_fn_sig<'tcx>(
11561162
// function isn't async without needing to execute the query `asyncness` at
11571163
// all which gives us a noticeable performance boost.
11581164
if let Some(did) = did
1159-
&& let Type::ImplTrait(_) = output
1165+
&& let Type::ImplTrait { .. } = output
11601166
&& cx.tcx.asyncness(did).is_async()
11611167
{
11621168
output = output.sugared_async_return_type();
@@ -1649,8 +1655,8 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
16491655
if let Some(new_ty) = cx.args.get(&did).and_then(|p| p.as_ty()).cloned() {
16501656
return new_ty;
16511657
}
1652-
if let Some(bounds) = cx.impl_trait_bounds.remove(&did.into()) {
1653-
return ImplTrait(bounds);
1658+
if let Some((bounds, origin)) = cx.impl_trait_bounds.remove(&did.into()) {
1659+
return ImplTrait { bounds, origin };
16541660
}
16551661
}
16561662

@@ -1847,7 +1853,9 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
18471853
}
18481854
TyKind::Tup(tys) => Tuple(tys.iter().map(|ty| clean_ty(ty, cx)).collect()),
18491855
TyKind::OpaqueDef(ty) => {
1850-
ImplTrait(ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect())
1856+
let bounds =
1857+
ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect::<Vec<_>>();
1858+
ImplTrait { bounds, origin: ImplTraitOrigin::Opaque { def_id: ty.def_id.to_def_id() } }
18511859
}
18521860
TyKind::Path(_) => clean_qpath(ty, cx),
18531861
TyKind::TraitObject(bounds, lifetime) => {
@@ -2235,8 +2243,8 @@ pub(crate) fn clean_middle_ty<'tcx>(
22352243
}
22362244

22372245
ty::Param(ref p) => {
2238-
if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) {
2239-
ImplTrait(bounds)
2246+
if let Some((bounds, origin)) = cx.impl_trait_bounds.remove(&p.index.into()) {
2247+
ImplTrait { bounds, origin }
22402248
} else if p.name == kw::SelfUpper {
22412249
SelfTy
22422250
} else {
@@ -2372,7 +2380,7 @@ fn clean_middle_opaque_bounds<'tcx>(
23722380
));
23732381
}
23742382

2375-
ImplTrait(bounds)
2383+
ImplTrait { bounds, origin: ImplTraitOrigin::Opaque { def_id: impl_trait_def_id } }
23762384
}
23772385

23782386
pub(crate) fn clean_field<'tcx>(field: &hir::FieldDef<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
@@ -3209,7 +3217,7 @@ fn clean_assoc_item_constraint<'tcx>(
32093217
}
32103218
}
32113219

3212-
fn clean_bound_vars<'tcx>(
3220+
pub(crate) fn clean_bound_vars<'tcx>(
32133221
bound_vars: &ty::List<ty::BoundVariableKind<'tcx>>,
32143222
cx: &mut DocContext<'tcx>,
32153223
) -> Vec<GenericParamDef> {

src/librustdoc/clean/types.rs

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,6 +1320,15 @@ pub(crate) struct PolyTrait {
13201320
pub(crate) generic_params: Vec<GenericParamDef>,
13211321
}
13221322

1323+
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1324+
pub(crate) enum ImplTraitOrigin {
1325+
/// Synthetic type parameter for `impl Trait` in argument position.
1326+
Param { def_id: DefId },
1327+
1328+
/// Opaque type backing `impl Trait`, such as in RPIT or TAIT.
1329+
Opaque { def_id: DefId },
1330+
}
1331+
13231332
/// Rustdoc's representation of types, mostly based on the [`hir::Ty`].
13241333
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
13251334
pub(crate) enum Type {
@@ -1366,7 +1375,25 @@ pub(crate) enum Type {
13661375
Infer,
13671376

13681377
/// An `impl Trait`: `impl TraitA + TraitB + ...`
1369-
ImplTrait(Vec<GenericBound>),
1378+
ImplTrait {
1379+
/// The bounds that are syntactically present:
1380+
/// ```rust
1381+
/// # trait TraitA {}
1382+
/// # trait TraitB {}
1383+
/// # struct Both;
1384+
/// # impl TraitA for Both {}
1385+
/// # impl TraitB for Both {}
1386+
/// fn example() -> impl TraitA + TraitB {
1387+
/// // ^^^^^^ ^^^^^^
1388+
/// // ...
1389+
/// # Both
1390+
/// }
1391+
/// ```
1392+
bounds: Vec<GenericBound>,
1393+
/// Whether this `impl Trait` is syntactic sugar for an anonymous generic parameter,
1394+
/// or represents an opaque type.
1395+
origin: ImplTraitOrigin,
1396+
},
13701397

13711398
UnsafeBinder(Box<UnsafeBinderTy>),
13721399
}
@@ -1494,8 +1521,8 @@ impl Type {
14941521
/// This function will panic if the return type does not match the expected sugaring for async
14951522
/// functions.
14961523
pub(crate) fn sugared_async_return_type(self) -> Type {
1497-
if let Type::ImplTrait(mut v) = self
1498-
&& let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = v.pop()
1524+
if let Type::ImplTrait { mut bounds, .. } = self
1525+
&& let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _)) = bounds.pop()
14991526
&& let Some(segment) = trait_.segments.pop()
15001527
&& let GenericArgs::AngleBracketed { mut constraints, .. } = segment.args
15011528
&& let Some(constraint) = constraints.pop()
@@ -1566,7 +1593,7 @@ impl Type {
15661593
Type::FieldOf(..) => PrimitiveType::FieldOf,
15671594
RawPointer(..) => PrimitiveType::RawPointer,
15681595
QPath(box QPathData { self_type, .. }) => return self_type.def_id(cache),
1569-
Generic(_) | SelfTy | Infer | ImplTrait(_) | UnsafeBinder(_) => return None,
1596+
Generic(_) | SelfTy | Infer | ImplTrait { .. } | UnsafeBinder(_) => return None,
15701597
};
15711598
Primitive(t).def_id(cache)
15721599
}
@@ -2424,14 +2451,14 @@ mod size_asserts {
24242451
// tidy-alphabetical-start
24252452
static_assert_size!(Crate, 16); // frequently moved by-value
24262453
static_assert_size!(DocFragment, 48);
2427-
static_assert_size!(GenericArg, 32);
2454+
static_assert_size!(GenericArg, 40);
24282455
static_assert_size!(GenericArgs, 24);
24292456
static_assert_size!(GenericParamDef, 40);
24302457
static_assert_size!(Generics, 16);
24312458
static_assert_size!(Item, 8);
24322459
static_assert_size!(ItemInner, 144);
24332460
static_assert_size!(ItemKind, 48);
24342461
static_assert_size!(PathSegment, 32);
2435-
static_assert_size!(Type, 32);
2462+
static_assert_size!(Type, 40);
24362463
// tidy-alphabetical-end
24372464
}

src/librustdoc/core.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,10 @@ pub(crate) struct DocContext<'tcx> {
5454
// therefore wouldn't use the corresp. generic arg anyway. Add support for them.
5555
pub(crate) args: DefIdMap<clean::GenericArg>,
5656
pub(crate) current_type_aliases: DefIdMap<usize>,
57-
/// Table synthetic type parameter for `impl Trait` in argument position -> bounds
58-
pub(crate) impl_trait_bounds: FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>,
57+
/// Table of synthetic type parameter
58+
/// for `impl Trait` in argument position -> (bounds, trait origin)
59+
pub(crate) impl_trait_bounds:
60+
FxHashMap<ImplTraitParam, (Vec<clean::GenericBound>, clean::ImplTraitOrigin)>,
5961
/// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
6062
// FIXME(eddyb) make this a `ty::TraitRef<'tcx>` set.
6163
pub(crate) generated_synthetics: FxHashSet<(Ty<'tcx>, DefId)>,

src/librustdoc/html/format.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,15 +1029,15 @@ fn fmt_type(
10291029
{
10301030
true
10311031
}
1032-
clean::ImplTrait(ref bounds) if bounds.len() > 1 => true,
1032+
clean::ImplTrait { ref bounds, .. } if bounds.len() > 1 => true,
10331033
_ => false,
10341034
};
10351035
Wrapped::with_parens()
10361036
.when(needs_parens)
10371037
.wrap_fn(|f| fmt_type(ty, f, use_absolute, cx))
10381038
.fmt(f)
10391039
}
1040-
clean::ImplTrait(bounds) => {
1040+
clean::ImplTrait { bounds, .. } => {
10411041
f.write_str("impl ")?;
10421042
print_generic_bounds(bounds, cx).fmt(f)
10431043
}

src/librustdoc/html/render/search_index.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2052,7 +2052,7 @@ fn get_index_type_id(
20522052
| clean::Type::FieldOf(..)
20532053
| clean::Generic(_)
20542054
| clean::SelfTy
2055-
| clean::ImplTrait(_)
2055+
| clean::ImplTrait { .. }
20562056
| clean::Infer
20572057
| clean::UnsafeBinder(_) => None,
20582058
}
@@ -2150,7 +2150,7 @@ fn simplify_fn_type<'a, 'tcx>(
21502150
RenderType { id: Some(RenderTypeId::Index(idx)), generics: None, bindings: None }
21512151
})
21522152
}
2153-
Type::ImplTrait(ref bounds) => {
2153+
Type::ImplTrait { ref bounds, .. } => {
21542154
let type_bounds = bounds
21552155
.iter()
21562156
.filter_map(|bound| bound.get_trait_path())

0 commit comments

Comments
 (0)