Skip to content

Commit db81709

Browse files
authored
Unrolled build for #142092
Rollup merge of #142092 - fmease:rustdoc-alias-terms, r=GuillaumeGomez rustdoc: Support middle::ty associated const equality predicates again Fix intentional regression from PR #125076. Fixes #125092. Fixes #134775. CC #141368 (`EqPredicates` and rustdoc).
2 parents d00435f + 95bf127 commit db81709

File tree

6 files changed

+106
-132
lines changed

6 files changed

+106
-132
lines changed

src/librustdoc/clean/mod.rs

Lines changed: 61 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -371,10 +371,9 @@ fn clean_where_predicate<'tcx>(
371371
bounds: wrp.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
372372
},
373373

374-
hir::WherePredicateKind::EqPredicate(wrp) => WherePredicate::EqPredicate {
375-
lhs: clean_ty(wrp.lhs_ty, cx),
376-
rhs: clean_ty(wrp.rhs_ty, cx).into(),
377-
},
374+
// We should never actually reach this case because these predicates should've already been
375+
// rejected in an earlier compiler pass. This feature isn't fully implemented (#20041).
376+
hir::WherePredicateKind::EqPredicate(_) => bug!("EqPredicate"),
378377
})
379378
}
380379

@@ -470,68 +469,55 @@ fn clean_projection_predicate<'tcx>(
470469
cx: &mut DocContext<'tcx>,
471470
) -> WherePredicate {
472471
WherePredicate::EqPredicate {
473-
lhs: clean_projection(
474-
pred.map_bound(|p| {
475-
// FIXME: This needs to be made resilient for `AliasTerm`s that
476-
// are associated consts.
477-
p.projection_term.expect_ty(cx.tcx)
478-
}),
479-
cx,
480-
None,
481-
),
472+
lhs: clean_projection(pred.map_bound(|p| p.projection_term), cx, None),
482473
rhs: clean_middle_term(pred.map_bound(|p| p.term), cx),
483474
}
484475
}
485476

486477
fn clean_projection<'tcx>(
487-
ty: ty::Binder<'tcx, ty::AliasTy<'tcx>>,
478+
proj: ty::Binder<'tcx, ty::AliasTerm<'tcx>>,
488479
cx: &mut DocContext<'tcx>,
489-
def_id: Option<DefId>,
490-
) -> Type {
491-
if cx.tcx.is_impl_trait_in_trait(ty.skip_binder().def_id) {
492-
return clean_middle_opaque_bounds(cx, ty.skip_binder().def_id, ty.skip_binder().args);
493-
}
494-
480+
parent_def_id: Option<DefId>,
481+
) -> QPathData {
495482
let trait_ = clean_trait_ref_with_constraints(
496483
cx,
497-
ty.map_bound(|ty| ty.trait_ref(cx.tcx)),
484+
proj.map_bound(|proj| proj.trait_ref(cx.tcx)),
498485
ThinVec::new(),
499486
);
500-
let self_type = clean_middle_ty(ty.map_bound(|ty| ty.self_ty()), cx, None, None);
501-
let self_def_id = if let Some(def_id) = def_id {
502-
cx.tcx.opt_parent(def_id).or(Some(def_id))
503-
} else {
504-
self_type.def_id(&cx.cache)
487+
let self_type = clean_middle_ty(proj.map_bound(|proj| proj.self_ty()), cx, None, None);
488+
let self_def_id = match parent_def_id {
489+
Some(parent_def_id) => cx.tcx.opt_parent(parent_def_id).or(Some(parent_def_id)),
490+
None => self_type.def_id(&cx.cache),
505491
};
506-
let should_show_cast = compute_should_show_cast(self_def_id, &trait_, &self_type);
507-
Type::QPath(Box::new(QPathData {
508-
assoc: projection_to_path_segment(ty, cx),
509-
should_show_cast,
492+
let should_fully_qualify = should_fully_qualify_path(self_def_id, &trait_, &self_type);
493+
494+
QPathData {
495+
assoc: projection_to_path_segment(proj, cx),
510496
self_type,
497+
should_fully_qualify,
511498
trait_: Some(trait_),
512-
}))
499+
}
513500
}
514501

515-
fn compute_should_show_cast(self_def_id: Option<DefId>, trait_: &Path, self_type: &Type) -> bool {
502+
fn should_fully_qualify_path(self_def_id: Option<DefId>, trait_: &Path, self_type: &Type) -> bool {
516503
!trait_.segments.is_empty()
517504
&& self_def_id
518505
.zip(Some(trait_.def_id()))
519506
.map_or(!self_type.is_self_type(), |(id, trait_)| id != trait_)
520507
}
521508

522509
fn projection_to_path_segment<'tcx>(
523-
ty: ty::Binder<'tcx, ty::AliasTy<'tcx>>,
510+
proj: ty::Binder<'tcx, ty::AliasTerm<'tcx>>,
524511
cx: &mut DocContext<'tcx>,
525512
) -> PathSegment {
526-
let def_id = ty.skip_binder().def_id;
527-
let item = cx.tcx.associated_item(def_id);
513+
let def_id = proj.skip_binder().def_id;
528514
let generics = cx.tcx.generics_of(def_id);
529515
PathSegment {
530-
name: item.name(),
516+
name: cx.tcx.item_name(def_id),
531517
args: GenericArgs::AngleBracketed {
532518
args: clean_middle_generic_args(
533519
cx,
534-
ty.map_bound(|ty| &ty.args[generics.parent_count..]),
520+
proj.map_bound(|ty| &ty.args[generics.parent_count..]),
535521
false,
536522
def_id,
537523
),
@@ -845,7 +831,7 @@ fn clean_ty_generics<'tcx>(
845831
.predicates
846832
.iter()
847833
.flat_map(|(pred, _)| {
848-
let mut projection = None;
834+
let mut proj_pred = None;
849835
let param_idx = {
850836
let bound_p = pred.kind();
851837
match bound_p.skip_binder() {
@@ -860,7 +846,7 @@ fn clean_ty_generics<'tcx>(
860846
ty::ClauseKind::Projection(p)
861847
if let ty::Param(param) = p.projection_term.self_ty().kind() =>
862848
{
863-
projection = Some(bound_p.rebind(p));
849+
proj_pred = Some(bound_p.rebind(p));
864850
Some(param.index)
865851
}
866852
_ => None,
@@ -874,22 +860,12 @@ fn clean_ty_generics<'tcx>(
874860

875861
bounds.extend(pred.get_bounds().into_iter().flatten().cloned());
876862

877-
if let Some(proj) = projection
878-
&& let lhs = clean_projection(
879-
proj.map_bound(|p| {
880-
// FIXME: This needs to be made resilient for `AliasTerm`s that
881-
// are associated consts.
882-
p.projection_term.expect_ty(cx.tcx)
883-
}),
884-
cx,
885-
None,
886-
)
887-
&& let Some((_, trait_did, name)) = lhs.projection()
888-
{
863+
if let Some(pred) = proj_pred {
864+
let lhs = clean_projection(pred.map_bound(|p| p.projection_term), cx, None);
889865
impl_trait_proj.entry(param_idx).or_default().push((
890-
trait_did,
891-
name,
892-
proj.map_bound(|p| p.term),
866+
lhs.trait_.unwrap().def_id(),
867+
lhs.assoc,
868+
pred.map_bound(|p| p.term),
893869
));
894870
}
895871

@@ -1695,10 +1671,11 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
16951671
register_res(cx, trait_.res);
16961672
let self_def_id = DefId::local(qself.hir_id.owner.def_id.local_def_index);
16971673
let self_type = clean_ty(qself, cx);
1698-
let should_show_cast = compute_should_show_cast(Some(self_def_id), &trait_, &self_type);
1674+
let should_fully_qualify =
1675+
should_fully_qualify_path(Some(self_def_id), &trait_, &self_type);
16991676
Type::QPath(Box::new(QPathData {
17001677
assoc: clean_path_segment(p.segments.last().expect("segments were empty"), cx),
1701-
should_show_cast,
1678+
should_fully_qualify,
17021679
self_type,
17031680
trait_: Some(trait_),
17041681
}))
@@ -1707,16 +1684,16 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
17071684
let ty = lower_ty(cx.tcx, hir_ty);
17081685
let self_type = clean_ty(qself, cx);
17091686

1710-
let (trait_, should_show_cast) = match ty.kind() {
1687+
let (trait_, should_fully_qualify) = match ty.kind() {
17111688
ty::Alias(ty::Projection, proj) => {
17121689
let res = Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id);
17131690
let trait_ = clean_path(&hir::Path { span, res, segments: &[] }, cx);
17141691
register_res(cx, trait_.res);
17151692
let self_def_id = res.opt_def_id();
1716-
let should_show_cast =
1717-
compute_should_show_cast(self_def_id, &trait_, &self_type);
1693+
let should_fully_qualify =
1694+
should_fully_qualify_path(self_def_id, &trait_, &self_type);
17181695

1719-
(Some(trait_), should_show_cast)
1696+
(Some(trait_), should_fully_qualify)
17201697
}
17211698
ty::Alias(ty::Inherent, _) => (None, false),
17221699
// Rustdoc handles `ty::Error`s by turning them into `Type::Infer`s.
@@ -1726,7 +1703,7 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
17261703

17271704
Type::QPath(Box::new(QPathData {
17281705
assoc: clean_path_segment(segment, cx),
1729-
should_show_cast,
1706+
should_fully_qualify,
17301707
self_type,
17311708
trait_,
17321709
}))
@@ -2145,14 +2122,8 @@ pub(crate) fn clean_middle_ty<'tcx>(
21452122
.map(|pb| AssocItemConstraint {
21462123
assoc: projection_to_path_segment(
21472124
pb.map_bound(|pb| {
2148-
pb
2149-
// HACK(compiler-errors): Doesn't actually matter what self
2150-
// type we put here, because we're only using the GAT's args.
2151-
.with_self_ty(cx.tcx, cx.tcx.types.self_param)
2125+
pb.with_self_ty(cx.tcx, cx.tcx.types.trait_object_dummy_self)
21522126
.projection_term
2153-
// FIXME: This needs to be made resilient for `AliasTerm`s
2154-
// that are associated consts.
2155-
.expect_ty(cx.tcx)
21562127
}),
21572128
cx,
21582129
),
@@ -2185,18 +2156,25 @@ pub(crate) fn clean_middle_ty<'tcx>(
21852156
Tuple(t.iter().map(|t| clean_middle_ty(bound_ty.rebind(t), cx, None, None)).collect())
21862157
}
21872158

2188-
ty::Alias(ty::Projection, data) => {
2189-
clean_projection(bound_ty.rebind(data), cx, parent_def_id)
2159+
ty::Alias(ty::Projection, alias_ty @ ty::AliasTy { def_id, args, .. }) => {
2160+
if cx.tcx.is_impl_trait_in_trait(def_id) {
2161+
clean_middle_opaque_bounds(cx, def_id, args)
2162+
} else {
2163+
Type::QPath(Box::new(clean_projection(
2164+
bound_ty.rebind(alias_ty.into()),
2165+
cx,
2166+
parent_def_id,
2167+
)))
2168+
}
21902169
}
21912170

2192-
ty::Alias(ty::Inherent, alias_ty) => {
2193-
let def_id = alias_ty.def_id;
2171+
ty::Alias(ty::Inherent, alias_ty @ ty::AliasTy { def_id, .. }) => {
21942172
let alias_ty = bound_ty.rebind(alias_ty);
21952173
let self_type = clean_middle_ty(alias_ty.map_bound(|ty| ty.self_ty()), cx, None, None);
21962174

21972175
Type::QPath(Box::new(QPathData {
21982176
assoc: PathSegment {
2199-
name: cx.tcx.associated_item(def_id).name(),
2177+
name: cx.tcx.item_name(def_id),
22002178
args: GenericArgs::AngleBracketed {
22012179
args: clean_middle_generic_args(
22022180
cx,
@@ -2207,26 +2185,21 @@ pub(crate) fn clean_middle_ty<'tcx>(
22072185
constraints: Default::default(),
22082186
},
22092187
},
2210-
should_show_cast: false,
2188+
should_fully_qualify: false,
22112189
self_type,
22122190
trait_: None,
22132191
}))
22142192
}
22152193

2216-
ty::Alias(ty::Free, data) => {
2194+
ty::Alias(ty::Free, ty::AliasTy { def_id, args, .. }) => {
22172195
if cx.tcx.features().lazy_type_alias() {
22182196
// Free type alias `data` represents the `type X` in `type X = Y`. If we need `Y`,
22192197
// we need to use `type_of`.
2220-
let path = clean_middle_path(
2221-
cx,
2222-
data.def_id,
2223-
false,
2224-
ThinVec::new(),
2225-
bound_ty.rebind(data.args),
2226-
);
2198+
let path =
2199+
clean_middle_path(cx, def_id, false, ThinVec::new(), bound_ty.rebind(args));
22272200
Type::Path { path }
22282201
} else {
2229-
let ty = cx.tcx.type_of(data.def_id).instantiate(cx.tcx, data.args);
2202+
let ty = cx.tcx.type_of(def_id).instantiate(cx.tcx, args);
22302203
clean_middle_ty(bound_ty.rebind(ty), cx, None, None)
22312204
}
22322205
}
@@ -2313,18 +2286,17 @@ fn clean_middle_opaque_bounds<'tcx>(
23132286
let bindings: ThinVec<_> = bounds
23142287
.iter()
23152288
.filter_map(|(bound, _)| {
2316-
if let ty::ClauseKind::Projection(proj) = bound.kind().skip_binder()
2317-
&& proj.projection_term.trait_ref(cx.tcx) == trait_ref.skip_binder()
2289+
let bound = bound.kind();
2290+
if let ty::ClauseKind::Projection(proj_pred) = bound.skip_binder()
2291+
&& proj_pred.projection_term.trait_ref(cx.tcx) == trait_ref.skip_binder()
23182292
{
23192293
return Some(AssocItemConstraint {
23202294
assoc: projection_to_path_segment(
2321-
// FIXME: This needs to be made resilient for `AliasTerm`s that
2322-
// are associated consts.
2323-
bound.kind().rebind(proj.projection_term.expect_ty(cx.tcx)),
2295+
bound.rebind(proj_pred.projection_term),
23242296
cx,
23252297
),
23262298
kind: AssocItemConstraintKind::Equality {
2327-
term: clean_middle_term(bound.kind().rebind(proj.term), cx),
2299+
term: clean_middle_term(bound.rebind(proj_pred.term), cx),
23282300
},
23292301
});
23302302
}

src/librustdoc/clean/simplify.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,8 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: ThinVec<WP>) -> ThinVe
4646
// Look for equality predicates on associated types that can be merged into
4747
// general bound predicates.
4848
equalities.retain(|(lhs, rhs)| {
49-
let Some((ty, trait_did, name)) = lhs.projection() else {
50-
return true;
51-
};
52-
let Some((bounds, _)) = tybounds.get_mut(ty) else { return true };
53-
merge_bounds(cx, bounds, trait_did, name, rhs)
49+
let Some((bounds, _)) = tybounds.get_mut(&lhs.self_type) else { return true };
50+
merge_bounds(cx, bounds, lhs.trait_.as_ref().unwrap().def_id(), lhs.assoc.clone(), rhs)
5451
});
5552

5653
// And finally, let's reassemble everything

src/librustdoc/clean/types.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,7 +1341,7 @@ impl PreciseCapturingArg {
13411341
pub(crate) enum WherePredicate {
13421342
BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
13431343
RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1344-
EqPredicate { lhs: Type, rhs: Term },
1344+
EqPredicate { lhs: QPathData, rhs: Term },
13451345
}
13461346

13471347
impl WherePredicate {
@@ -1704,14 +1704,6 @@ impl Type {
17041704
matches!(self, Type::Tuple(v) if v.is_empty())
17051705
}
17061706

1707-
pub(crate) fn projection(&self) -> Option<(&Type, DefId, PathSegment)> {
1708-
if let QPath(box QPathData { self_type, trait_, assoc, .. }) = self {
1709-
Some((self_type, trait_.as_ref()?.def_id(), assoc.clone()))
1710-
} else {
1711-
None
1712-
}
1713-
}
1714-
17151707
/// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
17161708
///
17171709
/// [clean]: crate::clean
@@ -1746,7 +1738,7 @@ pub(crate) struct QPathData {
17461738
pub assoc: PathSegment,
17471739
pub self_type: Type,
17481740
/// FIXME: compute this field on demand.
1749-
pub should_show_cast: bool,
1741+
pub should_fully_qualify: bool,
17501742
pub trait_: Option<Path>,
17511743
}
17521744

0 commit comments

Comments
 (0)