1
Fork 0

use TypingEnv when no infcx is available

the behavior of the type system not only depends on the current
assumptions, but also the currentnphase of the compiler. This is
mostly necessary as we need to decide whether and how to reveal
opaque types. We track this via the `TypingMode`.
This commit is contained in:
lcnr 2024-11-15 13:53:31 +01:00
parent bf6adec108
commit 9cba14b95b
240 changed files with 1739 additions and 1340 deletions

View file

@ -1,6 +1,6 @@
use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::{self, TyCtxt};
use tracing::debug;
use crate::util;
@ -40,10 +40,10 @@ pub(super) struct AddMovesForPackedDrops;
impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
debug!("add_moves_for_packed_drops({:?} @ {:?})", body.source, body.span);
let def_id = body.source.def_id();
let mut patch = MirPatch::new(body);
let param_env = tcx.param_env(def_id);
// FIXME(#132279): This is used during the phase transition from analysis
// to runtime, so we have to manually specify the correct typing mode.
let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
for (bb, data) in body.basic_blocks.iter_enumerated() {
let loc = Location { block: bb, statement_index: data.statements.len() };
@ -51,7 +51,7 @@ impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops {
match terminator.kind {
TerminatorKind::Drop { place, .. }
if util::is_disaligned(tcx, body, param_env, place) =>
if util::is_disaligned(tcx, body, typing_env, place) =>
{
add_move_for_packed_drop(
tcx,

View file

@ -9,9 +9,9 @@ pub(super) struct CheckPackedRef;
impl<'tcx> crate::MirLint<'tcx> for CheckPackedRef {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
let param_env = tcx.param_env(body.source.def_id());
let typing_env = body.typing_env(tcx);
let source_info = SourceInfo::outermost(body.span);
let mut checker = PackedRefChecker { body, tcx, param_env, source_info };
let mut checker = PackedRefChecker { body, tcx, typing_env, source_info };
checker.visit_body(body);
}
}
@ -19,7 +19,7 @@ impl<'tcx> crate::MirLint<'tcx> for CheckPackedRef {
struct PackedRefChecker<'a, 'tcx> {
body: &'a Body<'tcx>,
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
source_info: SourceInfo,
}
@ -37,7 +37,8 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
}
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
if context.is_borrow() && util::is_disaligned(self.tcx, self.body, self.param_env, *place) {
if context.is_borrow() && util::is_disaligned(self.tcx, self.body, self.typing_env, *place)
{
let def_id = self.body.source.instance.def_id();
if let Some(impl_def_id) = self.tcx.impl_of_method(def_id)
&& self.tcx.is_builtin_derived(impl_def_id)

View file

@ -1069,11 +1069,9 @@ fn elaborate_coroutine_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// Note that `elaborate_drops` only drops the upvars of a coroutine, and
// this is ok because `open_drop` can only be reached within that own
// coroutine's resume function.
let typing_env = body.typing_env(tcx);
let def_id = body.source.def_id();
let param_env = tcx.param_env(def_id);
let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, param_env };
let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, typing_env };
for (block, block_data) in body.basic_blocks.iter_enumerated() {
let (target, unwind, source_info) = match block_data.terminator() {
@ -1204,9 +1202,9 @@ fn insert_panic_block<'tcx>(
insert_term_block(body, kind)
}
fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool {
// Returning from a function with an uninhabited return type is undefined behavior.
if body.return_ty().is_privately_uninhabited(tcx, param_env) {
if body.return_ty().is_privately_uninhabited(tcx, typing_env) {
return false;
}
@ -1627,7 +1625,7 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
// `storage_liveness` tells us which locals have live storage at suspension points
let (remap, layout, storage_liveness) = compute_layout(liveness_info, body);
let can_return = can_return(tcx, body, tcx.param_env(body.source.def_id()));
let can_return = can_return(tcx, body, body.typing_env(tcx));
// Run the transformation which converts Places from Local to coroutine struct
// accesses for locals in `remap`.

View file

@ -1,7 +1,7 @@
use rustc_middle::bug;
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
use rustc_middle::ty::{self, Ty, TyCtxt};
const INSTR_COST: usize = 5;
const CALL_PENALTY: usize = 25;
@ -14,7 +14,7 @@ const CONST_SWITCH_BONUS: usize = 10;
#[derive(Clone)]
pub(super) struct CostChecker<'b, 'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
penalty: usize,
bonus: usize,
callee_body: &'b Body<'tcx>,
@ -24,11 +24,11 @@ pub(super) struct CostChecker<'b, 'tcx> {
impl<'b, 'tcx> CostChecker<'b, 'tcx> {
pub(super) fn new(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
instance: Option<ty::Instance<'tcx>>,
callee_body: &'b Body<'tcx>,
) -> CostChecker<'b, 'tcx> {
CostChecker { tcx, param_env, callee_body, instance, penalty: 0, bonus: 0 }
CostChecker { tcx, typing_env, callee_body, instance, penalty: 0, bonus: 0 }
}
/// Add function-level costs not well-represented by the block-level costs.
@ -119,7 +119,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
TerminatorKind::Drop { place, unwind, .. } => {
// If the place doesn't actually need dropping, treat it like a regular goto.
let ty = self.instantiate_ty(place.ty(self.callee_body, self.tcx).ty);
if ty.needs_drop(self.tcx, self.param_env) {
if ty.needs_drop(self.tcx, self.typing_env) {
self.penalty += CALL_PENALTY;
if let UnwindAction::Cleanup(_) = unwind {
self.penalty += LANDINGPAD_PENALTY;

View file

@ -16,7 +16,7 @@ use rustc_middle::bug;
use rustc_middle::mir::interpret::{InterpResult, Scalar};
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_mir_dataflow::fmt::DebugWithContext;
use rustc_mir_dataflow::lattice::{FlatSet, HasBottom};
@ -82,7 +82,7 @@ struct ConstAnalysis<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
local_decls: &'a LocalDecls<'tcx>,
ecx: InterpCx<'tcx, DummyMachine>,
param_env: ty::ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
}
impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> {
@ -144,13 +144,13 @@ impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> {
impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map<'tcx>) -> Self {
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
let typing_env = body.typing_env(tcx);
Self {
map,
tcx,
local_decls: &body.local_decls,
ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine),
param_env,
ecx: InterpCx::new(tcx, DUMMY_SP, typing_env.param_env, DummyMachine),
typing_env,
}
}
@ -389,7 +389,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
&& let Some(operand_ty) = operand_ty.builtin_deref(true)
&& let ty::Array(_, len) = operand_ty.kind()
&& let Some(len) = Const::Ty(self.tcx.types.usize, *len)
.try_eval_scalar_int(self.tcx, self.param_env)
.try_eval_scalar_int(self.tcx, self.typing_env)
{
state.insert_value_idx(target_len, FlatSet::Elem(len.into()), &self.map);
}
@ -411,7 +411,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
let place_ty = place.ty(self.local_decls, self.tcx);
if let ty::Array(_, len) = place_ty.ty.kind() {
Const::Ty(self.tcx.types.usize, *len)
.try_eval_scalar(self.tcx, self.param_env)
.try_eval_scalar(self.tcx, self.typing_env)
.map_or(FlatSet::Top, FlatSet::Elem)
} else if let [ProjectionElem::Deref] = place.projection[..] {
state.get_len(place.local.into(), &self.map)
@ -420,7 +420,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
}
}
Rvalue::Cast(CastKind::IntToInt | CastKind::IntToFloat, operand, ty) => {
let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else {
let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else {
return ValueOrPlace::Value(FlatSet::Top);
};
match self.eval_operand(operand, state) {
@ -434,7 +434,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
}
}
Rvalue::Cast(CastKind::FloatToInt | CastKind::FloatToFloat, operand, ty) => {
let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else {
let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else {
return ValueOrPlace::Value(FlatSet::Top);
};
match self.eval_operand(operand, state) {
@ -470,7 +470,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
FlatSet::Top => FlatSet::Top,
},
Rvalue::NullaryOp(null_op, ty) => {
let Ok(layout) = self.tcx.layout_of(self.param_env.and(*ty)) else {
let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else {
return ValueOrPlace::Value(FlatSet::Top);
};
let val = match null_op {
@ -479,7 +479,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
NullOp::OffsetOf(fields) => self
.ecx
.tcx
.offset_of_subfield(self.ecx.param_env(), layout, fields.iter())
.offset_of_subfield(self.typing_env, layout, fields.iter())
.bytes(),
_ => return ValueOrPlace::Value(FlatSet::Top),
};
@ -514,7 +514,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
) -> FlatSet<Scalar> {
constant
.const_
.try_eval_scalar(self.tcx, self.param_env)
.try_eval_scalar(self.tcx, self.typing_env)
.map_or(FlatSet::Top, FlatSet::Elem)
}
@ -554,7 +554,8 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
} else if rhs.projection.first() == Some(&PlaceElem::Deref)
&& let FlatSet::Elem(pointer) = state.get(rhs.local.into(), &self.map)
&& let rhs_ty = self.local_decls[rhs.local].ty
&& let Ok(rhs_layout) = self.tcx.layout_of(self.param_env.and(rhs_ty))
&& let Ok(rhs_layout) =
self.tcx.layout_of(self.typing_env.as_query_input(rhs_ty))
{
let op = ImmTy::from_scalar(pointer, rhs_layout).into();
self.assign_constant(state, place, op, rhs.projection);
@ -614,8 +615,10 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
TrackElem::DerefLen => {
let op: OpTy<'_> = self.ecx.deref_pointer(op).discard_err()?.into();
let len_usize = op.len(&self.ecx).discard_err()?;
let layout =
self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).unwrap();
let layout = self
.tcx
.layout_of(self.typing_env.as_query_input(self.tcx.types.usize))
.unwrap();
Some(ImmTy::from_uint(len_usize, layout).into())
}
},
@ -702,9 +705,11 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
FlatSet::Top => FlatSet::Top,
FlatSet::Elem(scalar) => {
let ty = op.ty(self.local_decls, self.tcx);
self.tcx.layout_of(self.param_env.and(ty)).map_or(FlatSet::Top, |layout| {
FlatSet::Elem(ImmTy::from_scalar(scalar, layout))
})
self.tcx
.layout_of(self.typing_env.as_query_input(ty))
.map_or(FlatSet::Top, |layout| {
FlatSet::Elem(ImmTy::from_scalar(scalar, layout))
})
}
FlatSet::Bottom => FlatSet::Bottom,
}
@ -714,7 +719,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
if !enum_ty.is_enum() {
return None;
}
let enum_ty_layout = self.tcx.layout_of(self.param_env.and(enum_ty)).ok()?;
let enum_ty_layout = self.tcx.layout_of(self.typing_env.as_query_input(enum_ty)).ok()?;
let discr_value =
self.ecx.discriminant_for_variant(enum_ty_layout.ty, variant_index).discard_err()?;
Some(discr_value.to_scalar())

View file

@ -198,7 +198,7 @@ pub(super) fn deduced_param_attrs<'tcx>(
// see [1].
//
// [1]: https://github.com/rust-lang/rust/pull/103172#discussion_r999139997
let param_env = tcx.param_env_reveal_all_normalized(def_id);
let typing_env = body.typing_env(tcx);
let mut deduced_param_attrs = tcx.arena.alloc_from_iter(
body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map(
|(arg_index, local_decl)| DeducedParamAttrs {
@ -207,8 +207,8 @@ pub(super) fn deduced_param_attrs<'tcx>(
// their generic parameters, otherwise we'll see exponential
// blow-up in compile times: #113372
&& tcx
.normalize_erasing_regions(param_env, local_decl.ty)
.is_freeze(tcx, param_env),
.normalize_erasing_regions(typing_env, local_decl.ty)
.is_freeze(tcx, typing_env.param_env),
},
),
);

View file

@ -3,6 +3,7 @@ use std::fmt;
use rustc_abi::{FieldIdx, VariantIdx};
use rustc_index::IndexVec;
use rustc_index::bit_set::BitSet;
use rustc_infer::traits::Reveal;
use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, TyCtxt};
@ -53,14 +54,14 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops {
#[instrument(level = "trace", skip(self, tcx, body))]
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
debug!("elaborate_drops({:?} @ {:?})", body.source, body.span);
let def_id = body.source.def_id();
let param_env = tcx.param_env_reveal_all_normalized(def_id);
// FIXME(#132279): This is used during the phase transition from analysis
// to runtime, so we have to manually specify the correct typing mode.
let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
// For types that do not need dropping, the behaviour is trivial. So we only need to track
// init/uninit for types that do need dropping.
let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, param_env));
let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, typing_env));
let elaborate_patch = {
let env = MoveDataParamEnv { move_data, param_env };
let env = MoveDataParamEnv { move_data, param_env: typing_env.param_env };
let mut inits = MaybeInitializedPlaces::new(tcx, body, &env.move_data)
.skipping_unreachable_unwind()
@ -147,8 +148,8 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for ElaborateDropsCtxt<'a, 'tcx> {
self.tcx
}
fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.param_env()
fn typing_env(&self) -> ty::TypingEnv<'tcx> {
self.typing_env()
}
#[instrument(level = "debug", skip(self), ret)]
@ -250,6 +251,11 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
self.env.param_env
}
fn typing_env(&self) -> ty::TypingEnv<'tcx> {
debug_assert_eq!(self.param_env().reveal(), Reveal::All);
ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env() }
}
fn create_drop_flag(&mut self, index: MovePathIndex, span: Span) {
let patch = &mut self.patch;
debug!("create_drop_flag({:?})", self.body.span);
@ -335,7 +341,7 @@ impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
if !place
.ty(&self.body.local_decls, self.tcx)
.ty
.needs_drop(self.tcx, self.env.param_env)
.needs_drop(self.tcx, self.typing_env())
{
self.patch.patch_terminator(bb, TerminatorKind::Goto { target });
continue;

View file

@ -100,7 +100,7 @@ use rustc_middle::bug;
use rustc_middle::mir::interpret::GlobalAlloc;
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::DUMMY_SP;
use rustc_span::def_id::DefId;
@ -295,6 +295,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
}
}
fn typing_env(&self) -> ty::TypingEnv<'tcx> {
ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env }
}
#[instrument(level = "trace", skip(self), ret)]
fn insert(&mut self, value: Value<'tcx>) -> VnIndex {
let (index, new) = self.values.insert_full(value);
@ -531,7 +535,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
NullOp::OffsetOf(fields) => self
.ecx
.tcx
.offset_of_subfield(self.ecx.param_env(), layout, fields.iter())
.offset_of_subfield(self.typing_env(), layout, fields.iter())
.bytes(),
NullOp::UbChecks => return None,
};
@ -1476,8 +1480,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
if left_meta_ty == right_meta_ty {
true
} else if let Ok(left) =
self.tcx.try_normalize_erasing_regions(self.param_env, left_meta_ty)
&& let Ok(right) = self.tcx.try_normalize_erasing_regions(self.param_env, right_meta_ty)
self.tcx.try_normalize_erasing_regions(self.typing_env(), left_meta_ty)
&& let Ok(right) =
self.tcx.try_normalize_erasing_regions(self.typing_env(), right_meta_ty)
{
left == right
} else {

View file

@ -13,9 +13,7 @@ use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
use rustc_middle::ty::{
self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt, TypeFlags, TypeVisitableExt,
};
use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypeFlags, TypeVisitableExt};
use rustc_session::config::{DebugInfo, OptLevel};
use rustc_span::source_map::Spanned;
use rustc_span::sym;
@ -94,12 +92,12 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
return false;
}
let param_env = tcx.param_env_reveal_all_normalized(def_id);
let typing_env = body.typing_env(tcx);
let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
let mut this = Inliner {
tcx,
param_env,
typing_env,
codegen_fn_attrs,
history: Vec::new(),
changed: false,
@ -115,7 +113,7 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
struct Inliner<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
/// Caller codegen attributes.
codegen_fn_attrs: &'tcx CodegenFnAttrs,
/// Stack of inlined instances.
@ -201,7 +199,11 @@ impl<'tcx> Inliner<'tcx> {
let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() };
let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty;
for arg in args {
if !arg.node.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.param_env) {
if !arg
.node
.ty(&caller_body.local_decls, self.tcx)
.is_sized(self.tcx, self.typing_env.param_env)
{
// We do not allow inlining functions with unsized params. Inlining these functions
// could create unsized locals, which are unsound and being phased out.
return Err("Call has unsized argument");
@ -219,7 +221,7 @@ impl<'tcx> Inliner<'tcx> {
let Ok(callee_body) = callsite.callee.try_instantiate_mir_and_normalize_erasing_regions(
self.tcx,
self.param_env,
self.typing_env,
ty::EarlyBinder::bind(callee_body.clone()),
) else {
return Err("failed to normalize callee body");
@ -230,7 +232,7 @@ impl<'tcx> Inliner<'tcx> {
if !validate_types(
self.tcx,
MirPhase::Runtime(RuntimePhase::Optimized),
self.param_env,
self.typing_env,
&callee_body,
&caller_body,
)
@ -243,13 +245,7 @@ impl<'tcx> Inliner<'tcx> {
// Normally, this shouldn't be required, but trait normalization failure can create a
// validation ICE.
let output_type = callee_body.return_ty();
if !util::sub_types(
self.tcx,
caller_body.typing_mode(self.tcx),
self.param_env,
output_type,
destination_ty,
) {
if !util::sub_types(self.tcx, self.typing_env, output_type, destination_ty) {
trace!(?output_type, ?destination_ty);
return Err("failed to normalize return type");
}
@ -279,13 +275,7 @@ impl<'tcx> Inliner<'tcx> {
self_arg_ty.into_iter().chain(arg_tuple_tys).zip(callee_body.args_iter())
{
let input_type = callee_body.local_decls[input].ty;
if !util::sub_types(
self.tcx,
caller_body.typing_mode(self.tcx),
self.param_env,
input_type,
arg_ty,
) {
if !util::sub_types(self.tcx, self.typing_env, input_type, arg_ty) {
trace!(?arg_ty, ?input_type);
return Err("failed to normalize tuple argument type");
}
@ -294,13 +284,7 @@ impl<'tcx> Inliner<'tcx> {
for (arg, input) in args.iter().zip(callee_body.args_iter()) {
let input_type = callee_body.local_decls[input].ty;
let arg_ty = arg.node.ty(&caller_body.local_decls, self.tcx);
if !util::sub_types(
self.tcx,
caller_body.typing_mode(self.tcx),
self.param_env,
input_type,
arg_ty,
) {
if !util::sub_types(self.tcx, self.typing_env, input_type, arg_ty) {
trace!(?arg_ty, ?input_type);
return Err("failed to normalize argument type");
}
@ -402,9 +386,10 @@ impl<'tcx> Inliner<'tcx> {
let func_ty = func.ty(caller_body, self.tcx);
if let ty::FnDef(def_id, args) = *func_ty.kind() {
// To resolve an instance its args have to be fully normalized.
let args = self.tcx.try_normalize_erasing_regions(self.param_env, args).ok()?;
let callee =
Instance::try_resolve(self.tcx, self.param_env, def_id, args).ok().flatten()?;
let args = self.tcx.try_normalize_erasing_regions(self.typing_env, args).ok()?;
let callee = Instance::try_resolve(self.tcx, self.typing_env, def_id, args)
.ok()
.flatten()?;
if let InstanceKind::Virtual(..) | InstanceKind::Intrinsic(_) = callee.def {
return None;
@ -528,7 +513,7 @@ impl<'tcx> Inliner<'tcx> {
// FIXME: Give a bonus to functions with only a single caller
let mut checker =
CostChecker::new(self.tcx, self.param_env, Some(callsite.callee), callee_body);
CostChecker::new(self.tcx, self.typing_env, Some(callsite.callee), callee_body);
checker.add_function_level_costs();
@ -552,7 +537,7 @@ impl<'tcx> Inliner<'tcx> {
self.tcx,
ty::EarlyBinder::bind(&place.ty(callee_body, tcx).ty),
);
if ty.needs_drop(tcx, self.param_env)
if ty.needs_drop(tcx, self.typing_env)
&& let UnwindAction::Cleanup(unwind) = unwind
{
work_list.push(unwind);

View file

@ -15,7 +15,6 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
(root, target): (ty::Instance<'tcx>, LocalDefId),
) -> bool {
trace!(%root, target = %tcx.def_path_str(target));
let param_env = tcx.param_env_reveal_all_normalized(target);
assert_ne!(
root.def_id().expect_local(),
target,
@ -31,11 +30,11 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
);
#[instrument(
level = "debug",
skip(tcx, param_env, target, stack, seen, recursion_limiter, caller, recursion_limit)
skip(tcx, typing_env, target, stack, seen, recursion_limiter, caller, recursion_limit)
)]
fn process<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
caller: ty::Instance<'tcx>,
target: LocalDefId,
stack: &mut Vec<ty::Instance<'tcx>>,
@ -47,13 +46,13 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
for &(callee, args) in tcx.mir_inliner_callees(caller.def) {
let Ok(args) = caller.try_instantiate_mir_and_normalize_erasing_regions(
tcx,
param_env,
typing_env,
ty::EarlyBinder::bind(args),
) else {
trace!(?caller, ?param_env, ?args, "cannot normalize, skipping");
trace!(?caller, ?typing_env, ?args, "cannot normalize, skipping");
continue;
};
let Ok(Some(callee)) = ty::Instance::try_resolve(tcx, param_env, callee, args) else {
let Ok(Some(callee)) = ty::Instance::try_resolve(tcx, typing_env, callee, args) else {
trace!(?callee, "cannot resolve, skipping");
continue;
};
@ -115,7 +114,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
let found_recursion = ensure_sufficient_stack(|| {
process(
tcx,
param_env,
typing_env,
callee,
target,
stack,
@ -146,7 +145,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
let recursion_limit = tcx.recursion_limit() / 2;
process(
tcx,
param_env,
ty::TypingEnv::post_analysis(tcx, target),
root,
target,
&mut Vec::new(),

View file

@ -69,6 +69,12 @@ struct InstSimplifyContext<'a, 'tcx> {
param_env: ParamEnv<'tcx>,
}
impl<'tcx> InstSimplifyContext<'_, 'tcx> {
fn typing_env(&self) -> ty::TypingEnv<'tcx> {
ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env }
}
}
impl<'tcx> InstSimplifyContext<'_, 'tcx> {
fn should_simplify(&self, source_info: &SourceInfo, rvalue: &Rvalue<'tcx>) -> bool {
self.should_simplify_custom(source_info, "Rvalue", rvalue)
@ -348,7 +354,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
}
let known_is_valid =
intrinsic_assert_panics(self.tcx, self.param_env, args[0], intrinsic_name);
intrinsic_assert_panics(self.tcx, self.typing_env(), args[0], intrinsic_name);
match known_is_valid {
// We don't know the layout or it's not validity assertion at all, don't touch it
None => {}
@ -366,13 +372,13 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
fn intrinsic_assert_panics<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
arg: ty::GenericArg<'tcx>,
intrinsic_name: Symbol,
) -> Option<bool> {
let requirement = ValidityRequirement::from_intrinsic(intrinsic_name)?;
let ty = arg.expect_ty();
Some(!tcx.check_validity_requirement((requirement, param_env.and(ty))).ok()?)
Some(!tcx.check_validity_requirement((requirement, typing_env.as_query_input(ty))).ok()?)
}
fn resolve_rust_intrinsic<'tcx>(

View file

@ -77,13 +77,12 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading {
return;
}
let param_env = tcx.param_env_reveal_all_normalized(def_id);
let typing_env = body.typing_env(tcx);
let arena = &DroplessArena::default();
let mut finder = TOFinder {
tcx,
param_env,
ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine),
typing_env,
ecx: InterpCx::new(tcx, DUMMY_SP, typing_env.param_env, DummyMachine),
body,
arena,
map: Map::new(tcx, body, Some(MAX_PLACES)),
@ -119,7 +118,7 @@ struct ThreadingOpportunity {
struct TOFinder<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
ecx: InterpCx<'tcx, DummyMachine>,
body: &'a Body<'tcx>,
map: Map<'tcx>,
@ -207,7 +206,7 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
let Some(discr) = self.map.find(discr.as_ref()) else { return };
debug!(?discr);
let cost = CostChecker::new(self.tcx, self.param_env, None, self.body);
let cost = CostChecker::new(self.tcx, self.typing_env, None, self.body);
let mut state = State::new_reachable();
let conds = if let Some((value, then, else_)) = targets.as_static_if() {
@ -528,7 +527,8 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
// Avoid handling them, though this could be extended in the future.
return;
}
let Some(value) = value.const_.try_eval_scalar_int(self.tcx, self.param_env) else {
let Some(value) = value.const_.try_eval_scalar_int(self.tcx, self.typing_env)
else {
return;
};
let conds = conditions.map(self.arena, |c| Condition {

View file

@ -18,7 +18,7 @@ use rustc_middle::bug;
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::{self, ConstInt, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{self, ConstInt, ScalarInt, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::Span;
use tracing::{debug, instrument, trace};
@ -65,7 +65,7 @@ impl<'tcx> crate::MirLint<'tcx> for KnownPanicsLint {
struct ConstPropagator<'mir, 'tcx> {
ecx: InterpCx<'tcx, DummyMachine>,
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
worklist: Vec<BasicBlock>,
visited_blocks: BitSet<BasicBlock>,
locals: IndexVec<Local, Value<'tcx>>,
@ -169,25 +169,26 @@ impl<'tcx> ty::layout::HasTyCtxt<'tcx> for ConstPropagator<'_, 'tcx> {
}
}
impl<'tcx> ty::layout::HasParamEnv<'tcx> for ConstPropagator<'_, 'tcx> {
impl<'tcx> ty::layout::HasTypingEnv<'tcx> for ConstPropagator<'_, 'tcx> {
#[inline]
fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.param_env
fn typing_env(&self) -> ty::TypingEnv<'tcx> {
self.typing_env
}
}
impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
fn new(body: &'mir Body<'tcx>, tcx: TyCtxt<'tcx>) -> ConstPropagator<'mir, 'tcx> {
let def_id = body.source.def_id();
let param_env = tcx.param_env_reveal_all_normalized(def_id);
let can_const_prop = CanConstProp::check(tcx, param_env, body);
let ecx = InterpCx::new(tcx, tcx.def_span(def_id), param_env, DummyMachine);
// FIXME(#132279): This is used during the phase transition from analysis
// to runtime, so we have to manually specify the correct typing mode.
let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
let can_const_prop = CanConstProp::check(tcx, typing_env, body);
let ecx = InterpCx::new(tcx, tcx.def_span(def_id), typing_env.param_env, DummyMachine);
ConstPropagator {
ecx,
tcx,
param_env,
typing_env,
worklist: vec![START_BLOCK],
visited_blocks: BitSet::new_empty(body.basic_blocks.len()),
locals: IndexVec::from_elem_n(Value::Uninit, body.local_decls.len()),
@ -260,7 +261,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
// that the `RevealAll` pass has happened and that the body's consts
// are normalized, so any call to resolve before that needs to be
// manually normalized.
let val = self.tcx.try_normalize_erasing_regions(self.param_env, c.const_).ok()?;
let val = self.tcx.try_normalize_erasing_regions(self.typing_env, c.const_).ok()?;
self.use_ecx(|this| this.ecx.eval_mir_constant(&val, c.span, None))?
.as_mplace_or_imm()
@ -450,7 +451,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
if rvalue.has_param() {
return None;
}
if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.param_env) {
if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.typing_env.param_env) {
// the interpreter doesn't support unsized locals (only unsized arguments),
// but rustc does (in a kinda broken way), so we have to skip them here
return None;
@ -622,7 +623,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
NullOp::AlignOf => op_layout.align.abi.bytes(),
NullOp::OffsetOf(fields) => self
.tcx
.offset_of_subfield(self.param_env, op_layout, fields.iter())
.offset_of_subfield(self.typing_env, op_layout, fields.iter())
.bytes(),
NullOp::UbChecks => return None,
};
@ -873,7 +874,7 @@ impl CanConstProp {
/// Returns true if `local` can be propagated
fn check<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
body: &Body<'tcx>,
) -> IndexVec<Local, ConstPropMode> {
let mut cpv = CanConstProp {
@ -888,7 +889,7 @@ impl CanConstProp {
// variant of a union
*val = ConstPropMode::NoPropagation;
} else {
match tcx.layout_of(param_env.and(ty)) {
match tcx.layout_of(typing_env.as_query_input(ty)) {
Ok(layout) if layout.size < Size::from_bytes(MAX_ALLOC_LIMIT) => {}
// Either the layout fails to compute, then we can't use this local anyway
// or the local is too large, then we don't want to.

View file

@ -3,7 +3,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_middle::mir::interpret::AllocId;
use rustc_middle::mir::*;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, AdtDef, ParamEnv, Ty, TyCtxt};
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
use rustc_session::Session;
/// A pass that seeks to optimize unnecessary moves of large enum types, if there is a large
@ -39,8 +39,7 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
// platform, but it will still be valid.
let mut alloc_cache = FxHashMap::default();
let body_did = body.source.def_id();
let param_env = tcx.param_env_reveal_all_normalized(body_did);
let typing_env = body.typing_env(tcx);
let blocks = body.basic_blocks.as_mut();
let local_decls = &mut body.local_decls;
@ -58,7 +57,7 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt {
let ty = lhs.ty(local_decls, tcx).ty;
let (adt_def, num_variants, alloc_id) =
self.candidate(tcx, param_env, ty, &mut alloc_cache)?;
self.candidate(tcx, typing_env, ty, &mut alloc_cache)?;
let source_info = st.source_info;
let span = source_info.span;
@ -207,7 +206,7 @@ impl EnumSizeOpt {
fn candidate<'tcx>(
&self,
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
ty: Ty<'tcx>,
alloc_cache: &mut FxHashMap<Ty<'tcx>, AllocId>,
) -> Option<(AdtDef<'tcx>, usize, AllocId)> {
@ -215,7 +214,7 @@ impl EnumSizeOpt {
ty::Adt(adt_def, _args) if adt_def.is_enum() => adt_def,
_ => return None,
};
let layout = tcx.layout_of(param_env.and(ty)).ok()?;
let layout = tcx.layout_of(typing_env.as_query_input(ty)).ok()?;
let variants = match &layout.variants {
Variants::Single { .. } => return None,
Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => return None,

View file

@ -333,10 +333,14 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LocalDefId> {
}
fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs {
let const_kind = tcx.hir().body_const_context(def);
// N.B., this `borrow()` is guaranteed to be valid (i.e., the value
// cannot yet be stolen), because `mir_promoted()`, which steals
// from `mir_built()`, forces this query to execute before
// performing the steal.
let body = &tcx.mir_built(def).borrow();
let ccx = check_consts::ConstCx::new(tcx, body);
// No need to const-check a non-const `fn`.
match const_kind {
match ccx.const_kind {
Some(ConstContext::Const { .. } | ConstContext::Static(_) | ConstContext::ConstFn) => {}
None => span_bug!(
tcx.def_span(def),
@ -344,20 +348,12 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs {
),
}
// N.B., this `borrow()` is guaranteed to be valid (i.e., the value
// cannot yet be stolen), because `mir_promoted()`, which steals
// from `mir_built()`, forces this query to execute before
// performing the steal.
let body = &tcx.mir_built(def).borrow();
if body.return_ty().references_error() {
// It's possible to reach here without an error being emitted (#121103).
tcx.dcx().span_delayed_bug(body.span, "mir_const_qualif: MIR had errors");
return Default::default();
}
let ccx = check_consts::ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def) };
let mut validator = check_consts::check::Checker::new(&ccx);
validator.check_body();

View file

@ -5,7 +5,7 @@ use rustc_index::IndexSlice;
use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::*;
use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
use rustc_middle::ty::{ParamEnv, ScalarInt, Ty, TyCtxt};
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
use rustc_type_ir::TyKind::*;
use super::simplify::simplify_cfg;
@ -19,8 +19,7 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let def_id = body.source.def_id();
let param_env = tcx.param_env_reveal_all_normalized(def_id);
let typing_env = body.typing_env(tcx);
let mut should_cleanup = false;
for i in 0..body.basic_blocks.len() {
let bbs = &*body.basic_blocks;
@ -40,11 +39,11 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification {
_ => continue,
};
if SimplifyToIf.simplify(tcx, body, bb_idx, param_env).is_some() {
if SimplifyToIf.simplify(tcx, body, bb_idx, typing_env).is_some() {
should_cleanup = true;
continue;
}
if SimplifyToExp::default().simplify(tcx, body, bb_idx, param_env).is_some() {
if SimplifyToExp::default().simplify(tcx, body, bb_idx, typing_env).is_some() {
should_cleanup = true;
continue;
}
@ -65,7 +64,7 @@ trait SimplifyMatch<'tcx> {
tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>,
switch_bb_idx: BasicBlock,
param_env: ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
) -> Option<()> {
let bbs = &body.basic_blocks;
let (discr, targets) = match bbs[switch_bb_idx].terminator().kind {
@ -74,7 +73,7 @@ trait SimplifyMatch<'tcx> {
};
let discr_ty = discr.ty(body.local_decls(), tcx);
self.can_simplify(tcx, targets, param_env, bbs, discr_ty)?;
self.can_simplify(tcx, targets, typing_env, bbs, discr_ty)?;
let mut patch = MirPatch::new(body);
@ -90,7 +89,16 @@ trait SimplifyMatch<'tcx> {
let parent_end = Location { block: switch_bb_idx, statement_index };
patch.add_statement(parent_end, StatementKind::StorageLive(discr_local));
patch.add_assign(parent_end, Place::from(discr_local), Rvalue::Use(discr));
self.new_stmts(tcx, targets, param_env, &mut patch, parent_end, bbs, discr_local, discr_ty);
self.new_stmts(
tcx,
targets,
typing_env,
&mut patch,
parent_end,
bbs,
discr_local,
discr_ty,
);
patch.add_statement(parent_end, StatementKind::StorageDead(discr_local));
patch.patch_terminator(switch_bb_idx, bbs[first].terminator().kind.clone());
patch.apply(body);
@ -104,7 +112,7 @@ trait SimplifyMatch<'tcx> {
&mut self,
tcx: TyCtxt<'tcx>,
targets: &SwitchTargets,
param_env: ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
bbs: &IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
discr_ty: Ty<'tcx>,
) -> Option<()>;
@ -113,7 +121,7 @@ trait SimplifyMatch<'tcx> {
&self,
tcx: TyCtxt<'tcx>,
targets: &SwitchTargets,
param_env: ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
patch: &mut MirPatch<'tcx>,
parent_end: Location,
bbs: &IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
@ -160,7 +168,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf {
&mut self,
tcx: TyCtxt<'tcx>,
targets: &SwitchTargets,
param_env: ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
bbs: &IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
_discr_ty: Ty<'tcx>,
) -> Option<()> {
@ -197,8 +205,8 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf {
) if lhs_f == lhs_s
&& f_c.const_.ty().is_bool()
&& s_c.const_.ty().is_bool()
&& f_c.const_.try_eval_bool(tcx, param_env).is_some()
&& s_c.const_.try_eval_bool(tcx, param_env).is_some() => {}
&& f_c.const_.try_eval_bool(tcx, typing_env).is_some()
&& s_c.const_.try_eval_bool(tcx, typing_env).is_some() => {}
// Otherwise we cannot optimize. Try another block.
_ => return None,
@ -211,7 +219,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf {
&self,
tcx: TyCtxt<'tcx>,
targets: &SwitchTargets,
param_env: ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
patch: &mut MirPatch<'tcx>,
parent_end: Location,
bbs: &IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
@ -235,15 +243,15 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToIf {
StatementKind::Assign(box (_, Rvalue::Use(Operand::Constant(s_c)))),
) => {
// From earlier loop we know that we are dealing with bool constants only:
let f_b = f_c.const_.try_eval_bool(tcx, param_env).unwrap();
let s_b = s_c.const_.try_eval_bool(tcx, param_env).unwrap();
let f_b = f_c.const_.try_eval_bool(tcx, typing_env).unwrap();
let s_b = s_c.const_.try_eval_bool(tcx, typing_env).unwrap();
if f_b == s_b {
// Same value in both blocks. Use statement as is.
patch.add_statement(parent_end, f.kind.clone());
} else {
// Different value between blocks. Make value conditional on switch
// condition.
let size = tcx.layout_of(param_env.and(discr_ty)).unwrap().size;
let size = tcx.layout_of(typing_env.as_query_input(discr_ty)).unwrap().size;
let const_cmp = Operand::const_from_scalar(
tcx,
discr_ty,
@ -363,7 +371,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
&mut self,
tcx: TyCtxt<'tcx>,
targets: &SwitchTargets,
param_env: ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
bbs: &IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
discr_ty: Ty<'tcx>,
) -> Option<()> {
@ -388,7 +396,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
return None;
}
let discr_layout = tcx.layout_of(param_env.and(discr_ty)).unwrap();
let discr_layout = tcx.layout_of(typing_env.as_query_input(discr_ty)).unwrap();
let first_stmts = &bbs[first_target].statements;
let (second_case_val, second_target) = target_iter.next().unwrap();
let second_stmts = &bbs[second_target].statements;
@ -414,8 +422,8 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
&& f_c.const_.ty().is_integral() =>
{
match (
f_c.const_.try_eval_scalar_int(tcx, param_env),
s_c.const_.try_eval_scalar_int(tcx, param_env),
f_c.const_.try_eval_scalar_int(tcx, typing_env),
s_c.const_.try_eval_scalar_int(tcx, typing_env),
) {
(Some(f), Some(s)) if f == s => ExpectedTransformKind::SameByEq {
place: lhs_f,
@ -467,11 +475,11 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
) if lhs_f == lhs_s
&& s_c.const_.ty() == f_ty
&& s_c.const_.try_eval_scalar_int(tcx, param_env) == Some(scalar) => {}
&& s_c.const_.try_eval_scalar_int(tcx, typing_env) == Some(scalar) => {}
(
ExpectedTransformKind::Cast { place: lhs_f, ty: f_ty },
StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
) if let Some(f) = s_c.const_.try_eval_scalar_int(tcx, param_env)
) if let Some(f) = s_c.const_.try_eval_scalar_int(tcx, typing_env)
&& lhs_f == lhs_s
&& s_c.const_.ty() == f_ty
&& can_cast(tcx, other_val, discr_layout, f_ty, f) => {}
@ -487,7 +495,7 @@ impl<'tcx> SimplifyMatch<'tcx> for SimplifyToExp {
&self,
_tcx: TyCtxt<'tcx>,
targets: &SwitchTargets,
_param_env: ParamEnv<'tcx>,
_typing_env: ty::TypingEnv<'tcx>,
patch: &mut MirPatch<'tcx>,
parent_end: Location,
bbs: &IndexSlice<BasicBlock, BasicBlockData<'tcx>>,

View file

@ -325,7 +325,7 @@ impl<'tcx> Validator<'_, 'tcx> {
if let TempState::Defined { location: loc, .. } = self.temps[local]
&& let Left(statement) = self.body.stmt_at(loc)
&& let Some((_, Rvalue::Use(Operand::Constant(c)))) = statement.kind.as_assign()
&& let Some(idx) = c.const_.try_eval_target_usize(self.tcx, self.param_env)
&& let Some(idx) = c.const_.try_eval_target_usize(self.tcx, self.typing_env)
// Determine the type of the thing we are indexing.
&& let ty::Array(_, len) = place_base.ty(self.body, self.tcx).ty.kind()
// It's an array; determine its length.
@ -490,7 +490,7 @@ impl<'tcx> Validator<'_, 'tcx> {
// Integer division: the RHS must be a non-zero const.
let rhs_val = match rhs {
Operand::Constant(c) => {
c.const_.try_eval_scalar_int(self.tcx, self.param_env)
c.const_.try_eval_scalar_int(self.tcx, self.typing_env)
}
_ => None,
};
@ -509,7 +509,7 @@ impl<'tcx> Validator<'_, 'tcx> {
let lhs_val = match lhs {
Operand::Constant(c) => c
.const_
.try_eval_scalar_int(self.tcx, self.param_env),
.try_eval_scalar_int(self.tcx, self.typing_env),
_ => None,
};
let lhs_min = sz.signed_int_min();

View file

@ -1,7 +1,7 @@
use rustc_abi::FieldIdx;
use rustc_index::bit_set::ChunkedBitSet;
use rustc_middle::mir::{Body, TerminatorKind};
use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, VariantDef};
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, VariantDef};
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
use rustc_mir_dataflow::{Analysis, MaybeReachable, move_path_children_matching};
@ -18,8 +18,8 @@ pub(super) struct RemoveUninitDrops;
impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let param_env = tcx.param_env(body.source.def_id());
let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, param_env));
let typing_env = body.typing_env(tcx);
let move_data = MoveData::gather_moves(body, tcx, |ty| ty.needs_drop(tcx, typing_env));
let mut maybe_inits = MaybeInitializedPlaces::new(tcx, body, &move_data)
.iterate_to_fixpoint(tcx, body, Some("remove_uninit_drops"))
@ -40,7 +40,7 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops {
let should_keep = is_needs_drop_and_init(
tcx,
param_env,
typing_env,
maybe_inits,
&move_data,
place.ty(body, tcx).ty,
@ -66,24 +66,24 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops {
fn is_needs_drop_and_init<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
maybe_inits: &ChunkedBitSet<MovePathIndex>,
move_data: &MoveData<'tcx>,
ty: Ty<'tcx>,
mpi: MovePathIndex,
) -> bool {
// No need to look deeper if the root is definitely uninit or if it has no `Drop` impl.
if !maybe_inits.contains(mpi) || !ty.needs_drop(tcx, param_env) {
if !maybe_inits.contains(mpi) || !ty.needs_drop(tcx, typing_env) {
return false;
}
let field_needs_drop_and_init = |(f, f_ty, mpi)| {
let child = move_path_children_matching(move_data, mpi, |x| x.is_field_to(f));
let Some(mpi) = child else {
return Ty::needs_drop(f_ty, tcx, param_env);
return Ty::needs_drop(f_ty, tcx, typing_env);
};
is_needs_drop_and_init(tcx, param_env, maybe_inits, move_data, f_ty, mpi)
is_needs_drop_and_init(tcx, typing_env, maybe_inits, move_data, f_ty, mpi)
};
// This pass is only needed for const-checking, so it doesn't handle as many cases as
@ -110,7 +110,7 @@ fn is_needs_drop_and_init<'tcx>(
let downcast =
move_path_children_matching(move_data, mpi, |x| x.is_downcast_to(vid));
let Some(dc_mpi) = downcast else {
return variant_needs_drop(tcx, param_env, args, variant);
return variant_needs_drop(tcx, typing_env, args, variant);
};
dc_mpi
@ -139,12 +139,12 @@ fn is_needs_drop_and_init<'tcx>(
fn variant_needs_drop<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
args: GenericArgsRef<'tcx>,
variant: &VariantDef,
) -> bool {
variant.fields.iter().any(|field| {
let f_ty = field.ty(tcx, args);
f_ty.needs_drop(tcx, param_env)
f_ty.needs_drop(tcx, typing_env)
})
}

View file

@ -16,18 +16,18 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
trace!("Running RemoveUnneededDrops on {:?}", body.source);
let did = body.source.def_id();
let param_env = tcx.param_env_reveal_all_normalized(did);
let typing_env = body.typing_env(tcx);
let mut should_simplify = false;
for block in body.basic_blocks.as_mut() {
let terminator = block.terminator_mut();
if let TerminatorKind::Drop { place, target, .. } = terminator.kind {
let ty = place.ty(&body.local_decls, tcx);
if ty.ty.needs_drop(tcx, param_env) {
if ty.ty.needs_drop(tcx, typing_env) {
continue;
}
if !tcx.consider_optimizing(|| format!("RemoveUnneededDrops {did:?} ")) {
if !tcx.consider_optimizing(|| {
format!("RemoveUnneededDrops {:?}", body.source.def_id())
}) {
continue;
}
debug!("SUCCESS: replacing `drop` with goto({:?})", target);

View file

@ -21,9 +21,9 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveZsts {
return;
}
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
let typing_env = body.typing_env(tcx);
let local_decls = &body.local_decls;
let mut replacer = Replacer { tcx, param_env, local_decls };
let mut replacer = Replacer { tcx, typing_env, local_decls };
for var_debug_info in &mut body.var_debug_info {
replacer.visit_var_debug_info(var_debug_info);
}
@ -35,7 +35,7 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveZsts {
struct Replacer<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
local_decls: &'a LocalDecls<'tcx>,
}
@ -61,7 +61,7 @@ impl<'tcx> Replacer<'_, 'tcx> {
if !maybe_zst(ty) {
return false;
}
let Ok(layout) = self.tcx.layout_of(self.param_env.and(ty)) else {
let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(ty)) else {
return false;
};
layout.is_zst()

View file

@ -8,14 +8,16 @@ pub(super) struct RevealAll;
impl<'tcx> crate::MirPass<'tcx> for RevealAll {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
RevealAllVisitor { tcx, param_env }.visit_body_preserves_cfg(body);
// FIXME(#132279): This is used during the phase transition from analysis
// to runtime, so we have to manually specify the correct typing mode.
let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
RevealAllVisitor { tcx, typing_env }.visit_body_preserves_cfg(body);
}
}
struct RevealAllVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> {
@ -53,7 +55,7 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> {
// We have to use `try_normalize_erasing_regions` here, since it's
// possible that we visit impossible-to-satisfy where clauses here,
// see #91745
if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.param_env, constant.const_) {
if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.typing_env, constant.const_) {
constant.const_ = c;
}
self.super_const_operand(constant, location);
@ -64,7 +66,7 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> {
// We have to use `try_normalize_erasing_regions` here, since it's
// possible that we visit impossible-to-satisfy where clauses here,
// see #91745
if let Ok(t) = self.tcx.try_normalize_erasing_regions(self.param_env, *ty) {
if let Ok(t) = self.tcx.try_normalize_erasing_regions(self.typing_env, *ty) {
*ty = t;
}
}

View file

@ -274,9 +274,9 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
if ty.is_some() {
let patch = {
let param_env = tcx.param_env_reveal_all_normalized(def_id);
let typing_env = ty::TypingEnv::post_analysis(tcx, def_id);
let mut elaborator =
DropShimElaborator { body: &body, patch: MirPatch::new(&body), tcx, param_env };
DropShimElaborator { body: &body, patch: MirPatch::new(&body), tcx, typing_env };
let dropee = tcx.mk_place_deref(dropee_ptr);
let resume_block = elaborator.patch.resume_block();
elaborate_drops::elaborate_drop(
@ -334,7 +334,7 @@ pub(super) struct DropShimElaborator<'a, 'tcx> {
pub body: &'a Body<'tcx>,
pub patch: MirPatch<'tcx>,
pub tcx: TyCtxt<'tcx>,
pub param_env: ty::ParamEnv<'tcx>,
pub typing_env: ty::TypingEnv<'tcx>,
}
impl fmt::Debug for DropShimElaborator<'_, '_> {
@ -355,8 +355,8 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn param_env(&self) -> ty::ParamEnv<'tcx> {
self.param_env
fn typing_env(&self) -> ty::TypingEnv<'tcx> {
self.typing_env
}
fn drop_style(&self, _path: Self::Path, mode: DropFlagMode) -> DropStyle {
@ -914,7 +914,7 @@ fn build_call_shim<'tcx>(
pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
debug_assert!(tcx.is_constructor(ctor_id));
let param_env = tcx.param_env_reveal_all_normalized(ctor_id);
let typing_env = ty::TypingEnv::post_analysis(tcx, ctor_id);
// Normalize the sig.
let sig = tcx
@ -922,7 +922,7 @@ pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
.instantiate_identity()
.no_bound_vars()
.expect("LBR in ADT constructor signature");
let sig = tcx.normalize_erasing_regions(param_env, sig);
let sig = tcx.normalize_erasing_regions(typing_env, sig);
let ty::Adt(adt_def, args) = sig.output().kind() else {
bug!("unexpected type for ADT ctor {:?}", sig.output());

View file

@ -48,7 +48,7 @@ struct AsyncDestructorCtorShimBuilder<'tcx> {
self_ty: Option<Ty<'tcx>>,
span: Span,
source_info: SourceInfo,
param_env: ty::ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
stack: Vec<Operand<'tcx>>,
last_bb: BasicBlock,
@ -86,14 +86,14 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
// Usual case: noop() + unwind resume + return
let mut bbs = IndexVec::with_capacity(3);
let param_env = tcx.param_env_reveal_all_normalized(def_id);
let typing_env = ty::TypingEnv::post_analysis(tcx, def_id);
AsyncDestructorCtorShimBuilder {
tcx,
def_id,
self_ty,
span,
source_info,
param_env,
typing_env,
stack: Vec::with_capacity(Self::MAX_STACK_LEN),
last_bb: bbs.push(BasicBlockData::new(None)),
@ -422,7 +422,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
statements: Vec::new(),
terminator: Some(Terminator {
source_info,
kind: if self.locals[local].ty.needs_drop(self.tcx, self.param_env) {
kind: if self.locals[local].ty.needs_drop(self.tcx, self.typing_env) {
TerminatorKind::Drop {
place: local.into(),
target: *top_cleanup_bb,

View file

@ -18,14 +18,14 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
trace!("Running SimplifyConstCondition on {:?}", body.source);
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
let typing_env = body.typing_env(tcx);
'blocks: for block in body.basic_blocks_mut() {
for stmt in block.statements.iter_mut() {
// Simplify `assume` of a known value: either a NOP or unreachable.
if let StatementKind::Intrinsic(box ref intrinsic) = stmt.kind
&& let NonDivergingIntrinsic::Assume(discr) = intrinsic
&& let Operand::Constant(ref c) = discr
&& let Some(constant) = c.const_.try_eval_bool(tcx, param_env)
&& let Some(constant) = c.const_.try_eval_bool(tcx, typing_env)
{
if constant {
stmt.make_nop();
@ -42,7 +42,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition {
TerminatorKind::SwitchInt {
discr: Operand::Constant(ref c), ref targets, ..
} => {
let constant = c.const_.try_eval_bits(tcx, param_env);
let constant = c.const_.try_eval_bits(tcx, typing_env);
if let Some(constant) = constant {
let target = targets.target_for_value(constant);
TerminatorKind::Goto { target }
@ -52,7 +52,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition {
}
TerminatorKind::Assert {
target, cond: Operand::Constant(ref c), expected, ..
} => match c.const_.try_eval_bool(tcx, param_env) {
} => match c.const_.try_eval_bool(tcx, typing_env) {
Some(v) if v == expected => TerminatorKind::Goto { target },
_ => continue,
},

View file

@ -37,7 +37,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
let opts = helper.find_optimizations();
let mut storage_deads_to_insert = vec![];
let mut storage_deads_to_remove: Vec<(usize, BasicBlock)> = vec![];
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
let typing_env = body.typing_env(tcx);
for opt in opts {
trace!("SUCCESS: Applying {:?}", opt);
// replace terminator with a switchInt that switches on the integer directly
@ -46,7 +46,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
let new_value = match opt.branch_value_scalar {
Scalar::Int(int) => {
let layout = tcx
.layout_of(param_env.and(opt.branch_value_ty))
.layout_of(typing_env.as_query_input(opt.branch_value_ty))
.expect("if we have an evaluated constant we must know the layout");
int.to_bits(layout.size)
}

View file

@ -28,12 +28,12 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates {
}
let mut excluded = excluded_locals(body);
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
let typing_env = body.typing_env(tcx);
loop {
debug!(?excluded);
let escaping = escaping_locals(tcx, param_env, &excluded, body);
let escaping = escaping_locals(tcx, typing_env, &excluded, body);
debug!(?escaping);
let replacements = compute_flattening(tcx, param_env, body, escaping);
let replacements = compute_flattening(tcx, typing_env, body, escaping);
debug!(?replacements);
let all_dead_locals = replace_flattened_locals(tcx, body, replacements);
if !all_dead_locals.is_empty() {
@ -59,7 +59,7 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates {
/// client code.
fn escaping_locals<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
excluded: &BitSet<Local>,
body: &Body<'tcx>,
) -> BitSet<Local> {
@ -84,7 +84,7 @@ fn escaping_locals<'tcx>(
// niche, so we do not want to automatically exclude it.
return false;
}
let Ok(layout) = tcx.layout_of(param_env.and(ty)) else {
let Ok(layout) = tcx.layout_of(typing_env.as_query_input(ty)) else {
// We can't get the layout
return true;
};
@ -196,7 +196,7 @@ impl<'tcx> ReplacementMap<'tcx> {
/// The replacement will be done later in `ReplacementVisitor`.
fn compute_flattening<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
body: &mut Body<'tcx>,
escaping: BitSet<Local>,
) -> ReplacementMap<'tcx> {
@ -208,7 +208,7 @@ fn compute_flattening<'tcx>(
}
let decl = body.local_decls[local].clone();
let ty = decl.ty;
iter_fields(ty, tcx, param_env, |variant, field, field_ty| {
iter_fields(ty, tcx, typing_env, |variant, field, field_ty| {
if variant.is_some() {
// Downcasts are currently not supported.
return;

View file

@ -92,9 +92,7 @@ impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching {
let Some(discriminant_ty) = get_switched_on_type(bb_data, tcx, body) else { continue };
let layout = tcx.layout_of(
tcx.param_env_reveal_all_normalized(body.source.def_id()).and(discriminant_ty),
);
let layout = tcx.layout_of(body.typing_env(tcx).as_query_input(discriminant_ty));
let mut allowed_variants = if let Ok(layout) = layout {
// Find allowed variants based on uninhabited.

View file

@ -12,8 +12,7 @@ use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::{
self, CoroutineArgsExt, InstanceKind, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitableExt,
Variance,
self, CoroutineArgsExt, InstanceKind, ScalarInt, Ty, TyCtxt, TypeVisitableExt, Variance,
};
use rustc_middle::{bug, span_bug};
use rustc_trait_selection::traits::ObligationCtxt;
@ -47,9 +46,10 @@ impl<'tcx> crate::MirPass<'tcx> for Validator {
if matches!(body.source.instance, InstanceKind::Intrinsic(..) | InstanceKind::Virtual(..)) {
return;
}
debug_assert_eq!(self.mir_phase, body.phase);
let def_id = body.source.def_id();
let mir_phase = self.mir_phase;
let param_env = mir_phase.param_env(tcx, def_id);
let mir_phase = body.phase;
let typing_env = body.typing_env(tcx);
let can_unwind = if mir_phase <= MirPhase::Runtime(RuntimePhase::Initial) {
// In this case `AbortUnwindingCalls` haven't yet been executed.
true
@ -86,7 +86,7 @@ impl<'tcx> crate::MirPass<'tcx> for Validator {
cfg_checker.check_cleanup_control_flow();
// Also run the TypeChecker.
for (location, msg) in validate_types(tcx, self.mir_phase, param_env, body, body) {
for (location, msg) in validate_types(tcx, self.mir_phase, typing_env, body, body) {
cfg_checker.fail(location, msg);
}
@ -532,12 +532,12 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
pub(super) fn validate_types<'tcx>(
tcx: TyCtxt<'tcx>,
mir_phase: MirPhase,
param_env: ty::ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
body: &Body<'tcx>,
caller_body: &Body<'tcx>,
) -> Vec<(Location, String)> {
let mut type_checker =
TypeChecker { body, caller_body, tcx, param_env, mir_phase, failures: Vec::new() };
TypeChecker { body, caller_body, tcx, typing_env, mir_phase, failures: Vec::new() };
type_checker.visit_body(body);
type_checker.failures
}
@ -546,7 +546,7 @@ struct TypeChecker<'a, 'tcx> {
body: &'a Body<'tcx>,
caller_body: &'a Body<'tcx>,
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
mir_phase: MirPhase,
failures: Vec<(Location, String)>,
}
@ -582,14 +582,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
Variance::Covariant
};
crate::util::relate_types(
self.tcx,
self.body.typing_mode(self.tcx),
self.param_env,
variance,
src,
dest,
)
crate::util::relate_types(self.tcx, self.typing_env, variance, src, dest)
}
/// Check that the given predicate definitely holds in the param-env of this MIR body.
@ -608,12 +601,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
return true;
}
let infcx = self.tcx.infer_ctxt().build(self.body.typing_mode(self.tcx));
let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env);
let ocx = ObligationCtxt::new(&infcx);
ocx.register_obligation(Obligation::new(
self.tcx,
ObligationCause::dummy(),
self.param_env,
param_env,
pred,
));
ocx.select_all_or_error().is_empty()
@ -630,7 +623,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
if let Operand::Copy(place) = operand {
let ty = place.ty(&self.body.local_decls, self.tcx).ty;
if !ty.is_copy_modulo_regions(self.tcx, self.param_env) {
if !ty.is_copy_modulo_regions(self.tcx, self.typing_env.param_env) {
self.fail(location, format!("`Operand::Copy` with non-`Copy` type {ty}"));
}
}
@ -802,8 +795,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
ProjectionElem::Subtype(ty) => {
if !util::sub_types(
self.tcx,
self.body.typing_mode(self.tcx),
self.param_env,
self.typing_env,
ty,
place_ref.ty(&self.body.local_decls, self.tcx).ty,
) {
@ -916,7 +908,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
assert!(adt_def.is_union());
assert_eq!(idx, FIRST_VARIANT);
let dest_ty = self.tcx.normalize_erasing_regions(
self.param_env,
self.typing_env,
adt_def.non_enum_variant().fields[field].ty(self.tcx, args),
);
if let [field] = fields.raw.as_slice() {
@ -938,7 +930,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
for (src, dest) in std::iter::zip(fields, &variant.fields) {
let dest_ty = self
.tcx
.normalize_erasing_regions(self.param_env, dest.ty(self.tcx, args));
.normalize_erasing_regions(self.typing_env, dest.ty(self.tcx, args));
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest_ty) {
self.fail(location, "adt field has the wrong type");
}
@ -997,7 +989,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
}
// FIXME: check `Thin` instead of `Sized`
if !in_pointee.is_sized(self.tcx, self.param_env) {
if !in_pointee.is_sized(self.tcx, self.typing_env.param_env) {
self.fail(location, "input pointer must be thin");
}
} else {
@ -1012,7 +1004,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
if !self.mir_assign_valid_types(metadata_ty, self.tcx.types.usize) {
self.fail(location, "slice metadata must be usize");
}
} else if pointee_ty.is_sized(self.tcx, self.param_env) {
} else if pointee_ty.is_sized(self.tcx, self.typing_env.param_env) {
if metadata_ty != self.tcx.types.unit {
self.fail(location, "metadata for pointer-to-thin must be unit");
}
@ -1301,8 +1293,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
if !self
.tcx
.normalize_erasing_regions(self.param_env, op_ty)
.is_sized(self.tcx, self.param_env)
.normalize_erasing_regions(self.typing_env, op_ty)
.is_sized(self.tcx, self.typing_env.param_env)
{
self.fail(
location,
@ -1311,8 +1303,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
}
if !self
.tcx
.normalize_erasing_regions(self.param_env, *target_type)
.is_sized(self.tcx, self.param_env)
.normalize_erasing_regions(self.typing_env, *target_type)
.is_sized(self.tcx, self.typing_env.param_env)
{
self.fail(
location,
@ -1353,7 +1345,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
return;
};
current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty);
current_ty = self.tcx.normalize_erasing_regions(self.typing_env, f_ty);
}
ty::Adt(adt_def, args) => {
let Some(field) = adt_def.variant(variant).fields.get(field) else {
@ -1362,7 +1354,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
};
let f_ty = field.ty(self.tcx, args);
current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty);
current_ty = self.tcx.normalize_erasing_regions(self.typing_env, f_ty);
}
_ => {
self.fail(