Assert that explicit_super_predicates_of and explicit_item_bounds truly only bounds for the type itself

This commit is contained in:
Michael Goulet 2024-09-21 11:37:20 -04:00
parent f48c99a004
commit a846d55d46
2 changed files with 76 additions and 10 deletions

View File

@ -10,6 +10,7 @@
use rustc_type_ir::Upcast; use rustc_type_ir::Upcast;
use tracing::{debug, instrument}; use tracing::{debug, instrument};
use super::predicates_of::assert_only_contains_predicates_from;
use super::ItemCtxt; use super::ItemCtxt;
use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter}; use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter};
@ -56,6 +57,9 @@ fn associated_type_bounds<'tcx>(
tcx.def_path_str(assoc_item_def_id.to_def_id()), tcx.def_path_str(assoc_item_def_id.to_def_id()),
all_bounds all_bounds
); );
assert_only_contains_predicates_from(filter, all_bounds, item_ty);
all_bounds all_bounds
} }
@ -108,18 +112,21 @@ pub(super) fn explicit_item_bounds_with_filter(
Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
let item = tcx.hir_node_by_def_id(opaque_def_id.expect_local()).expect_item(); let item = tcx.hir_node_by_def_id(opaque_def_id.expect_local()).expect_item();
let opaque_ty = item.expect_opaque_ty(); let opaque_ty = item.expect_opaque_ty();
return ty::EarlyBinder::bind(opaque_type_bounds( let item_ty = Ty::new_projection_from_args(
tcx,
opaque_def_id.expect_local(),
opaque_ty.bounds,
Ty::new_projection_from_args(
tcx, tcx,
def_id.to_def_id(), def_id.to_def_id(),
ty::GenericArgs::identity_for_item(tcx, def_id), ty::GenericArgs::identity_for_item(tcx, def_id),
), );
let bounds = opaque_type_bounds(
tcx,
opaque_def_id.expect_local(),
opaque_ty.bounds,
item_ty,
item.span, item.span,
filter, filter,
)); );
assert_only_contains_predicates_from(filter, bounds, item_ty);
return ty::EarlyBinder::bind(bounds);
} }
Some(ty::ImplTraitInTraitData::Impl { .. }) => span_bug!( Some(ty::ImplTraitInTraitData::Impl { .. }) => span_bug!(
tcx.def_span(def_id), tcx.def_span(def_id),
@ -167,7 +174,9 @@ pub(super) fn explicit_item_bounds_with_filter(
}) => { }) => {
let args = GenericArgs::identity_for_item(tcx, def_id); let args = GenericArgs::identity_for_item(tcx, def_id);
let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args); let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter) let bounds = opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter);
assert_only_contains_predicates_from(filter, bounds, item_ty);
bounds
} }
// Since RPITITs are lowered as projections in `<dyn HirTyLowerer>::lower_ty`, when we're // Since RPITITs are lowered as projections in `<dyn HirTyLowerer>::lower_ty`, when we're
// asking for the item bounds of the *opaques* in a trait's default method signature, we // asking for the item bounds of the *opaques* in a trait's default method signature, we
@ -184,15 +193,18 @@ pub(super) fn explicit_item_bounds_with_filter(
}; };
let args = GenericArgs::identity_for_item(tcx, def_id); let args = GenericArgs::identity_for_item(tcx, def_id);
let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args); let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
tcx.arena.alloc_slice( let bounds = &*tcx.arena.alloc_slice(
&opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter) &opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter)
.to_vec() .to_vec()
.fold_with(&mut AssocTyToOpaque { tcx, fn_def_id: fn_def_id.to_def_id() }), .fold_with(&mut AssocTyToOpaque { tcx, fn_def_id: fn_def_id.to_def_id() }),
) );
assert_only_contains_predicates_from(filter, bounds, item_ty);
bounds
} }
hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[], hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[],
_ => bug!("item_bounds called on {:?}", def_id), _ => bug!("item_bounds called on {:?}", def_id),
}; };
ty::EarlyBinder::bind(bounds) ty::EarlyBinder::bind(bounds)
} }

View File

@ -676,9 +676,63 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
_ => {} _ => {}
} }
assert_only_contains_predicates_from(filter, implied_bounds, tcx.types.self_param);
ty::EarlyBinder::bind(implied_bounds) ty::EarlyBinder::bind(implied_bounds)
} }
// Make sure when elaborating supertraits, probing for associated types, etc.,
// we really truly are elaborating clauses that have `Self` as their self type.
// This is very important since downstream code relies on this being correct.
pub(super) fn assert_only_contains_predicates_from<'tcx>(
filter: PredicateFilter,
bounds: &'tcx [(ty::Clause<'tcx>, Span)],
ty: Ty<'tcx>,
) {
if !cfg!(debug_assertions) {
return;
}
match filter {
PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => {
for (clause, _) in bounds {
match clause.kind().skip_binder() {
ty::ClauseKind::Trait(trait_predicate) => {
assert_eq!(
trait_predicate.self_ty(),
ty,
"expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
);
}
ty::ClauseKind::Projection(projection_predicate) => {
assert_eq!(
projection_predicate.self_ty(),
ty,
"expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
);
}
ty::ClauseKind::TypeOutlives(outlives_predicate) => {
assert_eq!(
outlives_predicate.0, ty,
"expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
);
}
ty::ClauseKind::RegionOutlives(_)
| ty::ClauseKind::ConstArgHasType(_, _)
| ty::ClauseKind::WellFormed(_)
| ty::ClauseKind::ConstEvaluatable(_) => {
bug!(
"unexpected non-`Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
);
}
}
}
}
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {}
}
}
/// Returns the predicates defined on `item_def_id` of the form /// Returns the predicates defined on `item_def_id` of the form
/// `X: Foo` where `X` is the type parameter `def_id`. /// `X: Foo` where `X` is the type parameter `def_id`.
#[instrument(level = "trace", skip(tcx))] #[instrument(level = "trace", skip(tcx))]