diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 58a23b9e558..c6b34d5bf1d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1727,7 +1727,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // `Sized` bound in no way depends on precise regions, so this // shouldn't affect `is_sized`. let erased_ty = tcx.erase_regions(ty); - if !erased_ty.is_sized(tcx, self.infcx.param_env) { + // FIXME(#132279): Using `Ty::is_sized` causes us to incorrectly handle opaques here. + if !erased_ty.is_sized(tcx, self.infcx.typing_env(self.infcx.param_env)) { // in current MIR construction, all non-control-flow rvalue // expressions evaluate through `as_temp` or `into` a return // slot or local, so to find all unsized rvalues it is enough diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 1b91d251bfd..77ee9773940 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -11,7 +11,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::InlineAsmMacro; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::adjustment::PointerCoercion; -use rustc_middle::ty::layout::FnAbiOf; +use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv}; use rustc_middle::ty::print::with_no_trimmed_paths; use crate::constant::ConstantCx; @@ -841,7 +841,7 @@ fn codegen_stmt<'tcx>( lval.write_cvalue(fx, CValue::by_val(operand, box_layout)); } Rvalue::NullaryOp(ref null_op, ty) => { - assert!(lval.layout().ty.is_sized(fx.tcx, ty::ParamEnv::reveal_all())); + assert!(lval.layout().ty.is_sized(fx.tcx, fx.typing_env())); let layout = fx.layout_of(fx.monomorphize(ty)); let val = match null_op { NullOp::SizeOf => layout.size.bytes(), diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index add081bc795..c663fa32965 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -103,7 +103,7 @@ fn clif_pair_type_from_ty<'tcx>( /// Is a pointer to this type a wide ptr? pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { - if ty.is_sized(tcx, ty::ParamEnv::reveal_all()) { + if ty.is_sized(tcx, ty::TypingEnv::fully_monomorphized()) { return false; } 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/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index c8b3b30218a..27c9cb0b31e 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -22,7 +22,7 @@ use rustc_middle::mir::BinOp; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; use rustc_middle::query::Providers; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout}; -use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypingMode}; +use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_session::Session; use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType}; use rustc_span::symbol::sym; @@ -119,7 +119,8 @@ pub fn validate_trivial_unsize<'tcx>( ) -> bool { match (source_data.principal(), target_data.principal()) { (Some(hr_source_principal), Some(hr_target_principal)) => { - let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis); + let (infcx, param_env) = + tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv::fully_monomorphized()); let universe = infcx.universe(); let ocx = ObligationCtxt::new(&infcx); infcx.enter_forall(hr_target_principal, |target_principal| { @@ -130,7 +131,7 @@ pub fn validate_trivial_unsize<'tcx>( ); let Ok(()) = ocx.eq_trace( &ObligationCause::dummy(), - ty::ParamEnv::reveal_all(), + param_env, ToTrace::to_trace( &ObligationCause::dummy(), hr_target_principal, 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_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index 3810c609fd4..6292d321f6b 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -78,15 +78,15 @@ pub trait DerivedTypeCodegenMethods<'tcx>: } fn type_is_sized(&self, ty: Ty<'tcx>) -> bool { - ty.is_sized(self.tcx(), ty::ParamEnv::reveal_all()) + ty.is_sized(self.tcx(), self.typing_env()) } fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { - ty.is_freeze(self.tcx(), ty::ParamEnv::reveal_all()) + ty.is_freeze(self.tcx(), self.typing_env()) } fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool { - if ty.is_sized(self.tcx(), self.param_env()) { + if ty.is_sized(self.tcx(), self.typing_env()) { return false; } diff --git a/compiler/rustc_const_eval/src/check_consts/resolver.rs b/compiler/rustc_const_eval/src/check_consts/resolver.rs index 03624a2ce50..0f9a460ca1b 100644 --- a/compiler/rustc_const_eval/src/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/check_consts/resolver.rs @@ -120,10 +120,7 @@ where /// /// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134 fn shared_borrow_allows_mutation(&self, place: mir::Place<'tcx>) -> bool { - !place - .ty(self.ccx.body, self.ccx.tcx) - .ty - .is_freeze(self.ccx.tcx, self.ccx.typing_env.param_env) + !place.ty(self.ccx.body, self.ccx.tcx).ty.is_freeze(self.ccx.tcx, self.ccx.typing_env) } } 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 19c3195aaa4..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.param_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 4f413c84615..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.param_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 7a1b92601a4..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.param_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 07566e9fda2..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.param_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 005b430bc8a..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.param_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.param_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,7 +1085,8 @@ 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.param_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/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index cf8c81c0b08..aa9d303cacb 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -90,24 +90,24 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b fn allowed_union_field<'tcx>( ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> bool { // We don't just accept all !needs_drop fields, due to semver concerns. match ty.kind() { ty::Ref(..) => true, // references never drop (even mutable refs, which are non-Copy and hence fail the later check) ty::Tuple(tys) => { // allow tuples of allowed types - tys.iter().all(|ty| allowed_union_field(ty, tcx, param_env)) + tys.iter().all(|ty| allowed_union_field(ty, tcx, typing_env)) } ty::Array(elem, _len) => { // Like `Copy`, we do *not* special-case length 0. - allowed_union_field(*elem, tcx, param_env) + allowed_union_field(*elem, tcx, typing_env) } _ => { // Fallback case: allow `ManuallyDrop` and things that are `Copy`, // also no need to report an error if the type is unresolved. ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop()) - || ty.is_copy_modulo_regions(tcx, param_env) + || ty.is_copy_modulo_regions(tcx, typing_env) || ty.references_error() } } @@ -121,7 +121,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b continue; }; - if !allowed_union_field(field_ty, tcx, typing_env.param_env) { + if !allowed_union_field(field_ty, tcx, typing_env) { let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) { // We are currently checking the type this field came from, so it must be local. Some(Node::Field(field)) => (field.span, field.ty.span), diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 77c324183c3..8a051e34f82 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1193,9 +1193,9 @@ fn compare_self_type<'tcx>( ty::AssocItemContainer::Trait => tcx.types.self_param, }; let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0); - let param_env = ty::ParamEnv::reveal_all(); - - let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); + let (infcx, param_env) = tcx + .infer_ctxt() + .build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, method.def_id)); let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty); let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty); match ExplicitSelf::determine(self_arg_ty, can_eq_self) { diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index e95669c9d40..dfddf93a5c2 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -15,7 +15,7 @@ use rustc_target::asm::{ pub struct InlineAsmCtxt<'a, 'tcx> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, get_operand_ty: Box) -> Ty<'tcx> + 'a>, } @@ -23,24 +23,29 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { pub fn new_global_asm(tcx: TyCtxt<'tcx>) -> Self { InlineAsmCtxt { tcx, - param_env: ty::ParamEnv::empty(), + typing_env: ty::TypingEnv { + typing_mode: ty::TypingMode::non_body_analysis(), + param_env: ty::ParamEnv::empty(), + }, get_operand_ty: Box::new(|e| bug!("asm operand in global asm: {e:?}")), } } + // FIXME(#132279): This likely causes us to incorrectly handle opaque types in their + // defining scope. pub fn new_in_fn( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, get_operand_ty: impl Fn(&'tcx hir::Expr<'tcx>) -> Ty<'tcx> + 'a, ) -> Self { - InlineAsmCtxt { tcx, param_env, get_operand_ty: Box::new(get_operand_ty) } + InlineAsmCtxt { tcx, typing_env, get_operand_ty: Box::new(get_operand_ty) } } // FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()` fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool { // Type still may have region variables, but `Sized` does not depend // on those, so just erase them before querying. - if ty.is_sized(self.tcx, self.param_env) { + if ty.is_sized(self.tcx, self.typing_env) { return true; } if let ty::Foreign(..) = ty.kind() { @@ -171,7 +176,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { // Check that the type implements Copy. The only case where this can // possibly fail is for SIMD types which don't #[derive(Copy)]. - if !ty.is_copy_modulo_regions(self.tcx, self.param_env) { + if !ty.is_copy_modulo_regions(self.tcx, self.typing_env) { let msg = "arguments for inline assembly must be copyable"; self.tcx .dcx() diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 8a1a887766c..eca85c22a40 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -172,7 +172,7 @@ pub(crate) fn orphan_check_impl( // impl AutoTrait for T {} // impl AutoTrait for T {} ty::Param(..) => ( - if self_ty.is_sized(tcx, tcx.param_env(impl_def_id)) { + if self_ty.is_sized(tcx, ty::TypingEnv::non_body_analysis(tcx, impl_def_id)) { LocalImpl::Allow } else { LocalImpl::Disallow { problematic_kind: "generic type" } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 564e45c677d..0a26b6776bb 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -190,8 +190,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_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 59bef8315d8..2a00530c434 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -228,7 +228,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) { } fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool { - ty.is_copy_modulo_regions(self.0.tcx, self.0.param_env) + ty.is_copy_modulo_regions(self.0.tcx, self.0.typing_env()) } fn body_owner_def_id(&self) -> LocalDefId { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 50d1322eba6..961526831fb 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -105,8 +105,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.erase_regions(ty) } }; - InlineAsmCtxt::new_in_fn(self.tcx, self.param_env, get_operand_ty) - .check_asm(asm, enclosing_id); + InlineAsmCtxt::new_in_fn( + self.tcx, + self.infcx.typing_env(self.param_env), + get_operand_ty, + ) + .check_asm(asm, enclosing_id); } } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 8694800ac43..2f436ce77a4 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -831,8 +831,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { // Normalize consts in writeback, because GCE doesn't normalize eagerly. if tcx.features().generic_const_exprs() { - value = - value.fold_with(&mut EagerlyNormalizeConsts { tcx, param_env: self.fcx.param_env }); + value = value.fold_with(&mut EagerlyNormalizeConsts::new(self.fcx)); } value @@ -873,16 +872,22 @@ impl<'cx, 'tcx> TypeFolder> for Resolver<'cx, 'tcx> { struct EagerlyNormalizeConsts<'tcx> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, } +impl<'tcx> EagerlyNormalizeConsts<'tcx> { + fn new(fcx: &FnCtxt<'_, 'tcx>) -> Self { + // FIXME(#132279, generic_const_exprs): Using `try_normalize_erasing_regions` here + // means we can't handle opaque types in their defining scope. + EagerlyNormalizeConsts { tcx: fcx.tcx, typing_env: fcx.typing_env(fcx.param_env) } + } +} + impl<'tcx> TypeFolder> for EagerlyNormalizeConsts<'tcx> { fn cx(&self) -> TyCtxt<'tcx> { self.tcx } fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - self.tcx - .try_normalize_erasing_regions(ty::TypingEnv::from_param_env(self.param_env), ct) - .unwrap_or(ct) + self.tcx.try_normalize_erasing_regions(self.typing_env, ct).unwrap_or(ct) } } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index f6366ec3b80..bda982a3675 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -32,7 +32,7 @@ use rustc_middle::bug; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode, Upcast, VariantDef}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef}; use rustc_session::lint::FutureIncompatibilityReason; // hardwired lints from rustc_lint_defs pub use rustc_session::lint::builtin::*; @@ -586,10 +586,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { return; } } - if ty.is_copy_modulo_regions(cx.tcx, cx.param_env) { + if ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) { return; } - if type_implements_negative_copy_modulo_regions(cx.tcx, ty, cx.param_env) { + if type_implements_negative_copy_modulo_regions(cx.tcx, ty, cx.typing_env()) { return; } if def.is_variant_list_non_exhaustive() @@ -637,8 +637,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { fn type_implements_negative_copy_modulo_regions<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> bool { + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); let trait_ref = ty::TraitRef::new(tcx, tcx.require_lang_item(hir::LangItem::Copy, None), [ty]); let pred = ty::TraitPredicate { trait_ref, polarity: ty::PredicatePolarity::Negative }; let obligation = traits::Obligation { @@ -647,10 +648,7 @@ fn type_implements_negative_copy_modulo_regions<'tcx>( recursion_depth: 0, predicate: pred.upcast(tcx), }; - - tcx.infer_ctxt() - .build(TypingMode::non_body_analysis()) - .predicate_must_hold_modulo_regions(&obligation) + infcx.predicate_must_hold_modulo_regions(&obligation) } declare_lint! { diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index 364c6fd488a..8fe86738658 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -144,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { && let Some(fn_name) = cx.tcx.get_diagnostic_name(def_id) { let arg_ty = cx.typeck_results().expr_ty(arg); - let is_copy = arg_ty.is_copy_modulo_regions(cx.tcx, cx.param_env); + let is_copy = arg_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()); let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr); let let_underscore_ignore_sugg = || { if let Some((_, node)) = cx.tcx.hir().parent_iter(expr.hir_id).nth(0) diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index beab4d4e6a9..1aacdbd448c 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::relate::{ Relate, RelateResult, TypeRelation, structurally_relate_consts, structurally_relate_tys, }; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, + self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint::FutureIncompatibilityReason; @@ -186,8 +186,8 @@ fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) { functional_variances.variances }), outlives_env: LazyCell::new(|| { - let param_env = tcx.param_env(parent_def_id); - let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); + let typing_env = ty::TypingEnv::non_body_analysis(tcx, parent_def_id); + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); let ocx = ObligationCtxt::new(&infcx); let assumed_wf_tys = ocx.assumed_wf_types(param_env, parent_def_id).unwrap_or_default(); let implied_bounds = diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index 45d97403d60..7c6656f91c9 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -168,7 +168,7 @@ fn is_cast_from_ref_to_mut_ptr<'tcx>( // Except on the presence of non concrete skeleton types (ie generics) // since there is no way to make it safe for arbitrary types. let inner_ty_has_interior_mutability = - !inner_ty.is_freeze(cx.tcx, cx.param_env) && inner_ty.has_concrete_skeleton(); + !inner_ty.is_freeze(cx.tcx, cx.typing_env()) && inner_ty.has_concrete_skeleton(); (!need_check_freeze || !inner_ty_has_interior_mutability) .then_some(inner_ty_has_interior_mutability) } else { diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 2e6cb993842..b1d7d4ab689 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -292,7 +292,7 @@ fn lint_wide_pointer<'tcx>( _ => return None, }; - (!ty.is_sized(cx.tcx, cx.param_env)) + (!ty.is_sized(cx.tcx, cx.typing_env())) .then(|| (refs, modifiers, matches!(ty.kind(), ty::Dynamic(_, _, ty::Dyn)))) }; @@ -904,7 +904,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if let Some(boxed) = ty.boxed_ty() && matches!(self.mode, CItemKind::Definition) { - if boxed.is_sized(tcx, self.cx.param_env) { + if boxed.is_sized(tcx, self.cx.typing_env()) { return FfiSafe; } else { return FfiUnsafe { @@ -1069,7 +1069,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { ty::RawPtr(ty, _) | ty::Ref(_, ty, _) if { matches!(self.mode, CItemKind::Definition) - && ty.is_sized(self.cx.tcx, self.cx.param_env) + && ty.is_sized(self.cx.tcx, self.cx.typing_env()) } => { FfiSafe diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index c4b0e6e39cc..8d73c9e76de 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -46,7 +46,7 @@ pub use self::pointer::{CtfeProvenance, Pointer, PointerArithmetic, Provenance}; pub use self::value::Scalar; use crate::mir; use crate::ty::codec::{TyDecoder, TyEncoder}; -use crate::ty::{self, Instance, ParamEnv, Ty, TyCtxt}; +use crate::ty::{self, Instance, Ty, TyCtxt}; /// Uniquely identifies one of the following: /// - A constant @@ -312,7 +312,7 @@ impl<'tcx> GlobalAlloc<'tcx> { } } - pub fn mutability(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Mutability { + pub fn mutability(&self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Mutability { // Let's see what kind of memory we are. match self { GlobalAlloc::Static(did) => { @@ -334,7 +334,7 @@ impl<'tcx> GlobalAlloc<'tcx> { .type_of(did) .no_bound_vars() .expect("statics should not have generic parameters") - .is_freeze(tcx, param_env) => + .is_freeze(tcx, typing_env) => { Mutability::Mut } 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/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 425cb059e57..e2379f282ec 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -459,10 +459,7 @@ impl<'tcx> Body<'tcx> { typing_mode: ty::TypingMode::non_body_analysis(), param_env: tcx.param_env(self.source.def_id()), }, - MirPhase::Runtime(_) => TypingEnv { - typing_mode: ty::TypingMode::PostAnalysis, - param_env: tcx.param_env_reveal_all_normalized(self.source.def_id()), - }, + MirPhase::Runtime(_) => TypingEnv::post_analysis(tcx, self.source.def_id()), } } 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 684d5b6c2a7..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" } } @@ -1390,19 +1390,19 @@ rustc_queries! { /// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`, /// `ty.is_copy()`, etc, since that will prune the environment where possible. - query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + query is_copy_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Copy`", env.value } } /// Query backing `Ty::is_sized`. - query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + query is_sized_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Sized`", env.value } } /// Query backing `Ty::is_freeze`. - query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + query is_freeze_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is freeze", env.value } } /// Query backing `Ty::is_unpin`. - query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + query is_unpin_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` is `Unpin`", env.value } } /// Query backing `Ty::needs_drop`. 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/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 8625a8dcb2a..fc29b438d3a 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1002,12 +1002,12 @@ where // attributes in LLVM have compile-time cost even in unoptimized builds). let optimize = tcx.sess.opts.optimize != OptLevel::No; let kind = match mt { - hir::Mutability::Not => PointerKind::SharedRef { - frozen: optimize && ty.is_freeze(tcx, typing_env.param_env), - }, - hir::Mutability::Mut => PointerKind::MutableRef { - unpin: optimize && ty.is_unpin(tcx, typing_env.param_env), - }, + hir::Mutability::Not => { + PointerKind::SharedRef { frozen: optimize && ty.is_freeze(tcx, typing_env) } + } + hir::Mutability::Mut => { + PointerKind::MutableRef { unpin: optimize && ty.is_unpin(tcx, typing_env) } + } }; tcx.layout_of(typing_env.as_query_input(ty)).ok().map(|layout| PointeeInfo { @@ -1100,7 +1100,7 @@ where debug_assert!(pointee.safe.is_none()); let optimize = tcx.sess.opts.optimize != OptLevel::No; pointee.safe = Some(PointerKind::Box { - unpin: optimize && boxed_ty.is_unpin(tcx, typing_env.param_env), + unpin: optimize && boxed_ty.is_unpin(tcx, typing_env), global: this.ty.is_box_global(tcx), }); } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 965a8c8c95e..dd8286c8eb9 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1140,12 +1140,6 @@ pub struct TypingEnv<'tcx> { } impl<'tcx> TypingEnv<'tcx> { - // FIXME(#132279): This method should be removed but simplifies the - // transition. - pub fn from_param_env(param_env: ParamEnv<'tcx>) -> TypingEnv<'tcx> { - TypingEnv { typing_mode: TypingMode::from_param_env(param_env), param_env } - } - /// Create a typing environment with no where-clauses in scope /// where all opaque types and default associated items are revealed. /// @@ -1192,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 @@ -1215,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_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 703a7826b7a..20c3f84bb4d 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1180,8 +1180,12 @@ impl<'tcx> Ty<'tcx> { /// does copies even when the type actually doesn't satisfy the /// full requirements for the `Copy` trait (cc #29149) -- this /// winds up being reported as an error during NLL borrow check. - pub fn is_copy_modulo_regions(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - self.is_trivially_pure_clone_copy() || tcx.is_copy_raw(param_env.and(self)) + pub fn is_copy_modulo_regions( + self, + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ) -> bool { + self.is_trivially_pure_clone_copy() || tcx.is_copy_raw(typing_env.as_query_input(self)) } /// Checks whether values of this type `T` have a size known at @@ -1190,8 +1194,8 @@ impl<'tcx> Ty<'tcx> { /// over-approximation in generic contexts, where one can have /// strange rules like `>::Bar: Sized` that /// actually carry lifetime requirements. - pub fn is_sized(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - self.is_trivially_sized(tcx) || tcx.is_sized_raw(param_env.and(self)) + pub fn is_sized(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { + self.is_trivially_sized(tcx) || tcx.is_sized_raw(typing_env.as_query_input(self)) } /// Checks whether values of this type `T` implement the `Freeze` @@ -1201,8 +1205,8 @@ impl<'tcx> Ty<'tcx> { /// optimization as well as the rules around static values. Note /// that the `Freeze` trait is not exposed to end users and is /// effectively an implementation detail. - pub fn is_freeze(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - self.is_trivially_freeze() || tcx.is_freeze_raw(param_env.and(self)) + pub fn is_freeze(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { + self.is_trivially_freeze() || tcx.is_freeze_raw(typing_env.as_query_input(self)) } /// Fast path helper for testing if a type is `Freeze`. @@ -1241,8 +1245,8 @@ impl<'tcx> Ty<'tcx> { } /// Checks whether values of this type `T` implement the `Unpin` trait. - pub fn is_unpin(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - self.is_trivially_unpin() || tcx.is_unpin_raw(param_env.and(self)) + pub fn is_unpin(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { + self.is_trivially_unpin() || tcx.is_unpin_raw(typing_env.as_query_input(self)) } /// Fast path helper for testing if a type is `Unpin`. diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs index aad7d54833b..159959d4f1f 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs @@ -165,11 +165,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if tcx.features().unsized_fn_params() { let ty = expr.ty; - let param_env = this.param_env; - - if !ty.is_sized(tcx, param_env) { + if !ty.is_sized(tcx, this.typing_env()) { // !sized means !copy, so this is an unsized move - assert!(!ty.is_copy_modulo_regions(tcx, param_env)); + assert!(!ty.is_copy_modulo_regions(tcx, this.typing_env())); // As described above, detect the case where we are passing a value of unsized // type, and that value is coming from the deref of a box. diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index cf8dc597b7b..3317f3b7f8a 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -148,6 +148,10 @@ struct BlockContext(Vec); struct Builder<'a, 'tcx> { tcx: TyCtxt<'tcx>, + // FIXME(@lcnr): Why does this use an `infcx`, there should be + // no shared type inference going on here. I feel like it would + // clearer to manually construct one where necessary or to provide + // a nice API for non-type inference trait system checks. infcx: InferCtxt<'tcx>, region_scope_tree: &'tcx region::ScopeTree, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index da6b52ce0b8..4a64a1f0f3e 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -11,7 +11,7 @@ use rustc_middle::span_bug; use rustc_middle::thir::visit::Visitor; use rustc_middle::thir::*; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::lint::Level; use rustc_session::lint::builtin::{DEPRECATED_SAFE_2024, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_span::def_id::{DefId, LocalDefId}; @@ -37,7 +37,7 @@ struct UnsafetyVisitor<'a, 'tcx> { /// of the LHS and the span of the assignment expression. assignment_info: Option>, in_union_destructure: bool, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, inside_adt: bool, warnings: &'a mut Vec, @@ -213,7 +213,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { body_target_features: self.body_target_features, assignment_info: self.assignment_info, in_union_destructure: false, - param_env: self.param_env, + typing_env: self.typing_env, inside_adt: false, warnings: self.warnings, suggest_unsafe_block: self.suggest_unsafe_block, @@ -370,7 +370,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { }; match rm { Mutability::Not => { - if !ty.is_freeze(self.tcx, self.param_env) { + if !ty.is_freeze(self.tcx, self.typing_env) { self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField); } } @@ -566,9 +566,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { && adt_def.is_union() { if let Some(assigned_ty) = self.assignment_info { - if assigned_ty - .needs_drop(self.tcx, ty::TypingEnv::from_param_env(self.param_env)) - { + if assigned_ty.needs_drop(self.tcx, self.typing_env) { // This would be unsafe, but should be outright impossible since we // reject such unions. assert!( @@ -608,7 +606,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { if visitor.found { match borrow_kind { BorrowKind::Fake(_) | BorrowKind::Shared - if !self.thir[arg].ty.is_freeze(self.tcx, self.param_env) => + if !self.thir[arg].ty.is_freeze(self.tcx, self.typing_env) => { self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField) } @@ -1026,7 +1024,8 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { body_target_features, assignment_info: None, in_union_destructure: false, - param_env: tcx.param_env(def), + // FIXME(#132279): we're clearly in a body here. + typing_env: ty::TypingEnv::non_body_analysis(tcx, def), inside_adt: false, warnings: &mut warnings, suggest_unsafe_block: true, diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index a1b75c22c4d..5cf33868ade 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -132,21 +132,16 @@ impl<'tcx> TerminatorClassifier<'tcx> for CallRecursion<'tcx> { return false; } let caller = body.source.def_id(); - let param_env = tcx.param_env(caller); + let typing_env = body.typing_env(tcx); let func_ty = func.ty(body, tcx); if let ty::FnDef(callee, args) = *func_ty.kind() { - let Ok(normalized_args) = - tcx.try_normalize_erasing_regions(ty::TypingEnv::from_param_env(param_env), args) - else { + let Ok(normalized_args) = tcx.try_normalize_erasing_regions(typing_env, args) else { return false; }; - let (callee, call_args) = if let Ok(Some(instance)) = Instance::try_resolve( - tcx, - ty::TypingEnv::from_param_env(param_env), - callee, - normalized_args, - ) { + let (callee, call_args) = if let Ok(Some(instance)) = + Instance::try_resolve(tcx, typing_env, callee, normalized_args) + { (instance.def_id(), instance.args) } else { (callee, normalized_args) diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index dfc180f5261..d47f7154c4b 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -123,7 +123,7 @@ impl<'tcx> Cx<'tcx> { #[instrument(level = "debug", skip(self))] fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Box> { - pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p) + pat_from_hir(self.tcx, self.typing_env(), self.typeck_results(), p) } fn closure_env_param(&self, owner_def: LocalDefId, expr_id: HirId) -> Option> { diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 73fcbeaef82..033501c66db 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -7,6 +7,7 @@ use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, struct_span_code_e use rustc_hir::def::*; use rustc_hir::def_id::LocalDefId; use rustc_hir::{self as hir, BindingMode, ByRef, HirId}; +use rustc_infer::traits::Reveal; use rustc_middle::bug; use rustc_middle::middle::limits::get_limit_size; use rustc_middle::thir::visit::Visitor; @@ -191,6 +192,15 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> { } impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + // FIXME(#132279): We're in a body, should handle opaques. + debug_assert_eq!(self.param_env.reveal(), Reveal::UserFacing); + ty::TypingEnv { + typing_mode: ty::TypingMode::non_body_analysis(), + param_env: self.param_env, + } + } + #[instrument(level = "trace", skip(self, f))] fn with_let_source(&mut self, let_source: LetSource, f: impl FnOnce(&mut Self)) { let old_let_source = self.let_source; @@ -760,7 +770,7 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat: return; }; - let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.param_env); + let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()); let sess = cx.tcx.sess; 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 6b462198db6..a40134e44e7 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 @@ -2,11 +2,11 @@ use rustc_abi::{FieldIdx, VariantIdx}; use rustc_apfloat::Float; use rustc_hir as hir; use rustc_index::Idx; -use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::Obligation; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::thir::{FieldPat, Pat, PatKind}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode, ValTree}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, ValTree}; use rustc_middle::{mir, span_bug}; use rustc_span::Span; use rustc_trait_selection::traits::ObligationCause; @@ -35,10 +35,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { id: hir::HirId, span: Span, ) -> Box> { - // FIXME(#132279): We likely want to be able to reveal the hidden types - // of opaques defined in this function here. - let infcx = self.tcx.infer_ctxt().build(TypingMode::non_body_analysis()); - let mut convert = ConstToPat::new(self, id, span, infcx); + let mut convert = ConstToPat::new(self, id, span); match c.kind() { ty::ConstKind::Unevaluated(uv) => convert.unevaluated_to_pat(uv, ty), @@ -49,27 +46,20 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } struct ConstToPat<'tcx> { + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, span: Span, - // inference context used for checking `T: Structural` bounds. - infcx: InferCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - treat_byte_string_as_slice: bool, } impl<'tcx> ConstToPat<'tcx> { - fn new( - pat_ctxt: &PatCtxt<'_, 'tcx>, - id: hir::HirId, - span: Span, - infcx: InferCtxt<'tcx>, - ) -> Self { + fn new(pat_ctxt: &PatCtxt<'_, 'tcx>, id: hir::HirId, span: Span) -> Self { trace!(?pat_ctxt.typeck_results.hir_owner); ConstToPat { + tcx: pat_ctxt.tcx, + typing_env: pat_ctxt.typing_env, span, - infcx, - param_env: pat_ctxt.param_env, treat_byte_string_as_slice: pat_ctxt .typeck_results .treat_byte_string_as_slice @@ -77,16 +67,8 @@ impl<'tcx> ConstToPat<'tcx> { } } - fn tcx(&self) -> TyCtxt<'tcx> { - self.infcx.tcx - } - - fn typing_env(&self) -> ty::TypingEnv<'tcx> { - self.infcx.typing_env(self.param_env) - } - fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool { - ty.is_structural_eq_shallow(self.infcx.tcx) + ty.is_structural_eq_shallow(self.tcx) } fn unevaluated_to_pat( @@ -105,22 +87,21 @@ impl<'tcx> ConstToPat<'tcx> { // FIXME: `const_eval_resolve_for_typeck` should probably just set the env to `Reveal::All` // instead of having this logic here let typing_env = - self.tcx().erase_regions(self.typing_env()).with_reveal_all_normalized(self.tcx()); - let uv = self.tcx().erase_regions(uv); + self.tcx.erase_regions(self.typing_env).with_reveal_all_normalized(self.tcx); + let uv = self.tcx.erase_regions(uv); // try to resolve e.g. associated constants to their definition on an impl, and then // evaluate the const. - let valtree = match self.infcx.tcx.const_eval_resolve_for_typeck(typing_env, uv, self.span) - { + let valtree = match self.tcx.const_eval_resolve_for_typeck(typing_env, uv, self.span) { Ok(Ok(c)) => c, Err(ErrorHandled::Reported(_, _)) => { // Let's tell the use where this failing const occurs. - let e = self.tcx().dcx().emit_err(CouldNotEvalConstPattern { span: self.span }); + let e = self.tcx.dcx().emit_err(CouldNotEvalConstPattern { span: self.span }); return pat_from_kind(PatKind::Error(e)); } Err(ErrorHandled::TooGeneric(_)) => { let e = self - .tcx() + .tcx .dcx() .emit_err(ConstPatternDependsOnGenericParameter { span: self.span }); return pat_from_kind(PatKind::Error(e)); @@ -130,13 +111,13 @@ impl<'tcx> ConstToPat<'tcx> { let e = match bad_ty.kind() { ty::Adt(def, ..) => { assert!(def.is_union()); - self.tcx().dcx().emit_err(UnionPattern { span: self.span }) + self.tcx.dcx().emit_err(UnionPattern { span: self.span }) } ty::FnPtr(..) | ty::RawPtr(..) => { - self.tcx().dcx().emit_err(PointerPattern { span: self.span }) + self.tcx.dcx().emit_err(PointerPattern { span: self.span }) } _ => self - .tcx() + .tcx .dcx() .emit_err(InvalidPattern { span: self.span, non_sm_ty: bad_ty }), }; @@ -151,7 +132,7 @@ impl<'tcx> ConstToPat<'tcx> { // Always check for `PartialEq` if we had no other errors yet. if !self.type_has_partial_eq_impl(ty) { let err = TypeNotPartialEq { span: self.span, non_peq_ty: ty }; - let e = self.tcx().dcx().emit_err(err); + let e = self.tcx.dcx().emit_err(err); return pat_from_kind(PatKind::Error(e)); } } @@ -161,18 +142,19 @@ impl<'tcx> ConstToPat<'tcx> { #[instrument(level = "trace", skip(self), ret)] fn type_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool { - let tcx = self.tcx(); + let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env); // double-check there even *is* a semantic `PartialEq` to dispatch to. // // (If there isn't, then we can safely issue a hard // error, because that's never worked, due to compiler // using `PartialEq::eq` in this scenario in the past.) - let partial_eq_trait_id = tcx.require_lang_item(hir::LangItem::PartialEq, Some(self.span)); + let partial_eq_trait_id = + self.tcx.require_lang_item(hir::LangItem::PartialEq, Some(self.span)); let partial_eq_obligation = Obligation::new( - tcx, + self.tcx, ObligationCause::dummy(), - self.param_env, - ty::TraitRef::new(tcx, partial_eq_trait_id, [ty, ty]), + param_env, + ty::TraitRef::new(self.tcx, partial_eq_trait_id, [ty, ty]), ); // This *could* accept a type that isn't actually `PartialEq`, because region bounds get @@ -181,7 +163,7 @@ impl<'tcx> ConstToPat<'tcx> { // `PartialEq` for some lifetime but *not* for `'static`? If this ever becomes a problem // we'll need to leave some sort of trace of this requirement in the MIR so that borrowck // can ensure that the type really implements `PartialEq`. - self.infcx.predicate_must_hold_modulo_regions(&partial_eq_obligation) + infcx.predicate_must_hold_modulo_regions(&partial_eq_obligation) } fn field_pats( @@ -192,7 +174,7 @@ impl<'tcx> ConstToPat<'tcx> { .map(|(idx, (val, ty))| { let field = FieldIdx::new(idx); // Patterns can only use monomorphic types. - let ty = self.tcx().normalize_erasing_regions(self.typing_env(), ty); + let ty = self.tcx.normalize_erasing_regions(self.typing_env, ty); FieldPat { field, pattern: self.valtree_to_pat(val, ty) } }) .collect() @@ -202,14 +184,12 @@ impl<'tcx> ConstToPat<'tcx> { #[instrument(skip(self), level = "debug")] fn valtree_to_pat(&self, cv: ValTree<'tcx>, ty: Ty<'tcx>) -> Box> { let span = self.span; - let tcx = self.tcx(); - let param_env = self.param_env; - + let tcx = self.tcx; let kind = match ty.kind() { ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => { // Extremely important check for all ADTs! Make sure they opted-in to be used in // patterns. - debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty,); + debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty); let err = TypeNotStructural { span, non_sm_ty: ty }; let e = tcx.dcx().emit_err(err); // We errored. Signal that in the pattern, so that follow up errors can be silenced. @@ -227,7 +207,7 @@ impl<'tcx> ConstToPat<'tcx> { adt_def.variants()[variant_index] .fields .iter() - .map(|field| field.ty(self.tcx(), args)), + .map(|field| field.ty(self.tcx, args)), ), ), } @@ -235,14 +215,9 @@ impl<'tcx> ConstToPat<'tcx> { ty::Adt(def, args) => { assert!(!def.is_union()); // Valtree construction would never succeed for unions. PatKind::Leaf { - subpatterns: self.field_pats( - cv.unwrap_branch().iter().copied().zip( - def.non_enum_variant() - .fields - .iter() - .map(|field| field.ty(self.tcx(), args)), - ), - ), + subpatterns: self.field_pats(cv.unwrap_branch().iter().copied().zip( + def.non_enum_variant().fields.iter().map(|field| field.ty(self.tcx, args)), + )), } } ty::Tuple(fields) => PatKind::Leaf { @@ -276,7 +251,7 @@ impl<'tcx> ConstToPat<'tcx> { // convert the dereferenced constant to a pattern that is the sub-pattern of the // deref pattern. _ => { - if !pointee_ty.is_sized(tcx, param_env) && !pointee_ty.is_slice() { + if !pointee_ty.is_sized(tcx, self.typing_env) && !pointee_ty.is_slice() { let err = UnsizedPattern { span, non_sm_ty: *pointee_ty }; let e = tcx.dcx().emit_err(err); // We errored. Signal that in the pattern, so that follow up errors can be silenced. diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index d17bc8566cc..6b9e3b85999 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -30,7 +30,7 @@ use crate::thir::util::UserAnnotatedTyHelpers; struct PatCtxt<'a, 'tcx> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>, /// Used by the Rust 2024 migration lint. @@ -39,13 +39,13 @@ struct PatCtxt<'a, 'tcx> { pub(super) fn pat_from_hir<'a, 'tcx>( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>, pat: &'tcx hir::Pat<'tcx>, ) -> Box> { let mut pcx = PatCtxt { tcx, - param_env, + typing_env, typeck_results, rust_2024_migration_suggestion: typeck_results .rust_2024_migration_desugared_pats() @@ -242,7 +242,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let lo = lo.unwrap_or(PatRangeBoundary::NegInfinity); let hi = hi.unwrap_or(PatRangeBoundary::PosInfinity); - let cmp = lo.compare_with(hi, ty, self.tcx, ty::TypingEnv::from_param_env(self.param_env)); + let cmp = lo.compare_with(hi, ty, self.tcx, self.typing_env); let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty })); match (end, cmp) { // `x..y` where `x < y`. diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index a9600f77c0b..1b7c89fd251 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -3,7 +3,7 @@ use rustc_index::IndexVec; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::Session; use tracing::{debug, trace}; @@ -25,9 +25,9 @@ impl<'tcx> crate::MirPass<'tcx> for CheckAlignment { return; } + let typing_env = body.typing_env(tcx); let basic_blocks = body.basic_blocks.as_mut(); let local_decls = &mut body.local_decls; - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); // This pass inserts new blocks. Each insertion changes the Location for all // statements/blocks after. Iterating or visiting the MIR in order would require updating @@ -41,7 +41,7 @@ impl<'tcx> crate::MirPass<'tcx> for CheckAlignment { let source_info = statement.source_info; let mut finder = - PointerFinder { tcx, local_decls, param_env, pointers: Vec::new() }; + PointerFinder { tcx, local_decls, typing_env, pointers: Vec::new() }; finder.visit_statement(statement, location); for (local, ty) in finder.pointers { @@ -65,7 +65,7 @@ impl<'tcx> crate::MirPass<'tcx> for CheckAlignment { struct PointerFinder<'a, 'tcx> { tcx: TyCtxt<'tcx>, local_decls: &'a mut LocalDecls<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, pointers: Vec<(Place<'tcx>, Ty<'tcx>)>, } @@ -107,7 +107,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PointerFinder<'a, 'tcx> { let pointee_ty = pointer_ty.builtin_deref(true).expect("no builtin_deref for an unsafe pointer"); // Ideally we'd support this in the future, but for now we are limited to sized types. - if !pointee_ty.is_sized(self.tcx, self.param_env) { + if !pointee_ty.is_sized(self.tcx, self.typing_env) { debug!("Unsafe pointer, but pointee is not known to be sized: {:?}", pointer_ty); return; } diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index 7d6ae9843b1..9b3443d3209 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -28,8 +28,8 @@ impl<'tcx> crate::MirPass<'tcx> for CopyProp { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!(def_id = ?body.source.def_id()); - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - let ssa = SsaLocals::new(tcx, body, param_env); + let typing_env = body.typing_env(tcx); + let ssa = SsaLocals::new(tcx, body, typing_env); let fully_moved = fully_moved_locals(&ssa, body); debug!(?fully_moved); 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/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index db72ec522a2..67b215c7c9d 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -208,7 +208,7 @@ pub(super) fn deduced_param_attrs<'tcx>( // blow-up in compile times: #113372 && tcx .normalize_erasing_regions(typing_env, local_decl.ty) - .is_freeze(tcx, typing_env.param_env), + .is_freeze(tcx, typing_env), }, ), ); diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 27fe0ad72e7..b3d9af37204 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -120,12 +120,12 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!(def_id = ?body.source.def_id()); - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - let ssa = SsaLocals::new(tcx, body, param_env); + let typing_env = body.typing_env(tcx); + let ssa = SsaLocals::new(tcx, body, typing_env); // Clone dominators because we need them while mutating the body. let dominators = body.basic_blocks.dominators().clone(); - let mut state = VnState::new(tcx, body, 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| { @@ -241,7 +241,6 @@ enum Value<'tcx> { struct VnState<'body, 'tcx> { tcx: TyCtxt<'tcx>, ecx: InterpCx<'tcx, DummyMachine>, - param_env: ty::ParamEnv<'tcx>, local_decls: &'body LocalDecls<'tcx>, /// Value stored in each local. locals: IndexVec>, @@ -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,8 +279,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { + 4 * body.basic_blocks.len(); VnState { tcx, - ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine), - param_env, + 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), @@ -296,7 +294,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } fn typing_env(&self) -> ty::TypingEnv<'tcx> { - ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env } + self.ecx.typing_env } #[instrument(level = "trace", skip(self), ret)] @@ -347,7 +345,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // Only register the value if its type is `Sized`, as we will emit copies of it. let is_sized = !self.feature_unsized_locals - || self.local_decls[local].ty.is_sized(self.tcx, self.param_env); + || self.local_decls[local].ty.is_sized(self.tcx, self.typing_env()); if is_sized { self.rev_locals[value].push(local); } @@ -642,7 +640,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let ty = place.ty(self.local_decls, self.tcx).ty; if let Some(Mutability::Not) = ty.ref_mutability() && let Some(pointee_ty) = ty.builtin_deref(true) - && pointee_ty.is_freeze(self.tcx, self.param_env) + && pointee_ty.is_freeze(self.tcx, self.typing_env()) { // An immutable borrow `_x` always points to the same value for the // lifetime of the borrow, so we can merge all instances of `*_x`. @@ -1061,7 +1059,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { && let ty::RawPtr(from_pointee_ty, from_mtbl) = cast_from.kind() && let ty::RawPtr(_, output_mtbl) = output_pointer_ty.kind() && from_mtbl == output_mtbl - && from_pointee_ty.is_sized(self.tcx, self.param_env) + && from_pointee_ty.is_sized(self.tcx, self.typing_env()) { fields[0] = *cast_value; *data_pointer_ty = *cast_from; @@ -1383,7 +1381,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { && let Value::Aggregate(AggregateTy::RawPtr { data_pointer_ty, .. }, _, fields) = self.get(value) && let ty::RawPtr(to_pointee, _) = to.kind() - && to_pointee.is_sized(self.tcx, self.param_env) + && to_pointee.is_sized(self.tcx, self.typing_env()) { from = *data_pointer_ty; value = fields[0]; diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index fcb51fbddd9..00f6c3845d4 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -199,10 +199,7 @@ impl<'tcx> Inliner<'tcx> { let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() }; let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty; for arg in args { - if !arg - .node - .ty(&caller_body.local_decls, self.tcx) - .is_sized(self.tcx, self.typing_env.param_env) + if !arg.node.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.typing_env) { // We do not allow inlining functions with unsized params. Inlining these functions // could create unsized locals, which are unsound and being phased out. diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index b80abcca969..3352d583f2c 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -6,7 +6,7 @@ use rustc_hir::LangItem; use rustc_middle::bug; use rustc_middle::mir::*; use rustc_middle::ty::layout::ValidityRequirement; -use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, layout}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, layout}; use rustc_span::sym; use rustc_span::symbol::Symbol; @@ -34,7 +34,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { let ctx = InstSimplifyContext { tcx, local_decls: &body.local_decls, - param_env: tcx.param_env_reveal_all_normalized(body.source.def_id()), + typing_env: body.typing_env(tcx), }; let preserve_ub_checks = attr::contains_name(tcx.hir().krate_attrs(), sym::rustc_preserve_ub_checks); @@ -66,13 +66,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { struct InstSimplifyContext<'a, 'tcx> { tcx: TyCtxt<'tcx>, local_decls: &'a LocalDecls<'tcx>, - param_env: ParamEnv<'tcx>, -} - -impl<'tcx> InstSimplifyContext<'_, 'tcx> { - fn typing_env(&self) -> ty::TypingEnv<'tcx> { - ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env } - } + typing_env: ty::TypingEnv<'tcx>, } impl<'tcx> InstSimplifyContext<'_, 'tcx> { @@ -354,7 +348,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { } let known_is_valid = - intrinsic_assert_panics(self.tcx, self.typing_env(), args[0], intrinsic_name); + intrinsic_assert_panics(self.tcx, self.typing_env, args[0], intrinsic_name); match known_is_valid { // We don't know the layout or it's not validity assertion at all, don't touch it None => {} 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 3911b0a2db6..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, @@ -451,7 +451,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { if rvalue.has_param() { return None; } - if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.typing_env.param_env) { + if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.typing_env) { // the interpreter doesn't support unsized locals (only unsized arguments), // but rustc does (in a kinda broken way), so we have to skip them here return None; diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index b11b503e8d4..af438ac2177 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -85,8 +85,8 @@ impl<'tcx> crate::MirPass<'tcx> for ReferencePropagation { } fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { - let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); - let ssa = SsaLocals::new(tcx, body, param_env); + let typing_env = body.typing_env(tcx); + let ssa = SsaLocals::new(tcx, body, typing_env); let mut replacer = compute_replacement(tcx, body, &ssa); debug!(?replacer.targets); diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index 84df666e34a..5653aef0aae 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -13,7 +13,7 @@ use rustc_middle::bug; use rustc_middle::middle::resolve_bound_vars::Set1; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; -use rustc_middle::ty::{ParamEnv, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt}; use tracing::{debug, instrument, trace}; pub(super) struct SsaLocals { @@ -42,7 +42,7 @@ impl SsaLocals { pub(super) fn new<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> SsaLocals { let assignment_order = Vec::with_capacity(body.local_decls.len()); @@ -80,7 +80,7 @@ impl SsaLocals { // have already been marked as non-SSA. debug!(?visitor.borrowed_locals); for local in visitor.borrowed_locals.iter() { - if !body.local_decls[local].ty.is_freeze(tcx, param_env) { + if !body.local_decls[local].ty.is_freeze(tcx, typing_env) { visitor.assignments[local] = Set1::Many; } } diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index ae0e6f594ee..724238ecfc9 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -623,7 +623,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if let Operand::Copy(place) = operand { let ty = place.ty(&self.body.local_decls, self.tcx).ty; - if !ty.is_copy_modulo_regions(self.tcx, self.typing_env.param_env) { + if !ty.is_copy_modulo_regions(self.tcx, self.typing_env) { self.fail(location, format!("`Operand::Copy` with non-`Copy` type {ty}")); } } @@ -989,7 +989,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } // FIXME: check `Thin` instead of `Sized` - if !in_pointee.is_sized(self.tcx, self.typing_env.param_env) { + if !in_pointee.is_sized(self.tcx, self.typing_env) { self.fail(location, "input pointer must be thin"); } } else { @@ -1004,7 +1004,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if !self.mir_assign_valid_types(metadata_ty, self.tcx.types.usize) { self.fail(location, "slice metadata must be usize"); } - } else if pointee_ty.is_sized(self.tcx, self.typing_env.param_env) { + } else if pointee_ty.is_sized(self.tcx, self.typing_env) { if metadata_ty != self.tcx.types.unit { self.fail(location, "metadata for pointer-to-thin must be unit"); } @@ -1294,7 +1294,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if !self .tcx .normalize_erasing_regions(self.typing_env, op_ty) - .is_sized(self.tcx, self.typing_env.param_env) + .is_sized(self.tcx, self.typing_env) { self.fail( location, @@ -1304,7 +1304,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { if !self .tcx .normalize_erasing_regions(self.typing_env, *target_type) - .is_sized(self.tcx, self.typing_env.param_env) + .is_sized(self.tcx, self.typing_env) { self.fail( location, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 1b94c627f81..8ee9ac3df72 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1036,7 +1036,7 @@ fn find_vtable_types_for_unsizing<'tcx>( let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| { let typing_env = ty::TypingEnv::fully_monomorphized(); let type_has_metadata = |ty: Ty<'tcx>| -> bool { - if ty.is_sized(tcx.tcx, typing_env.param_env) { + if ty.is_sized(tcx.tcx, typing_env) { return false; } let tail = tcx.struct_tail_for_codegen(ty, typing_env); diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index c6c99852952..9cd95a0b02d 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -468,7 +468,7 @@ const ACC_USE: u32 = 4; struct Liveness<'a, 'tcx> { ir: &'a mut IrMaps<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, closure_min_captures: Option<&'tcx RootVariableMinCaptureList<'tcx>>, successors: IndexVec>, rwu_table: rwu_table::RWUTable, @@ -491,7 +491,8 @@ struct Liveness<'a, 'tcx> { impl<'a, 'tcx> Liveness<'a, 'tcx> { fn new(ir: &'a mut IrMaps<'tcx>, body_owner: LocalDefId) -> Liveness<'a, 'tcx> { let typeck_results = ir.tcx.typeck(body_owner); - let param_env = ir.tcx.param_env(body_owner); + // FIXME(#132279): we're in a body here. + let typing_env = ty::TypingEnv::non_body_analysis(ir.tcx, body_owner); let closure_min_captures = typeck_results.closure_min_captures.get(&body_owner); let closure_ln = ir.add_live_node(ClosureNode); let exit_ln = ir.add_live_node(ExitNode); @@ -502,7 +503,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { Liveness { ir, typeck_results, - param_env, + typing_env, closure_min_captures, successors: IndexVec::from_elem_n(None, num_live_nodes), rwu_table: rwu_table::RWUTable::new(num_live_nodes, num_vars), @@ -1297,7 +1298,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn check_is_ty_uninhabited(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNode { let ty = self.typeck_results.expr_ty(expr); let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id(); - if ty.is_inhabited_from(self.ir.tcx, m, ty::TypingEnv::from_param_env(self.param_env)) { + if ty.is_inhabited_from(self.ir.tcx, m, self.typing_env) { return succ; } match self.ir.lnks[succ] { 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/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 94f51b87cff..dcbc5f0f76d 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -233,11 +233,11 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { let key = self.tcx.def_key(impl_def_id); let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id }; - let mut param_env = self.tcx.param_env_reveal_all_normalized(impl_def_id); + let mut typing_env = ty::TypingEnv::post_analysis(self.tcx, impl_def_id); if !args.is_empty() { - param_env = EarlyBinder::bind(param_env).instantiate(self.tcx, args); + typing_env.param_env = + EarlyBinder::bind(typing_env.param_env).instantiate(self.tcx, args); } - let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env }; match &mut impl_trait_ref { Some(impl_trait_ref) => { diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 8f1c8a29663..43244eb5dcb 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -32,8 +32,10 @@ impl<'tcx> InferCtxt<'tcx> { fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { let ty = self.resolve_vars_if_possible(ty); + // FIXME(#132279): This should be removed as it causes us to incorrectly + // handle opaques in their defining scope. if !(param_env, ty).has_infer() { - return ty.is_copy_modulo_regions(self.tcx, param_env); + return ty.is_copy_modulo_regions(self.tcx, self.typing_env(param_env)); } let copy_def_id = self.tcx.require_lang_item(LangItem::Copy, None); diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 103f7c76a86..fac0414d714 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -9,7 +9,6 @@ use rustc_data_structures::unord::UnordSet; use rustc_infer::infer::DefineOpaqueTypes; use rustc_middle::ty::{Region, RegionVid}; use tracing::debug; -use ty::TypingMode; use super::*; use crate::errors::UnableToConstructConstantValue; @@ -71,7 +70,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { pub fn find_auto_trait_generics( &self, ty: Ty<'tcx>, - orig_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, trait_did: DefId, mut auto_trait_callback: impl FnMut(AutoTraitInfo<'tcx>) -> A, ) -> AutoTraitResult { @@ -79,7 +78,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { let trait_ref = ty::TraitRef::new(tcx, trait_did, [ty]); - let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); + let (infcx, orig_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); let mut selcx = SelectionContext::new(&infcx); for polarity in [ty::PredicatePolarity::Positive, ty::PredicatePolarity::Negative] { let result = selcx.select(&Obligation::new( @@ -89,17 +88,13 @@ impl<'tcx> AutoTraitFinder<'tcx> { ty::TraitPredicate { trait_ref, polarity }, )); if let Ok(Some(ImplSource::UserDefined(_))) = result { - debug!( - "find_auto_trait_generics({:?}): \ - manual impl found, bailing out", - trait_ref - ); + debug!("find_auto_trait_generics({trait_ref:?}): manual impl found, bailing out"); // If an explicit impl exists, it always takes priority over an auto impl return AutoTraitResult::ExplicitImpl; } } - let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); + let (infcx, orig_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); let mut fresh_preds = FxIndexSet::default(); // Due to the way projections are handled by SelectionContext, we need to run diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index c0603c06d42..80cef690028 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -698,8 +698,8 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>( /// used during analysis. pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec>) -> bool { debug!("impossible_predicates(predicates={:?})", predicates); - let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis); - let param_env = ty::ParamEnv::reveal_all(); + let (infcx, param_env) = + tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv::fully_monomorphized()); let ocx = ObligationCtxt::new(&infcx); let predicates = ocx.normalize(&ObligationCause::dummy(), param_env, predicates); for predicate in predicates { diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 8352d31d13a..b5bc8364c7b 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -9,8 +9,7 @@ use rustc_infer::traits::util::PredicateSet; use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::{ - self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, TypingMode, Upcast, - VtblEntry, + self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, Upcast, VtblEntry, }; use rustc_span::{DUMMY_SP, Span, sym}; use smallvec::{SmallVec, smallvec}; @@ -442,8 +441,8 @@ fn trait_refs_are_compatible<'tcx>( return false; } - let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis); - let param_env = ty::ParamEnv::reveal_all(); + let (infcx, param_env) = + tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv::fully_monomorphized()); let ocx = ObligationCtxt::new(&infcx); let hr_source_principal = ocx.normalize(&ObligationCause::dummy(), param_env, hr_vtable_principal); diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index e2283383196..a5a9125c8b5 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -397,7 +397,7 @@ fn adjust_for_rust_scalar<'tcx>( Some(kind) } else if let Some(pointee) = drop_target_pointee { // The argument to `drop_in_place` is semantically equivalent to a mutable reference. - Some(PointerKind::MutableRef { unpin: pointee.is_unpin(tcx, cx.typing_env.param_env) }) + Some(PointerKind::MutableRef { unpin: pointee.is_unpin(tcx, cx.typing_env) }) } else { None }; diff --git a/compiler/rustc_ty_utils/src/common_traits.rs b/compiler/rustc_ty_utils/src/common_traits.rs index c26b41d8960..2157ab3c402 100644 --- a/compiler/rustc_ty_utils/src/common_traits.rs +++ b/compiler/rustc_ty_utils/src/common_traits.rs @@ -3,34 +3,33 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_trait_selection::traits; -fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { +fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { is_item_raw(tcx, query, LangItem::Copy) } -fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { +fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { is_item_raw(tcx, query, LangItem::Sized) } -fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { +fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { is_item_raw(tcx, query, LangItem::Freeze) } -fn is_unpin_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { +fn is_unpin_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { is_item_raw(tcx, query, LangItem::Unpin) } fn is_item_raw<'tcx>( tcx: TyCtxt<'tcx>, - query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, + query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>, item: LangItem, ) -> bool { - let (param_env, ty) = query.into_parts(); + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(query.typing_env); let trait_def_id = tcx.require_lang_item(item, None); - let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); - traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id) + traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, query.value, trait_def_id) } pub(crate) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 84fc03a8f13..29fc92e1f2f 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -13,7 +13,7 @@ use rustc_span::sym; use rustc_trait_selection::traits; use rustc_type_ir::ClosureKind; use tracing::debug; -use traits::{Reveal, translate_args}; +use traits::translate_args; use crate::errors::UnexpectedFnPtrAssociatedItem; @@ -133,18 +133,6 @@ fn resolve_associated_item<'tcx>( bug!("{:?} not found in {:?}", trait_item_id, impl_data.impl_def_id); }); - let typing_env = typing_env.with_reveal_all_normalized(tcx); - let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); - let args = rcvr_args.rebase_onto(tcx, trait_def_id, impl_data.args); - let args = translate_args( - &infcx, - param_env, - impl_data.impl_def_id, - args, - leaf_def.defining_node, - ); - let args = infcx.tcx.erase_regions(args); - // Since this is a trait item, we need to see if the item is either a trait default item // or a specialization because we can't resolve those unless we can `Reveal::All`. // NOTE: This should be kept in sync with the similar code in @@ -157,16 +145,28 @@ fn resolve_associated_item<'tcx>( // and the obligation is monomorphic, otherwise passes such as // transmute checking and polymorphic MIR optimizations could // get a result which isn't correct for all monomorphizations. - if param_env.reveal() == Reveal::All { - !trait_ref.still_further_specializable() - } else { - false + match typing_env.typing_mode { + ty::TypingMode::Coherence + | ty::TypingMode::Analysis { defining_opaque_types: _ } => false, + ty::TypingMode::PostAnalysis => !trait_ref.still_further_specializable(), } }; if !eligible { return Ok(None); } + let typing_env = typing_env.with_reveal_all_normalized(tcx); + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); + let args = rcvr_args.rebase_onto(tcx, trait_def_id, impl_data.args); + let args = translate_args( + &infcx, + param_env, + impl_data.impl_def_id, + args, + leaf_def.defining_node, + ); + let args = infcx.tcx.erase_regions(args); + // HACK: We may have overlapping `dyn Trait` built-in impls and // user-provided blanket impls. Detect that case here, and return // ambiguity. diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 02ee3f32915..092e140a600 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -105,7 +105,7 @@ fn map_error<'tcx>( // This is sometimes not a compile error if there are trivially false where clauses. // See `tests/ui/layout/trivial-bounds-sized.rs` for an example. assert!(field.layout.is_unsized(), "invalid layout error {err:#?}"); - if !field.ty.is_sized(cx.tcx(), cx.typing_env.param_env) { + if !field.ty.is_sized(cx.tcx(), cx.typing_env) { cx.tcx().dcx().delayed_bug(format!( "encountered unexpected unsized field in layout of {ty:?}: {field:#?}" )); @@ -236,7 +236,7 @@ fn layout_of_uncached<'tcx>( } let pointee = tcx.normalize_erasing_regions(cx.typing_env, pointee); - if pointee.is_sized(tcx, cx.typing_env.param_env) { + if pointee.is_sized(tcx, cx.typing_env) { return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr))); } @@ -594,8 +594,8 @@ fn layout_of_uncached<'tcx>( let maybe_unsized = def.is_struct() && def.non_enum_variant().tail_opt().is_some_and(|last_field| { - let param_env = tcx.param_env(def.did()); - !tcx.type_of(last_field.did).instantiate_identity().is_sized(tcx, param_env) + let typing_env = ty::TypingEnv::post_analysis(tcx, def.did()); + !tcx.type_of(last_field.did).instantiate_identity().is_sized(tcx, typing_env) }); let layout = cx @@ -620,11 +620,7 @@ fn layout_of_uncached<'tcx>( // If the struct tail is sized and can be unsized, check that unsizing doesn't move the fields around. if cfg!(debug_assertions) && maybe_unsized - && def - .non_enum_variant() - .tail() - .ty(tcx, args) - .is_sized(tcx, cx.typing_env.param_env) + && def.non_enum_variant().tail().ty(tcx, args).is_sized(tcx, cx.typing_env) { let mut variants = variants; let tail_replacement = cx.layout_of(Ty::new_slice(tcx, tcx.types.u8)).unwrap(); diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index d462dbd9416..03ab3a55486 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -186,7 +186,7 @@ where } } - _ if component.is_copy_modulo_regions(tcx, self.typing_env.param_env) => (), + _ if component.is_copy_modulo_regions(tcx, self.typing_env) => (), ty::Closure(_, args) => { for upvar in args.as_closure().upvar_tys() { diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 105ae76708b..b01d3dc5269 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -4,10 +4,8 @@ use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use crate::fold::TypeFoldable; -use crate::inherent::*; use crate::relate::RelateResult; use crate::relate::combine::PredicateEmittingRelation; -use crate::solve::Reveal; use crate::{self as ty, Interner}; /// The current typing mode of an inference context. We unfortunately have some @@ -58,18 +56,6 @@ impl TypingMode { pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode { TypingMode::Analysis { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) } } - - /// FIXME(#132279): Using this function is questionable as the `param_env` - /// does not track `defining_opaque_types` and whether we're in coherence mode. - /// Many uses of this function should also use a not-yet implemented typing mode - /// which reveals already defined opaque types in the future. This function will - /// get completely removed at some point. - pub fn from_param_env(param_env: I::ParamEnv) -> TypingMode { - match param_env.reveal() { - Reveal::UserFacing => TypingMode::non_body_analysis(), - Reveal::All => TypingMode::PostAnalysis, - } - } } pub trait InferCtxtLike: Sized { diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 31e4e79c00a..3fe567b1c39 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -21,7 +21,7 @@ pub(crate) fn synthesize_auto_trait_impls<'tcx>( item_def_id: DefId, ) -> Vec { let tcx = cx.tcx; - let param_env = tcx.param_env(item_def_id); + let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id); let ty = tcx.type_of(item_def_id).instantiate_identity(); let finder = auto_trait::AutoTraitFinder::new(tcx); @@ -34,7 +34,7 @@ pub(crate) fn synthesize_auto_trait_impls<'tcx>( cx, ty, trait_def_id, - param_env, + typing_env, item_def_id, &finder, DiscardPositiveImpls::No, @@ -42,13 +42,13 @@ pub(crate) fn synthesize_auto_trait_impls<'tcx>( }) .collect(); // We are only interested in case the type *doesn't* implement the `Sized` trait. - if !ty.is_sized(tcx, param_env) + if !ty.is_sized(tcx, typing_env) && let Some(sized_trait_def_id) = tcx.lang_items().sized_trait() && let Some(impl_item) = synthesize_auto_trait_impl( cx, ty, sized_trait_def_id, - param_env, + typing_env, item_def_id, &finder, DiscardPositiveImpls::Yes, @@ -64,7 +64,7 @@ fn synthesize_auto_trait_impl<'tcx>( cx: &mut DocContext<'tcx>, ty: Ty<'tcx>, trait_def_id: DefId, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, item_def_id: DefId, finder: &auto_trait::AutoTraitFinder<'tcx>, discard_positive_impls: DiscardPositiveImpls, @@ -76,7 +76,7 @@ fn synthesize_auto_trait_impl<'tcx>( return None; } - let result = finder.find_auto_trait_generics(ty, param_env, trait_def_id, |info| { + let result = finder.find_auto_trait_generics(ty, typing_env, trait_def_id, |info| { clean_param_env(cx, item_def_id, info.full_user_env, info.region_data, info.vid_to_region) }); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e42350dc5e6..031696d445d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1818,9 +1818,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T let ct = if let hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) = const_arg.kind { - // Only anon consts can implicitly capture params. - // FIXME: is this correct behavior? - let typing_env = ty::TypingEnv::from_param_env(cx.tcx.param_env(*def_id)); + let typing_env = ty::TypingEnv::post_analysis(cx.tcx, *def_id); cx.tcx.normalize_erasing_regions(typing_env, ct) } else { ct diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs index 86c5f6b9f0b..46d67e615c7 100644 --- a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs @@ -39,7 +39,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) { (Mutability::Not, Mutability::Not) | (Mutability::Mut, Mutability::Mut)) // The `U` in `pointer::cast` have to be `Sized` // as explained here: https://github.com/rust-lang/rust/issues/60602. - && to_pointee_ty.is_sized(cx.tcx, cx.param_env) + && to_pointee_ty.is_sized(cx.tcx, cx.typing_env()) { let mut app = Applicability::MachineApplicable; let turbofish = match &cast_to_hir_ty.kind { diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index f864b7a5a8a..fce7f9985ea 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -15,6 +15,7 @@ use rustc_hir::{ self as hir, BindingMode, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, Pat, PatKind, Path, QPath, TyKind, UnOp, }; +use rustc_hir::def_id::DefId; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypeckResults}; @@ -753,11 +754,10 @@ impl TyCoercionStability { fn for_defined_ty<'tcx>(cx: &LateContext<'tcx>, ty: DefinedTy<'tcx>, for_return: bool) -> Self { match ty { DefinedTy::Hir(ty) => Self::for_hir_ty(ty), - DefinedTy::Mir(ty) => Self::for_mir_ty( + DefinedTy::Mir { def_site_def_id, ty } => Self::for_mir_ty( cx.tcx, - // FIXME(#132279): convert `DefinedTy` to use `TypingEnv` instead. - ty::TypingEnv::from_param_env(ty.param_env), - cx.tcx.instantiate_bound_regions_with_erased(ty.value), + def_site_def_id, + cx.tcx.instantiate_bound_regions_with_erased(ty), for_return, ), } @@ -824,12 +824,15 @@ impl TyCoercionStability { } } - fn for_mir_ty<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, for_return: bool) -> Self { + fn for_mir_ty<'tcx>(tcx: TyCtxt<'tcx>, def_site_def_id: Option, ty: Ty<'tcx>, for_return: bool) -> Self { let ty::Ref(_, mut ty, _) = *ty.kind() else { return Self::None; }; - ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty); + if let Some(def_id) = def_site_def_id { + let typing_env = ty::TypingEnv::non_body_analysis(tcx, def_id); + ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty); + } loop { break match *ty.kind() { ty::Ref(_, ref_ty, _) => { @@ -1028,7 +1031,7 @@ fn report<'tcx>( State::ExplicitDeref { mutability } => { if is_block_like(expr) && let ty::Ref(_, ty, _) = data.adjusted_ty.kind() - && ty.is_sized(cx.tcx, cx.param_env) + && ty.is_sized(cx.tcx, cx.typing_env()) { // Rustc bug: auto deref doesn't work on block expression when targeting sized types. return; diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index 0db6a822ec0..3b6b3c89858 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -454,13 +454,13 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r && cx.tcx.is_diagnostic_item(sym::PartialEq, def_id) && !has_non_exhaustive_attr(cx.tcx, *adt) && !ty_implements_eq_trait(cx.tcx, ty, eq_trait_def_id) - && let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id) + && let typing_env = typing_env_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id) && let Some(local_def_id) = adt.did().as_local() // If all of our fields implement `Eq`, we can implement `Eq` too && adt .all_fields() .map(|f| f.ty(cx.tcx, args)) - .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[])) + .all(|ty| implements_trait_with_env(cx.tcx, typing_env, ty, eq_trait_def_id, None, &[])) { span_lint_hir_and_then( cx, @@ -485,7 +485,7 @@ fn ty_implements_eq_trait<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, eq_trait_id: De } /// Creates the `ParamEnv` used for the give type's derived `Eq` impl. -fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> ParamEnv<'_> { +fn typing_env_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> ty::TypingEnv<'_> { // Initial map from generic index to param def. // Vec<(param_def, needs_eq)> let mut params = tcx @@ -506,7 +506,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> } } - ParamEnv::new( + let param_env = ParamEnv::new( tcx.mk_clauses_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain( params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| { ClauseKind::Trait(TraitPredicate { @@ -517,5 +517,9 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> }), )), Reveal::UserFacing, - ) + ); + ty::TypingEnv { + typing_mode: ty::TypingMode::non_body_analysis(), + param_env, + } } diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index c74ba088b78..175d92d2d79 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -198,7 +198,7 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, tys: &mut DefIdSet) // primitive types are never mutable ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false, ty::Adt(adt, args) => { - tys.insert(adt.did()) && !ty.is_freeze(cx.tcx, cx.param_env) + tys.insert(adt.did()) && !ty.is_freeze(cx.tcx, cx.typing_env()) || matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::Rc | sym::Arc)) && args.types().any(|ty| is_mutable_ty(cx, ty, tys)) }, diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs index 0e488cee6b7..5db28e9ae9b 100644 --- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs +++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs @@ -80,7 +80,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq { let has_interior_mutability = !cx .typeck_results() .node_type(canonical_id) - .is_freeze(cx.tcx, cx.param_env); + .is_freeze(cx.tcx, cx.typing_env()); if has_interior_mutability { return; } diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs index 48318682f33..d999e1a0585 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs @@ -115,11 +115,11 @@ fn is_ref_iterable<'tcx>( .tcx .liberate_late_bound_regions(fn_id, cx.tcx.fn_sig(fn_id).skip_binder()) && let &[req_self_ty, req_res_ty] = &**sig.inputs_and_output - && let param_env = cx.tcx.param_env(fn_id) - && implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, Some(fn_id), &[]) + && let typing_env = ty::TypingEnv::non_body_analysis(cx.tcx, fn_id) + && implements_trait_with_env(cx.tcx, typing_env, req_self_ty, trait_id, Some(fn_id), &[]) && let Some(into_iter_ty) = - make_normalized_projection_with_regions(cx.tcx, param_env, trait_id, sym!(IntoIter), [req_self_ty]) - && let req_res_ty = normalize_with_regions(cx.tcx, param_env, req_res_ty) + make_normalized_projection_with_regions(cx.tcx, typing_env, trait_id, sym!(IntoIter), [req_self_ty]) + && let req_res_ty = normalize_with_regions(cx.tcx, typing_env, req_res_ty) && into_iter_ty == req_res_ty { let adjustments = typeck.expr_adjustments(self_arg); diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs index 223b0630bfd..7aa13d8d5b6 100644 --- a/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/manual_inspect.rs @@ -148,7 +148,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name: _ => {}, } } - requires_copy |= !ty.is_copy_modulo_regions(cx.tcx, cx.param_env); + requires_copy |= !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()); break; } }, @@ -158,9 +158,9 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name: } if can_lint - && (!requires_copy || arg_ty.is_copy_modulo_regions(cx.tcx, cx.param_env)) + && (!requires_copy || arg_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env())) // This case could be handled, but a fair bit of care would need to be taken. - && (!requires_deref || arg_ty.is_freeze(cx.tcx, cx.param_env)) + && (!requires_deref || arg_ty.is_freeze(cx.tcx, cx.typing_env())) { if requires_deref { edits.push((param.span.shrink_to_lo(), "&".into())); diff --git a/src/tools/clippy/clippy_lints/src/mut_mut.rs b/src/tools/clippy/clippy_lints/src/mut_mut.rs index 6cddd7ea813..e2ab5e98504 100644 --- a/src/tools/clippy/clippy_lints/src/mut_mut.rs +++ b/src/tools/clippy/clippy_lints/src/mut_mut.rs @@ -80,7 +80,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for MutVisitor<'_, 'tcx> { "generally you want to avoid `&mut &mut _` if possible", ); } else if let ty::Ref(_, ty, hir::Mutability::Mut) = self.cx.typeck_results().expr_ty(e).kind() { - if ty.peel_refs().is_sized(self.cx.tcx, self.cx.param_env) { + if ty.peel_refs().is_sized(self.cx.tcx, self.cx.typing_env()) { span_lint_hir( self.cx, MUT_MUT, diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs index 43b885fbd2c..9ebef531bc5 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -85,8 +85,8 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowsForGenericArgs<'tcx> { && use_cx.same_ctxt && !use_cx.is_ty_unified && let use_node = use_cx.use_node(cx) - && let Some(DefinedTy::Mir(ty)) = use_node.defined_ty(cx) - && let ty::Param(ty) = *ty.value.skip_binder().kind() + && let Some(DefinedTy::Mir { def_site_def_id: _, ty }) = use_node.defined_ty(cx) + && let ty::Param(param_ty) = *ty.skip_binder().kind() && let Some((hir_id, fn_id, i)) = match use_node { ExprUseNode::MethodArg(_, _, 0) => None, ExprUseNode::MethodArg(hir_id, None, i) => cx @@ -112,7 +112,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowsForGenericArgs<'tcx> { fn_id, cx.typeck_results().node_args(hir_id), i, - ty, + param_ty, expr, &self.msrv, ) diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 0775d7abdbb..b65ec8c3c48 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -180,11 +180,16 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { if !is_self(arg) && !ty.is_mutable_ptr() && !is_copy(cx, ty) - && ty.is_sized(cx.tcx, cx.param_env) + && ty.is_sized(cx.tcx, cx.typing_env()) && !allowed_traits.iter().any(|&t| { - implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, t, None, [Option::< - ty::GenericArg<'tcx>, - >::None]) + implements_trait_with_env_from_iter( + cx.tcx, + cx.typing_env(), + ty, + t, + None, + [None::>] + ) }) && !implements_borrow_trait && !all_borrowable_trait 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/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index a00fd01a62e..f69cb9be4ca 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -251,7 +251,7 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex { let mut applicability = Applicability::MachineApplicable; let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability); - let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env) + let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) && !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)); let sugg = if let Some(else_inner) = r#else { if eq_expr_value(cx, caller, peel_blocks(else_inner)) { diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs index 0772b284968..bf6700b1b6b 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ptr.rs @@ -27,7 +27,7 @@ pub(super) fn check<'tcx>( |diag| { if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) { if from_mutbl == to_mutbl - && to_pointee_ty.is_sized(cx.tcx, cx.param_env) + && to_pointee_ty.is_sized(cx.tcx, cx.typing_env()) && msrv.meets(msrvs::POINTER_CAST) { diag.span_suggestion_verbose( diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs index 4dc1290e8b1..48d65eb15d9 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs @@ -206,12 +206,12 @@ fn reduce_refs<'tcx>(cx: &LateContext<'tcx>, mut from_ty: Ty<'tcx>, mut to_ty: T continue; }, (&(ty::Ref(_, unsized_ty, _) | ty::RawPtr(unsized_ty, _)), _) - if !unsized_ty.is_sized(cx.tcx, cx.param_env) => + if !unsized_ty.is_sized(cx.tcx, cx.typing_env()) => { (true, false) }, (_, &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(unsized_ty, _))) - if !unsized_ty.is_sized(cx.tcx, cx.param_env) => + if !unsized_ty.is_sized(cx.tcx, cx.typing_env()) => { (false, true) }, diff --git a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs index 1a656088b17..de3456a8ba5 100644 --- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs +++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs @@ -60,7 +60,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath: // here because `mod.rs` guarantees this lint is only run on types outside of bodies and // is not run on locals. let ty = lower_ty(cx.tcx, hir_ty); - if ty.has_escaping_bound_vars() || !ty.is_sized(cx.tcx, cx.param_env) { + if ty.has_escaping_bound_vars() || !ty.is_sized(cx.tcx, cx.typing_env()) { return false; } hir_ty.span diff --git a/src/tools/clippy/clippy_lints/src/types/vec_box.rs b/src/tools/clippy/clippy_lints/src/types/vec_box.rs index 230239335c6..9b236d3bda5 100644 --- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs @@ -37,7 +37,7 @@ pub(super) fn check<'tcx>( && let boxed_alloc_ty = last.args.get(1) && let ty_ty = lower_ty(cx.tcx, boxed_ty) && !ty_ty.has_escaping_bound_vars() - && ty_ty.is_sized(cx.tcx, cx.param_env) + && ty_ty.is_sized(cx.tcx, cx.typing_env()) && let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes()) && ty_ty_size < box_size_threshold // https://github.com/rust-lang/rust-clippy/issues/7114 diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs index 14f4aa6676b..34df1d5560a 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs @@ -82,7 +82,7 @@ impl UnnecessaryBoxReturns { // It's sometimes useful to return Box if T is unsized, so don't lint those. // Also, don't lint if we know that T is very large, in which case returning // a Box may be beneficial. - if boxed_ty.is_sized(cx.tcx, cx.param_env) && approx_ty_size(cx, boxed_ty) <= self.maximum_size { + if boxed_ty.is_sized(cx.tcx, cx.typing_env()) && approx_ty_size(cx, boxed_ty) <= self.maximum_size { span_lint_and_then( cx, UNNECESSARY_BOX_RETURNS, diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index f28e5c9ed0e..6408cc938cb 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -116,8 +116,8 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ - self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, FloatTy, GenericArgsRef, IntTy, ParamEnv, - ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt, UintTy, UpvarCapture, + self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, FloatTy, GenericArgsRef, IntTy, + Ty, TyCtxt, TypeVisitableExt, UintTy, UpvarCapture, }; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::SourceMap; @@ -2712,9 +2712,17 @@ pub fn walk_to_expr_usage<'tcx, T>( pub enum DefinedTy<'tcx> { // Used for locals and closures defined within the function. Hir(&'tcx hir::Ty<'tcx>), - /// Used for function signatures, and constant and static values. This includes the `ParamEnv` - /// from the definition site. - Mir(ParamEnvAnd<'tcx, Binder<'tcx, Ty<'tcx>>>), + /// Used for function signatures, and constant and static values. The type is + /// in the context of its definition site. We also track the `def_id` of its + /// definition site. + /// + /// WARNING: As the `ty` in in the scope of the definition, not of the function + /// using it, you must be very careful with how you use it. Using it in the wrong + /// scope easily results in ICEs. + Mir { + def_site_def_id: Option, + ty: Binder<'tcx, Ty<'tcx>>, + }, } /// The context an expressions value is used in. @@ -2833,10 +2841,10 @@ impl<'tcx> ExprUseNode<'tcx> { pub fn defined_ty(&self, cx: &LateContext<'tcx>) -> Option> { match *self { Self::LetStmt(LetStmt { ty: Some(ty), .. }) => Some(DefinedTy::Hir(ty)), - Self::ConstStatic(id) => Some(DefinedTy::Mir( - cx.param_env - .and(Binder::dummy(cx.tcx.type_of(id).instantiate_identity())), - )), + Self::ConstStatic(id) => Some(DefinedTy::Mir { + def_site_def_id: Some(id.def_id.to_def_id()), + ty: Binder::dummy(cx.tcx.type_of(id).instantiate_identity()), + }), Self::Return(id) => { if let Node::Expr(Expr { kind: ExprKind::Closure(c), @@ -2848,9 +2856,8 @@ impl<'tcx> ExprUseNode<'tcx> { FnRetTy::Return(ty) => Some(DefinedTy::Hir(ty)), } } else { - Some(DefinedTy::Mir( - cx.param_env.and(cx.tcx.fn_sig(id).instantiate_identity().output()), - )) + let ty = cx.tcx.fn_sig(id).instantiate_identity().output(); + Some(DefinedTy::Mir { def_site_def_id: Some(id.def_id.to_def_id()), ty }) } }, Self::Field(field) => match get_parent_expr_for_hir(cx, field.hir_id) { @@ -2866,12 +2873,9 @@ impl<'tcx> ExprUseNode<'tcx> { .find(|f| f.name == field.ident.name) .map(|f| (adt, f)) }) - .map(|(adt, field_def)| { - DefinedTy::Mir( - cx.tcx - .param_env(adt.did()) - .and(Binder::dummy(cx.tcx.type_of(field_def.did).instantiate_identity())), - ) + .map(|(adt, field_def)| DefinedTy::Mir { + def_site_def_id: Some(adt.did()), + ty: Binder::dummy(cx.tcx.type_of(field_def.did).instantiate_identity()), }), _ => None, }, @@ -2880,17 +2884,19 @@ impl<'tcx> ExprUseNode<'tcx> { let (hir_ty, ty) = sig.input_with_hir(i)?; Some(match hir_ty { Some(hir_ty) => DefinedTy::Hir(hir_ty), - None => DefinedTy::Mir( - sig.predicates_id() - .map_or(ParamEnv::empty(), |id| cx.tcx.param_env(id)) - .and(ty), - ), + None => DefinedTy::Mir { + def_site_def_id: sig.predicates_id(), + ty, + } }) }, Self::MethodArg(id, _, i) => { let id = cx.typeck_results().type_dependent_def_id(id)?; let sig = cx.tcx.fn_sig(id).skip_binder(); - Some(DefinedTy::Mir(cx.tcx.param_env(id).and(sig.input(i)))) + Some(DefinedTy::Mir { + def_site_def_id: Some(id), + ty: sig.input(i), + }) }, Self::LetStmt(_) | Self::FieldAccess(..) | Self::Callee | Self::Other | Self::AddrOf(..) => None, } diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 2aad867dc0d..3498606dfd3 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -19,7 +19,7 @@ use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::{ self, AdtDef, AliasTy, AssocItem, AssocKind, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind, GenericArgsRef, GenericParamDefKind, IntTy, ParamEnv, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, UintTy, Upcast, VariantDef, VariantDiscr, + TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr, }; use rustc_span::symbol::Ident; use rustc_span::{DUMMY_SP, Span, Symbol, sym}; @@ -38,7 +38,7 @@ pub use type_certainty::expr_type_is_certain; /// Checks if the given type implements copy. pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - ty.is_copy_modulo_regions(cx.tcx, cx.param_env) + ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) } /// This checks whether a given type is known to implement Debug. @@ -226,7 +226,7 @@ pub fn implements_trait<'tcx>( trait_id: DefId, args: &[GenericArg<'tcx>], ) -> bool { - implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, trait_id, None, args.iter().map(|&x| Some(x))) + implements_trait_with_env_from_iter(cx.tcx, cx.typing_env(), ty, trait_id, None, args.iter().map(|&x| Some(x))) } /// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context. @@ -235,19 +235,19 @@ pub fn implements_trait<'tcx>( /// environment, used for checking const traits. pub fn implements_trait_with_env<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, trait_id: DefId, callee_id: Option, args: &[GenericArg<'tcx>], ) -> bool { - implements_trait_with_env_from_iter(tcx, param_env, ty, trait_id, callee_id, args.iter().map(|&x| Some(x))) + implements_trait_with_env_from_iter(tcx, typing_env, ty, trait_id, callee_id, args.iter().map(|&x| Some(x))) } /// Same as `implements_trait_from_env` but takes the arguments as an iterator. pub fn implements_trait_with_env_from_iter<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, trait_id: DefId, callee_id: Option, @@ -268,7 +268,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>( return false; } - let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); let args = args .into_iter() .map(|arg| arg.into().unwrap_or_else(|| infcx.next_ty_var(DUMMY_SP).into())) @@ -1239,12 +1239,12 @@ impl<'tcx> InteriorMut<'tcx> { pub fn make_normalized_projection_with_regions<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, container_id: DefId, assoc_ty: Symbol, args: impl IntoIterator>>, ) -> Option> { - fn helper<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { + fn helper<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: AliasTy<'tcx>) -> Option> { #[cfg(debug_assertions)] if let Some((i, arg)) = ty .args @@ -1261,10 +1261,8 @@ pub fn make_normalized_projection_with_regions<'tcx>( return None; } let cause = ObligationCause::dummy(); - match tcx - .infer_ctxt() - .build(TypingMode::from_param_env(param_env)) - .at(&cause, param_env) + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); + match infcx.at(&cause, param_env) .query_normalize(Ty::new_projection_from_args(tcx, ty.def_id, ty.args)) { Ok(ty) => Some(ty.value), @@ -1274,20 +1272,13 @@ pub fn make_normalized_projection_with_regions<'tcx>( }, } } - helper(tcx, param_env, make_projection(tcx, container_id, assoc_ty, args)?) + helper(tcx, typing_env, make_projection(tcx, container_id, assoc_ty, args)?) } -pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { +pub fn normalize_with_regions<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { let cause = ObligationCause::dummy(); - match tcx - .infer_ctxt() - .build(TypingMode::from_param_env(param_env)) - .at(&cause, param_env) - .query_normalize(ty) - { - Ok(ty) => ty.value, - Err(_) => ty, - } + let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); + infcx.at(&cause, param_env).query_normalize(ty).map_or(ty, |ty| ty.value) } /// Checks if the type is `core::mem::ManuallyDrop<_>` 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 745316913d9..9627447b342 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -12,7 +12,6 @@ use std::{cmp, mem}; use rustc_abi::{BackendRepr, Size}; use rustc_data_structures::fx::FxHashSet; use rustc_middle::mir::{Mutability, RetagKind}; -use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::{self, Ty}; use self::diagnostics::{RetagCause, RetagInfo}; @@ -71,7 +70,7 @@ impl NewPermission { access: None, protector: None, } - } else if pointee.is_unpin(*cx.tcx, cx.param_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, @@ -129,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.param_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 { @@ -608,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.param_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 255a3578aae..61a2e2bc8d9 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -1,6 +1,5 @@ use rustc_abi::{BackendRepr, Size}; use rustc_middle::mir::{Mutability, RetagKind}; -use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::{self, Ty}; use rustc_span::def_id::DefId; @@ -132,8 +131,8 @@ impl<'tcx> NewPermission { kind: RetagKind, cx: &crate::MiriInterpCx<'tcx>, ) -> Option { - let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.param_env()); - let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.param_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. @@ -164,10 +163,10 @@ impl<'tcx> NewPermission { zero_size: bool, ) -> Option { let pointee = ty.builtin_deref(true).unwrap(); - pointee.is_unpin(*cx.tcx, cx.param_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.param_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 { @@ -521,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.param_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!(