diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 25537dc3eefce..57ccbb8ff10ea 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -19,7 +19,7 @@ use crate::const_eval::CheckAlignment; use crate::interpret::{ CtfeValidationMode, GlobalId, Immediate, InternError, InternKind, InterpCx, InterpErrorKind, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, ReturnContinuation, create_static_alloc, - intern_const_alloc_recursive, interp_ok, throw_exhaust, + ensure_monomorphic_enough, intern_const_alloc_recursive, interp_ok, throw_exhaust, }; use crate::{CTRL_C_RECEIVED, diagnostics}; @@ -96,8 +96,10 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>( body: &'tcx mir::Body<'tcx>, ) -> InterpResult<'tcx, R> { let tcx = *ecx.tcx; - let layout = ecx - .layout_of(body.bound_return_ty(tcx).instantiate(tcx, cid.instance.args).skip_norm_wip())?; + let ty = body.bound_return_ty(tcx).instantiate(tcx, cid.instance.args).skip_norm_wip(); + ensure_monomorphic_enough(ty)?; + + let layout = ecx.layout_of(ty)?; let (intern_kind, ret) = setup_for_eval(ecx, cid, layout)?; trace!( diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 545a3a3ff523a..c0756a25db8b1 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -693,7 +693,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { sym::field_offset => { let frt_ty = instance.args.type_at(0); - ensure_monomorphic_enough(ecx.tcx.tcx, frt_ty)?; + ensure_monomorphic_enough(frt_ty)?; let (ty, variant, field) = if let ty::Adt(def, args) = frt_ty.kind() && let Some(FieldInfo { base, variant_idx, field_idx, .. }) = diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 77839302692e0..8c0500e0e6593 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -76,7 +76,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer(_), _) => { // All reifications must be monomorphic, bail out otherwise. - ensure_monomorphic_enough(*self.tcx, src.layout.ty)?; + ensure_monomorphic_enough(src.layout.ty)?; // The src operand does not matter, just its type match *src.layout.ty.kind() { @@ -112,7 +112,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_), _) => { // All reifications must be monomorphic, bail out otherwise. - ensure_monomorphic_enough(*self.tcx, src.layout.ty)?; + ensure_monomorphic_enough(src.layout.ty)?; // The src operand does not matter, just its type match *src.layout.ty.kind() { @@ -445,8 +445,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } _ => { // Do not ICE if we are not monomorphic enough. - ensure_monomorphic_enough(*self.tcx, src.layout.ty)?; - ensure_monomorphic_enough(*self.tcx, cast_ty)?; + ensure_monomorphic_enough(src.layout.ty)?; + ensure_monomorphic_enough(cast_ty)?; span_bug!( self.cur_span(), @@ -502,8 +502,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } _ => { // Do not ICE if we are not monomorphic enough. - ensure_monomorphic_enough(*self.tcx, src.layout.ty)?; - ensure_monomorphic_enough(*self.tcx, cast_ty.ty)?; + ensure_monomorphic_enough(src.layout.ty)?; + ensure_monomorphic_enough(cast_ty.ty)?; span_bug!( self.cur_span(), diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 256af69b55f13..8001725c438b8 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -186,7 +186,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { match intrinsic_name { sym::type_name => { let tp_ty = instance.args.type_at(0); - ensure_monomorphic_enough(tcx, tp_ty)?; + ensure_monomorphic_enough(tp_ty)?; let (alloc_id, meta) = alloc_type_name(tcx, tp_ty); let val = ConstValue::Slice { alloc_id, meta }; let val = self.const_val_to_op(val, dest.layout.ty, Some(dest.layout))?; @@ -194,14 +194,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } sym::needs_drop => { let tp_ty = instance.args.type_at(0); - ensure_monomorphic_enough(tcx, tp_ty)?; + ensure_monomorphic_enough(tp_ty)?; let val = ConstValue::from_bool(tp_ty.needs_drop(tcx, self.typing_env)); let val = self.const_val_to_op(val, tcx.types.bool, Some(dest.layout))?; self.copy_op(&val, dest)?; } sym::type_id => { let tp_ty = instance.args.type_at(0); - ensure_monomorphic_enough(tcx, tp_ty)?; + ensure_monomorphic_enough(tp_ty)?; self.write_type_id(tp_ty, dest)?; } sym::type_id_eq => { diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index d982ed9616742..a8f5e406e29ee 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs @@ -26,8 +26,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let (ty, dyn_ty) = self.tcx.erase_and_anonymize_regions((ty, dyn_ty)); // All vtables must be monomorphic, bail out otherwise. - ensure_monomorphic_enough(*self.tcx, ty)?; - ensure_monomorphic_enough(*self.tcx, dyn_ty)?; + ensure_monomorphic_enough(ty)?; + ensure_monomorphic_enough(dyn_ty)?; let salt = M::get_global_alloc_salt(self, None); let vtable_symbolic_allocation = self.tcx.reserve_and_set_vtable_alloc(ty, dyn_ty, salt); diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index 57a02769643b7..cbef1de487c43 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -19,8 +19,8 @@ pub(crate) fn type_implements_dyn_trait<'tcx, M: Machine<'tcx>>( ty: Ty<'tcx>, trait_ty: Ty<'tcx>, ) -> InterpResult<'tcx, (bool, &'tcx ty::List>)> { - ensure_monomorphic_enough(ecx.tcx.tcx, ty)?; - ensure_monomorphic_enough(ecx.tcx.tcx, trait_ty)?; + ensure_monomorphic_enough(ty)?; + ensure_monomorphic_enough(trait_ty)?; let ty::Dynamic(preds, _) = trait_ty.kind() else { span_bug!( @@ -50,7 +50,7 @@ pub(crate) fn type_implements_dyn_trait<'tcx, M: Machine<'tcx>>( /// Checks whether a type contains generic parameters which must be instantiated. /// /// In case it does, returns a `TooGeneric` const eval error. -pub(crate) fn ensure_monomorphic_enough<'tcx, T>(_tcx: TyCtxt<'tcx>, ty: T) -> InterpResult<'tcx> +pub(crate) fn ensure_monomorphic_enough<'tcx, T>(ty: T) -> InterpResult<'tcx> where T: TypeVisitable>, { diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 9eefc6718ceb2..75a6753fe3d0e 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -35,7 +35,6 @@ use super::{ format_interp_error, }; use crate::enter_trace_span; -use crate::interpret::ensure_monomorphic_enough; // for the validation errors #[rustfmt::skip] @@ -1585,9 +1584,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> InterpResult<'tcx> { trace!("validate_operand_internal: {:?}, {:?}", *val, val.layout.ty); - // We can't check validity if there are any generics left. - ensure_monomorphic_enough(*self.tcx, val.layout.ty)?; - // Run the visitor. self.run_for_validation_mut(|ecx| { let reset_padding = reset_provenance_and_padding && { diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index e2a9bbd2960b6..b46beb4a29af3 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -341,7 +341,7 @@ impl<'tcx> Const<'tcx> { // FIXME: We might want to have a `try_eval`-like function on `Unevaluated` tcx.const_eval_resolve(typing_env, uneval, span) } - Const::Val(val, _) => Ok(val), + Const::Val(val, _ty) => Ok(val), } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 7c714fd7281d5..6a8d154d3f1a3 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -111,7 +111,7 @@ impl<'tcx> ConstToPat<'tcx> { // implemented as `type` consts (project-const-generics#76). At that point it'll // become necessary to just use type system normalization for all const patterns // but that's not yet possible. - let mut thir_pat = if alias_const.kind.is_type_const(self.tcx) { + let const_value = if alias_const.kind.is_type_const(self.tcx) { let Ok(normalize) = self .tcx .try_normalize_erasing_regions(self.typing_env, Unnormalized::new_wip(self.c)) @@ -124,7 +124,7 @@ impl<'tcx> ConstToPat<'tcx> { let err = self.tcx.dcx().create_err(CouldNotEvalConstPattern { span: self.span }); return self.mk_err(err, ty); }; - self.valtree_to_pat(value) + value } else { // try to resolve e.g. associated constants to their definition on an impl, and then // evaluate the const. @@ -192,8 +192,10 @@ impl<'tcx> ConstToPat<'tcx> { }; // Lower the valtree to a THIR pattern. - self.valtree_to_pat(ty::Value { ty, valtree }) + ty::Value { ty, valtree } }; + debug_assert!(!const_value.ty.has_param()); + let mut thir_pat = self.valtree_to_pat(const_value); if !thir_pat.references_error() { // Always check for `PartialEq` if we had no other errors yet. diff --git a/tests/ui/pattern/generic-in-path.rs b/tests/ui/pattern/generic-in-path.rs new file mode 100644 index 0000000000000..f92ad70e07a25 --- /dev/null +++ b/tests/ui/pattern/generic-in-path.rs @@ -0,0 +1,17 @@ +//! Ensure we can deal with a pattern that depends on a generic in its path, but the +//! actual pattern value can be computed independent of the generic. +#[derive(PartialEq)] +pub struct Thing; + +impl Thing { + const A: Self = Thing; +} + +fn broken(x: Thing) { + match x { + >::A => {} //~ERROR: cannot depend on generic + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/pattern/generic-in-path.stderr b/tests/ui/pattern/generic-in-path.stderr new file mode 100644 index 0000000000000..4f522626e52fe --- /dev/null +++ b/tests/ui/pattern/generic-in-path.stderr @@ -0,0 +1,14 @@ +error[E0158]: constant pattern cannot depend on generic parameters + --> $DIR/generic-in-path.rs:12:9 + | +LL | impl Thing { + | ----------------------------- +LL | const A: Self = Thing; + | ------------- constant defined here +... +LL | >::A => {} + | ^^^^^^^^^^^^^ `const` depends on a generic parameter + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0158`.