From a846d55d46c80660b6a311c6393fb66e486a7d43 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 21 Sep 2024 11:37:20 -0400 Subject: [PATCH] Assert that explicit_super_predicates_of and explicit_item_bounds truly only bounds for the type itself --- .../src/collect/item_bounds.rs | 32 +++++++---- .../src/collect/predicates_of.rs | 54 +++++++++++++++++++ 2 files changed, 76 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index d62727e76b5..7a254c884c2 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -10,6 +10,7 @@ use rustc_span::Span; use rustc_type_ir::Upcast; use tracing::{debug, instrument}; +use super::predicates_of::assert_only_contains_predicates_from; use super::ItemCtxt; 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()), all_bounds ); + + assert_only_contains_predicates_from(filter, all_bounds, item_ty); + all_bounds } @@ -108,18 +112,21 @@ pub(super) fn explicit_item_bounds_with_filter( Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { let item = tcx.hir_node_by_def_id(opaque_def_id.expect_local()).expect_item(); let opaque_ty = item.expect_opaque_ty(); - return ty::EarlyBinder::bind(opaque_type_bounds( + let item_ty = Ty::new_projection_from_args( + tcx, + def_id.to_def_id(), + ty::GenericArgs::identity_for_item(tcx, def_id), + ); + let bounds = opaque_type_bounds( tcx, opaque_def_id.expect_local(), opaque_ty.bounds, - Ty::new_projection_from_args( - tcx, - def_id.to_def_id(), - ty::GenericArgs::identity_for_item(tcx, def_id), - ), + item_ty, item.span, filter, - )); + ); + assert_only_contains_predicates_from(filter, bounds, item_ty); + return ty::EarlyBinder::bind(bounds); } Some(ty::ImplTraitInTraitData::Impl { .. }) => span_bug!( 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 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 `::lower_ty`, when we're // 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 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) .to_vec() .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(..), .. }) => &[], _ => bug!("item_bounds called on {:?}", def_id), }; + ty::EarlyBinder::bind(bounds) } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 7243e85ce98..cb98aa3d315 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -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) } +// 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 /// `X: Foo` where `X` is the type parameter `def_id`. #[instrument(level = "trace", skip(tcx))]