diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index d0b0c08aa79..14ea7816291 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -9,6 +9,8 @@ use rustc_span::def_id::DefId; use rustc_span::Span; +use crate::hir_ty_lowering::OnlySelfBounds; + /// Collects together a list of type bounds. These lists of bounds occur in many places /// in Rust's syntax: /// @@ -50,6 +52,7 @@ pub(crate) fn push_trait_bound( span: Span, polarity: ty::PredicatePolarity, constness: ty::BoundConstness, + only_self_bounds: OnlySelfBounds, ) { let clause = ( bound_trait_ref @@ -66,7 +69,10 @@ pub(crate) fn push_trait_bound( self.clauses.push(clause); } - if !tcx.features().effects { + // FIXME(effects): Lift this out of `push_trait_bound`, and move it somewhere else. + // Perhaps moving this into `lower_poly_trait_ref`, just like we lower associated + // type bounds. + if !tcx.features().effects || only_self_bounds.0 { return; } // For `T: ~const Tr` or `T: const Tr`, we need to add an additional bound on the 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_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 f9539ad0efb..67d8813d1f7 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -677,9 +677,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))] diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 4416caa71ff..35eebcb6be1 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -719,6 +719,7 @@ pub(crate) fn lower_poly_trait_ref( span, polarity, constness, + only_self_bounds, ); let mut dup_constraints = FxIndexMap::default(); diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs index 348bf839b69..ea3cbabf302 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs @@ -39,7 +39,6 @@ impl const Foo for NonConstAdd { #[const_trait] trait Baz { type Qux: Add; - //~^ ERROR the trait bound } impl const Baz for NonConstAdd { diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr index 405212b52c7..c20b53c210f 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr @@ -12,17 +12,5 @@ error: using `#![feature(effects)]` without enabling next trait solver globally = note: the next trait solver must be enabled globally for the effects feature to work correctly = help: use `-Znext-solver` to enable -error[E0277]: the trait bound `Add::{synthetic#0}: Compat` is not satisfied - --> $DIR/assoc-type.rs:41:15 - | -LL | type Qux: Add; - | ^^^ the trait `Compat` is not implemented for `Add::{synthetic#0}` - | -help: consider further restricting the associated type - | -LL | trait Baz where Add::{synthetic#0}: Compat { - | ++++++++++++++++++++++++++++++++ +error: aborting due to 1 previous error; 1 warning emitted -error: aborting due to 2 previous errors; 1 warning emitted - -For more information about this error, try `rustc --explain E0277`.