diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index c663f6fc2d3..3318c0797ec 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -744,7 +744,11 @@ fn codegen_regular_intrinsic_call<'tcx>( let const_val = fx .tcx - .const_eval_instance(ty::ParamEnv::reveal_all(), instance, source_info.span) + .const_eval_instance( + ty::TypingEnv::fully_monomorphized(), + instance, + source_info.span, + ) .unwrap(); let val = crate::constant::codegen_const_value(fx, const_val, ret.layout().ty); ret.write_cvalue(fx, val); diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index c35d0b90706..299b98c0a4f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -146,10 +146,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { | sym::type_id | sym::type_name | sym::variant_count => { - let value = bx - .tcx() - .const_eval_instance(ty::ParamEnv::reveal_all(), instance, span) - .unwrap(); + let value = bx.tcx().const_eval_instance(bx.typing_env(), instance, span).unwrap(); OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx) } sym::arith_offset => { 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 ca3ee6773a0..64331eea75c 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -7,7 +7,6 @@ use rustc_middle::bug; use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo}; use rustc_middle::mir::{self, ConstAlloc, ConstValue}; use rustc_middle::query::TyCtxtAt; -use rustc_middle::traits::Reveal; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -31,7 +30,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>( cid: GlobalId<'tcx>, body: &'tcx mir::Body<'tcx>, ) -> InterpResult<'tcx, R> { - trace!(?ecx.param_env); + trace!(?ecx.typing_env); let tcx = *ecx.tcx; assert!( cid.promoted.is_some() @@ -126,14 +125,14 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>( pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>( tcx: TyCtxt<'tcx>, root_span: Span, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, can_access_mut_global: CanAccessMutGlobal, ) -> CompileTimeInterpCx<'tcx> { - debug!("mk_eval_cx: {:?}", param_env); + debug!("mk_eval_cx: {:?}", typing_env); InterpCx::new( tcx, root_span, - param_env, + typing_env, CompileTimeMachine::new(can_access_mut_global, CheckAlignment::No), ) } @@ -142,11 +141,11 @@ pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>( /// Returns both the context and an `OpTy` that represents the constant. pub fn mk_eval_cx_for_const_val<'tcx>( tcx: TyCtxtAt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, val: mir::ConstValue<'tcx>, ty: Ty<'tcx>, ) -> Option<(CompileTimeInterpCx<'tcx>, OpTy<'tcx>)> { - let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, param_env, CanAccessMutGlobal::No); + let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, typing_env, CanAccessMutGlobal::No); // FIXME: is it a problem to discard the error here? let op = ecx.const_val_to_op(val, ty, None).discard_err()?; Some((ecx, op)) @@ -221,7 +220,7 @@ pub(super) fn op_to_const<'tcx>( let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs debug_assert!( matches!( - ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env()).kind(), + ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env).kind(), ty::Str | ty::Slice(..), ), "`ConstValue::Slice` is for slice-tailed types only, but got {}", @@ -245,7 +244,7 @@ pub(super) fn op_to_const<'tcx>( pub(crate) fn turn_into_const_value<'tcx>( tcx: TyCtxt<'tcx>, constant: ConstAlloc<'tcx>, - key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, + key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>, ) -> ConstValue<'tcx> { let cid = key.value; let def_id = cid.instance.def.def_id(); @@ -254,7 +253,7 @@ pub(crate) fn turn_into_const_value<'tcx>( let ecx = mk_eval_cx_to_read_const_val( tcx, tcx.def_span(key.value.instance.def_id()), - key.param_env, + key.typing_env, CanAccessMutGlobal::from(is_static), ); @@ -274,23 +273,16 @@ pub(crate) fn turn_into_const_value<'tcx>( #[instrument(skip(tcx), level = "debug")] pub fn eval_to_const_value_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, - key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, + key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> { - // Const eval always happens in Reveal::All mode in order to be able to use the hidden types of - // opaque types. This is needed for trivial things like `size_of`, but also for using associated - // types that are not specified in the opaque type. - assert_eq!(key.param_env.reveal(), Reveal::All); - let typing_env = - ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: key.param_env }; - // We call `const_eval` for zero arg intrinsics, too, in order to cache their value. // Catch such calls and evaluate them instead of trying to load a constant's MIR. if let ty::InstanceKind::Intrinsic(def_id) = key.value.instance.def { - let ty = key.value.instance.ty(tcx, typing_env); + let ty = key.value.instance.ty(tcx, key.typing_env); let ty::FnDef(_, args) = ty.kind() else { bug!("intrinsic with type {:?}", ty); }; - return eval_nullary_intrinsic(tcx, key.param_env, def_id, args).report_err().map_err( + return eval_nullary_intrinsic(tcx, key.typing_env, def_id, args).report_err().map_err( |error| { let span = tcx.def_span(def_id); @@ -317,7 +309,7 @@ pub fn eval_static_initializer_provider<'tcx>( let instance = ty::Instance::mono(tcx, def_id.to_def_id()); let cid = rustc_middle::mir::interpret::GlobalId { instance, promoted: None }; - eval_in_interpreter(tcx, cid, ty::ParamEnv::reveal_all()) + eval_in_interpreter(tcx, cid, ty::TypingEnv::fully_monomorphized()) } pub trait InterpretationResult<'tcx> { @@ -342,16 +334,14 @@ impl<'tcx> InterpretationResult<'tcx> for ConstAlloc<'tcx> { #[instrument(skip(tcx), level = "debug")] pub fn eval_to_allocation_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, - key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, + key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> { // This shouldn't be used for statics, since statics are conceptually places, // not values -- so what we do here could break pointer identity. assert!(key.value.promoted.is_some() || !tcx.is_static(key.value.instance.def_id())); - // Const eval always happens in Reveal::All mode in order to be able to use the hidden types of - // opaque types. This is needed for trivial things like `size_of`, but also for using associated - // types that are not specified in the opaque type. - - assert_eq!(key.param_env.reveal(), Reveal::All); + // Const eval always happens in PostAnalysis mode . See the comment in + // `InterpCx::new` for more details. + debug_assert_eq!(key.typing_env.typing_mode, ty::TypingMode::PostAnalysis); if cfg!(debug_assertions) { // Make sure we format the instance even if we do not print it. // This serves as a regression test against an ICE on printing. @@ -362,13 +352,13 @@ pub fn eval_to_allocation_raw_provider<'tcx>( trace!("const eval: {:?} ({})", key, instance); } - eval_in_interpreter(tcx, key.value, key.param_env) + eval_in_interpreter(tcx, key.value, key.typing_env) } fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>( tcx: TyCtxt<'tcx>, cid: GlobalId<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Result { let def = cid.instance.def.def_id(); let is_static = tcx.is_static(def); @@ -376,7 +366,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>( let mut ecx = InterpCx::new( tcx, tcx.def_span(def), - param_env, + typing_env, // Statics (and promoteds inside statics) may access mutable global memory, because unlike consts // they do not have to behave "as if" they were evaluated at runtime. // For consts however we want to ensure they behave "as if" they were evaluated at runtime, diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 347b1557d87..db82050c73c 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -667,7 +667,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { .is_some_and(|p| !p.immutable()) { // That next check is expensive, that's why we have all the guards above. - let is_immutable = ty.is_freeze(*ecx.tcx, ecx.typing_env()); + let is_immutable = ty.is_freeze(*ecx.tcx, ecx.typing_env); let place = ecx.ref_to_mplace(val)?; let new_place = if is_immutable { place.map_provenance(CtfeProvenance::as_immutable) diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index d5012236c34..8cbdcd68e13 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -38,8 +38,8 @@ pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>( val: mir::ConstValue<'tcx>, ty: Ty<'tcx>, ) -> Option> { - let param_env = ty::ParamEnv::reveal_all(); - let (ecx, op) = mk_eval_cx_for_const_val(tcx, param_env, val, ty)?; + let typing_env = ty::TypingEnv::fully_monomorphized(); + let (ecx, op) = mk_eval_cx_for_const_val(tcx, typing_env, val, ty)?; // We go to `usize` as we cannot allocate anything bigger anyway. let (field_count, variant, down) = match ty.kind() { @@ -76,10 +76,12 @@ pub fn tag_for_variant_provider<'tcx>( ) -> Option { assert!(ty.is_enum()); + // FIXME: This uses an empty `TypingEnv` even though + // it may be used by a generic CTFE. let ecx = InterpCx::new( tcx, ty.default_span(tcx), - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), crate::const_eval::DummyMachine, ); diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 64bedea3b3f..515028e6826 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -2,7 +2,6 @@ use rustc_abi::{BackendRepr, VariantIdx}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId}; use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; -use rustc_middle::ty::solve::Reveal; use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; use rustc_middle::{bug, mir}; use rustc_span::DUMMY_SP; @@ -229,16 +228,19 @@ fn create_valtree_place<'tcx>( /// Evaluates a constant and turns it into a type-level constant value. pub(crate) fn eval_to_valtree<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, cid: GlobalId<'tcx>, ) -> EvalToValTreeResult<'tcx> { - let const_alloc = tcx.eval_to_allocation_raw(param_env.and(cid))?; + // Const eval always happens in PostAnalysis mode . See the comment in + // `InterpCx::new` for more details. + debug_assert_eq!(typing_env.typing_mode, ty::TypingMode::PostAnalysis); + let const_alloc = tcx.eval_to_allocation_raw(typing_env.as_query_input(cid))?; // FIXME Need to provide a span to `eval_to_valtree` let ecx = mk_eval_cx_to_read_const_val( tcx, DUMMY_SP, - param_env, + typing_env, // It is absolutely crucial for soundness that // we do not read from mutable memory. CanAccessMutGlobal::No, @@ -273,7 +275,8 @@ pub(crate) fn eval_to_valtree<'tcx>( #[instrument(skip(tcx), level = "debug", ret)] pub fn valtree_to_const_value<'tcx>( tcx: TyCtxt<'tcx>, - param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, + typing_env: ty::TypingEnv<'tcx>, + ty: Ty<'tcx>, valtree: ty::ValTree<'tcx>, ) -> mir::ConstValue<'tcx> { // Basic idea: We directly construct `Scalar` values from trivial `ValTree`s @@ -282,10 +285,6 @@ pub fn valtree_to_const_value<'tcx>( // the `ValTree` and using `place_projection` and `place_field` to // create inner `MPlace`s which are filled recursively. // FIXME Does this need an example? - let (param_env, ty) = param_env_ty.into_parts(); - debug_assert_eq!(param_env.reveal(), Reveal::All); - let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env }; - match *ty.kind() { ty::FnDef(..) => { assert!(valtree.unwrap_branch().is_empty()); @@ -299,10 +298,10 @@ pub fn valtree_to_const_value<'tcx>( ), } } - ty::Pat(ty, _) => valtree_to_const_value(tcx, param_env.and(ty), valtree), + ty::Pat(ty, _) => valtree_to_const_value(tcx, typing_env, ty, valtree), ty::Ref(_, inner_ty, _) => { let mut ecx = - mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No); + mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, typing_env, CanAccessMutGlobal::No); let imm = valtree_to_ref(&mut ecx, valtree, inner_ty); let imm = ImmTy::from_immediate(imm, tcx.layout_of(typing_env.as_query_input(ty)).unwrap()); @@ -324,14 +323,14 @@ pub fn valtree_to_const_value<'tcx>( for (i, &inner_valtree) in branches.iter().enumerate() { let field = layout.field(&LayoutCx::new(tcx, typing_env), i); if !field.is_zst() { - return valtree_to_const_value(tcx, param_env.and(field.ty), inner_valtree); + return valtree_to_const_value(tcx, typing_env, field.ty, inner_valtree); } } bug!("could not find non-ZST field during in {layout:#?}"); } let mut ecx = - mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No); + mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, typing_env, CanAccessMutGlobal::No); // Need to create a place for this valtree. let place = create_valtree_place(&mut ecx, layout, valtree); diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 6cfe4b21907..ed4a1a9e647 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -215,7 +215,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // Even if `ty` is normalized, the search for the unsized tail will project // to fields, which can yield non-normalized types. So we need to provide a // normalization function. - let normalize = |ty| self.tcx.normalize_erasing_regions(self.typing_env(), ty); + let normalize = |ty| self.tcx.normalize_erasing_regions(self.typing_env, ty); ty.ptr_metadata_ty(*self.tcx, normalize) }; return interp_ok(meta_ty(caller) == meta_ty(callee)); @@ -652,35 +652,35 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; // Obtain the underlying trait we are working on, and the adjusted receiver argument. - let (trait_, dyn_ty, adjusted_recv) = - if let ty::Dynamic(data, _, ty::DynStar) = receiver_place.layout.ty.kind() { - let recv = self.unpack_dyn_star(&receiver_place, data)?; + let (trait_, dyn_ty, adjusted_recv) = if let ty::Dynamic(data, _, ty::DynStar) = + receiver_place.layout.ty.kind() + { + let recv = self.unpack_dyn_star(&receiver_place, data)?; - (data.principal(), recv.layout.ty, recv.ptr()) - } else { - // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`. - // (For that reason we also cannot use `unpack_dyn_trait`.) - let receiver_tail = self - .tcx - .struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env()); - let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else { - span_bug!( - self.cur_span(), - "dynamic call on non-`dyn` type {}", - receiver_tail - ) - }; - assert!(receiver_place.layout.is_unsized()); - - // Get the required information from the vtable. - let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?; - let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?; - - // It might be surprising that we use a pointer as the receiver even if this - // is a by-val case; this works because by-val passing of an unsized `dyn - // Trait` to a function is actually desugared to a pointer. - (receiver_trait.principal(), dyn_ty, receiver_place.ptr()) + (data.principal(), recv.layout.ty, recv.ptr()) + } else { + // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`. + // (For that reason we also cannot use `unpack_dyn_trait`.) + let receiver_tail = + self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env); + let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else { + span_bug!( + self.cur_span(), + "dynamic call on non-`dyn` type {}", + receiver_tail + ) }; + assert!(receiver_place.layout.is_unsized()); + + // Get the required information from the vtable. + let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?; + let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?; + + // It might be surprising that we use a pointer as the receiver even if this + // is a by-val case; this works because by-val passing of an unsized `dyn + // Trait` to a function is actually desugared to a pointer. + (receiver_trait.principal(), dyn_ty, receiver_place.ptr()) + }; // Now determine the actual method to call. Usually we use the easy way of just // looking up the method at index `idx`. @@ -704,7 +704,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let concrete_method = Instance::expect_resolve_for_vtable( tcx, - self.typing_env(), + self.typing_env, def_id, instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args), self.cur_span(), diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 2d1bb5c9551..c95e51f0a1f 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -83,7 +83,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ty::FnDef(def_id, args) => { let instance = ty::Instance::resolve_for_fn_ptr( *self.tcx, - self.typing_env(), + self.typing_env, def_id, args, ) @@ -384,7 +384,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) -> InterpResult<'tcx> { // A -> A conversion let (src_pointee_ty, dest_pointee_ty) = - self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.typing_env()); + self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.typing_env); match (src_pointee_ty.kind(), dest_pointee_ty.kind()) { (&ty::Array(_, length), &ty::Slice(_)) => { diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 31ce1600ce7..42fdf32e91e 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -1,10 +1,12 @@ +use std::assert_matches::debug_assert_matches; + use either::{Left, Right}; use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout}; use rustc_errors::DiagCtxtHandle; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::at::ToTrace; -use rustc_infer::traits::{ObligationCause, Reveal}; +use rustc_infer::traits::ObligationCause; use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo}; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{ @@ -36,8 +38,9 @@ pub struct InterpCx<'tcx, M: Machine<'tcx>> { /// we are evaluating (if this is CTFE). pub tcx: TyCtxtAt<'tcx>, - /// Bounds in scope for polymorphic evaluations. - pub(crate) param_env: ty::ParamEnv<'tcx>, + /// The current context in case we're evaluating in a + /// polymorphic context. This always uses `ty::TypingMode::PostAnalysis` + pub typing_env: ty::TypingEnv<'tcx>, /// The virtual memory system. pub memory: Memory<'tcx, M>, @@ -68,7 +71,7 @@ where M: Machine<'tcx>, { fn typing_env(&self) -> ty::TypingEnv<'tcx> { - self.typing_env() + self.typing_env } } @@ -189,25 +192,23 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { pub fn new( tcx: TyCtxt<'tcx>, root_span: Span, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, machine: M, ) -> Self { + // Const eval always happens in post analysis mode in order to be able to use the hidden types of + // opaque types. This is needed for trivial things like `size_of`, but also for using associated + // types that are not specified in the opaque type. We also use MIR bodies whose opaque types have + // already been revealed, so we'd be able to at least partially observe the hidden types anyways. + debug_assert_matches!(typing_env.typing_mode, ty::TypingMode::PostAnalysis); InterpCx { machine, tcx: tcx.at(root_span), - param_env, + typing_env, memory: Memory::new(), recursion_limit: tcx.recursion_limit(), } } - /// During CTFE we're always in `PostAnalysis` mode. - #[inline(always)] - pub fn typing_env(&self) -> ty::TypingEnv<'tcx> { - debug_assert_eq!(self.param_env.reveal(), Reveal::All); - ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env } - } - /// Returns the span of the currently executed statement/terminator. /// This is the span typically used for error reporting. #[inline(always)] @@ -250,7 +251,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { #[inline] pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { - ty.is_freeze(*self.tcx, self.typing_env()) + ty.is_freeze(*self.tcx, self.typing_env) } pub fn load_mir( @@ -296,7 +297,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .instance .try_instantiate_mir_and_normalize_erasing_regions( *self.tcx, - self.typing_env(), + self.typing_env, ty::EarlyBinder::bind(value), ) .map_err(|_| ErrorHandled::TooGeneric(self.cur_span())) @@ -309,9 +310,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { args: GenericArgsRef<'tcx>, ) -> InterpResult<'tcx, ty::Instance<'tcx>> { trace!("resolve: {:?}, {:#?}", def, args); - trace!("param_env: {:#?}", self.param_env); + trace!("typing_env: {:#?}", self.typing_env); trace!("args: {:#?}", args); - match ty::Instance::try_resolve(*self.tcx, self.typing_env(), def, args) { + match ty::Instance::try_resolve(*self.tcx, self.typing_env, def, args) { Ok(Some(instance)) => interp_ok(instance), Ok(None) => throw_inval!(TooGeneric), @@ -332,7 +333,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { return true; } // Slow path: spin up an inference context to check if these traits are sufficiently equal. - let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env()); + let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env); let ocx = ObligationCtxt::new(&infcx); let cause = ObligationCause::dummy_with_span(self.cur_span()); // equate the two trait refs after normalization @@ -564,10 +565,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let val = if self.tcx.is_static(gid.instance.def_id()) { let alloc_id = self.tcx.reserve_and_set_static_alloc(gid.instance.def_id()); - let ty = instance.ty(self.tcx.tcx, self.typing_env()); + let ty = instance.ty(self.tcx.tcx, self.typing_env); mir::ConstAlloc { alloc_id, ty } } else { - self.ctfe_query(|tcx| tcx.eval_to_allocation_raw(self.param_env.and(gid)))? + self.ctfe_query(|tcx| tcx.eval_to_allocation_raw(self.typing_env.as_query_input(gid)))? }; self.raw_const_to_mplace(val) } @@ -579,7 +580,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { layout: Option>, ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { M::eval_mir_constant(self, *val, span, layout, |ecx, val, span, layout| { - let const_val = val.eval(*ecx.tcx, ecx.typing_env(), span).map_err(|err| { + let const_val = val.eval(*ecx.tcx, ecx.typing_env, span).map_err(|err| { if M::ALL_CONSTS_ARE_PRECHECKED { match err { ErrorHandled::TooGeneric(..) => {}, diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 2d695688ae5..0cbb3b157f3 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -165,7 +165,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval InternKind::Static(Mutability::Not) => { ( // Outermost allocation is mutable if `!Freeze`. - if ret.layout.ty.is_freeze(*ecx.tcx, ecx.typing_env()) { + if ret.layout.ty.is_freeze(*ecx.tcx, ecx.typing_env) { Mutability::Not } else { Mutability::Mut diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index c8859ab3e88..a79923e8555 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -34,13 +34,12 @@ pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAll /// inside an `InterpCx` and instead have their value computed directly from rustc internal info. pub(crate) fn eval_nullary_intrinsic<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>, ) -> InterpResult<'tcx, ConstValue<'tcx>> { let tp_ty = args.type_at(0); let name = tcx.item_name(def_id); - let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env }; interp_ok(match name { sym::type_name => { ensure_monomorphic_enough(tcx, tp_ty)?; @@ -152,8 +151,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { sym::type_name => Ty::new_static_str(self.tcx.tcx), _ => bug!(), }; - let val = - self.ctfe_query(|tcx| tcx.const_eval_global_id(self.param_env, gid, tcx.span))?; + let val = self + .ctfe_query(|tcx| tcx.const_eval_global_id(self.typing_env, gid, tcx.span))?; let val = self.const_val_to_op(val, ty, Some(dest.layout))?; self.copy_op(&val, dest)?; } @@ -358,7 +357,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let should_panic = !self .tcx - .check_validity_requirement((requirement, self.typing_env().as_query_input(ty))) + .check_validity_requirement((requirement, self.typing_env.as_query_input(ty))) .map_err(|_| err_inval!(TooGeneric))?; if should_panic { diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 9bae9c4b310..277d293597a 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -859,8 +859,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // # Global allocations if let Some(global_alloc) = self.tcx.try_get_global_alloc(id) { - let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env()); - let mutbl = global_alloc.mutability(*self.tcx, self.typing_env()); + let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env); + let mutbl = global_alloc.mutability(*self.tcx, self.typing_env); let kind = match global_alloc { GlobalAlloc::Static { .. } | GlobalAlloc::Memory { .. } => AllocKind::LiveData, GlobalAlloc::Function { .. } => bug!("We already checked function pointers above"), diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 201f1b5dc62..1fa5dcbd24f 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -533,7 +533,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } OffsetOf(fields) => { let val = - self.tcx.offset_of_subfield(self.typing_env(), layout, fields.iter()).bytes(); + self.tcx.offset_of_subfield(self.typing_env, layout, fields.iter()).bytes(); ImmTy::from_uint(val, usize_layout()) } UbChecks => ImmTy::from_bool(M::ub_checks(self)?, *self.tcx), diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 13fcccca76b..2beec544fad 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -540,7 +540,7 @@ where )?; if !mir_assign_valid_types( *self.tcx, - self.typing_env(), + self.typing_env, self.layout_of(normalized_place_ty)?, place.layout, ) { @@ -871,7 +871,7 @@ where // We do NOT compare the types for equality, because well-typed code can // actually "transmute" `&mut T` to `&T` in an assignment without a cast. let layout_compat = - mir_assign_valid_types(*self.tcx, self.typing_env(), src.layout(), dest.layout()); + mir_assign_valid_types(*self.tcx, self.typing_env, src.layout(), dest.layout()); if !allow_transmute && !layout_compat { span_bug!( self.cur_span(), diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs index 037c1a233ee..8ce11c71b8b 100644 --- a/compiler/rustc_const_eval/src/interpret/stack.rs +++ b/compiler/rustc_const_eval/src/interpret/stack.rs @@ -379,7 +379,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { for &const_ in body.required_consts() { let c = self.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?; - c.eval(*self.tcx, self.typing_env(), const_.span).map_err(|err| { + c.eval(*self.tcx, self.typing_env, const_.span).map_err(|err| { err.emit_note(*self.tcx); err })?; @@ -596,7 +596,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { return interp_ok(layout); } - let layout = from_known_layout(self.tcx, self.typing_env(), layout, || { + let layout = from_known_layout(self.tcx, self.typing_env, layout, || { let local_ty = frame.body.local_decls[local].ty; let local_ty = self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?; diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index d4525243642..98aca37e73e 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -418,8 +418,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .collect::>>()?; let fn_sig_binder = func.layout.ty.fn_sig(*self.tcx); - let fn_sig = - self.tcx.normalize_erasing_late_bound_regions(self.typing_env(), fn_sig_binder); + let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.typing_env, fn_sig_binder); let extra_args = &args[fn_sig.inputs().len()..]; let extra_args = self.tcx.mk_type_list_from_iter(extra_args.iter().map(|arg| arg.layout().ty)); diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 9ff24a01689..273eaf42d87 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -448,7 +448,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { meta: MemPlaceMeta, pointee: TyAndLayout<'tcx>, ) -> InterpResult<'tcx> { - let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.typing_env()); + let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.typing_env); match tail.kind() { ty::Dynamic(data, _, ty::Dyn) => { let vtable = meta.unwrap_meta().to_pointer(self.ecx)?; @@ -568,7 +568,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind }); }; let (size, _align) = - global_alloc.size_and_align(*self.ecx.tcx, self.ecx.typing_env()); + global_alloc.size_and_align(*self.ecx.tcx, self.ecx.typing_env); if let GlobalAlloc::Static(did) = global_alloc { let DefKind::Static { nested, .. } = self.ecx.tcx.def_kind(did) else { @@ -619,7 +619,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { }; // Determine what it actually points to. let alloc_actual_mutbl = - global_alloc.mutability(*self.ecx.tcx, self.ecx.typing_env()); + global_alloc.mutability(*self.ecx.tcx, self.ecx.typing_env); // Mutable pointer to immutable memory is no good. if ptr_expected_mutbl == Mutability::Mut && alloc_actual_mutbl == Mutability::Not @@ -848,7 +848,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { if let Some(alloc_id) = mplace.ptr().provenance.and_then(|p| p.get_alloc_id()) { let tcx = *self.ecx.tcx; // Everything must be already interned. - let mutbl = tcx.global_alloc(alloc_id).mutability(tcx, self.ecx.typing_env()); + let mutbl = tcx.global_alloc(alloc_id).mutability(tcx, self.ecx.typing_env); if let Some((_, alloc)) = self.ecx.memory.alloc_map.get(alloc_id) { assert_eq!(alloc.mutability, mutbl); } @@ -955,7 +955,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { ) -> Cow<'e, RangeSet> { assert!(layout.ty.is_union()); assert!(layout.is_sized(), "there are no unsized unions"); - let layout_cx = LayoutCx::new(*ecx.tcx, ecx.typing_env()); + let layout_cx = LayoutCx::new(*ecx.tcx, ecx.typing_env); return M::cached_union_data_range(ecx, layout.ty, || { let mut out = RangeSet(Vec::new()); union_data_range_uncached(&layout_cx, layout, Size::ZERO, &mut out); @@ -1085,8 +1085,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, ) -> InterpResult<'tcx> { // Special check for CTFE validation, preventing `UnsafeCell` inside unions in immutable memory. if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) { - if !val.layout.is_zst() - && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.typing_env()) + if !val.layout.is_zst() && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.typing_env) { if !self.in_mutable_memory(val) { throw_validation_failure!(self.path, UnsafeCellInImmutable); diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 527236b2c22..2a7408f1c70 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -40,14 +40,13 @@ pub fn provide(providers: &mut Providers) { providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider; providers.eval_static_initializer = const_eval::eval_static_initializer_provider; providers.hooks.const_caller_location = util::caller_location::const_caller_location_provider; - providers.eval_to_valtree = |tcx, param_env_and_value| { - let (param_env, raw) = param_env_and_value.into_parts(); - const_eval::eval_to_valtree(tcx, param_env, raw) + providers.eval_to_valtree = |tcx, ty::PseudoCanonicalInput { typing_env, value }| { + const_eval::eval_to_valtree(tcx, typing_env, value) }; providers.hooks.try_destructure_mir_constant_for_user_output = const_eval::try_destructure_mir_constant_for_user_output; providers.valtree_to_const_val = |tcx, (ty, valtree)| { - const_eval::valtree_to_const_value(tcx, ty::ParamEnv::reveal_all().and(ty), valtree) + const_eval::valtree_to_const_value(tcx, ty::TypingEnv::fully_monomorphized(), ty, valtree) }; providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| { util::check_validity_requirement(tcx, init_kind, param_env_and_ty) diff --git a/compiler/rustc_const_eval/src/util/caller_location.rs b/compiler/rustc_const_eval/src/util/caller_location.rs index 7f4c36835e4..9bf16d4fe16 100644 --- a/compiler/rustc_const_eval/src/util/caller_location.rs +++ b/compiler/rustc_const_eval/src/util/caller_location.rs @@ -60,7 +60,7 @@ pub(crate) fn const_caller_location_provider( let mut ecx = mk_eval_cx_to_read_const_val( tcx.tcx, tcx.span, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), CanAccessMutGlobal::No, ); diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index 1afc910ce8f..651a797e97c 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -49,7 +49,7 @@ fn check_validity_requirement_strict<'tcx>( ) -> Result> { let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error); - let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.typing_env.param_env, machine); + let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.typing_env, machine); let allocated = cx .allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap)) diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 5830636c6e8..629cca88043 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -188,8 +188,8 @@ pub fn check_crate(tcx: TyCtxt<'_>) { DefKind::Const if tcx.generics_of(item_def_id).is_empty() => { let instance = ty::Instance::new(item_def_id.into(), ty::GenericArgs::empty()); let cid = GlobalId { instance, promoted: None }; - let param_env = ty::ParamEnv::reveal_all(); - tcx.ensure().eval_to_const_value_raw(param_env.and(cid)); + let typing_env = ty::TypingEnv::fully_monomorphized(); + tcx.ensure().eval_to_const_value_raw(typing_env.as_query_input(cid)); } _ => (), } diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 7092f87a7d1..6eeafe18b35 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -25,8 +25,8 @@ impl<'tcx> TyCtxt<'tcx> { let args = GenericArgs::identity_for_item(self, def_id); let instance = ty::Instance::new(def_id, args); let cid = GlobalId { instance, promoted: None }; - let param_env = self.param_env(def_id).with_reveal_all_normalized(self); - self.const_eval_global_id(param_env, cid, DUMMY_SP) + let typing_env = ty::TypingEnv::post_analysis(self, def_id); + self.const_eval_global_id(typing_env, cid, DUMMY_SP) } /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts @@ -41,8 +41,8 @@ impl<'tcx> TyCtxt<'tcx> { let args = GenericArgs::identity_for_item(self, def_id); let instance = ty::Instance::new(def_id, args); let cid = GlobalId { instance, promoted: None }; - let param_env = self.param_env(def_id).with_reveal_all_normalized(self); - let inputs = self.erase_regions(param_env.and(cid)); + let typing_env = ty::TypingEnv::post_analysis(self, def_id); + let inputs = self.erase_regions(typing_env.as_query_input(cid)); self.eval_to_allocation_raw(inputs) } @@ -76,7 +76,7 @@ impl<'tcx> TyCtxt<'tcx> { match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: ct.promoted }; - self.const_eval_global_id(typing_env.param_env, cid, span) + self.const_eval_global_id(typing_env, cid, span) } // For errors during resolution, we deliberately do not point at the usage site of the constant, // since for these errors the place the constant is used shouldn't matter. @@ -105,7 +105,7 @@ impl<'tcx> TyCtxt<'tcx> { match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: None }; - self.const_eval_global_id_for_typeck(typing_env.param_env, cid, span).inspect(|_| { + self.const_eval_global_id_for_typeck(typing_env, cid, span).inspect(|_| { // We are emitting the lint here instead of in `is_const_evaluatable` // as we normalize obligations before checking them, and normalization // uses this function to evaluate this constant. @@ -144,24 +144,25 @@ impl<'tcx> TyCtxt<'tcx> { pub fn const_eval_instance( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, instance: ty::Instance<'tcx>, span: Span, ) -> EvalToConstValueResult<'tcx> { - self.const_eval_global_id(param_env, GlobalId { instance, promoted: None }, span) + self.const_eval_global_id(typing_env, GlobalId { instance, promoted: None }, span) } /// Evaluate a constant to a `ConstValue`. #[instrument(skip(self), level = "debug")] pub fn const_eval_global_id( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, cid: GlobalId<'tcx>, span: Span, ) -> EvalToConstValueResult<'tcx> { // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. - let inputs = self.erase_regions(param_env.with_reveal_all_normalized(self).and(cid)); + let inputs = + self.erase_regions(typing_env.with_reveal_all_normalized(self).as_query_input(cid)); if !span.is_dummy() { // The query doesn't know where it is being invoked, so we need to fix the span. self.at(span).eval_to_const_value_raw(inputs).map_err(|e| e.with_span(span)) @@ -174,13 +175,14 @@ impl<'tcx> TyCtxt<'tcx> { #[instrument(skip(self), level = "debug")] pub fn const_eval_global_id_for_typeck( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, cid: GlobalId<'tcx>, span: Span, ) -> EvalToValTreeResult<'tcx> { // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. - let inputs = self.erase_regions(param_env.with_reveal_all_normalized(self).and(cid)); + let inputs = + self.erase_regions(typing_env.with_reveal_all_normalized(self).as_query_input(cid)); debug!(?inputs); if !span.is_dummy() { // The query doesn't know where it is being invoked, so we need to fix the span. @@ -202,12 +204,12 @@ impl<'tcx> TyCtxtEnsure<'tcx> { // into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are // encountered. let args = GenericArgs::identity_for_item(self.tcx, def_id); - let instance = ty::Instance::new(def_id, args); + let instance = ty::Instance::new(def_id, self.tcx.erase_regions(args)); let cid = GlobalId { instance, promoted: None }; - let param_env = self.tcx.param_env(def_id).with_reveal_all_normalized(self.tcx); + let typing_env = ty::TypingEnv::post_analysis(self.tcx, def_id); // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // improve caching of queries. - let inputs = self.tcx.erase_regions(param_env.and(cid)); + let inputs = self.tcx.erase_regions(typing_env.as_query_input(cid)); self.eval_to_const_value_raw(inputs) } } diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index d2fab8e78d5..8fd99303622 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -456,18 +456,6 @@ impl<'tcx> Key for ty::ParamEnv<'tcx> { } } -impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> { - type Cache = DefaultCache; - - fn default_span(&self, tcx: TyCtxt<'_>) -> Span { - self.value.default_span(tcx) - } - - fn ty_def_id(&self) -> Option { - self.value.ty_def_id() - } -} - impl<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> { type Cache = DefaultCache; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index b8291e8a352..9ae519dfe7e 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1095,7 +1095,7 @@ rustc_queries! { /// Evaluates a constant and returns the computed allocation. /// /// **Do not use this** directly, use the `eval_to_const_value` or `eval_to_valtree` instead. - query eval_to_allocation_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) + query eval_to_allocation_raw(key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>) -> EvalToAllocationRawResult<'tcx> { desc { |tcx| "const-evaluating + checking `{}`", @@ -1121,7 +1121,7 @@ rustc_queries! { /// /// **Do not use this** directly, use one of the following wrappers: `tcx.const_eval_poly`, /// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_global_id`. - query eval_to_const_value_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) + query eval_to_const_value_raw(key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>) -> EvalToConstValueResult<'tcx> { desc { |tcx| "simplifying constant for the type system `{}`", @@ -1133,7 +1133,7 @@ rustc_queries! { /// Evaluate a constant and convert it to a type level constant or /// return `None` if that is not possible. query eval_to_valtree( - key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>> + key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>> ) -> EvalToValTreeResult<'tcx> { desc { "evaluating type-level constant" } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index d42b6be4787..dab3e18de33 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -537,9 +537,7 @@ impl<'tcx> Instance<'tcx> { // All regions in the result of this query are erased, so it's // fine to erase all of the input regions. - let typing_env = tcx.erase_regions(typing_env); - let args = tcx.erase_regions(args); - tcx.resolve_instance_raw(typing_env.as_query_input((def_id, args))) + tcx.resolve_instance_raw(tcx.erase_regions(typing_env.as_query_input((def_id, args)))) } pub fn expect_resolve( diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index d1f8d1b0949..3078209a068 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1186,7 +1186,6 @@ impl<'tcx> TypingEnv<'tcx> { where T: TypeVisitable>, { - debug_assert!(!value.has_infer()); // FIXME(#132279): We should assert that the value does not contain any placeholders // as these placeholders are also local to the current inference context. However, we // currently use pseudo-canonical queries in the trait solver which replaces params with @@ -1209,7 +1208,7 @@ impl<'tcx> TypingEnv<'tcx> { /// This should be created by using `infcx.pseudo_canonicalize_query(param_env, value)` /// or by using `typing_env.as_query_input(value)`. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -#[derive(HashStable)] +#[derive(HashStable, TypeVisitable, TypeFoldable)] pub struct PseudoCanonicalInput<'tcx, T> { pub typing_env: TypingEnv<'tcx>, pub value: T, diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 500515bc3cc..26480be29f3 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -149,7 +149,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { map, tcx, local_decls: &body.local_decls, - ecx: InterpCx::new(tcx, DUMMY_SP, typing_env.param_env, DummyMachine), + ecx: InterpCx::new(tcx, DUMMY_SP, typing_env, DummyMachine), typing_env, } } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 5150cb752bd..b3d9af37204 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -125,8 +125,7 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { // Clone dominators because we need them while mutating the body. let dominators = body.basic_blocks.dominators().clone(); - let mut state = - VnState::new(tcx, body, typing_env.param_env, &ssa, dominators, &body.local_decls); + let mut state = VnState::new(tcx, body, typing_env, &ssa, dominators, &body.local_decls); ssa.for_each_assignment_mut( body.basic_blocks.as_mut_preserves_cfg(), |local, value, location| { @@ -266,7 +265,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { fn new( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ssa: &'body SsaLocals, dominators: Dominators, local_decls: &'body LocalDecls<'tcx>, @@ -280,7 +279,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { + 4 * body.basic_blocks.len(); VnState { tcx, - ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine), + ecx: InterpCx::new(tcx, DUMMY_SP, typing_env, DummyMachine), local_decls, locals: IndexVec::from_elem(None, local_decls), rev_locals: IndexVec::with_capacity(num_values), @@ -295,7 +294,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } fn typing_env(&self) -> ty::TypingEnv<'tcx> { - self.ecx.typing_env() + self.ecx.typing_env } #[instrument(level = "trace", skip(self), ret)] diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 71a843a785c..5c2c36db0f7 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -82,7 +82,7 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading { let mut finder = TOFinder { tcx, typing_env, - ecx: InterpCx::new(tcx, DUMMY_SP, typing_env.param_env, DummyMachine), + ecx: InterpCx::new(tcx, DUMMY_SP, typing_env, DummyMachine), body, arena, map: Map::new(tcx, body, Some(MAX_PLACES)), diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 67afd19aa73..53e282e9b46 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -183,7 +183,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // to runtime, so we have to manually specify the correct typing mode. let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id()); let can_const_prop = CanConstProp::check(tcx, typing_env, body); - let ecx = InterpCx::new(tcx, tcx.def_span(def_id), typing_env.param_env, DummyMachine); + let ecx = InterpCx::new(tcx, tcx.def_span(def_id), typing_env, DummyMachine); ConstPropagator { ecx, diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index b19adf321c3..9025b47c422 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::layout::{ }; use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths}; use rustc_middle::ty::{ - GenericPredicates, Instance, List, ParamEnv, ScalarInt, TyCtxt, TypeVisitableExt, ValTree, + GenericPredicates, Instance, List, ScalarInt, TyCtxt, TypeVisitableExt, ValTree, }; use rustc_middle::{mir, ty}; use rustc_span::def_id::LOCAL_CRATE; @@ -713,7 +713,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let instance = tables.instances[def]; let tcx = tables.tcx; let result = tcx.const_eval_instance( - ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), instance, tcx.def_span(instance.def_id()), ); diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 57fa4797c5e..5416e00fe0c 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -270,8 +270,8 @@ impl<'tcx> NonCopyConst<'tcx> { instance, promoted: None, }; - let param_env = cx.tcx.param_env(def_id).with_reveal_all_normalized(cx.tcx); - let result = cx.tcx.const_eval_global_id_for_typeck(param_env, cid, DUMMY_SP); + let typing_env = ty::TypingEnv::post_analysis(cx.tcx, def_id); + let result = cx.tcx.const_eval_global_id_for_typeck(typing_env, cid, DUMMY_SP); Self::is_value_unfrozen_raw(cx, result, ty) } @@ -294,7 +294,7 @@ impl<'tcx> NonCopyConst<'tcx> { instance, promoted: None, }; - tcx.const_eval_global_id_for_typeck(typing_env.param_env, cid, span) + tcx.const_eval_global_id_for_typeck(typing_env, cid, span) }, Ok(None) => Err(ErrorHandled::TooGeneric(span)), Err(err) => Err(ErrorHandled::Reported(err.into(), span)), diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index f46557ac630..9627447b342 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -70,7 +70,7 @@ impl NewPermission { access: None, protector: None, } - } else if pointee.is_unpin(*cx.tcx, cx.typing_env()) { + } else if pointee.is_unpin(*cx.tcx, cx.typing_env) { // A regular full mutable reference. On `FnEntry` this is `noalias` and `dereferenceable`. NewPermission::Uniform { perm: Permission::Unique, @@ -128,7 +128,7 @@ impl NewPermission { fn from_box_ty<'tcx>(ty: Ty<'tcx>, kind: RetagKind, cx: &crate::MiriInterpCx<'tcx>) -> Self { // `ty` is not the `Box` but the field of the Box with this pointer (due to allocator handling). let pointee = ty.builtin_deref(true).unwrap(); - if pointee.is_unpin(*cx.tcx, cx.typing_env()) { + if pointee.is_unpin(*cx.tcx, cx.typing_env) { // A regular box. On `FnEntry` this is `noalias`, but not `dereferenceable` (hence only // a weak protector). NewPermission::Uniform { @@ -607,7 +607,7 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> { match new_perm { NewPermission::Uniform { perm, .. } => write!(kind_str, "{perm:?} permission").unwrap(), - NewPermission::FreezeSensitive { freeze_perm, .. } if ty.is_freeze(*this.tcx, this.typing_env()) => + NewPermission::FreezeSensitive { freeze_perm, .. } if ty.is_freeze(*this.tcx, this.typing_env) => write!(kind_str, "{freeze_perm:?} permission").unwrap(), NewPermission::FreezeSensitive { freeze_perm, nonfreeze_perm, .. } => write!(kind_str, "{freeze_perm:?}/{nonfreeze_perm:?} permission for frozen/non-frozen parts").unwrap(), diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 8f8e29846c9..61a2e2bc8d9 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -131,8 +131,8 @@ impl<'tcx> NewPermission { kind: RetagKind, cx: &crate::MiriInterpCx<'tcx>, ) -> Option { - let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.typing_env()); - let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.typing_env()); + let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.typing_env); + let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.typing_env); let is_protected = kind == RetagKind::FnEntry; // As demonstrated by `tests/fail/tree_borrows/reservedim_spurious_write.rs`, // interior mutability and protectors interact poorly. @@ -163,10 +163,10 @@ impl<'tcx> NewPermission { zero_size: bool, ) -> Option { let pointee = ty.builtin_deref(true).unwrap(); - pointee.is_unpin(*cx.tcx, cx.typing_env()).then_some(()).map(|()| { + pointee.is_unpin(*cx.tcx, cx.typing_env).then_some(()).map(|()| { // Regular `Unpin` box, give it `noalias` but only a weak protector // because it is valid to deallocate it within the function. - let ty_is_freeze = ty.is_freeze(*cx.tcx, cx.typing_env()); + let ty_is_freeze = ty.is_freeze(*cx.tcx, cx.typing_env); let protected = kind == RetagKind::FnEntry; let initial_state = Permission::new_reserved(ty_is_freeze, protected); Self { @@ -520,7 +520,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Note: if we were to inline `new_reserved` below we would find out that // `ty_is_freeze` is eventually unused because it appears in a `ty_is_freeze || true`. // We are nevertheless including it here for clarity. - let ty_is_freeze = place.layout.ty.is_freeze(*this.tcx, this.typing_env()); + let ty_is_freeze = place.layout.ty.is_freeze(*this.tcx, this.typing_env); // Retag it. With protection! That is the entire point. let new_perm = NewPermission { initial_state: Permission::new_reserved(ty_is_freeze, /* protected */ true), diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 5ec497ef0ea..85591a0b370 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -273,7 +273,7 @@ pub fn create_ecx<'tcx>( let mut ecx = InterpCx::new( tcx, rustc_span::DUMMY_SP, - typing_env.param_env, + typing_env, MiriMachine::new(config, layout_cx) ); diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 9c1951ec87a..3ab606e5847 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1128,7 +1128,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { let info = ecx.get_alloc_info(alloc_id); let def_ty = ecx.tcx.type_of(def_id).instantiate_identity(); let extern_decl_layout = ecx.tcx.layout_of( - ecx.typing_env().as_query_input(def_ty) + ecx.typing_env.as_query_input(def_ty) ).unwrap(); if extern_decl_layout.size != info.size || extern_decl_layout.align.abi != info.align { throw_unsup_format!(