1
Fork 0

Auto merge of #132460 - lcnr:questionable-uwu, r=compiler-errors

Use `TypingMode` throughout the compiler instead of `ParamEnv`

Hopefully the biggest single PR as part of https://github.com/rust-lang/types-team/issues/128.

## `infcx.typing_env` while defining opaque types

I don't know how'll be able to correctly handle opaque types when using something taking a `TypingEnv` while defining opaque types. To correctly handle the opaques we need to be able to pass in the current `opaque_type_storage` and return constraints, i.e. we need to use a proper canonical query. We should migrate all the queries used during HIR typeck and borrowck where this matters to proper canonical queries. This is

## `layout_of` and `Reveal::All`

We convert the `ParamEnv` to `Reveal::All` right at the start of the `layout_of` query, so I've changed callers of `layout_of` to already use a post analysis `TypingEnv` when encountering it.

ca87b535a0/compiler/rustc_ty_utils/src/layout.rs (L51)

## `Ty::is_[unpin|sized|whatever]`

I haven't migrated `fn is_item_raw` to use `TypingEnv`, will do so in a followup PR, this should significantly reduce the amount of `typing_env.param_env`. At some point there will probably be zero such uses as using the type system while ignoring the `typing_mode` is incorrect.

## `MirPhase` and phase-transitions

When inside of a MIR-body, we can mostly use its `MirPhase` to figure out the right `typing_mode`. This does not work during phase transitions, most notably when transitioning from `Analysis` to `Runtime`:

dae7ac133b/compiler/rustc_mir_transform/src/lib.rs (L606-L625)

All these passes still run with `MirPhase::Analysis`, but we should only use `Reveal::All` once we're run the `RevealAll` pass. This required me to manually construct the right `TypingEnv` in all these passes. Given that it feels somewhat easy to accidentally miss this going forward, I would maybe like to change `Body::phase` to an `Option` and replace it at the start of phase transitions. This then makes it clear that the MIR is currently in a weird state.

r? `@ghost`
This commit is contained in:
bors 2024-11-18 21:07:05 +00:00
commit b71fb5edc0
240 changed files with 1745 additions and 1341 deletions

View file

@ -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]

View file

@ -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)
}

View file

@ -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.

View file

@ -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 {

View file

@ -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 {

View file

@ -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`].

View file

@ -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>`

View file

@ -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 }
}

View file

@ -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) => {

View file

@ -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 {

View file

@ -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))
}

View file

@ -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))
}

View file

@ -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)
}),
}
}

View file

@ -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)
}
}

View file

@ -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())
}
}

View file

@ -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",

View file

@ -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,105 @@ 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. As of writing this comment, this is
// only used by `fn layout_is_pointer_like` when calling `layout_of`.
//
// 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

View file

@ -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)
}
}

View file

@ -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))
}
}
}

View file

@ -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);

View file

@ -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,