diff options
Diffstat (limited to 'compiler/rustc_middle')
21 files changed, 405 insertions, 254 deletions
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index f95635370dc..a51370369b8 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -102,10 +102,11 @@ impl<'tcx> ConstValue<'tcx> { pub fn try_to_bits_for_ty( &self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, ) -> Option<u128> { - let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; + let size = + tcx.layout_of(typing_env.with_reveal_all_normalized(tcx).as_query_input(ty)).ok()?.size; self.try_to_bits(size) } @@ -314,7 +315,7 @@ impl<'tcx> Const<'tcx> { pub fn eval( self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, span: Span, ) -> Result<ConstValue<'tcx>, ErrorHandled> { match self { @@ -333,7 +334,7 @@ impl<'tcx> Const<'tcx> { } Const::Unevaluated(uneval, _) => { // FIXME: We might want to have a `try_eval`-like function on `Unevaluated` - tcx.const_eval_resolve(param_env, uneval, span) + tcx.const_eval_resolve(typing_env, uneval, span) } Const::Val(val, _) => Ok(val), } @@ -343,7 +344,7 @@ impl<'tcx> Const<'tcx> { pub fn try_eval_scalar( self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option<Scalar> { if let Const::Ty(_, c) = self && let ty::ConstKind::Value(ty, val) = c.kind() @@ -354,7 +355,7 @@ impl<'tcx> Const<'tcx> { // pointer here, which valtrees don't represent.) Some(val.unwrap_leaf().into()) } else { - self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar() + self.eval(tcx, typing_env, DUMMY_SP).ok()?.try_to_scalar() } } @@ -362,23 +363,29 @@ impl<'tcx> Const<'tcx> { pub fn try_eval_scalar_int( self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option<ScalarInt> { - self.try_eval_scalar(tcx, param_env)?.try_to_scalar_int().ok() + self.try_eval_scalar(tcx, typing_env)?.try_to_scalar_int().ok() } #[inline] - pub fn try_eval_bits(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<u128> { - let int = self.try_eval_scalar_int(tcx, param_env)?; - let size = - tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size; + pub fn try_eval_bits( + &self, + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ) -> Option<u128> { + let int = self.try_eval_scalar_int(tcx, typing_env)?; + let size = tcx + .layout_of(typing_env.with_reveal_all_normalized(tcx).as_query_input(self.ty())) + .ok()? + .size; Some(int.to_bits(size)) } /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. #[inline] - pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u128 { - self.try_eval_bits(tcx, param_env) + pub fn eval_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> u128 { + self.try_eval_bits(tcx, typing_env) .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", self.ty(), self)) } @@ -386,21 +393,21 @@ impl<'tcx> Const<'tcx> { pub fn try_eval_target_usize( self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option<u64> { - Some(self.try_eval_scalar_int(tcx, param_env)?.to_target_usize(tcx)) + Some(self.try_eval_scalar_int(tcx, typing_env)?.to_target_usize(tcx)) } #[inline] /// Panics if the value cannot be evaluated or doesn't contain a valid `usize`. - pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u64 { - self.try_eval_target_usize(tcx, param_env) + pub fn eval_target_usize(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> u64 { + self.try_eval_target_usize(tcx, typing_env) .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) } #[inline] - pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<bool> { - self.try_eval_scalar_int(tcx, param_env)?.try_into().ok() + pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option<bool> { + self.try_eval_scalar_int(tcx, typing_env)?.try_into().ok() } #[inline] @@ -411,17 +418,16 @@ impl<'tcx> Const<'tcx> { pub fn from_bits( tcx: TyCtxt<'tcx>, bits: u128, - param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, + typing_env: ty::TypingEnv<'tcx>, + ty: Ty<'tcx>, ) -> Self { let size = tcx - .layout_of(param_env_ty) - .unwrap_or_else(|e| { - bug!("could not compute layout for {:?}: {:?}", param_env_ty.value, e) - }) + .layout_of(typing_env.as_query_input(ty)) + .unwrap_or_else(|e| bug!("could not compute layout for {ty:?}: {e:?}")) .size; let cv = ConstValue::Scalar(Scalar::from_uint(bits, size)); - Self::Val(cv, param_env_ty.value) + Self::Val(cv, ty) } #[inline] @@ -438,7 +444,8 @@ impl<'tcx> Const<'tcx> { pub fn from_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self { let ty = tcx.types.usize; - Self::from_bits(tcx, n as u128, ty::ParamEnv::empty().and(ty)) + let typing_env = ty::TypingEnv::fully_monomorphized(); + Self::from_bits(tcx, n as u128, typing_env, ty) } #[inline] diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index f225ad94aa7..c4b0e6e39cc 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -351,7 +351,11 @@ impl<'tcx> GlobalAlloc<'tcx> { } } - pub fn size_and_align(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> (Size, Align) { + pub fn size_and_align( + &self, + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ) -> (Size, Align) { match self { GlobalAlloc::Static(def_id) => { let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { @@ -374,7 +378,7 @@ impl<'tcx> GlobalAlloc<'tcx> { .type_of(def_id) .no_bound_vars() .expect("statics should not have generic parameters"); - let layout = tcx.layout_of(param_env.and(ty)).unwrap(); + let layout = tcx.layout_of(typing_env.as_query_input(ty)).unwrap(); assert!(layout.is_sized()); (layout.size, layout.align.abi) } diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 2ecf1d0bcf8..7092f87a7d1 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -58,7 +58,7 @@ impl<'tcx> TyCtxt<'tcx> { #[instrument(level = "debug", skip(self))] pub fn const_eval_resolve( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ct: mir::UnevaluatedConst<'tcx>, span: Span, ) -> EvalToConstValueResult<'tcx> { @@ -72,14 +72,11 @@ impl<'tcx> TyCtxt<'tcx> { bug!("did not expect inference variables here"); } - match ty::Instance::try_resolve( - self, param_env, - // FIXME: maybe have a separate version for resolving mir::UnevaluatedConst? - ct.def, ct.args, - ) { + // FIXME: maybe have a separate version for resolving mir::UnevaluatedConst? + 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(param_env, cid, span) + self.const_eval_global_id(typing_env.param_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. @@ -91,7 +88,7 @@ impl<'tcx> TyCtxt<'tcx> { #[instrument(level = "debug", skip(self))] pub fn const_eval_resolve_for_typeck( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ct: ty::UnevaluatedConst<'tcx>, span: Span, ) -> EvalToValTreeResult<'tcx> { @@ -105,10 +102,10 @@ impl<'tcx> TyCtxt<'tcx> { bug!("did not expect inference variables here"); } - match ty::Instance::try_resolve(self, param_env, ct.def, ct.args) { + 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(param_env, cid, span).inspect(|_| { + self.const_eval_global_id_for_typeck(typing_env.param_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. diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 260c6543f98..425cb059e57 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -39,7 +39,7 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable}; use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths}; use crate::ty::visit::TypeVisitableExt; use crate::ty::{ - self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypingMode, + self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypingEnv, UserTypeAnnotationIndex, }; @@ -452,12 +452,17 @@ impl<'tcx> Body<'tcx> { self.basic_blocks.as_mut() } - pub fn typing_mode(&self, _tcx: TyCtxt<'tcx>) -> TypingMode<'tcx> { + pub fn typing_env(&self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> { match self.phase { - // FIXME(#132279): the MIR is quite clearly inside of a body, so we - // should instead reveal opaques defined by that body here. - MirPhase::Built | MirPhase::Analysis(_) => TypingMode::non_body_analysis(), - MirPhase::Runtime(_) => TypingMode::PostAnalysis, + // FIXME(#132279): we should reveal the opaques defined in the body during analysis. + MirPhase::Built | MirPhase::Analysis(_) => TypingEnv { + 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()), + }, } } @@ -618,7 +623,7 @@ impl<'tcx> Body<'tcx> { } /// If this basic block ends with a [`TerminatorKind::SwitchInt`] for which we can evaluate the - /// dimscriminant in monomorphization, we return the discriminant bits and the + /// discriminant in monomorphization, we return the discriminant bits and the /// [`SwitchTargets`], just so the caller doesn't also have to match on the terminator. fn try_const_mono_switchint<'a>( tcx: TyCtxt<'tcx>, @@ -627,13 +632,15 @@ impl<'tcx> Body<'tcx> { ) -> Option<(u128, &'a SwitchTargets)> { // There are two places here we need to evaluate a constant. let eval_mono_const = |constant: &ConstOperand<'tcx>| { - let env = ty::ParamEnv::reveal_all(); + // FIXME(#132279): what is this, why are we using an empty environment with + // `RevealAll` here. + let typing_env = ty::TypingEnv::fully_monomorphized(); let mono_literal = instance.instantiate_mir_and_normalize_erasing_regions( tcx, - env, + typing_env, crate::ty::EarlyBinder::bind(constant.const_), ); - mono_literal.try_eval_bits(tcx, env) + mono_literal.try_eval_bits(tcx, typing_env) }; let TerminatorKind::SwitchInt { discr, targets } = &block.terminator().kind else { diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 88ed90c3114..1ce735cec63 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -332,9 +332,9 @@ impl<'tcx> Operand<'tcx> { span: Span, ) -> Operand<'tcx> { debug_assert!({ - let param_env_and_ty = ty::ParamEnv::empty().and(ty); + let typing_env = ty::TypingEnv::fully_monomorphized(); let type_size = tcx - .layout_of(param_env_and_ty) + .layout_of(typing_env.as_query_input(ty)) .unwrap_or_else(|e| panic!("could not compute layout for {ty:?}: {e:?}")) .size; let scalar_size = match val { diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index f01ac305d3f..2083279e128 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -20,7 +20,7 @@ use smallvec::SmallVec; use super::{BasicBlock, Const, Local, UserTypeProjection}; use crate::mir::coverage::CoverageKind; use crate::ty::adjustment::PointerCoercion; -use crate::ty::{self, GenericArgsRef, List, Region, Ty, TyCtxt, UserTypeAnnotationIndex}; +use crate::ty::{self, GenericArgsRef, List, Region, Ty, UserTypeAnnotationIndex}; /// Represents the "flavors" of MIR. /// @@ -100,13 +100,6 @@ impl MirPhase { MirPhase::Runtime(RuntimePhase::Optimized) => "runtime-optimized", } } - - pub fn param_env<'tcx>(&self, tcx: TyCtxt<'tcx>, body_def_id: DefId) -> ty::ParamEnv<'tcx> { - match self { - MirPhase::Built | MirPhase::Analysis(_) => tcx.param_env(body_def_id), - MirPhase::Runtime(_) => tcx.param_env_reveal_all_normalized(body_def_id), - } - } } /// See [`MirPhase::Analysis`]. diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index c5def5fc65b..9cb11cdd3b7 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -467,6 +467,18 @@ impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> { } } +impl<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> { + type Cache<V> = DefaultCache<Self, V>; + + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + self.value.default_span(tcx) + } + + fn ty_def_id(&self) -> Option<DefId> { + self.value.ty_def_id() + } +} + impl Key for Symbol { type Cache<V> = DefaultCache<Self, V>; @@ -575,7 +587,7 @@ impl Key for (LocalDefId, HirId) { } } -impl<'tcx> Key for (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) { +impl<'tcx> Key for (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) { type Cache<V> = DefaultCache<Self, V>; // Just forward to `Ty<'tcx>` diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 4068d06f6df..684d5b6c2a7 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -81,8 +81,8 @@ use crate::ty::layout::ValidityRequirement; use crate::ty::print::{PrintTraitRefExt, describe_as_module}; use crate::ty::util::AlwaysRequiresDrop; use crate::ty::{ - self, CrateInherentImpls, GenericArg, GenericArgsRef, ParamEnvAnd, Ty, TyCtxt, TyCtxtFeed, - UnusedGenericParams, + self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, Ty, TyCtxt, + TyCtxtFeed, UnusedGenericParams, }; use crate::{dep_graph, mir, thir}; @@ -1341,10 +1341,10 @@ rustc_queries! { } query codegen_select_candidate( - key: (ty::ParamEnv<'tcx>, ty::TraitRef<'tcx>) + key: PseudoCanonicalInput<'tcx, ty::TraitRef<'tcx>> ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> { cache_on_disk_if { true } - desc { |tcx| "computing candidate for `{}`", key.1 } + desc { |tcx| "computing candidate for `{}`", key.value } } /// Return all `impl` blocks in the current crate. @@ -1406,15 +1406,15 @@ rustc_queries! { desc { "computing whether `{}` is `Unpin`", env.value } } /// Query backing `Ty::needs_drop`. - query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + query needs_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` needs drop", env.value } } /// Query backing `Ty::needs_async_drop`. - query needs_async_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + query needs_async_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` needs async drop", env.value } } /// Query backing `Ty::has_significant_drop_raw`. - query has_significant_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + query has_significant_drop_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { desc { "computing whether `{}` has a significant drop", env.value } } @@ -1451,7 +1451,7 @@ rustc_queries! { /// Computes the layout of a type. Note that this implicitly /// executes in "reveal all" mode, and will normalize the input type. query layout_of( - key: ty::ParamEnvAnd<'tcx, Ty<'tcx>> + key: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>> ) -> Result<ty::layout::TyAndLayout<'tcx>, &'tcx ty::layout::LayoutError<'tcx>> { depth_limit desc { "computing layout of `{}`", key.value } @@ -1464,7 +1464,7 @@ rustc_queries! { /// NB: this doesn't handle virtual calls - those should use `fn_abi_of_instance` /// instead, where the instance is an `InstanceKind::Virtual`. query fn_abi_of_fn_ptr( - key: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)> + key: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)> ) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { desc { "computing call ABI of `{}` function pointers", key.value.0 } } @@ -1475,7 +1475,7 @@ rustc_queries! { /// NB: that includes virtual calls, which are represented by "direct calls" /// to an `InstanceKind::Virtual` instance (of `<dyn Trait as Trait>::fn`). query fn_abi_of_instance( - key: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)> + key: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)> ) -> Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, &'tcx ty::layout::FnAbiError<'tcx>> { desc { "computing call ABI of `{}`", key.value.0 } } @@ -2088,7 +2088,7 @@ rustc_queries! { /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead. query try_normalize_generic_arg_after_erasing_regions( - goal: ParamEnvAnd<'tcx, GenericArg<'tcx>> + goal: PseudoCanonicalInput<'tcx, GenericArg<'tcx>> ) -> Result<GenericArg<'tcx>, NoSolution> { desc { "normalizing `{}`", goal.value } } @@ -2245,7 +2245,7 @@ rustc_queries! { /// from `Ok(None)` to avoid misleading diagnostics when an error /// has already been/will be emitted, for the original cause. query resolve_instance_raw( - key: ty::ParamEnvAnd<'tcx, (DefId, GenericArgsRef<'tcx>)> + key: ty::PseudoCanonicalInput<'tcx, (DefId, GenericArgsRef<'tcx>)> ) -> Result<Option<ty::Instance<'tcx>>, ErrorGuaranteed> { desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) } } @@ -2283,7 +2283,7 @@ rustc_queries! { desc { "computing the backend features for CLI flags" } } - query check_validity_requirement(key: (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result<bool, &'tcx ty::layout::LayoutError<'tcx>> { + query check_validity_requirement(key: (ValidityRequirement, ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>)) -> Result<bool, &'tcx ty::layout::LayoutError<'tcx>> { desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 } } diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 45ceb0a555d..8f26e05cb72 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -905,7 +905,7 @@ impl<'tcx> PatRange<'tcx> { &self, value: mir::Const<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option<bool> { use Ordering::*; debug_assert_eq!(self.ty, value.ty()); @@ -913,10 +913,10 @@ impl<'tcx> PatRange<'tcx> { let value = PatRangeBoundary::Finite(value); // For performance, it's important to only do the second comparison if necessary. Some( - match self.lo.compare_with(value, ty, tcx, param_env)? { + match self.lo.compare_with(value, ty, tcx, typing_env)? { Less | Equal => true, Greater => false, - } && match value.compare_with(self.hi, ty, tcx, param_env)? { + } && match value.compare_with(self.hi, ty, tcx, typing_env)? { Less => true, Equal => self.end == RangeEnd::Included, Greater => false, @@ -929,17 +929,17 @@ impl<'tcx> PatRange<'tcx> { &self, other: &Self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option<bool> { use Ordering::*; debug_assert_eq!(self.ty, other.ty); // For performance, it's important to only do the second comparison if necessary. Some( - match other.lo.compare_with(self.hi, self.ty, tcx, param_env)? { + match other.lo.compare_with(self.hi, self.ty, tcx, typing_env)? { Less => true, Equal => self.end == RangeEnd::Included, Greater => false, - } && match self.lo.compare_with(other.hi, self.ty, tcx, param_env)? { + } && match self.lo.compare_with(other.hi, self.ty, tcx, typing_env)? { Less => true, Equal => other.end == RangeEnd::Included, Greater => false, @@ -985,9 +985,14 @@ impl<'tcx> PatRangeBoundary<'tcx> { Self::NegInfinity | Self::PosInfinity => None, } } - pub fn eval_bits(self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> u128 { + pub fn eval_bits( + self, + ty: Ty<'tcx>, + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ) -> u128 { match self { - Self::Finite(value) => value.eval_bits(tcx, param_env), + Self::Finite(value) => value.eval_bits(tcx, typing_env), Self::NegInfinity => { // Unwrap is ok because the type is known to be numeric. ty.numeric_min_and_max_as_bits(tcx).unwrap().0 @@ -999,13 +1004,13 @@ impl<'tcx> PatRangeBoundary<'tcx> { } } - #[instrument(skip(tcx, param_env), level = "debug", ret)] + #[instrument(skip(tcx, typing_env), level = "debug", ret)] pub fn compare_with( self, other: Self, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Option<Ordering> { use PatRangeBoundary::*; match (self, other) { @@ -1034,8 +1039,8 @@ impl<'tcx> PatRangeBoundary<'tcx> { _ => {} } - let a = self.eval_bits(ty, tcx, param_env); - let b = other.eval_bits(ty, tcx, param_env); + let a = self.eval_bits(ty, tcx, typing_env); + let b = other.eval_bits(ty, tcx, typing_env); match ty.kind() { ty::Float(ty::FloatTy::F16) => { diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 0773eb7a3be..79d56702be2 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -498,12 +498,13 @@ impl<'tcx> AdtDef<'tcx> { expr_did: DefId, ) -> Result<Discr<'tcx>, ErrorGuaranteed> { assert!(self.is_enum()); - let param_env = tcx.param_env(expr_did); + let repr_type = self.repr().discr_type(); match tcx.const_eval_poly(expr_did) { Ok(val) => { + let typing_env = ty::TypingEnv::post_analysis(tcx, expr_did); let ty = repr_type.to_ty(tcx); - if let Some(b) = val.try_to_bits_for_ty(tcx, param_env, ty) { + if let Some(b) = val.try_to_bits_for_ty(tcx, typing_env, ty) { trace!("discriminants: {} ({:?})", b, repr_type); Ok(Discr { val: b, ty }) } else { diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 5689f3d4265..3bd09fc91c6 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -9,7 +9,7 @@ use tracing::{debug, instrument}; use crate::middle::resolve_bound_vars as rbv; use crate::mir::interpret::{LitToConstInput, Scalar}; -use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; +use crate::ty::{self, GenericArgs, Ty, TyCtxt, TypeVisitableExt}; mod int; mod kind; @@ -330,17 +330,22 @@ impl<'tcx> Const<'tcx> { None } - #[inline] /// Creates a constant with the given integer value and interns it. - pub fn from_bits(tcx: TyCtxt<'tcx>, bits: u128, ty: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Self { + #[inline] + pub fn from_bits( + tcx: TyCtxt<'tcx>, + bits: u128, + typing_env: ty::TypingEnv<'tcx>, + ty: Ty<'tcx>, + ) -> Self { let size = tcx - .layout_of(ty) + .layout_of(typing_env.as_query_input(ty)) .unwrap_or_else(|e| panic!("could not compute layout for {ty:?}: {e:?}")) .size; ty::Const::new_value( tcx, ty::ValTree::from_scalar_int(ScalarInt::try_from_uint(bits, size).unwrap()), - ty.value, + ty, ) } @@ -353,13 +358,13 @@ impl<'tcx> Const<'tcx> { #[inline] /// Creates an interned bool constant. pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self { - Self::from_bits(tcx, v as u128, ParamEnv::empty().and(tcx.types.bool)) + Self::from_bits(tcx, v as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.bool) } #[inline] /// Creates an interned usize constant. pub fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self { - Self::from_bits(tcx, n as u128, ParamEnv::empty().and(tcx.types.usize)) + Self::from_bits(tcx, n as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.usize) } /// Panics if self.kind != ty::ConstKind::Value @@ -393,15 +398,15 @@ impl<'tcx> Const<'tcx> { self.try_to_valtree()?.0.try_to_target_usize(tcx) } - #[inline] /// Attempts to evaluate the given constant to bits. Can fail to evaluate in the presence of /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it /// contains const generic parameters or pointers). - pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<u128> { + #[inline] + pub fn try_to_bits(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Option<u128> { let (scalar, ty) = self.try_to_scalar()?; let scalar = scalar.try_to_scalar_int().ok()?; - let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; - // if `ty` does not depend on generic parameters, use an empty param_env + let input = typing_env.with_reveal_all_normalized(tcx).as_query_input(ty); + let size = tcx.layout_of(input).ok()?.size; Some(scalar.to_bits(size)) } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 84ac281c258..2ba1bf2822f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -596,8 +596,16 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.coroutine_is_async_gen(coroutine_def_id) } - fn layout_is_pointer_like(self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { - self.layout_of(self.erase_regions(param_env.and(ty))) + // We don't use `TypingEnv` here as it's only defined in `rustc_middle` and + // `rustc_next_trait_solver` shouldn't have to know about it. + fn layout_is_pointer_like( + self, + typing_mode: ty::TypingMode<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + ) -> bool { + let typing_env = ty::TypingEnv { typing_mode, param_env }; + self.layout_of(self.erase_regions(typing_env).as_query_input(self.erase_regions(ty))) .is_ok_and(|layout| layout.layout.is_pointer_like(&self.data_layout)) } diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index bf741f63a3d..505c7278176 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -3,7 +3,7 @@ use smallvec::SmallVec; use tracing::instrument; use crate::ty::context::TyCtxt; -use crate::ty::{self, DefId, OpaqueTypeKey, ParamEnv, Ty}; +use crate::ty::{self, DefId, OpaqueTypeKey, Ty, TypingEnv}; /// Represents whether some type is inhabited in a given context. /// Examples of uninhabited types are `!`, `enum Void {}`, or a struct @@ -35,8 +35,13 @@ pub enum InhabitedPredicate<'tcx> { impl<'tcx> InhabitedPredicate<'tcx> { /// Returns true if the corresponding type is inhabited in the given `ParamEnv` and module. - pub fn apply(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, module_def_id: DefId) -> bool { - self.apply_revealing_opaque(tcx, param_env, module_def_id, &|_| None) + pub fn apply( + self, + tcx: TyCtxt<'tcx>, + typing_env: TypingEnv<'tcx>, + module_def_id: DefId, + ) -> bool { + self.apply_revealing_opaque(tcx, typing_env, module_def_id, &|_| None) } /// Returns true if the corresponding type is inhabited in the given `ParamEnv` and module, @@ -44,13 +49,13 @@ impl<'tcx> InhabitedPredicate<'tcx> { pub fn apply_revealing_opaque( self, tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, module_def_id: DefId, reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>>, ) -> bool { let Ok(result) = self.apply_inner::<!>( tcx, - param_env, + typing_env, &mut Default::default(), &|id| Ok(tcx.is_descendant_of(module_def_id, id)), reveal_opaque, @@ -59,25 +64,25 @@ impl<'tcx> InhabitedPredicate<'tcx> { } /// Same as `apply`, but returns `None` if self contains a module predicate - pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> { - self.apply_inner(tcx, param_env, &mut Default::default(), &|_| Err(()), &|_| None).ok() + pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>) -> Option<bool> { + self.apply_inner(tcx, typing_env, &mut Default::default(), &|_| Err(()), &|_| None).ok() } /// Same as `apply`, but `NotInModule(_)` predicates yield `false`. That is, /// privately uninhabited types are considered always uninhabited. - pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> bool { + pub fn apply_ignore_module(self, tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>) -> bool { let Ok(result) = - self.apply_inner::<!>(tcx, param_env, &mut Default::default(), &|_| Ok(true), &|_| { + self.apply_inner::<!>(tcx, typing_env, &mut Default::default(), &|_| Ok(true), &|_| { None }); result } - #[instrument(level = "debug", skip(tcx, param_env, in_module, reveal_opaque), ret)] + #[instrument(level = "debug", skip(tcx, typing_env, in_module, reveal_opaque), ret)] fn apply_inner<E: std::fmt::Debug>( self, tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, eval_stack: &mut SmallVec<[Ty<'tcx>; 1]>, // for cycle detection in_module: &impl Fn(DefId) -> Result<bool, E>, reveal_opaque: &impl Fn(OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>>, @@ -94,7 +99,7 @@ impl<'tcx> InhabitedPredicate<'tcx> { // we have a param_env available, we can do better. Self::GenericType(t) => { let normalized_pred = tcx - .try_normalize_erasing_regions(param_env, t) + .try_normalize_erasing_regions(typing_env, t) .map_or(self, |t| t.inhabited_predicate(tcx)); match normalized_pred { // We don't have more information than we started with, so consider inhabited. @@ -107,7 +112,7 @@ impl<'tcx> InhabitedPredicate<'tcx> { } eval_stack.push(t); let ret = - pred.apply_inner(tcx, param_env, eval_stack, in_module, reveal_opaque); + pred.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque); eval_stack.pop(); ret } @@ -126,7 +131,7 @@ impl<'tcx> InhabitedPredicate<'tcx> { eval_stack.push(t); let ret = t.inhabited_predicate(tcx).apply_inner( tcx, - param_env, + typing_env, eval_stack, in_module, reveal_opaque, @@ -136,10 +141,10 @@ impl<'tcx> InhabitedPredicate<'tcx> { } }, Self::And([a, b]) => try_and(a, b, |x| { - x.apply_inner(tcx, param_env, eval_stack, in_module, reveal_opaque) + x.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque) }), Self::Or([a, b]) => try_or(a, b, |x| { - x.apply_inner(tcx, param_env, eval_stack, in_module, reveal_opaque) + x.apply_inner(tcx, typing_env, eval_stack, in_module, reveal_opaque) }), } } diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index dd00db8635f..4a5f6d80f24 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -181,18 +181,18 @@ impl<'tcx> Ty<'tcx> { self, tcx: TyCtxt<'tcx>, module: DefId, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> bool { - self.inhabited_predicate(tcx).apply(tcx, param_env, module) + self.inhabited_predicate(tcx).apply(tcx, typing_env, module) } /// Returns true if the type is uninhabited without regard to visibility pub fn is_privately_uninhabited( self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> bool { - !self.inhabited_predicate(tcx).apply_ignore_module(tcx, param_env) + !self.inhabited_predicate(tcx).apply_ignore_module(tcx, typing_env) } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 0d1c56f0d38..d42b6be4787 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -178,9 +178,9 @@ pub enum InstanceKind<'tcx> { impl<'tcx> Instance<'tcx> { /// Returns the `Ty` corresponding to this `Instance`, with generic instantiations applied and /// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization. - pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { + pub fn ty(&self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Ty<'tcx> { let ty = tcx.type_of(self.def.def_id()); - tcx.instantiate_and_normalize_erasing_regions(self.args, param_env, ty) + tcx.instantiate_and_normalize_erasing_regions(self.args, typing_env, ty) } /// Finds a crate that contains a monomorphization of this instance that @@ -519,7 +519,7 @@ impl<'tcx> Instance<'tcx> { #[instrument(level = "debug", skip(tcx), ret)] pub fn try_resolve( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>, ) -> Result<Option<Instance<'tcx>>, ErrorGuaranteed> { @@ -537,17 +537,14 @@ 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. - - // HACK(eddyb) erase regions in `args` first, so that `param_env.and(...)` - // below is more likely to ignore the bounds in scope (e.g. if the only - // generic parameters mentioned by `args` were lifetime ones). + let typing_env = tcx.erase_regions(typing_env); let args = tcx.erase_regions(args); - tcx.resolve_instance_raw(tcx.erase_regions(param_env.and((def_id, args)))) + tcx.resolve_instance_raw(typing_env.as_query_input((def_id, args))) } pub fn expect_resolve( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>, span: Span, @@ -558,7 +555,7 @@ impl<'tcx> Instance<'tcx> { let span_or_local_def_span = || if span.is_dummy() && def_id.is_local() { tcx.def_span(def_id) } else { span }; - match ty::Instance::try_resolve(tcx, param_env, def_id, args) { + match ty::Instance::try_resolve(tcx, typing_env, def_id, args) { Ok(Some(instance)) => instance, Ok(None) => { let type_length = type_length(args); @@ -600,7 +597,7 @@ impl<'tcx> Instance<'tcx> { pub fn resolve_for_fn_ptr( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>, ) -> Option<Instance<'tcx>> { @@ -608,7 +605,7 @@ impl<'tcx> Instance<'tcx> { // Use either `resolve_closure` or `resolve_for_vtable` assert!(!tcx.is_closure_like(def_id), "Called `resolve_for_fn_ptr` on closure: {def_id:?}"); let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::FnPtr); - Instance::try_resolve(tcx, param_env, def_id, args).ok().flatten().map(|mut resolved| { + Instance::try_resolve(tcx, typing_env, def_id, args).ok().flatten().map(|mut resolved| { match resolved.def { InstanceKind::Item(def) if resolved.def.requires_caller_location(tcx) => { debug!(" => fn pointer created for function with #[track_caller]"); @@ -648,7 +645,7 @@ impl<'tcx> Instance<'tcx> { pub fn expect_resolve_for_vtable( tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>, span: Span, @@ -664,7 +661,7 @@ impl<'tcx> Instance<'tcx> { return Instance { def: InstanceKind::VTableShim(def_id), args }; } - let mut resolved = Instance::expect_resolve(tcx, param_env, def_id, args, span); + let mut resolved = Instance::expect_resolve(tcx, typing_env, def_id, args, span); let reason = tcx.sess.is_sanitizer_kcfi_enabled().then_some(ReifyReason::Vtable); match resolved.def { @@ -743,7 +740,7 @@ impl<'tcx> Instance<'tcx> { let args = tcx.mk_args(&[ty.into()]); Instance::expect_resolve( tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), def_id, args, ty.ty_adt_def().and_then(|adt| tcx.hir().span_if_local(adt.did())).unwrap_or(DUMMY_SP), @@ -755,7 +752,7 @@ impl<'tcx> Instance<'tcx> { let args = tcx.mk_args(&[ty.into()]); Instance::expect_resolve( tcx, - ty::ParamEnv::reveal_all(), + ty::TypingEnv::fully_monomorphized(), def_id, args, ty.ty_adt_def().and_then(|adt| tcx.hir().span_if_local(adt.did())).unwrap_or(DUMMY_SP), @@ -883,16 +880,16 @@ impl<'tcx> Instance<'tcx> { pub fn instantiate_mir_and_normalize_erasing_regions<T>( &self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, v: EarlyBinder<'tcx, T>, ) -> T where T: TypeFoldable<TyCtxt<'tcx>>, { if let Some(args) = self.args_for_mir_body() { - tcx.instantiate_and_normalize_erasing_regions(args, param_env, v) + tcx.instantiate_and_normalize_erasing_regions(args, typing_env, v) } else { - tcx.normalize_erasing_regions(param_env, v.instantiate_identity()) + tcx.normalize_erasing_regions(typing_env, v.instantiate_identity()) } } @@ -901,21 +898,21 @@ impl<'tcx> Instance<'tcx> { pub fn try_instantiate_mir_and_normalize_erasing_regions<T>( &self, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, v: EarlyBinder<'tcx, T>, ) -> Result<T, NormalizationError<'tcx>> where T: TypeFoldable<TyCtxt<'tcx>>, { if let Some(args) = self.args_for_mir_body() { - tcx.try_instantiate_and_normalize_erasing_regions(args, param_env, v) + tcx.try_instantiate_and_normalize_erasing_regions(args, typing_env, v) } else { // We're using `instantiate_identity` as e.g. // `FnPtrShim` is separately generated for every // instantiation of the `FnDef`, so the MIR body // is already instantiated. Any generic parameters it // contains are generic parameters from the caller. - tcx.try_normalize_erasing_regions(param_env, v.instantiate_identity()) + tcx.try_normalize_erasing_regions(typing_env, v.instantiate_identity()) } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index a0eb9029319..8625a8dcb2a 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -297,12 +297,12 @@ impl<'tcx> IntoDiagArg for LayoutError<'tcx> { #[derive(Clone, Copy)] pub struct LayoutCx<'tcx> { pub calc: abi::LayoutCalculator<TyCtxt<'tcx>>, - pub param_env: ty::ParamEnv<'tcx>, + pub typing_env: ty::TypingEnv<'tcx>, } impl<'tcx> LayoutCx<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { - Self { calc: abi::LayoutCalculator::new(tcx), param_env } + pub fn new(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Self { + Self { calc: abi::LayoutCalculator::new(tcx), typing_env } } } @@ -337,12 +337,12 @@ impl<'tcx> SizeSkeleton<'tcx> { pub fn compute( ty: Ty<'tcx>, tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> Result<SizeSkeleton<'tcx>, &'tcx LayoutError<'tcx>> { debug_assert!(!ty.has_non_region_infer()); // First try computing a static layout. - let err = match tcx.layout_of(param_env.and(ty)) { + let err = match tcx.layout_of(typing_env.as_query_input(ty)) { Ok(layout) => { if layout.is_sized() { return Ok(SizeSkeleton::Known(layout.size, Some(layout.align.abi))); @@ -367,7 +367,7 @@ impl<'tcx> SizeSkeleton<'tcx> { let tail = tcx.struct_tail_raw( pointee, - |ty| match tcx.try_normalize_erasing_regions(param_env, ty) { + |ty| match tcx.try_normalize_erasing_regions(typing_env, ty) { Ok(ty) => ty, Err(e) => Ty::new_error_with_message( tcx, @@ -402,7 +402,7 @@ impl<'tcx> SizeSkeleton<'tcx> { return Ok(SizeSkeleton::Known(Size::from_bytes(0), None)); } - match SizeSkeleton::compute(inner, tcx, param_env)? { + match SizeSkeleton::compute(inner, tcx, typing_env)? { // This may succeed because the multiplication of two types may overflow // but a single size of a nested array will not. SizeSkeleton::Known(s, a) => { @@ -432,7 +432,7 @@ impl<'tcx> SizeSkeleton<'tcx> { let i = VariantIdx::from_usize(i); let fields = def.variant(i).fields.iter().map(|field| { - SizeSkeleton::compute(field.ty(tcx, args), tcx, param_env) + SizeSkeleton::compute(field.ty(tcx, args), tcx, typing_env) }); let mut ptr = None; for field in fields { @@ -491,11 +491,11 @@ impl<'tcx> SizeSkeleton<'tcx> { } ty::Alias(..) => { - let normalized = tcx.normalize_erasing_regions(param_env, ty); + let normalized = tcx.normalize_erasing_regions(typing_env, ty); if ty == normalized { Err(err) } else { - SizeSkeleton::compute(normalized, tcx, param_env) + SizeSkeleton::compute(normalized, tcx, typing_env) } } @@ -521,8 +521,14 @@ pub trait HasTyCtxt<'tcx>: HasDataLayout { fn tcx(&self) -> TyCtxt<'tcx>; } -pub trait HasParamEnv<'tcx> { - fn param_env(&self) -> ty::ParamEnv<'tcx>; +pub trait HasTypingEnv<'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx>; + + /// FIXME(#132279): This method should not be used as in the future + /// everything should take a `TypingEnv` instead. Remove it as that point. + fn param_env(&self) -> ty::ParamEnv<'tcx> { + self.typing_env().param_env + } } impl<'tcx> HasDataLayout for TyCtxt<'tcx> { @@ -577,9 +583,9 @@ impl<'tcx> HasTyCtxt<'tcx> for TyCtxtAt<'tcx> { } } -impl<'tcx> HasParamEnv<'tcx> for LayoutCx<'tcx> { - fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env +impl<'tcx> HasTypingEnv<'tcx> for LayoutCx<'tcx> { + fn typing_env(&self) -> ty::TypingEnv<'tcx> { + self.typing_env } } @@ -646,7 +652,7 @@ pub type TyAndLayout<'tcx> = rustc_abi::TyAndLayout<'tcx, Ty<'tcx>>; /// Trait for contexts that want to be able to compute layouts of types. /// This automatically gives access to `LayoutOf`, through a blanket `impl`. -pub trait LayoutOfHelpers<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasParamEnv<'tcx> { +pub trait LayoutOfHelpers<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasTypingEnv<'tcx> { /// The `TyAndLayout`-wrapping type (or `TyAndLayout` itself), which will be /// returned from `layout_of` (see also `handle_layout_err`). type LayoutOfResult: MaybeResult<TyAndLayout<'tcx>> = TyAndLayout<'tcx>; @@ -692,7 +698,7 @@ pub trait LayoutOf<'tcx>: LayoutOfHelpers<'tcx> { let tcx = self.tcx().at(span); MaybeResult::from( - tcx.layout_of(self.param_env().and(ty)) + tcx.layout_of(self.typing_env().as_query_input(ty)) .map_err(|err| self.handle_layout_err(*err, span, ty)), ) } @@ -716,7 +722,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx> { impl<'tcx, C> TyAbiInterface<'tcx, C> for Ty<'tcx> where - C: HasTyCtxt<'tcx> + HasParamEnv<'tcx>, + C: HasTyCtxt<'tcx> + HasTypingEnv<'tcx>, { fn ty_and_layout_for_variant( this: TyAndLayout<'tcx>, @@ -736,10 +742,10 @@ where Variants::Single { index } => { let tcx = cx.tcx(); - let param_env = cx.param_env(); + let typing_env = cx.typing_env(); // Deny calling for_variant more than once for non-Single enums. - if let Ok(original_layout) = tcx.layout_of(param_env.and(this.ty)) { + if let Ok(original_layout) = tcx.layout_of(typing_env.as_query_input(this.ty)) { assert_eq!(original_layout.variants, Variants::Single { index }); } @@ -780,7 +786,7 @@ where fn field_ty_or_layout<'tcx>( this: TyAndLayout<'tcx>, - cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>), + cx: &(impl HasTyCtxt<'tcx> + HasTypingEnv<'tcx>), i: usize, ) -> TyMaybeWithLayout<'tcx> { let tcx = cx.tcx(); @@ -823,12 +829,13 @@ where Ty::new_mut_ref(tcx, tcx.lifetimes.re_static, nil) }; - // NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing - // the `Result` should always work because the type is - // always either `*mut ()` or `&'static mut ()`. + // NOTE: using an fully monomorphized typing env and `unwrap`-ing + // the `Result` should always work because the type is always either + // `*mut ()` or `&'static mut ()`. + let typing_env = ty::TypingEnv::fully_monomorphized(); return TyMaybeWithLayout::TyAndLayout(TyAndLayout { ty: this.ty, - ..tcx.layout_of(ty::ParamEnv::reveal_all().and(unit_ptr_ty)).unwrap() + ..tcx.layout_of(typing_env.as_query_input(unit_ptr_ty)).unwrap() }); } @@ -848,7 +855,7 @@ where && !pointee.references_error() { let metadata = tcx.normalize_erasing_regions( - cx.param_env(), + cx.typing_env(), Ty::new_projection(tcx, metadata_def_id, [pointee]), ); @@ -865,7 +872,7 @@ where metadata } } else { - match tcx.struct_tail_for_codegen(pointee, cx.param_env()).kind() { + match tcx.struct_tail_for_codegen(pointee, cx.typing_env()).kind() { ty::Slice(_) | ty::Str => tcx.types.usize, ty::Dynamic(data, _, ty::Dyn) => mk_dyn_vtable(data.principal()), _ => bug!("TyAndLayout::field({:?}): not applicable", this), @@ -953,7 +960,7 @@ where match field_ty_or_layout(this, cx, i) { TyMaybeWithLayout::Ty(field_ty) => { - cx.tcx().layout_of(cx.param_env().and(field_ty)).unwrap_or_else(|e| { + cx.tcx().layout_of(cx.typing_env().as_query_input(field_ty)).unwrap_or_else(|e| { bug!( "failed to get layout for `{field_ty}`: {e:?},\n\ despite it being a field (#{i}) of an existing layout: {this:#?}", @@ -972,18 +979,18 @@ where offset: Size, ) -> Option<PointeeInfo> { let tcx = cx.tcx(); - let param_env = cx.param_env(); + let typing_env = cx.typing_env(); let pointee_info = match *this.ty.kind() { ty::RawPtr(p_ty, _) if offset.bytes() == 0 => { - tcx.layout_of(param_env.and(p_ty)).ok().map(|layout| PointeeInfo { + tcx.layout_of(typing_env.as_query_input(p_ty)).ok().map(|layout| PointeeInfo { size: layout.size, align: layout.align.abi, safe: None, }) } ty::FnPtr(..) if offset.bytes() == 0 => { - tcx.layout_of(param_env.and(this.ty)).ok().map(|layout| PointeeInfo { + tcx.layout_of(typing_env.as_query_input(this.ty)).ok().map(|layout| PointeeInfo { size: layout.size, align: layout.align.abi, safe: None, @@ -996,14 +1003,14 @@ where let optimize = tcx.sess.opts.optimize != OptLevel::No; let kind = match mt { hir::Mutability::Not => PointerKind::SharedRef { - frozen: optimize && ty.is_freeze(tcx, cx.param_env()), + frozen: optimize && ty.is_freeze(tcx, typing_env.param_env), }, hir::Mutability::Mut => PointerKind::MutableRef { - unpin: optimize && ty.is_unpin(tcx, cx.param_env()), + unpin: optimize && ty.is_unpin(tcx, typing_env.param_env), }, }; - tcx.layout_of(param_env.and(ty)).ok().map(|layout| PointeeInfo { + tcx.layout_of(typing_env.as_query_input(ty)).ok().map(|layout| PointeeInfo { size: layout.size, align: layout.align.abi, safe: Some(kind), @@ -1093,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, cx.param_env()), + unpin: optimize && boxed_ty.is_unpin(tcx, typing_env.param_env), global: this.ty.is_box_global(tcx), }); } @@ -1304,9 +1311,11 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> { let span = self.layout_tcx_at_span(); let tcx = self.tcx().at(span); - MaybeResult::from(tcx.fn_abi_of_fn_ptr(self.param_env().and((sig, extra_args))).map_err( - |err| self.handle_fn_abi_err(*err, span, FnAbiRequest::OfFnPtr { sig, extra_args }), - )) + MaybeResult::from( + tcx.fn_abi_of_fn_ptr(self.typing_env().as_query_input((sig, extra_args))).map_err( + |err| self.handle_fn_abi_err(*err, span, FnAbiRequest::OfFnPtr { sig, extra_args }), + ), + ) } /// Compute a `FnAbi` suitable for declaring/defining an `fn` instance, and for @@ -1326,17 +1335,19 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> { let tcx = self.tcx().at(span); MaybeResult::from( - tcx.fn_abi_of_instance(self.param_env().and((instance, extra_args))).map_err(|err| { - // HACK(eddyb) at least for definitions of/calls to `Instance`s, - // we can get some kind of span even if one wasn't provided. - // However, we don't do this early in order to avoid calling - // `def_span` unconditionally (which may have a perf penalty). - let span = if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) }; - self.handle_fn_abi_err(*err, span, FnAbiRequest::OfInstance { - instance, - extra_args, - }) - }), + tcx.fn_abi_of_instance(self.typing_env().as_query_input((instance, extra_args))) + .map_err(|err| { + // HACK(eddyb) at least for definitions of/calls to `Instance`s, + // we can get some kind of span even if one wasn't provided. + // However, we don't do this early in order to avoid calling + // `def_span` unconditionally (which may have a perf penalty). + let span = + if !span.is_dummy() { span } else { tcx.def_span(instance.def_id()) }; + self.handle_fn_abi_err(*err, span, FnAbiRequest::OfInstance { + instance, + extra_args, + }) + }), ) } } @@ -1346,14 +1357,14 @@ impl<'tcx, C: FnAbiOfHelpers<'tcx>> FnAbiOf<'tcx> for C {} impl<'tcx> TyCtxt<'tcx> { pub fn offset_of_subfield<I>( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, mut layout: TyAndLayout<'tcx>, indices: I, ) -> Size where I: Iterator<Item = (VariantIdx, FieldIdx)>, { - let cx = LayoutCx::new(self, param_env); + let cx = LayoutCx::new(self, typing_env); let mut offset = Size::ZERO; for (variant, field) in indices { @@ -1363,7 +1374,7 @@ impl<'tcx> TyCtxt<'tcx> { layout = layout.field(&cx, index); if !layout.is_sized() { // If it is not sized, then the tail must still have at least a known static alignment. - let tail = self.struct_tail_for_codegen(layout.ty, param_env); + let tail = self.struct_tail_for_codegen(layout.ty, typing_env); if !matches!(tail.kind(), ty::Slice(..)) { bug!( "offset of not-statically-aligned field (type {:?}) cannot be computed statically", diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 7fda0662a34..d6f7ee748bb 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -103,7 +103,7 @@ use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; use crate::metadata::ModChild; use crate::middle::privacy::EffectiveVisibilities; use crate::mir::{Body, CoroutineLayout}; -use crate::query::Providers; +use crate::query::{IntoQueryParam, Providers}; use crate::traits::{self, Reveal}; use crate::ty; pub use crate::ty::diagnostics::*; @@ -1122,6 +1122,104 @@ impl<'tcx, T> ParamEnvAnd<'tcx, T> { } } +/// The environment in which to do trait solving. +/// +/// Most of the time you only need to care about the `ParamEnv` +/// as the `TypingMode` is simply stored in the `InferCtxt`. +/// +/// However, there are some places which rely on trait solving +/// without using an `InferCtxt` themselves. For these to be +/// able to use the trait system they have to be able to initialize +/// such an `InferCtxt` with the right `typing_mode`, so they need +/// to track both. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] +#[derive(TypeVisitable, TypeFoldable)] +pub struct TypingEnv<'tcx> { + pub typing_mode: TypingMode<'tcx>, + pub param_env: ParamEnv<'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. + /// + /// This is only suitable for monomorphized, post-typeck environments. + /// Do not use this for MIR optimizations, as even though they also + /// use `TypingMode::PostAnalysis`, they may still have where-clauses + /// in scope. + pub fn fully_monomorphized() -> TypingEnv<'tcx> { + TypingEnv { typing_mode: TypingMode::PostAnalysis, param_env: ParamEnv::reveal_all() } + } + + /// Create a typing environment for use during analysis outside of a body. + /// + /// Using a typing environment inside of bodies is not supported as the body + /// may define opaque types. In this case the used functions have to be + /// converted to use proper canonical inputs instead. + pub fn non_body_analysis( + tcx: TyCtxt<'tcx>, + def_id: impl IntoQueryParam<DefId>, + ) -> TypingEnv<'tcx> { + TypingEnv { typing_mode: TypingMode::non_body_analysis(), param_env: tcx.param_env(def_id) } + } + + pub fn post_analysis(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryParam<DefId>) -> TypingEnv<'tcx> { + TypingEnv { + typing_mode: TypingMode::PostAnalysis, + param_env: tcx.param_env_reveal_all_normalized(def_id), + } + } + + /// Modify the `typing_mode` to `PostAnalysis` and eagerly reveal all + /// opaque types in the `param_env`. + pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> { + let TypingEnv { typing_mode: _, param_env } = self; + let param_env = param_env.with_reveal_all_normalized(tcx); + TypingEnv { typing_mode: TypingMode::PostAnalysis, param_env } + } + + /// Combine this typing environment with the given `value` to be used by + /// not (yet) canonicalized queries. This only works if the value does not + /// contain anything local to some `InferCtxt`, i.e. inference variables or + /// placeholders. + pub fn as_query_input<T>(self, value: T) -> PseudoCanonicalInput<'tcx, T> + where + T: TypeVisitable<TyCtxt<'tcx>>, + { + 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 + // placeholders. We should also simply not use pseudo-canonical queries in the trait + // solver, at which point we can readd this assert. + // + // debug_assert!(!value.has_placeholders()); + PseudoCanonicalInput { typing_env: self, value } + } +} + +/// Similar to `CanonicalInput`, this carries the `typing_mode` and the environment +/// necessary to do any kind of trait solving inside of nested queries. +/// +/// Unlike proper canonicalization, this requires the `param_env` and the `value` to not +/// contain anything local to the `infcx` of the caller, so we don't actually canonicalize +/// anything. +/// +/// 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)] +pub struct PseudoCanonicalInput<'tcx, T> { + pub typing_env: TypingEnv<'tcx>, + pub value: T, +} + #[derive(Copy, Clone, Debug, HashStable, Encodable, Decodable)] pub struct Destructor { /// The `DefId` of the destructor method diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index e51d2201922..f611b69905c 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -35,16 +35,16 @@ impl<'tcx> TyCtxt<'tcx> { /// /// This should only be used outside of type inference. For example, /// it assumes that normalization will succeed. - #[tracing::instrument(level = "debug", skip(self, param_env), ret)] - pub fn normalize_erasing_regions<T>(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T + #[tracing::instrument(level = "debug", skip(self, typing_env), ret)] + pub fn normalize_erasing_regions<T>(self, typing_env: ty::TypingEnv<'tcx>, value: T) -> T where T: TypeFoldable<TyCtxt<'tcx>>, { debug!( - "normalize_erasing_regions::<{}>(value={:?}, param_env={:?})", + "normalize_erasing_regions::<{}>(value={:?}, typing_env={:?})", std::any::type_name::<T>(), value, - param_env, + typing_env, ); // Erase first before we do the real query -- this keeps the @@ -55,7 +55,7 @@ impl<'tcx> TyCtxt<'tcx> { if !value.has_aliases() { value } else { - value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env }) + value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, typing_env }) } } @@ -66,17 +66,17 @@ impl<'tcx> TyCtxt<'tcx> { /// succeeds. pub fn try_normalize_erasing_regions<T>( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, value: T, ) -> Result<T, NormalizationError<'tcx>> where T: TypeFoldable<TyCtxt<'tcx>>, { debug!( - "try_normalize_erasing_regions::<{}>(value={:?}, param_env={:?})", + "try_normalize_erasing_regions::<{}>(value={:?}, typing_env={:?})", std::any::type_name::<T>(), value, - param_env, + typing_env, ); // Erase first before we do the real query -- this keeps the @@ -87,7 +87,7 @@ impl<'tcx> TyCtxt<'tcx> { if !value.has_aliases() { Ok(value) } else { - let mut folder = TryNormalizeAfterErasingRegionsFolder::new(self, param_env); + let mut folder = TryNormalizeAfterErasingRegionsFolder::new(self, typing_env); value.try_fold_with(&mut folder) } } @@ -103,17 +103,17 @@ impl<'tcx> TyCtxt<'tcx> { // FIXME(@lcnr): This method should not be necessary, we now normalize // inside of binders. We should be able to only use // `tcx.instantiate_bound_regions_with_erased`. - #[tracing::instrument(level = "debug", skip(self, param_env))] + #[tracing::instrument(level = "debug", skip(self, typing_env))] pub fn normalize_erasing_late_bound_regions<T>( self, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, value: ty::Binder<'tcx, T>, ) -> T where T: TypeFoldable<TyCtxt<'tcx>>, { let value = self.instantiate_bound_regions_with_erased(value); - self.normalize_erasing_regions(param_env, value) + self.normalize_erasing_regions(typing_env, value) } /// Monomorphizes a type from the AST by first applying the @@ -125,14 +125,14 @@ impl<'tcx> TyCtxt<'tcx> { pub fn instantiate_and_normalize_erasing_regions<T>( self, param_args: GenericArgsRef<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, value: EarlyBinder<'tcx, T>, ) -> T where T: TypeFoldable<TyCtxt<'tcx>>, { let instantiated = value.instantiate(self, param_args); - self.normalize_erasing_regions(param_env, instantiated) + self.normalize_erasing_regions(typing_env, instantiated) } /// Monomorphizes a type from the AST by first applying the @@ -143,20 +143,20 @@ impl<'tcx> TyCtxt<'tcx> { pub fn try_instantiate_and_normalize_erasing_regions<T>( self, param_args: GenericArgsRef<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, value: EarlyBinder<'tcx, T>, ) -> Result<T, NormalizationError<'tcx>> where T: TypeFoldable<TyCtxt<'tcx>>, { let instantiated = value.instantiate(self, param_args); - self.try_normalize_erasing_regions(param_env, instantiated) + self.try_normalize_erasing_regions(typing_env, instantiated) } } struct NormalizeAfterErasingRegionsFolder<'tcx> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, } impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> { @@ -164,8 +164,7 @@ impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> { &self, arg: ty::GenericArg<'tcx>, ) -> ty::GenericArg<'tcx> { - let arg = self.param_env.and(arg); - + let arg = self.typing_env.as_query_input(arg); self.tcx.try_normalize_generic_arg_after_erasing_regions(arg).unwrap_or_else(|_| bug!( "Failed to normalize {:?}, maybe try to call `try_normalize_erasing_regions` instead", arg.value @@ -189,12 +188,12 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for NormalizeAfterErasingRegionsFolder<'tcx> struct TryNormalizeAfterErasingRegionsFolder<'tcx> { tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, } impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> { - fn new(tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { - TryNormalizeAfterErasingRegionsFolder { tcx, param_env } + fn new(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Self { + TryNormalizeAfterErasingRegionsFolder { tcx, typing_env } } #[instrument(skip(self), level = "debug")] @@ -202,10 +201,8 @@ impl<'tcx> TryNormalizeAfterErasingRegionsFolder<'tcx> { &self, arg: ty::GenericArg<'tcx>, ) -> Result<ty::GenericArg<'tcx>, NoSolution> { - let arg = self.param_env.and(arg); - debug!(?arg); - - self.tcx.try_normalize_generic_arg_after_erasing_regions(arg) + let input = self.typing_env.as_query_input(arg); + self.tcx.try_normalize_generic_arg_after_erasing_regions(input) } } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 3c6e34160f4..1108619828d 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -18,6 +18,7 @@ use rustc_span::sym; use smallvec::{SmallVec, smallvec}; use tracing::{debug, instrument}; +use super::TypingEnv; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::Providers; use crate::ty::layout::{FloatExt, IntegerExt}; @@ -177,9 +178,13 @@ impl<'tcx> TyCtxt<'tcx> { /// Should only be called if `ty` has no inference variables and does not /// need its lifetimes preserved (e.g. as part of codegen); otherwise /// normalization attempt may cause compiler bugs. - pub fn struct_tail_for_codegen(self, ty: Ty<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { + pub fn struct_tail_for_codegen( + self, + ty: Ty<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ) -> Ty<'tcx> { let tcx = self; - tcx.struct_tail_raw(ty, |ty| tcx.normalize_erasing_regions(param_env, ty), || {}) + tcx.struct_tail_raw(ty, |ty| tcx.normalize_erasing_regions(typing_env, ty), || {}) } /// Returns the deeply last field of nested structures, or the same type if @@ -271,11 +276,11 @@ impl<'tcx> TyCtxt<'tcx> { self, source: Ty<'tcx>, target: Ty<'tcx>, - param_env: ty::ParamEnv<'tcx>, + typing_env: ty::TypingEnv<'tcx>, ) -> (Ty<'tcx>, Ty<'tcx>) { let tcx = self; tcx.struct_lockstep_tails_raw(source, target, |ty| { - tcx.normalize_erasing_regions(param_env, ty) + tcx.normalize_erasing_regions(typing_env, ty) }) } @@ -420,10 +425,10 @@ impl<'tcx> TyCtxt<'tcx> { // Async drop glue morphology is an internal detail, so reveal_all probably // should be fine - let param_env = ty::ParamEnv::reveal_all(); - if ty.needs_async_drop(self, param_env) { + let typing_env = ty::TypingEnv::fully_monomorphized(); + if ty.needs_async_drop(self, typing_env) { AsyncDropGlueMorphology::Custom - } else if ty.needs_drop(self, param_env) { + } else if ty.needs_drop(self, typing_env) { AsyncDropGlueMorphology::DeferredDropInPlace } else { AsyncDropGlueMorphology::Noop @@ -683,12 +688,10 @@ impl<'tcx> TyCtxt<'tcx> { } /// Get the type of the pointer to the static that we use in MIR. - pub fn static_ptr_ty(self, def_id: DefId) -> Ty<'tcx> { + pub fn static_ptr_ty(self, def_id: DefId, typing_env: ty::TypingEnv<'tcx>) -> Ty<'tcx> { // Make sure that any constants in the static's type are evaluated. - let static_ty = self.normalize_erasing_regions( - ty::ParamEnv::empty(), - self.type_of(def_id).instantiate_identity(), - ); + let static_ty = + self.normalize_erasing_regions(typing_env, self.type_of(def_id).instantiate_identity()); // Make sure that accesses to unsafe statics end up using raw pointers. // For thread-locals, this needs to be kept in sync with `Rvalue::ty`. @@ -1157,15 +1160,17 @@ impl<'tcx> Ty<'tcx> { /// Returns the maximum value for the given numeric type (including `char`s) /// or returns `None` if the type is not numeric. pub fn numeric_max_val(self, tcx: TyCtxt<'tcx>) -> Option<ty::Const<'tcx>> { + let typing_env = TypingEnv::fully_monomorphized(); self.numeric_min_and_max_as_bits(tcx) - .map(|(_, max)| ty::Const::from_bits(tcx, max, ty::ParamEnv::empty().and(self))) + .map(|(_, max)| ty::Const::from_bits(tcx, max, typing_env, self)) } /// Returns the minimum value for the given numeric type (including `char`s) /// or returns `None` if the type is not numeric. pub fn numeric_min_val(self, tcx: TyCtxt<'tcx>) -> Option<ty::Const<'tcx>> { + let typing_env = TypingEnv::fully_monomorphized(); self.numeric_min_and_max_as_bits(tcx) - .map(|(min, _)| ty::Const::from_bits(tcx, min, ty::ParamEnv::empty().and(self))) + .map(|(min, _)| ty::Const::from_bits(tcx, min, typing_env, self)) } /// Checks whether values of this type `T` are *moved* or *copied* @@ -1345,7 +1350,7 @@ impl<'tcx> Ty<'tcx> { /// /// Note that this method is used to check eligible types in unions. #[inline] - pub fn needs_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + pub fn needs_drop(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { // Avoid querying in simple cases. match needs_drop_components(tcx, self) { Err(AlwaysRequiresDrop) => true, @@ -1359,14 +1364,13 @@ impl<'tcx> Ty<'tcx> { }; // This doesn't depend on regions, so try to minimize distinct - // query keys used. - // If normalization fails, we just use `query_ty`. - debug_assert!(!param_env.has_infer()); + // query keys used. If normalization fails, we just use `query_ty`. + debug_assert!(!typing_env.param_env.has_infer()); let query_ty = tcx - .try_normalize_erasing_regions(param_env, query_ty) + .try_normalize_erasing_regions(typing_env, query_ty) .unwrap_or_else(|_| tcx.erase_regions(query_ty)); - tcx.needs_drop_raw(param_env.and(query_ty)) + tcx.needs_drop_raw(typing_env.as_query_input(query_ty)) } } } @@ -1385,7 +1389,7 @@ impl<'tcx> Ty<'tcx> { // FIXME(zetanumbers): Note that this method is used to check eligible types // in unions. #[inline] - pub fn needs_async_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + pub fn needs_async_drop(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { // Avoid querying in simple cases. match needs_drop_components(tcx, self) { Err(AlwaysRequiresDrop) => true, @@ -1401,12 +1405,12 @@ impl<'tcx> Ty<'tcx> { // This doesn't depend on regions, so try to minimize distinct // query keys used. // If normalization fails, we just use `query_ty`. - debug_assert!(!param_env.has_infer()); + debug_assert!(!typing_env.has_infer()); let query_ty = tcx - .try_normalize_erasing_regions(param_env, query_ty) + .try_normalize_erasing_regions(typing_env, query_ty) .unwrap_or_else(|_| tcx.erase_regions(query_ty)); - tcx.needs_async_drop_raw(param_env.and(query_ty)) + tcx.needs_async_drop_raw(typing_env.as_query_input(query_ty)) } } } @@ -1420,7 +1424,7 @@ impl<'tcx> Ty<'tcx> { /// Note that this method is used to check for change in drop order for /// 2229 drop reorder migration analysis. #[inline] - pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { + pub fn has_significant_drop(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool { // Avoid querying in simple cases. match needs_drop_components(tcx, self) { Err(AlwaysRequiresDrop) => true, @@ -1443,8 +1447,8 @@ impl<'tcx> Ty<'tcx> { // This doesn't depend on regions, so try to minimize distinct // query keys used. - let erased = tcx.normalize_erasing_regions(param_env, query_ty); - tcx.has_significant_drop_raw(param_env.and(erased)) + let erased = tcx.normalize_erasing_regions(typing_env, query_ty); + tcx.has_significant_drop_raw(typing_env.as_query_input(erased)) } } } diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index 963fa12a8c7..e5eeb23be25 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -97,7 +97,7 @@ pub(super) fn vtable_allocation_provider<'tcx>( assert!(vtable_entries.len() >= vtable_min_entries(tcx, poly_trait_ref)); let layout = tcx - .layout_of(ty::ParamEnv::reveal_all().and(ty)) + .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) .expect("failed to build vtable representation"); assert!(layout.is_sized(), "can't create a vtable for an unsized type"); let size = layout.size.bytes(); @@ -117,7 +117,7 @@ pub(super) fn vtable_allocation_provider<'tcx>( let idx: u64 = u64::try_from(idx).unwrap(); let scalar = match entry { VtblEntry::MetadataDropInPlace => { - if ty.needs_drop(tcx, ty::ParamEnv::reveal_all()) { + if ty.needs_drop(tcx, ty::TypingEnv::fully_monomorphized()) { let instance = ty::Instance::resolve_drop_in_place(tcx, ty); let fn_alloc_id = tcx.reserve_and_set_fn_alloc(instance, CTFE_ALLOC_SALT); let fn_ptr = Pointer::from(fn_alloc_id); diff --git a/compiler/rustc_middle/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs index ed27a880562..acfb78b3f6e 100644 --- a/compiler/rustc_middle/src/util/call_kind.rs +++ b/compiler/rustc_middle/src/util/call_kind.rs @@ -8,7 +8,7 @@ use rustc_span::symbol::Ident; use rustc_span::{DesugaringKind, Span, sym}; use tracing::debug; -use crate::ty::{AssocItemContainer, GenericArgsRef, Instance, ParamEnv, Ty, TyCtxt}; +use crate::ty::{AssocItemContainer, GenericArgsRef, Instance, Ty, TyCtxt, TypingEnv}; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum CallDesugaringKind { @@ -62,7 +62,7 @@ pub enum CallKind<'tcx> { pub fn call_kind<'tcx>( tcx: TyCtxt<'tcx>, - param_env: ParamEnv<'tcx>, + typing_env: TypingEnv<'tcx>, method_did: DefId, method_args: GenericArgsRef<'tcx>, fn_call_span: Span, @@ -98,10 +98,10 @@ pub fn call_kind<'tcx>( Some(CallKind::Operator { self_arg, trait_id, self_ty: method_args.type_at(0) }) } else if is_deref { let deref_target = tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| { - Instance::try_resolve(tcx, param_env, deref_target, method_args).transpose() + Instance::try_resolve(tcx, typing_env, deref_target, method_args).transpose() }); if let Some(Ok(instance)) = deref_target { - let deref_target_ty = instance.ty(tcx, param_env); + let deref_target_ty = instance.ty(tcx, typing_env); Some(CallKind::DerefCoercion { deref_target: tcx.def_span(instance.def_id()), deref_target_ty, |
