diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index dc29b6311cc7e..fc16b6d44c310 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -504,7 +504,16 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // (*) The predicates of an inherent associated type include the // predicates of the impl that it's contained in. - if !data.self_ty().has_escaping_bound_vars() { + // In an ideal world, there are no escaping bound vars here. However, WF is jank, and + // sometimes there are. We can only `compute_inherent_assoc_term_args` if the Self ty in the + // args has no escaping bound vars. If we already have impl format args, though, + // `compute_inherent_assoc_term_args` is a no-op (and we have no Self type), so no need to + // check for escaping bound vars. + let can_compute_impl_args = + matches!(data.kind, ty::AliasTermKind::InherentConstImpl { .. }) + || !data.self_ty().has_escaping_bound_vars(); + + if can_compute_impl_args { // FIXME(inherent_associated_types): Should this happen inside of a snapshot? // FIXME(inherent_associated_types): This is incompatible with the new solver and lazy norm! let args = traits::project::compute_inherent_assoc_term_args( @@ -1099,10 +1108,12 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { self.add_wf_preds_for_inherent_projection(alias_const.into()); return; // Subtree is handled by above function } - // please ping khyperia and/or BoxyUwU if this `bug!` fires - ty::AliasConstKind::InherentImpl { .. } => bug!( - "This ought to be unreachable, the entrypoints of WF should still have InherentSelf-form alias consts." - ), + // FIXME: This should be unreachable but isn't because we normalize in item + // wfck before computing wf requirements + ty::AliasConstKind::InherentImpl { .. } => { + self.add_wf_preds_for_inherent_projection(alias_const.into()); + return; + } ty::AliasConstKind::Projection { def_id } | ty::AliasConstKind::Free { def_id } | ty::AliasConstKind::Anon { def_id } => { diff --git a/compiler/rustc_type_ir/src/term_kind.rs b/compiler/rustc_type_ir/src/term_kind.rs index bb4ebf054d263..ed23b196fe269 100644 --- a/compiler/rustc_type_ir/src/term_kind.rs +++ b/compiler/rustc_type_ir/src/term_kind.rs @@ -1,3 +1,5 @@ +use std::debug_assert_matches; + use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{Decodable_NoContext, Encodable_NoContext, StableHash_NoContext}; @@ -265,11 +267,25 @@ impl AliasTerm { /// The following methods work only with (trait) associated term projections. // FIXME: Replace by an impl on Alias impl AliasTerm { + fn debug_assert_has_self(self) { + // InherentConstImpl is deliberately omitted here, it is not self-format args + debug_assert_matches!( + self.kind, + AliasTermKind::ProjectionTy { .. } + | AliasTermKind::ProjectionConst { .. } + | AliasTermKind::InherentTy { .. } + | AliasTermKind::InherentConstSelf { .. }, + "AliasTerm::self_ty is only valid on projection and inherent aliases" + ); + } + pub fn self_ty(self) -> I::Ty { + self.debug_assert_has_self(); self.args.type_at(0) } pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self { + self.debug_assert_has_self(); AliasTerm::new( interner, self.kind, diff --git a/tests/ui/const-generics/gca/wf-inherentimpl.old.stderr b/tests/ui/const-generics/gca/wf-inherentimpl.old.stderr new file mode 100644 index 0000000000000..0766847a93b18 --- /dev/null +++ b/tests/ui/const-generics/gca/wf-inherentimpl.old.stderr @@ -0,0 +1,10 @@ +error: `generic_const_args` requires -Znext-solver=globally to be enabled + --> $DIR/wf-inherentimpl.rs:7:12 + | +LL | #![feature(generic_const_args, min_generic_const_args)] + | ^^^^^^^^^^^^^^^^^^ + | + = help: enable all of these features + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/gca/wf-inherentimpl.rs b/tests/ui/const-generics/gca/wf-inherentimpl.rs new file mode 100644 index 0000000000000..cb3df20daa2dc --- /dev/null +++ b/tests/ui/const-generics/gca/wf-inherentimpl.rs @@ -0,0 +1,16 @@ +//@[next] check-pass +//@ revisions: next old +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +#![feature(inherent_associated_types)] +#![feature(macroless_generic_const_args)] +#![feature(generic_const_args, min_generic_const_args)] +//[old]~^ ERROR `generic_const_args` requires -Znext-solver=globally to be enabled +struct Foo; +impl Foo { + const SIZE: usize = { todo!() }; + fn to_bytes() -> [u8; Self::SIZE] { + todo!() + } +} +fn main() {}