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

continue `ParamEnv` to `TypingEnv` transition

cc #132279

r? `@compiler-errors`
This commit is contained in:
bors 2024-11-20 06:22:01 +00:00
commit 70e814bd9e
107 changed files with 512 additions and 575 deletions

View File

@ -1727,7 +1727,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// `Sized` bound in no way depends on precise regions, so this // `Sized` bound in no way depends on precise regions, so this
// shouldn't affect `is_sized`. // shouldn't affect `is_sized`.
let erased_ty = tcx.erase_regions(ty); let erased_ty = tcx.erase_regions(ty);
if !erased_ty.is_sized(tcx, self.infcx.param_env) { // FIXME(#132279): Using `Ty::is_sized` causes us to incorrectly handle opaques here.
if !erased_ty.is_sized(tcx, self.infcx.typing_env(self.infcx.param_env)) {
// in current MIR construction, all non-control-flow rvalue // in current MIR construction, all non-control-flow rvalue
// expressions evaluate through `as_temp` or `into` a return // expressions evaluate through `as_temp` or `into` a return
// slot or local, so to find all unsized rvalues it is enough // slot or local, so to find all unsized rvalues it is enough

View File

@ -11,7 +11,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::InlineAsmMacro; use rustc_middle::mir::InlineAsmMacro;
use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::TypeVisitableExt;
use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv};
use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::print::with_no_trimmed_paths;
use crate::constant::ConstantCx; use crate::constant::ConstantCx;
@ -841,7 +841,7 @@ fn codegen_stmt<'tcx>(
lval.write_cvalue(fx, CValue::by_val(operand, box_layout)); lval.write_cvalue(fx, CValue::by_val(operand, box_layout));
} }
Rvalue::NullaryOp(ref null_op, ty) => { Rvalue::NullaryOp(ref null_op, ty) => {
assert!(lval.layout().ty.is_sized(fx.tcx, ty::ParamEnv::reveal_all())); assert!(lval.layout().ty.is_sized(fx.tcx, fx.typing_env()));
let layout = fx.layout_of(fx.monomorphize(ty)); let layout = fx.layout_of(fx.monomorphize(ty));
let val = match null_op { let val = match null_op {
NullOp::SizeOf => layout.size.bytes(), NullOp::SizeOf => layout.size.bytes(),

View File

@ -103,7 +103,7 @@ fn clif_pair_type_from_ty<'tcx>(
/// Is a pointer to this type a wide ptr? /// Is a pointer to this type a wide ptr?
pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
if ty.is_sized(tcx, ty::ParamEnv::reveal_all()) { if ty.is_sized(tcx, ty::TypingEnv::fully_monomorphized()) {
return false; return false;
} }

View File

@ -744,7 +744,11 @@ fn codegen_regular_intrinsic_call<'tcx>(
let const_val = fx let const_val = fx
.tcx .tcx
.const_eval_instance(ty::ParamEnv::reveal_all(), instance, source_info.span) .const_eval_instance(
ty::TypingEnv::fully_monomorphized(),
instance,
source_info.span,
)
.unwrap(); .unwrap();
let val = crate::constant::codegen_const_value(fx, const_val, ret.layout().ty); let val = crate::constant::codegen_const_value(fx, const_val, ret.layout().ty);
ret.write_cvalue(fx, val); ret.write_cvalue(fx, val);

View File

@ -22,7 +22,7 @@ use rustc_middle::mir::BinOp;
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout}; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypingMode}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_session::Session; use rustc_session::Session;
use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType}; use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
@ -119,7 +119,8 @@ pub fn validate_trivial_unsize<'tcx>(
) -> bool { ) -> bool {
match (source_data.principal(), target_data.principal()) { match (source_data.principal(), target_data.principal()) {
(Some(hr_source_principal), Some(hr_target_principal)) => { (Some(hr_source_principal), Some(hr_target_principal)) => {
let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis); let (infcx, param_env) =
tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv::fully_monomorphized());
let universe = infcx.universe(); let universe = infcx.universe();
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
infcx.enter_forall(hr_target_principal, |target_principal| { infcx.enter_forall(hr_target_principal, |target_principal| {
@ -130,7 +131,7 @@ pub fn validate_trivial_unsize<'tcx>(
); );
let Ok(()) = ocx.eq_trace( let Ok(()) = ocx.eq_trace(
&ObligationCause::dummy(), &ObligationCause::dummy(),
ty::ParamEnv::reveal_all(), param_env,
ToTrace::to_trace( ToTrace::to_trace(
&ObligationCause::dummy(), &ObligationCause::dummy(),
hr_target_principal, hr_target_principal,

View File

@ -146,10 +146,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
| sym::type_id | sym::type_id
| sym::type_name | sym::type_name
| sym::variant_count => { | sym::variant_count => {
let value = bx let value = bx.tcx().const_eval_instance(bx.typing_env(), instance, span).unwrap();
.tcx()
.const_eval_instance(ty::ParamEnv::reveal_all(), instance, span)
.unwrap();
OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx) OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx)
} }
sym::arith_offset => { sym::arith_offset => {

View File

@ -78,15 +78,15 @@ pub trait DerivedTypeCodegenMethods<'tcx>:
} }
fn type_is_sized(&self, ty: Ty<'tcx>) -> bool { fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
ty.is_sized(self.tcx(), ty::ParamEnv::reveal_all()) ty.is_sized(self.tcx(), self.typing_env())
} }
fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
ty.is_freeze(self.tcx(), ty::ParamEnv::reveal_all()) ty.is_freeze(self.tcx(), self.typing_env())
} }
fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool { fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
if ty.is_sized(self.tcx(), self.param_env()) { if ty.is_sized(self.tcx(), self.typing_env()) {
return false; return false;
} }

View File

@ -120,10 +120,7 @@ where
/// ///
/// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134 /// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134
fn shared_borrow_allows_mutation(&self, place: mir::Place<'tcx>) -> bool { fn shared_borrow_allows_mutation(&self, place: mir::Place<'tcx>) -> bool {
!place !place.ty(self.ccx.body, self.ccx.tcx).ty.is_freeze(self.ccx.tcx, self.ccx.typing_env)
.ty(self.ccx.body, self.ccx.tcx)
.ty
.is_freeze(self.ccx.tcx, self.ccx.typing_env.param_env)
} }
} }

View File

@ -7,7 +7,6 @@ use rustc_middle::bug;
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo}; use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo};
use rustc_middle::mir::{self, ConstAlloc, ConstValue}; use rustc_middle::mir::{self, ConstAlloc, ConstValue};
use rustc_middle::query::TyCtxtAt; use rustc_middle::query::TyCtxtAt;
use rustc_middle::traits::Reveal;
use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
@ -31,7 +30,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
cid: GlobalId<'tcx>, cid: GlobalId<'tcx>,
body: &'tcx mir::Body<'tcx>, body: &'tcx mir::Body<'tcx>,
) -> InterpResult<'tcx, R> { ) -> InterpResult<'tcx, R> {
trace!(?ecx.param_env); trace!(?ecx.typing_env);
let tcx = *ecx.tcx; let tcx = *ecx.tcx;
assert!( assert!(
cid.promoted.is_some() cid.promoted.is_some()
@ -126,14 +125,14 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>( pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
root_span: Span, root_span: Span,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
can_access_mut_global: CanAccessMutGlobal, can_access_mut_global: CanAccessMutGlobal,
) -> CompileTimeInterpCx<'tcx> { ) -> CompileTimeInterpCx<'tcx> {
debug!("mk_eval_cx: {:?}", param_env); debug!("mk_eval_cx: {:?}", typing_env);
InterpCx::new( InterpCx::new(
tcx, tcx,
root_span, root_span,
param_env, typing_env,
CompileTimeMachine::new(can_access_mut_global, CheckAlignment::No), CompileTimeMachine::new(can_access_mut_global, CheckAlignment::No),
) )
} }
@ -142,11 +141,11 @@ pub(crate) fn mk_eval_cx_to_read_const_val<'tcx>(
/// Returns both the context and an `OpTy` that represents the constant. /// Returns both the context and an `OpTy` that represents the constant.
pub fn mk_eval_cx_for_const_val<'tcx>( pub fn mk_eval_cx_for_const_val<'tcx>(
tcx: TyCtxtAt<'tcx>, tcx: TyCtxtAt<'tcx>,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
val: mir::ConstValue<'tcx>, val: mir::ConstValue<'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
) -> Option<(CompileTimeInterpCx<'tcx>, OpTy<'tcx>)> { ) -> Option<(CompileTimeInterpCx<'tcx>, OpTy<'tcx>)> {
let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, param_env, CanAccessMutGlobal::No); let ecx = mk_eval_cx_to_read_const_val(tcx.tcx, tcx.span, typing_env, CanAccessMutGlobal::No);
// FIXME: is it a problem to discard the error here? // FIXME: is it a problem to discard the error here?
let op = ecx.const_val_to_op(val, ty, None).discard_err()?; let op = ecx.const_val_to_op(val, ty, None).discard_err()?;
Some((ecx, op)) Some((ecx, op))
@ -221,7 +220,7 @@ pub(super) fn op_to_const<'tcx>(
let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs
debug_assert!( debug_assert!(
matches!( matches!(
ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env()).kind(), ecx.tcx.struct_tail_for_codegen(pointee_ty, ecx.typing_env).kind(),
ty::Str | ty::Slice(..), ty::Str | ty::Slice(..),
), ),
"`ConstValue::Slice` is for slice-tailed types only, but got {}", "`ConstValue::Slice` is for slice-tailed types only, but got {}",
@ -245,7 +244,7 @@ pub(super) fn op_to_const<'tcx>(
pub(crate) fn turn_into_const_value<'tcx>( pub(crate) fn turn_into_const_value<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
constant: ConstAlloc<'tcx>, constant: ConstAlloc<'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
) -> ConstValue<'tcx> { ) -> ConstValue<'tcx> {
let cid = key.value; let cid = key.value;
let def_id = cid.instance.def.def_id(); let def_id = cid.instance.def.def_id();
@ -254,7 +253,7 @@ pub(crate) fn turn_into_const_value<'tcx>(
let ecx = mk_eval_cx_to_read_const_val( let ecx = mk_eval_cx_to_read_const_val(
tcx, tcx,
tcx.def_span(key.value.instance.def_id()), tcx.def_span(key.value.instance.def_id()),
key.param_env, key.typing_env,
CanAccessMutGlobal::from(is_static), CanAccessMutGlobal::from(is_static),
); );
@ -274,23 +273,16 @@ pub(crate) fn turn_into_const_value<'tcx>(
#[instrument(skip(tcx), level = "debug")] #[instrument(skip(tcx), level = "debug")]
pub fn eval_to_const_value_raw_provider<'tcx>( pub fn eval_to_const_value_raw_provider<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> { ) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> {
// Const eval always happens in Reveal::All mode in order to be able to use the hidden types of
// opaque types. This is needed for trivial things like `size_of`, but also for using associated
// types that are not specified in the opaque type.
assert_eq!(key.param_env.reveal(), Reveal::All);
let typing_env =
ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: key.param_env };
// We call `const_eval` for zero arg intrinsics, too, in order to cache their value. // We call `const_eval` for zero arg intrinsics, too, in order to cache their value.
// Catch such calls and evaluate them instead of trying to load a constant's MIR. // Catch such calls and evaluate them instead of trying to load a constant's MIR.
if let ty::InstanceKind::Intrinsic(def_id) = key.value.instance.def { if let ty::InstanceKind::Intrinsic(def_id) = key.value.instance.def {
let ty = key.value.instance.ty(tcx, typing_env); let ty = key.value.instance.ty(tcx, key.typing_env);
let ty::FnDef(_, args) = ty.kind() else { let ty::FnDef(_, args) = ty.kind() else {
bug!("intrinsic with type {:?}", ty); bug!("intrinsic with type {:?}", ty);
}; };
return eval_nullary_intrinsic(tcx, key.param_env, def_id, args).report_err().map_err( return eval_nullary_intrinsic(tcx, key.typing_env, def_id, args).report_err().map_err(
|error| { |error| {
let span = tcx.def_span(def_id); let span = tcx.def_span(def_id);
@ -317,7 +309,7 @@ pub fn eval_static_initializer_provider<'tcx>(
let instance = ty::Instance::mono(tcx, def_id.to_def_id()); let instance = ty::Instance::mono(tcx, def_id.to_def_id());
let cid = rustc_middle::mir::interpret::GlobalId { instance, promoted: None }; let cid = rustc_middle::mir::interpret::GlobalId { instance, promoted: None };
eval_in_interpreter(tcx, cid, ty::ParamEnv::reveal_all()) eval_in_interpreter(tcx, cid, ty::TypingEnv::fully_monomorphized())
} }
pub trait InterpretationResult<'tcx> { pub trait InterpretationResult<'tcx> {
@ -342,16 +334,14 @@ impl<'tcx> InterpretationResult<'tcx> for ConstAlloc<'tcx> {
#[instrument(skip(tcx), level = "debug")] #[instrument(skip(tcx), level = "debug")]
pub fn eval_to_allocation_raw_provider<'tcx>( pub fn eval_to_allocation_raw_provider<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>,
) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> { ) -> ::rustc_middle::mir::interpret::EvalToAllocationRawResult<'tcx> {
// This shouldn't be used for statics, since statics are conceptually places, // This shouldn't be used for statics, since statics are conceptually places,
// not values -- so what we do here could break pointer identity. // not values -- so what we do here could break pointer identity.
assert!(key.value.promoted.is_some() || !tcx.is_static(key.value.instance.def_id())); assert!(key.value.promoted.is_some() || !tcx.is_static(key.value.instance.def_id()));
// Const eval always happens in Reveal::All mode in order to be able to use the hidden types of // Const eval always happens in PostAnalysis mode . See the comment in
// opaque types. This is needed for trivial things like `size_of`, but also for using associated // `InterpCx::new` for more details.
// types that are not specified in the opaque type. debug_assert_eq!(key.typing_env.typing_mode, ty::TypingMode::PostAnalysis);
assert_eq!(key.param_env.reveal(), Reveal::All);
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
// Make sure we format the instance even if we do not print it. // Make sure we format the instance even if we do not print it.
// This serves as a regression test against an ICE on printing. // This serves as a regression test against an ICE on printing.
@ -362,13 +352,13 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
trace!("const eval: {:?} ({})", key, instance); trace!("const eval: {:?} ({})", key, instance);
} }
eval_in_interpreter(tcx, key.value, key.param_env) eval_in_interpreter(tcx, key.value, key.typing_env)
} }
fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>( fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
cid: GlobalId<'tcx>, cid: GlobalId<'tcx>,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
) -> Result<R, ErrorHandled> { ) -> Result<R, ErrorHandled> {
let def = cid.instance.def.def_id(); let def = cid.instance.def.def_id();
let is_static = tcx.is_static(def); let is_static = tcx.is_static(def);
@ -376,7 +366,7 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
let mut ecx = InterpCx::new( let mut ecx = InterpCx::new(
tcx, tcx,
tcx.def_span(def), tcx.def_span(def),
param_env, typing_env,
// Statics (and promoteds inside statics) may access mutable global memory, because unlike consts // Statics (and promoteds inside statics) may access mutable global memory, because unlike consts
// they do not have to behave "as if" they were evaluated at runtime. // they do not have to behave "as if" they were evaluated at runtime.
// For consts however we want to ensure they behave "as if" they were evaluated at runtime, // For consts however we want to ensure they behave "as if" they were evaluated at runtime,

View File

@ -667,7 +667,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
.is_some_and(|p| !p.immutable()) .is_some_and(|p| !p.immutable())
{ {
// That next check is expensive, that's why we have all the guards above. // That next check is expensive, that's why we have all the guards above.
let is_immutable = ty.is_freeze(*ecx.tcx, ecx.param_env); let is_immutable = ty.is_freeze(*ecx.tcx, ecx.typing_env);
let place = ecx.ref_to_mplace(val)?; let place = ecx.ref_to_mplace(val)?;
let new_place = if is_immutable { let new_place = if is_immutable {
place.map_provenance(CtfeProvenance::as_immutable) place.map_provenance(CtfeProvenance::as_immutable)

View File

@ -38,8 +38,8 @@ pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>(
val: mir::ConstValue<'tcx>, val: mir::ConstValue<'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
) -> Option<mir::DestructuredConstant<'tcx>> { ) -> Option<mir::DestructuredConstant<'tcx>> {
let param_env = ty::ParamEnv::reveal_all(); let typing_env = ty::TypingEnv::fully_monomorphized();
let (ecx, op) = mk_eval_cx_for_const_val(tcx, param_env, val, ty)?; let (ecx, op) = mk_eval_cx_for_const_val(tcx, typing_env, val, ty)?;
// We go to `usize` as we cannot allocate anything bigger anyway. // We go to `usize` as we cannot allocate anything bigger anyway.
let (field_count, variant, down) = match ty.kind() { let (field_count, variant, down) = match ty.kind() {
@ -76,10 +76,12 @@ pub fn tag_for_variant_provider<'tcx>(
) -> Option<ty::ScalarInt> { ) -> Option<ty::ScalarInt> {
assert!(ty.is_enum()); assert!(ty.is_enum());
// FIXME: This uses an empty `TypingEnv` even though
// it may be used by a generic CTFE.
let ecx = InterpCx::new( let ecx = InterpCx::new(
tcx, tcx,
ty.default_span(tcx), ty.default_span(tcx),
ty::ParamEnv::reveal_all(), ty::TypingEnv::fully_monomorphized(),
crate::const_eval::DummyMachine, crate::const_eval::DummyMachine,
); );

View File

@ -2,7 +2,6 @@ use rustc_abi::{BackendRepr, VariantIdx};
use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId}; use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
use rustc_middle::ty::solve::Reveal;
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
use rustc_middle::{bug, mir}; use rustc_middle::{bug, mir};
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
@ -229,16 +228,19 @@ fn create_valtree_place<'tcx>(
/// Evaluates a constant and turns it into a type-level constant value. /// Evaluates a constant and turns it into a type-level constant value.
pub(crate) fn eval_to_valtree<'tcx>( pub(crate) fn eval_to_valtree<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
cid: GlobalId<'tcx>, cid: GlobalId<'tcx>,
) -> EvalToValTreeResult<'tcx> { ) -> EvalToValTreeResult<'tcx> {
let const_alloc = tcx.eval_to_allocation_raw(param_env.and(cid))?; // Const eval always happens in PostAnalysis mode . See the comment in
// `InterpCx::new` for more details.
debug_assert_eq!(typing_env.typing_mode, ty::TypingMode::PostAnalysis);
let const_alloc = tcx.eval_to_allocation_raw(typing_env.as_query_input(cid))?;
// FIXME Need to provide a span to `eval_to_valtree` // FIXME Need to provide a span to `eval_to_valtree`
let ecx = mk_eval_cx_to_read_const_val( let ecx = mk_eval_cx_to_read_const_val(
tcx, tcx,
DUMMY_SP, DUMMY_SP,
param_env, typing_env,
// It is absolutely crucial for soundness that // It is absolutely crucial for soundness that
// we do not read from mutable memory. // we do not read from mutable memory.
CanAccessMutGlobal::No, CanAccessMutGlobal::No,
@ -273,7 +275,8 @@ pub(crate) fn eval_to_valtree<'tcx>(
#[instrument(skip(tcx), level = "debug", ret)] #[instrument(skip(tcx), level = "debug", ret)]
pub fn valtree_to_const_value<'tcx>( pub fn valtree_to_const_value<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, typing_env: ty::TypingEnv<'tcx>,
ty: Ty<'tcx>,
valtree: ty::ValTree<'tcx>, valtree: ty::ValTree<'tcx>,
) -> mir::ConstValue<'tcx> { ) -> mir::ConstValue<'tcx> {
// Basic idea: We directly construct `Scalar` values from trivial `ValTree`s // Basic idea: We directly construct `Scalar` values from trivial `ValTree`s
@ -282,10 +285,6 @@ pub fn valtree_to_const_value<'tcx>(
// the `ValTree` and using `place_projection` and `place_field` to // the `ValTree` and using `place_projection` and `place_field` to
// create inner `MPlace`s which are filled recursively. // create inner `MPlace`s which are filled recursively.
// FIXME Does this need an example? // FIXME Does this need an example?
let (param_env, ty) = param_env_ty.into_parts();
debug_assert_eq!(param_env.reveal(), Reveal::All);
let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env };
match *ty.kind() { match *ty.kind() {
ty::FnDef(..) => { ty::FnDef(..) => {
assert!(valtree.unwrap_branch().is_empty()); assert!(valtree.unwrap_branch().is_empty());
@ -299,10 +298,10 @@ pub fn valtree_to_const_value<'tcx>(
), ),
} }
} }
ty::Pat(ty, _) => valtree_to_const_value(tcx, param_env.and(ty), valtree), ty::Pat(ty, _) => valtree_to_const_value(tcx, typing_env, ty, valtree),
ty::Ref(_, inner_ty, _) => { ty::Ref(_, inner_ty, _) => {
let mut ecx = let mut ecx =
mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No); mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, typing_env, CanAccessMutGlobal::No);
let imm = valtree_to_ref(&mut ecx, valtree, inner_ty); let imm = valtree_to_ref(&mut ecx, valtree, inner_ty);
let imm = let imm =
ImmTy::from_immediate(imm, tcx.layout_of(typing_env.as_query_input(ty)).unwrap()); ImmTy::from_immediate(imm, tcx.layout_of(typing_env.as_query_input(ty)).unwrap());
@ -324,14 +323,14 @@ pub fn valtree_to_const_value<'tcx>(
for (i, &inner_valtree) in branches.iter().enumerate() { for (i, &inner_valtree) in branches.iter().enumerate() {
let field = layout.field(&LayoutCx::new(tcx, typing_env), i); let field = layout.field(&LayoutCx::new(tcx, typing_env), i);
if !field.is_zst() { if !field.is_zst() {
return valtree_to_const_value(tcx, param_env.and(field.ty), inner_valtree); return valtree_to_const_value(tcx, typing_env, field.ty, inner_valtree);
} }
} }
bug!("could not find non-ZST field during in {layout:#?}"); bug!("could not find non-ZST field during in {layout:#?}");
} }
let mut ecx = let mut ecx =
mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, param_env, CanAccessMutGlobal::No); mk_eval_cx_to_read_const_val(tcx, DUMMY_SP, typing_env, CanAccessMutGlobal::No);
// Need to create a place for this valtree. // Need to create a place for this valtree.
let place = create_valtree_place(&mut ecx, layout, valtree); let place = create_valtree_place(&mut ecx, layout, valtree);

View File

@ -215,7 +215,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// Even if `ty` is normalized, the search for the unsized tail will project // Even if `ty` is normalized, the search for the unsized tail will project
// to fields, which can yield non-normalized types. So we need to provide a // to fields, which can yield non-normalized types. So we need to provide a
// normalization function. // normalization function.
let normalize = |ty| self.tcx.normalize_erasing_regions(self.typing_env(), ty); let normalize = |ty| self.tcx.normalize_erasing_regions(self.typing_env, ty);
ty.ptr_metadata_ty(*self.tcx, normalize) ty.ptr_metadata_ty(*self.tcx, normalize)
}; };
return interp_ok(meta_ty(caller) == meta_ty(callee)); return interp_ok(meta_ty(caller) == meta_ty(callee));
@ -652,17 +652,17 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
}; };
// Obtain the underlying trait we are working on, and the adjusted receiver argument. // Obtain the underlying trait we are working on, and the adjusted receiver argument.
let (trait_, dyn_ty, adjusted_recv) = let (trait_, dyn_ty, adjusted_recv) = if let ty::Dynamic(data, _, ty::DynStar) =
if let ty::Dynamic(data, _, ty::DynStar) = receiver_place.layout.ty.kind() { receiver_place.layout.ty.kind()
{
let recv = self.unpack_dyn_star(&receiver_place, data)?; let recv = self.unpack_dyn_star(&receiver_place, data)?;
(data.principal(), recv.layout.ty, recv.ptr()) (data.principal(), recv.layout.ty, recv.ptr())
} else { } else {
// Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`. // Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
// (For that reason we also cannot use `unpack_dyn_trait`.) // (For that reason we also cannot use `unpack_dyn_trait`.)
let receiver_tail = self let receiver_tail =
.tcx self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env);
.struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env());
let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else { let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else {
span_bug!( span_bug!(
self.cur_span(), self.cur_span(),
@ -704,7 +704,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let concrete_method = Instance::expect_resolve_for_vtable( let concrete_method = Instance::expect_resolve_for_vtable(
tcx, tcx,
self.typing_env(), self.typing_env,
def_id, def_id,
instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args), instance.args.rebase_onto(tcx, trait_def_id, concrete_trait_ref.args),
self.cur_span(), self.cur_span(),

View File

@ -83,7 +83,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
ty::FnDef(def_id, args) => { ty::FnDef(def_id, args) => {
let instance = ty::Instance::resolve_for_fn_ptr( let instance = ty::Instance::resolve_for_fn_ptr(
*self.tcx, *self.tcx,
self.typing_env(), self.typing_env,
def_id, def_id,
args, args,
) )
@ -384,7 +384,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
// A<Struct> -> A<Trait> conversion // A<Struct> -> A<Trait> conversion
let (src_pointee_ty, dest_pointee_ty) = let (src_pointee_ty, dest_pointee_ty) =
self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.typing_env()); self.tcx.struct_lockstep_tails_for_codegen(source_ty, cast_ty, self.typing_env);
match (src_pointee_ty.kind(), dest_pointee_ty.kind()) { match (src_pointee_ty.kind(), dest_pointee_ty.kind()) {
(&ty::Array(_, length), &ty::Slice(_)) => { (&ty::Array(_, length), &ty::Slice(_)) => {

View File

@ -1,10 +1,12 @@
use std::assert_matches::debug_assert_matches;
use either::{Left, Right}; use either::{Left, Right};
use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout}; use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout};
use rustc_errors::DiagCtxtHandle; use rustc_errors::DiagCtxtHandle;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::at::ToTrace;
use rustc_infer::traits::{ObligationCause, Reveal}; use rustc_infer::traits::ObligationCause;
use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo}; use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo};
use rustc_middle::query::TyCtxtAt; use rustc_middle::query::TyCtxtAt;
use rustc_middle::ty::layout::{ use rustc_middle::ty::layout::{
@ -36,8 +38,9 @@ pub struct InterpCx<'tcx, M: Machine<'tcx>> {
/// we are evaluating (if this is CTFE). /// we are evaluating (if this is CTFE).
pub tcx: TyCtxtAt<'tcx>, pub tcx: TyCtxtAt<'tcx>,
/// Bounds in scope for polymorphic evaluations. /// The current context in case we're evaluating in a
pub(crate) param_env: ty::ParamEnv<'tcx>, /// polymorphic context. This always uses `ty::TypingMode::PostAnalysis`
pub typing_env: ty::TypingEnv<'tcx>,
/// The virtual memory system. /// The virtual memory system.
pub memory: Memory<'tcx, M>, pub memory: Memory<'tcx, M>,
@ -68,7 +71,7 @@ where
M: Machine<'tcx>, M: Machine<'tcx>,
{ {
fn typing_env(&self) -> ty::TypingEnv<'tcx> { fn typing_env(&self) -> ty::TypingEnv<'tcx> {
self.typing_env() self.typing_env
} }
} }
@ -189,25 +192,23 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
pub fn new( pub fn new(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
root_span: Span, root_span: Span,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
machine: M, machine: M,
) -> Self { ) -> Self {
// Const eval always happens in post analysis mode in order to be able to use the hidden types of
// opaque types. This is needed for trivial things like `size_of`, but also for using associated
// types that are not specified in the opaque type. We also use MIR bodies whose opaque types have
// already been revealed, so we'd be able to at least partially observe the hidden types anyways.
debug_assert_matches!(typing_env.typing_mode, ty::TypingMode::PostAnalysis);
InterpCx { InterpCx {
machine, machine,
tcx: tcx.at(root_span), tcx: tcx.at(root_span),
param_env, typing_env,
memory: Memory::new(), memory: Memory::new(),
recursion_limit: tcx.recursion_limit(), recursion_limit: tcx.recursion_limit(),
} }
} }
/// During CTFE we're always in `PostAnalysis` mode.
#[inline(always)]
pub fn typing_env(&self) -> ty::TypingEnv<'tcx> {
debug_assert_eq!(self.param_env.reveal(), Reveal::All);
ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env }
}
/// Returns the span of the currently executed statement/terminator. /// Returns the span of the currently executed statement/terminator.
/// This is the span typically used for error reporting. /// This is the span typically used for error reporting.
#[inline(always)] #[inline(always)]
@ -250,7 +251,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
#[inline] #[inline]
pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
ty.is_freeze(*self.tcx, self.param_env) ty.is_freeze(*self.tcx, self.typing_env)
} }
pub fn load_mir( pub fn load_mir(
@ -296,7 +297,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
.instance .instance
.try_instantiate_mir_and_normalize_erasing_regions( .try_instantiate_mir_and_normalize_erasing_regions(
*self.tcx, *self.tcx,
self.typing_env(), self.typing_env,
ty::EarlyBinder::bind(value), ty::EarlyBinder::bind(value),
) )
.map_err(|_| ErrorHandled::TooGeneric(self.cur_span())) .map_err(|_| ErrorHandled::TooGeneric(self.cur_span()))
@ -309,9 +310,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
args: GenericArgsRef<'tcx>, args: GenericArgsRef<'tcx>,
) -> InterpResult<'tcx, ty::Instance<'tcx>> { ) -> InterpResult<'tcx, ty::Instance<'tcx>> {
trace!("resolve: {:?}, {:#?}", def, args); trace!("resolve: {:?}, {:#?}", def, args);
trace!("param_env: {:#?}", self.param_env); trace!("typing_env: {:#?}", self.typing_env);
trace!("args: {:#?}", args); trace!("args: {:#?}", args);
match ty::Instance::try_resolve(*self.tcx, self.typing_env(), def, args) { match ty::Instance::try_resolve(*self.tcx, self.typing_env, def, args) {
Ok(Some(instance)) => interp_ok(instance), Ok(Some(instance)) => interp_ok(instance),
Ok(None) => throw_inval!(TooGeneric), Ok(None) => throw_inval!(TooGeneric),
@ -332,7 +333,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
return true; return true;
} }
// Slow path: spin up an inference context to check if these traits are sufficiently equal. // Slow path: spin up an inference context to check if these traits are sufficiently equal.
let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env()); let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env);
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
let cause = ObligationCause::dummy_with_span(self.cur_span()); let cause = ObligationCause::dummy_with_span(self.cur_span());
// equate the two trait refs after normalization // equate the two trait refs after normalization
@ -564,10 +565,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let val = if self.tcx.is_static(gid.instance.def_id()) { let val = if self.tcx.is_static(gid.instance.def_id()) {
let alloc_id = self.tcx.reserve_and_set_static_alloc(gid.instance.def_id()); let alloc_id = self.tcx.reserve_and_set_static_alloc(gid.instance.def_id());
let ty = instance.ty(self.tcx.tcx, self.typing_env()); let ty = instance.ty(self.tcx.tcx, self.typing_env);
mir::ConstAlloc { alloc_id, ty } mir::ConstAlloc { alloc_id, ty }
} else { } else {
self.ctfe_query(|tcx| tcx.eval_to_allocation_raw(self.param_env.and(gid)))? self.ctfe_query(|tcx| tcx.eval_to_allocation_raw(self.typing_env.as_query_input(gid)))?
}; };
self.raw_const_to_mplace(val) self.raw_const_to_mplace(val)
} }
@ -579,7 +580,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
layout: Option<TyAndLayout<'tcx>>, layout: Option<TyAndLayout<'tcx>>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> { ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
M::eval_mir_constant(self, *val, span, layout, |ecx, val, span, layout| { M::eval_mir_constant(self, *val, span, layout, |ecx, val, span, layout| {
let const_val = val.eval(*ecx.tcx, ecx.typing_env(), span).map_err(|err| { let const_val = val.eval(*ecx.tcx, ecx.typing_env, span).map_err(|err| {
if M::ALL_CONSTS_ARE_PRECHECKED { if M::ALL_CONSTS_ARE_PRECHECKED {
match err { match err {
ErrorHandled::TooGeneric(..) => {}, ErrorHandled::TooGeneric(..) => {},

View File

@ -165,7 +165,7 @@ pub fn intern_const_alloc_recursive<'tcx, M: CompileTimeMachine<'tcx, const_eval
InternKind::Static(Mutability::Not) => { InternKind::Static(Mutability::Not) => {
( (
// Outermost allocation is mutable if `!Freeze`. // Outermost allocation is mutable if `!Freeze`.
if ret.layout.ty.is_freeze(*ecx.tcx, ecx.param_env) { if ret.layout.ty.is_freeze(*ecx.tcx, ecx.typing_env) {
Mutability::Not Mutability::Not
} else { } else {
Mutability::Mut Mutability::Mut

View File

@ -34,13 +34,12 @@ pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAll
/// inside an `InterpCx` and instead have their value computed directly from rustc internal info. /// inside an `InterpCx` and instead have their value computed directly from rustc internal info.
pub(crate) fn eval_nullary_intrinsic<'tcx>( pub(crate) fn eval_nullary_intrinsic<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
def_id: DefId, def_id: DefId,
args: GenericArgsRef<'tcx>, args: GenericArgsRef<'tcx>,
) -> InterpResult<'tcx, ConstValue<'tcx>> { ) -> InterpResult<'tcx, ConstValue<'tcx>> {
let tp_ty = args.type_at(0); let tp_ty = args.type_at(0);
let name = tcx.item_name(def_id); let name = tcx.item_name(def_id);
let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env };
interp_ok(match name { interp_ok(match name {
sym::type_name => { sym::type_name => {
ensure_monomorphic_enough(tcx, tp_ty)?; ensure_monomorphic_enough(tcx, tp_ty)?;
@ -152,8 +151,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
sym::type_name => Ty::new_static_str(self.tcx.tcx), sym::type_name => Ty::new_static_str(self.tcx.tcx),
_ => bug!(), _ => bug!(),
}; };
let val = let val = self
self.ctfe_query(|tcx| tcx.const_eval_global_id(self.param_env, gid, tcx.span))?; .ctfe_query(|tcx| tcx.const_eval_global_id(self.typing_env, gid, tcx.span))?;
let val = self.const_val_to_op(val, ty, Some(dest.layout))?; let val = self.const_val_to_op(val, ty, Some(dest.layout))?;
self.copy_op(&val, dest)?; self.copy_op(&val, dest)?;
} }
@ -358,7 +357,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let should_panic = !self let should_panic = !self
.tcx .tcx
.check_validity_requirement((requirement, self.typing_env().as_query_input(ty))) .check_validity_requirement((requirement, self.typing_env.as_query_input(ty)))
.map_err(|_| err_inval!(TooGeneric))?; .map_err(|_| err_inval!(TooGeneric))?;
if should_panic { if should_panic {

View File

@ -859,8 +859,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// # Global allocations // # Global allocations
if let Some(global_alloc) = self.tcx.try_get_global_alloc(id) { if let Some(global_alloc) = self.tcx.try_get_global_alloc(id) {
let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env()); let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env);
let mutbl = global_alloc.mutability(*self.tcx, self.param_env); let mutbl = global_alloc.mutability(*self.tcx, self.typing_env);
let kind = match global_alloc { let kind = match global_alloc {
GlobalAlloc::Static { .. } | GlobalAlloc::Memory { .. } => AllocKind::LiveData, GlobalAlloc::Static { .. } | GlobalAlloc::Memory { .. } => AllocKind::LiveData,
GlobalAlloc::Function { .. } => bug!("We already checked function pointers above"), GlobalAlloc::Function { .. } => bug!("We already checked function pointers above"),

View File

@ -533,7 +533,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
} }
OffsetOf(fields) => { OffsetOf(fields) => {
let val = let val =
self.tcx.offset_of_subfield(self.typing_env(), layout, fields.iter()).bytes(); self.tcx.offset_of_subfield(self.typing_env, layout, fields.iter()).bytes();
ImmTy::from_uint(val, usize_layout()) ImmTy::from_uint(val, usize_layout())
} }
UbChecks => ImmTy::from_bool(M::ub_checks(self)?, *self.tcx), UbChecks => ImmTy::from_bool(M::ub_checks(self)?, *self.tcx),

View File

@ -540,7 +540,7 @@ where
)?; )?;
if !mir_assign_valid_types( if !mir_assign_valid_types(
*self.tcx, *self.tcx,
self.typing_env(), self.typing_env,
self.layout_of(normalized_place_ty)?, self.layout_of(normalized_place_ty)?,
place.layout, place.layout,
) { ) {
@ -871,7 +871,7 @@ where
// We do NOT compare the types for equality, because well-typed code can // We do NOT compare the types for equality, because well-typed code can
// actually "transmute" `&mut T` to `&T` in an assignment without a cast. // actually "transmute" `&mut T` to `&T` in an assignment without a cast.
let layout_compat = let layout_compat =
mir_assign_valid_types(*self.tcx, self.typing_env(), src.layout(), dest.layout()); mir_assign_valid_types(*self.tcx, self.typing_env, src.layout(), dest.layout());
if !allow_transmute && !layout_compat { if !allow_transmute && !layout_compat {
span_bug!( span_bug!(
self.cur_span(), self.cur_span(),

View File

@ -379,7 +379,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
for &const_ in body.required_consts() { for &const_ in body.required_consts() {
let c = let c =
self.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?; self.instantiate_from_current_frame_and_normalize_erasing_regions(const_.const_)?;
c.eval(*self.tcx, self.typing_env(), const_.span).map_err(|err| { c.eval(*self.tcx, self.typing_env, const_.span).map_err(|err| {
err.emit_note(*self.tcx); err.emit_note(*self.tcx);
err err
})?; })?;
@ -596,7 +596,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
return interp_ok(layout); return interp_ok(layout);
} }
let layout = from_known_layout(self.tcx, self.typing_env(), layout, || { let layout = from_known_layout(self.tcx, self.typing_env, layout, || {
let local_ty = frame.body.local_decls[local].ty; let local_ty = frame.body.local_decls[local].ty;
let local_ty = let local_ty =
self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?; self.instantiate_from_frame_and_normalize_erasing_regions(frame, local_ty)?;

View File

@ -418,8 +418,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
.collect::<InterpResult<'tcx, Vec<_>>>()?; .collect::<InterpResult<'tcx, Vec<_>>>()?;
let fn_sig_binder = func.layout.ty.fn_sig(*self.tcx); let fn_sig_binder = func.layout.ty.fn_sig(*self.tcx);
let fn_sig = let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.typing_env, fn_sig_binder);
self.tcx.normalize_erasing_late_bound_regions(self.typing_env(), fn_sig_binder);
let extra_args = &args[fn_sig.inputs().len()..]; let extra_args = &args[fn_sig.inputs().len()..];
let extra_args = let extra_args =
self.tcx.mk_type_list_from_iter(extra_args.iter().map(|arg| arg.layout().ty)); self.tcx.mk_type_list_from_iter(extra_args.iter().map(|arg| arg.layout().ty));

View File

@ -448,7 +448,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
meta: MemPlaceMeta<M::Provenance>, meta: MemPlaceMeta<M::Provenance>,
pointee: TyAndLayout<'tcx>, pointee: TyAndLayout<'tcx>,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.typing_env()); let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.typing_env);
match tail.kind() { match tail.kind() {
ty::Dynamic(data, _, ty::Dyn) => { ty::Dynamic(data, _, ty::Dyn) => {
let vtable = meta.unwrap_meta().to_pointer(self.ecx)?; let vtable = meta.unwrap_meta().to_pointer(self.ecx)?;
@ -568,7 +568,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind }); throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind });
}; };
let (size, _align) = let (size, _align) =
global_alloc.size_and_align(*self.ecx.tcx, self.ecx.typing_env()); global_alloc.size_and_align(*self.ecx.tcx, self.ecx.typing_env);
if let GlobalAlloc::Static(did) = global_alloc { if let GlobalAlloc::Static(did) = global_alloc {
let DefKind::Static { nested, .. } = self.ecx.tcx.def_kind(did) else { let DefKind::Static { nested, .. } = self.ecx.tcx.def_kind(did) else {
@ -619,7 +619,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
}; };
// Determine what it actually points to. // Determine what it actually points to.
let alloc_actual_mutbl = let alloc_actual_mutbl =
global_alloc.mutability(*self.ecx.tcx, self.ecx.param_env); global_alloc.mutability(*self.ecx.tcx, self.ecx.typing_env);
// Mutable pointer to immutable memory is no good. // Mutable pointer to immutable memory is no good.
if ptr_expected_mutbl == Mutability::Mut if ptr_expected_mutbl == Mutability::Mut
&& alloc_actual_mutbl == Mutability::Not && alloc_actual_mutbl == Mutability::Not
@ -848,7 +848,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
if let Some(alloc_id) = mplace.ptr().provenance.and_then(|p| p.get_alloc_id()) { if let Some(alloc_id) = mplace.ptr().provenance.and_then(|p| p.get_alloc_id()) {
let tcx = *self.ecx.tcx; let tcx = *self.ecx.tcx;
// Everything must be already interned. // Everything must be already interned.
let mutbl = tcx.global_alloc(alloc_id).mutability(tcx, self.ecx.param_env); let mutbl = tcx.global_alloc(alloc_id).mutability(tcx, self.ecx.typing_env);
if let Some((_, alloc)) = self.ecx.memory.alloc_map.get(alloc_id) { if let Some((_, alloc)) = self.ecx.memory.alloc_map.get(alloc_id) {
assert_eq!(alloc.mutability, mutbl); assert_eq!(alloc.mutability, mutbl);
} }
@ -955,7 +955,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
) -> Cow<'e, RangeSet> { ) -> Cow<'e, RangeSet> {
assert!(layout.ty.is_union()); assert!(layout.ty.is_union());
assert!(layout.is_sized(), "there are no unsized unions"); assert!(layout.is_sized(), "there are no unsized unions");
let layout_cx = LayoutCx::new(*ecx.tcx, ecx.typing_env()); let layout_cx = LayoutCx::new(*ecx.tcx, ecx.typing_env);
return M::cached_union_data_range(ecx, layout.ty, || { return M::cached_union_data_range(ecx, layout.ty, || {
let mut out = RangeSet(Vec::new()); let mut out = RangeSet(Vec::new());
union_data_range_uncached(&layout_cx, layout, Size::ZERO, &mut out); union_data_range_uncached(&layout_cx, layout, Size::ZERO, &mut out);
@ -1085,7 +1085,8 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
// Special check for CTFE validation, preventing `UnsafeCell` inside unions in immutable memory. // Special check for CTFE validation, preventing `UnsafeCell` inside unions in immutable memory.
if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) { if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) {
if !val.layout.is_zst() && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) { if !val.layout.is_zst() && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.typing_env)
{
if !self.in_mutable_memory(val) { if !self.in_mutable_memory(val) {
throw_validation_failure!(self.path, UnsafeCellInImmutable); throw_validation_failure!(self.path, UnsafeCellInImmutable);
} }

View File

@ -40,14 +40,13 @@ pub fn provide(providers: &mut Providers) {
providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider; providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider;
providers.eval_static_initializer = const_eval::eval_static_initializer_provider; providers.eval_static_initializer = const_eval::eval_static_initializer_provider;
providers.hooks.const_caller_location = util::caller_location::const_caller_location_provider; providers.hooks.const_caller_location = util::caller_location::const_caller_location_provider;
providers.eval_to_valtree = |tcx, param_env_and_value| { providers.eval_to_valtree = |tcx, ty::PseudoCanonicalInput { typing_env, value }| {
let (param_env, raw) = param_env_and_value.into_parts(); const_eval::eval_to_valtree(tcx, typing_env, value)
const_eval::eval_to_valtree(tcx, param_env, raw)
}; };
providers.hooks.try_destructure_mir_constant_for_user_output = providers.hooks.try_destructure_mir_constant_for_user_output =
const_eval::try_destructure_mir_constant_for_user_output; const_eval::try_destructure_mir_constant_for_user_output;
providers.valtree_to_const_val = |tcx, (ty, valtree)| { providers.valtree_to_const_val = |tcx, (ty, valtree)| {
const_eval::valtree_to_const_value(tcx, ty::ParamEnv::reveal_all().and(ty), valtree) const_eval::valtree_to_const_value(tcx, ty::TypingEnv::fully_monomorphized(), ty, valtree)
}; };
providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| { providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| {
util::check_validity_requirement(tcx, init_kind, param_env_and_ty) util::check_validity_requirement(tcx, init_kind, param_env_and_ty)

View File

@ -60,7 +60,7 @@ pub(crate) fn const_caller_location_provider(
let mut ecx = mk_eval_cx_to_read_const_val( let mut ecx = mk_eval_cx_to_read_const_val(
tcx.tcx, tcx.tcx,
tcx.span, tcx.span,
ty::ParamEnv::reveal_all(), ty::TypingEnv::fully_monomorphized(),
CanAccessMutGlobal::No, CanAccessMutGlobal::No,
); );

View File

@ -49,7 +49,7 @@ fn check_validity_requirement_strict<'tcx>(
) -> Result<bool, &'tcx LayoutError<'tcx>> { ) -> Result<bool, &'tcx LayoutError<'tcx>> {
let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error); let machine = CompileTimeMachine::new(CanAccessMutGlobal::No, CheckAlignment::Error);
let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.typing_env.param_env, machine); let mut cx = InterpCx::new(cx.tcx(), rustc_span::DUMMY_SP, cx.typing_env, machine);
let allocated = cx let allocated = cx
.allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap)) .allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))

View File

@ -90,24 +90,24 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
fn allowed_union_field<'tcx>( fn allowed_union_field<'tcx>(
ty: Ty<'tcx>, ty: Ty<'tcx>,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
) -> bool { ) -> bool {
// We don't just accept all !needs_drop fields, due to semver concerns. // We don't just accept all !needs_drop fields, due to semver concerns.
match ty.kind() { match ty.kind() {
ty::Ref(..) => true, // references never drop (even mutable refs, which are non-Copy and hence fail the later check) ty::Ref(..) => true, // references never drop (even mutable refs, which are non-Copy and hence fail the later check)
ty::Tuple(tys) => { ty::Tuple(tys) => {
// allow tuples of allowed types // allow tuples of allowed types
tys.iter().all(|ty| allowed_union_field(ty, tcx, param_env)) tys.iter().all(|ty| allowed_union_field(ty, tcx, typing_env))
} }
ty::Array(elem, _len) => { ty::Array(elem, _len) => {
// Like `Copy`, we do *not* special-case length 0. // Like `Copy`, we do *not* special-case length 0.
allowed_union_field(*elem, tcx, param_env) allowed_union_field(*elem, tcx, typing_env)
} }
_ => { _ => {
// Fallback case: allow `ManuallyDrop` and things that are `Copy`, // Fallback case: allow `ManuallyDrop` and things that are `Copy`,
// also no need to report an error if the type is unresolved. // also no need to report an error if the type is unresolved.
ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop()) ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop())
|| ty.is_copy_modulo_regions(tcx, param_env) || ty.is_copy_modulo_regions(tcx, typing_env)
|| ty.references_error() || ty.references_error()
} }
} }
@ -121,7 +121,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
continue; continue;
}; };
if !allowed_union_field(field_ty, tcx, typing_env.param_env) { if !allowed_union_field(field_ty, tcx, typing_env) {
let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) { let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) {
// We are currently checking the type this field came from, so it must be local. // We are currently checking the type this field came from, so it must be local.
Some(Node::Field(field)) => (field.span, field.ty.span), Some(Node::Field(field)) => (field.span, field.ty.span),

View File

@ -1193,9 +1193,9 @@ fn compare_self_type<'tcx>(
ty::AssocItemContainer::Trait => tcx.types.self_param, ty::AssocItemContainer::Trait => tcx.types.self_param,
}; };
let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0); let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0);
let param_env = ty::ParamEnv::reveal_all(); let (infcx, param_env) = tcx
.infer_ctxt()
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); .build_with_typing_env(ty::TypingEnv::non_body_analysis(tcx, method.def_id));
let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty); let self_arg_ty = tcx.liberate_late_bound_regions(method.def_id, self_arg_ty);
let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty); let can_eq_self = |ty| infcx.can_eq(param_env, untransformed_self_ty, ty);
match ExplicitSelf::determine(self_arg_ty, can_eq_self) { match ExplicitSelf::determine(self_arg_ty, can_eq_self) {

View File

@ -15,7 +15,7 @@ use rustc_target::asm::{
pub struct InlineAsmCtxt<'a, 'tcx> { pub struct InlineAsmCtxt<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
get_operand_ty: Box<dyn Fn(&'tcx hir::Expr<'tcx>) -> Ty<'tcx> + 'a>, get_operand_ty: Box<dyn Fn(&'tcx hir::Expr<'tcx>) -> Ty<'tcx> + 'a>,
} }
@ -23,24 +23,29 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
pub fn new_global_asm(tcx: TyCtxt<'tcx>) -> Self { pub fn new_global_asm(tcx: TyCtxt<'tcx>) -> Self {
InlineAsmCtxt { InlineAsmCtxt {
tcx, tcx,
typing_env: ty::TypingEnv {
typing_mode: ty::TypingMode::non_body_analysis(),
param_env: ty::ParamEnv::empty(), param_env: ty::ParamEnv::empty(),
},
get_operand_ty: Box::new(|e| bug!("asm operand in global asm: {e:?}")), get_operand_ty: Box::new(|e| bug!("asm operand in global asm: {e:?}")),
} }
} }
// FIXME(#132279): This likely causes us to incorrectly handle opaque types in their
// defining scope.
pub fn new_in_fn( pub fn new_in_fn(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
get_operand_ty: impl Fn(&'tcx hir::Expr<'tcx>) -> Ty<'tcx> + 'a, get_operand_ty: impl Fn(&'tcx hir::Expr<'tcx>) -> Ty<'tcx> + 'a,
) -> Self { ) -> Self {
InlineAsmCtxt { tcx, param_env, get_operand_ty: Box::new(get_operand_ty) } InlineAsmCtxt { tcx, typing_env, get_operand_ty: Box::new(get_operand_ty) }
} }
// FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()` // FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()`
fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool { fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool {
// Type still may have region variables, but `Sized` does not depend // Type still may have region variables, but `Sized` does not depend
// on those, so just erase them before querying. // on those, so just erase them before querying.
if ty.is_sized(self.tcx, self.param_env) { if ty.is_sized(self.tcx, self.typing_env) {
return true; return true;
} }
if let ty::Foreign(..) = ty.kind() { if let ty::Foreign(..) = ty.kind() {
@ -171,7 +176,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// Check that the type implements Copy. The only case where this can // Check that the type implements Copy. The only case where this can
// possibly fail is for SIMD types which don't #[derive(Copy)]. // possibly fail is for SIMD types which don't #[derive(Copy)].
if !ty.is_copy_modulo_regions(self.tcx, self.param_env) { if !ty.is_copy_modulo_regions(self.tcx, self.typing_env) {
let msg = "arguments for inline assembly must be copyable"; let msg = "arguments for inline assembly must be copyable";
self.tcx self.tcx
.dcx() .dcx()

View File

@ -172,7 +172,7 @@ pub(crate) fn orphan_check_impl(
// impl<T> AutoTrait for T {} // impl<T> AutoTrait for T {}
// impl<T: ?Sized> AutoTrait for T {} // impl<T: ?Sized> AutoTrait for T {}
ty::Param(..) => ( ty::Param(..) => (
if self_ty.is_sized(tcx, tcx.param_env(impl_def_id)) { if self_ty.is_sized(tcx, ty::TypingEnv::non_body_analysis(tcx, impl_def_id)) {
LocalImpl::Allow LocalImpl::Allow
} else { } else {
LocalImpl::Disallow { problematic_kind: "generic type" } LocalImpl::Disallow { problematic_kind: "generic type" }

View File

@ -190,8 +190,8 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
DefKind::Const if tcx.generics_of(item_def_id).is_empty() => { DefKind::Const if tcx.generics_of(item_def_id).is_empty() => {
let instance = ty::Instance::new(item_def_id.into(), ty::GenericArgs::empty()); let instance = ty::Instance::new(item_def_id.into(), ty::GenericArgs::empty());
let cid = GlobalId { instance, promoted: None }; let cid = GlobalId { instance, promoted: None };
let param_env = ty::ParamEnv::reveal_all(); let typing_env = ty::TypingEnv::fully_monomorphized();
tcx.ensure().eval_to_const_value_raw(param_env.and(cid)); tcx.ensure().eval_to_const_value_raw(typing_env.as_query_input(cid));
} }
_ => (), _ => (),
} }

View File

@ -228,7 +228,7 @@ impl<'tcx> TypeInformationCtxt<'tcx> for (&LateContext<'tcx>, LocalDefId) {
} }
fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool { fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>) -> bool {
ty.is_copy_modulo_regions(self.0.tcx, self.0.param_env) ty.is_copy_modulo_regions(self.0.tcx, self.0.typing_env())
} }
fn body_owner_def_id(&self) -> LocalDefId { fn body_owner_def_id(&self) -> LocalDefId {

View File

@ -105,7 +105,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.erase_regions(ty) self.tcx.erase_regions(ty)
} }
}; };
InlineAsmCtxt::new_in_fn(self.tcx, self.param_env, get_operand_ty) InlineAsmCtxt::new_in_fn(
self.tcx,
self.infcx.typing_env(self.param_env),
get_operand_ty,
)
.check_asm(asm, enclosing_id); .check_asm(asm, enclosing_id);
} }
} }

View File

@ -831,8 +831,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
// Normalize consts in writeback, because GCE doesn't normalize eagerly. // Normalize consts in writeback, because GCE doesn't normalize eagerly.
if tcx.features().generic_const_exprs() { if tcx.features().generic_const_exprs() {
value = value = value.fold_with(&mut EagerlyNormalizeConsts::new(self.fcx));
value.fold_with(&mut EagerlyNormalizeConsts { tcx, param_env: self.fcx.param_env });
} }
value value
@ -873,16 +872,22 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
struct EagerlyNormalizeConsts<'tcx> { struct EagerlyNormalizeConsts<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
} }
impl<'tcx> EagerlyNormalizeConsts<'tcx> {
fn new(fcx: &FnCtxt<'_, 'tcx>) -> Self {
// FIXME(#132279, generic_const_exprs): Using `try_normalize_erasing_regions` here
// means we can't handle opaque types in their defining scope.
EagerlyNormalizeConsts { tcx: fcx.tcx, typing_env: fcx.typing_env(fcx.param_env) }
}
}
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerlyNormalizeConsts<'tcx> { impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerlyNormalizeConsts<'tcx> {
fn cx(&self) -> TyCtxt<'tcx> { fn cx(&self) -> TyCtxt<'tcx> {
self.tcx self.tcx
} }
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
self.tcx self.tcx.try_normalize_erasing_regions(self.typing_env, ct).unwrap_or(ct)
.try_normalize_erasing_regions(ty::TypingEnv::from_param_env(self.param_env), ct)
.unwrap_or(ct)
} }
} }

View File

@ -32,7 +32,7 @@ use rustc_middle::bug;
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode, Upcast, VariantDef}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, Upcast, VariantDef};
use rustc_session::lint::FutureIncompatibilityReason; use rustc_session::lint::FutureIncompatibilityReason;
// hardwired lints from rustc_lint_defs // hardwired lints from rustc_lint_defs
pub use rustc_session::lint::builtin::*; pub use rustc_session::lint::builtin::*;
@ -586,10 +586,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
return; return;
} }
} }
if ty.is_copy_modulo_regions(cx.tcx, cx.param_env) { if ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()) {
return; return;
} }
if type_implements_negative_copy_modulo_regions(cx.tcx, ty, cx.param_env) { if type_implements_negative_copy_modulo_regions(cx.tcx, ty, cx.typing_env()) {
return; return;
} }
if def.is_variant_list_non_exhaustive() if def.is_variant_list_non_exhaustive()
@ -637,8 +637,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
fn type_implements_negative_copy_modulo_regions<'tcx>( fn type_implements_negative_copy_modulo_regions<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
) -> bool { ) -> bool {
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
let trait_ref = ty::TraitRef::new(tcx, tcx.require_lang_item(hir::LangItem::Copy, None), [ty]); let trait_ref = ty::TraitRef::new(tcx, tcx.require_lang_item(hir::LangItem::Copy, None), [ty]);
let pred = ty::TraitPredicate { trait_ref, polarity: ty::PredicatePolarity::Negative }; let pred = ty::TraitPredicate { trait_ref, polarity: ty::PredicatePolarity::Negative };
let obligation = traits::Obligation { let obligation = traits::Obligation {
@ -647,10 +648,7 @@ fn type_implements_negative_copy_modulo_regions<'tcx>(
recursion_depth: 0, recursion_depth: 0,
predicate: pred.upcast(tcx), predicate: pred.upcast(tcx),
}; };
infcx.predicate_must_hold_modulo_regions(&obligation)
tcx.infer_ctxt()
.build(TypingMode::non_body_analysis())
.predicate_must_hold_modulo_regions(&obligation)
} }
declare_lint! { declare_lint! {

View File

@ -144,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
&& let Some(fn_name) = cx.tcx.get_diagnostic_name(def_id) && let Some(fn_name) = cx.tcx.get_diagnostic_name(def_id)
{ {
let arg_ty = cx.typeck_results().expr_ty(arg); let arg_ty = cx.typeck_results().expr_ty(arg);
let is_copy = arg_ty.is_copy_modulo_regions(cx.tcx, cx.param_env); let is_copy = arg_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env());
let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr); let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
let let_underscore_ignore_sugg = || { let let_underscore_ignore_sugg = || {
if let Some((_, node)) = cx.tcx.hir().parent_iter(expr.hir_id).nth(0) if let Some((_, node)) = cx.tcx.hir().parent_iter(expr.hir_id).nth(0)

View File

@ -15,7 +15,7 @@ use rustc_middle::ty::relate::{
Relate, RelateResult, TypeRelation, structurally_relate_consts, structurally_relate_tys, Relate, RelateResult, TypeRelation, structurally_relate_consts, structurally_relate_tys,
}; };
use rustc_middle::ty::{ use rustc_middle::ty::{
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
}; };
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_session::lint::FutureIncompatibilityReason; use rustc_session::lint::FutureIncompatibilityReason;
@ -186,8 +186,8 @@ fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) {
functional_variances.variances functional_variances.variances
}), }),
outlives_env: LazyCell::new(|| { outlives_env: LazyCell::new(|| {
let param_env = tcx.param_env(parent_def_id); let typing_env = ty::TypingEnv::non_body_analysis(tcx, parent_def_id);
let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
let assumed_wf_tys = ocx.assumed_wf_types(param_env, parent_def_id).unwrap_or_default(); let assumed_wf_tys = ocx.assumed_wf_types(param_env, parent_def_id).unwrap_or_default();
let implied_bounds = let implied_bounds =

View File

@ -168,7 +168,7 @@ fn is_cast_from_ref_to_mut_ptr<'tcx>(
// Except on the presence of non concrete skeleton types (ie generics) // Except on the presence of non concrete skeleton types (ie generics)
// since there is no way to make it safe for arbitrary types. // since there is no way to make it safe for arbitrary types.
let inner_ty_has_interior_mutability = let inner_ty_has_interior_mutability =
!inner_ty.is_freeze(cx.tcx, cx.param_env) && inner_ty.has_concrete_skeleton(); !inner_ty.is_freeze(cx.tcx, cx.typing_env()) && inner_ty.has_concrete_skeleton();
(!need_check_freeze || !inner_ty_has_interior_mutability) (!need_check_freeze || !inner_ty_has_interior_mutability)
.then_some(inner_ty_has_interior_mutability) .then_some(inner_ty_has_interior_mutability)
} else { } else {

View File

@ -292,7 +292,7 @@ fn lint_wide_pointer<'tcx>(
_ => return None, _ => return None,
}; };
(!ty.is_sized(cx.tcx, cx.param_env)) (!ty.is_sized(cx.tcx, cx.typing_env()))
.then(|| (refs, modifiers, matches!(ty.kind(), ty::Dynamic(_, _, ty::Dyn)))) .then(|| (refs, modifiers, matches!(ty.kind(), ty::Dynamic(_, _, ty::Dyn))))
}; };
@ -904,7 +904,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
if let Some(boxed) = ty.boxed_ty() if let Some(boxed) = ty.boxed_ty()
&& matches!(self.mode, CItemKind::Definition) && matches!(self.mode, CItemKind::Definition)
{ {
if boxed.is_sized(tcx, self.cx.param_env) { if boxed.is_sized(tcx, self.cx.typing_env()) {
return FfiSafe; return FfiSafe;
} else { } else {
return FfiUnsafe { return FfiUnsafe {
@ -1069,7 +1069,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
ty::RawPtr(ty, _) | ty::Ref(_, ty, _) ty::RawPtr(ty, _) | ty::Ref(_, ty, _)
if { if {
matches!(self.mode, CItemKind::Definition) matches!(self.mode, CItemKind::Definition)
&& ty.is_sized(self.cx.tcx, self.cx.param_env) && ty.is_sized(self.cx.tcx, self.cx.typing_env())
} => } =>
{ {
FfiSafe FfiSafe

View File

@ -46,7 +46,7 @@ pub use self::pointer::{CtfeProvenance, Pointer, PointerArithmetic, Provenance};
pub use self::value::Scalar; pub use self::value::Scalar;
use crate::mir; use crate::mir;
use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::codec::{TyDecoder, TyEncoder};
use crate::ty::{self, Instance, ParamEnv, Ty, TyCtxt}; use crate::ty::{self, Instance, Ty, TyCtxt};
/// Uniquely identifies one of the following: /// Uniquely identifies one of the following:
/// - A constant /// - A constant
@ -312,7 +312,7 @@ impl<'tcx> GlobalAlloc<'tcx> {
} }
} }
pub fn mutability(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Mutability { pub fn mutability(&self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> Mutability {
// Let's see what kind of memory we are. // Let's see what kind of memory we are.
match self { match self {
GlobalAlloc::Static(did) => { GlobalAlloc::Static(did) => {
@ -334,7 +334,7 @@ impl<'tcx> GlobalAlloc<'tcx> {
.type_of(did) .type_of(did)
.no_bound_vars() .no_bound_vars()
.expect("statics should not have generic parameters") .expect("statics should not have generic parameters")
.is_freeze(tcx, param_env) => .is_freeze(tcx, typing_env) =>
{ {
Mutability::Mut Mutability::Mut
} }

View File

@ -25,8 +25,8 @@ impl<'tcx> TyCtxt<'tcx> {
let args = GenericArgs::identity_for_item(self, def_id); let args = GenericArgs::identity_for_item(self, def_id);
let instance = ty::Instance::new(def_id, args); let instance = ty::Instance::new(def_id, args);
let cid = GlobalId { instance, promoted: None }; let cid = GlobalId { instance, promoted: None };
let param_env = self.param_env(def_id).with_reveal_all_normalized(self); let typing_env = ty::TypingEnv::post_analysis(self, def_id);
self.const_eval_global_id(param_env, cid, DUMMY_SP) self.const_eval_global_id(typing_env, cid, DUMMY_SP)
} }
/// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts
@ -41,8 +41,8 @@ impl<'tcx> TyCtxt<'tcx> {
let args = GenericArgs::identity_for_item(self, def_id); let args = GenericArgs::identity_for_item(self, def_id);
let instance = ty::Instance::new(def_id, args); let instance = ty::Instance::new(def_id, args);
let cid = GlobalId { instance, promoted: None }; let cid = GlobalId { instance, promoted: None };
let param_env = self.param_env(def_id).with_reveal_all_normalized(self); let typing_env = ty::TypingEnv::post_analysis(self, def_id);
let inputs = self.erase_regions(param_env.and(cid)); let inputs = self.erase_regions(typing_env.as_query_input(cid));
self.eval_to_allocation_raw(inputs) self.eval_to_allocation_raw(inputs)
} }
@ -76,7 +76,7 @@ impl<'tcx> TyCtxt<'tcx> {
match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) { match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) {
Ok(Some(instance)) => { Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted: ct.promoted }; let cid = GlobalId { instance, promoted: ct.promoted };
self.const_eval_global_id(typing_env.param_env, cid, span) self.const_eval_global_id(typing_env, cid, span)
} }
// For errors during resolution, we deliberately do not point at the usage site of the constant, // 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. // since for these errors the place the constant is used shouldn't matter.
@ -105,7 +105,7 @@ impl<'tcx> TyCtxt<'tcx> {
match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) { match ty::Instance::try_resolve(self, typing_env, ct.def, ct.args) {
Ok(Some(instance)) => { Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted: None }; let cid = GlobalId { instance, promoted: None };
self.const_eval_global_id_for_typeck(typing_env.param_env, cid, span).inspect(|_| { self.const_eval_global_id_for_typeck(typing_env, cid, span).inspect(|_| {
// We are emitting the lint here instead of in `is_const_evaluatable` // We are emitting the lint here instead of in `is_const_evaluatable`
// as we normalize obligations before checking them, and normalization // as we normalize obligations before checking them, and normalization
// uses this function to evaluate this constant. // uses this function to evaluate this constant.
@ -144,24 +144,25 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn const_eval_instance( pub fn const_eval_instance(
self, self,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
instance: ty::Instance<'tcx>, instance: ty::Instance<'tcx>,
span: Span, span: Span,
) -> EvalToConstValueResult<'tcx> { ) -> EvalToConstValueResult<'tcx> {
self.const_eval_global_id(param_env, GlobalId { instance, promoted: None }, span) self.const_eval_global_id(typing_env, GlobalId { instance, promoted: None }, span)
} }
/// Evaluate a constant to a `ConstValue`. /// Evaluate a constant to a `ConstValue`.
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]
pub fn const_eval_global_id( pub fn const_eval_global_id(
self, self,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
cid: GlobalId<'tcx>, cid: GlobalId<'tcx>,
span: Span, span: Span,
) -> EvalToConstValueResult<'tcx> { ) -> EvalToConstValueResult<'tcx> {
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
// improve caching of queries. // improve caching of queries.
let inputs = self.erase_regions(param_env.with_reveal_all_normalized(self).and(cid)); let inputs =
self.erase_regions(typing_env.with_reveal_all_normalized(self).as_query_input(cid));
if !span.is_dummy() { if !span.is_dummy() {
// The query doesn't know where it is being invoked, so we need to fix the span. // The query doesn't know where it is being invoked, so we need to fix the span.
self.at(span).eval_to_const_value_raw(inputs).map_err(|e| e.with_span(span)) self.at(span).eval_to_const_value_raw(inputs).map_err(|e| e.with_span(span))
@ -174,13 +175,14 @@ impl<'tcx> TyCtxt<'tcx> {
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]
pub fn const_eval_global_id_for_typeck( pub fn const_eval_global_id_for_typeck(
self, self,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
cid: GlobalId<'tcx>, cid: GlobalId<'tcx>,
span: Span, span: Span,
) -> EvalToValTreeResult<'tcx> { ) -> EvalToValTreeResult<'tcx> {
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
// improve caching of queries. // improve caching of queries.
let inputs = self.erase_regions(param_env.with_reveal_all_normalized(self).and(cid)); let inputs =
self.erase_regions(typing_env.with_reveal_all_normalized(self).as_query_input(cid));
debug!(?inputs); debug!(?inputs);
if !span.is_dummy() { if !span.is_dummy() {
// The query doesn't know where it is being invoked, so we need to fix the span. // The query doesn't know where it is being invoked, so we need to fix the span.
@ -202,12 +204,12 @@ impl<'tcx> TyCtxtEnsure<'tcx> {
// into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are // into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are
// encountered. // encountered.
let args = GenericArgs::identity_for_item(self.tcx, def_id); let args = GenericArgs::identity_for_item(self.tcx, def_id);
let instance = ty::Instance::new(def_id, args); let instance = ty::Instance::new(def_id, self.tcx.erase_regions(args));
let cid = GlobalId { instance, promoted: None }; let cid = GlobalId { instance, promoted: None };
let param_env = self.tcx.param_env(def_id).with_reveal_all_normalized(self.tcx); let typing_env = ty::TypingEnv::post_analysis(self.tcx, def_id);
// Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should
// improve caching of queries. // improve caching of queries.
let inputs = self.tcx.erase_regions(param_env.and(cid)); let inputs = self.tcx.erase_regions(typing_env.as_query_input(cid));
self.eval_to_const_value_raw(inputs) self.eval_to_const_value_raw(inputs)
} }
} }

View File

@ -459,10 +459,7 @@ impl<'tcx> Body<'tcx> {
typing_mode: ty::TypingMode::non_body_analysis(), typing_mode: ty::TypingMode::non_body_analysis(),
param_env: tcx.param_env(self.source.def_id()), param_env: tcx.param_env(self.source.def_id()),
}, },
MirPhase::Runtime(_) => TypingEnv { MirPhase::Runtime(_) => TypingEnv::post_analysis(tcx, self.source.def_id()),
typing_mode: ty::TypingMode::PostAnalysis,
param_env: tcx.param_env_reveal_all_normalized(self.source.def_id()),
},
} }
} }

View File

@ -456,18 +456,6 @@ impl<'tcx> Key for ty::ParamEnv<'tcx> {
} }
} }
impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'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<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> { impl<'tcx, T: Key> Key for ty::PseudoCanonicalInput<'tcx, T> {
type Cache<V> = DefaultCache<Self, V>; type Cache<V> = DefaultCache<Self, V>;

View File

@ -1095,7 +1095,7 @@ rustc_queries! {
/// Evaluates a constant and returns the computed allocation. /// Evaluates a constant and returns the computed allocation.
/// ///
/// **Do not use this** directly, use the `eval_to_const_value` or `eval_to_valtree` instead. /// **Do not use this** directly, use the `eval_to_const_value` or `eval_to_valtree` instead.
query eval_to_allocation_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) query eval_to_allocation_raw(key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>)
-> EvalToAllocationRawResult<'tcx> { -> EvalToAllocationRawResult<'tcx> {
desc { |tcx| desc { |tcx|
"const-evaluating + checking `{}`", "const-evaluating + checking `{}`",
@ -1121,7 +1121,7 @@ rustc_queries! {
/// ///
/// **Do not use this** directly, use one of the following wrappers: `tcx.const_eval_poly`, /// **Do not use this** directly, use one of the following wrappers: `tcx.const_eval_poly`,
/// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_global_id`. /// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_global_id`.
query eval_to_const_value_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) query eval_to_const_value_raw(key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>)
-> EvalToConstValueResult<'tcx> { -> EvalToConstValueResult<'tcx> {
desc { |tcx| desc { |tcx|
"simplifying constant for the type system `{}`", "simplifying constant for the type system `{}`",
@ -1133,7 +1133,7 @@ rustc_queries! {
/// Evaluate a constant and convert it to a type level constant or /// Evaluate a constant and convert it to a type level constant or
/// return `None` if that is not possible. /// return `None` if that is not possible.
query eval_to_valtree( query eval_to_valtree(
key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>> key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>
) -> EvalToValTreeResult<'tcx> { ) -> EvalToValTreeResult<'tcx> {
desc { "evaluating type-level constant" } desc { "evaluating type-level constant" }
} }
@ -1390,19 +1390,19 @@ rustc_queries! {
/// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`, /// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`,
/// `ty.is_copy()`, etc, since that will prune the environment where possible. /// `ty.is_copy()`, etc, since that will prune the environment where possible.
query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { query is_copy_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` is `Copy`", env.value } desc { "computing whether `{}` is `Copy`", env.value }
} }
/// Query backing `Ty::is_sized`. /// Query backing `Ty::is_sized`.
query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { query is_sized_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` is `Sized`", env.value } desc { "computing whether `{}` is `Sized`", env.value }
} }
/// Query backing `Ty::is_freeze`. /// Query backing `Ty::is_freeze`.
query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { query is_freeze_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` is freeze", env.value } desc { "computing whether `{}` is freeze", env.value }
} }
/// Query backing `Ty::is_unpin`. /// Query backing `Ty::is_unpin`.
query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { query is_unpin_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` is `Unpin`", env.value } desc { "computing whether `{}` is `Unpin`", env.value }
} }
/// Query backing `Ty::needs_drop`. /// Query backing `Ty::needs_drop`.

View File

@ -537,9 +537,7 @@ impl<'tcx> Instance<'tcx> {
// All regions in the result of this query are erased, so it's // All regions in the result of this query are erased, so it's
// fine to erase all of the input regions. // fine to erase all of the input regions.
let typing_env = tcx.erase_regions(typing_env); tcx.resolve_instance_raw(tcx.erase_regions(typing_env.as_query_input((def_id, args))))
let args = tcx.erase_regions(args);
tcx.resolve_instance_raw(typing_env.as_query_input((def_id, args)))
} }
pub fn expect_resolve( pub fn expect_resolve(

View File

@ -1002,12 +1002,12 @@ where
// attributes in LLVM have compile-time cost even in unoptimized builds). // attributes in LLVM have compile-time cost even in unoptimized builds).
let optimize = tcx.sess.opts.optimize != OptLevel::No; let optimize = tcx.sess.opts.optimize != OptLevel::No;
let kind = match mt { let kind = match mt {
hir::Mutability::Not => PointerKind::SharedRef { hir::Mutability::Not => {
frozen: optimize && ty.is_freeze(tcx, typing_env.param_env), PointerKind::SharedRef { frozen: optimize && ty.is_freeze(tcx, typing_env) }
}, }
hir::Mutability::Mut => PointerKind::MutableRef { hir::Mutability::Mut => {
unpin: optimize && ty.is_unpin(tcx, typing_env.param_env), PointerKind::MutableRef { unpin: optimize && ty.is_unpin(tcx, typing_env) }
}, }
}; };
tcx.layout_of(typing_env.as_query_input(ty)).ok().map(|layout| PointeeInfo { tcx.layout_of(typing_env.as_query_input(ty)).ok().map(|layout| PointeeInfo {
@ -1100,7 +1100,7 @@ where
debug_assert!(pointee.safe.is_none()); debug_assert!(pointee.safe.is_none());
let optimize = tcx.sess.opts.optimize != OptLevel::No; let optimize = tcx.sess.opts.optimize != OptLevel::No;
pointee.safe = Some(PointerKind::Box { pointee.safe = Some(PointerKind::Box {
unpin: optimize && boxed_ty.is_unpin(tcx, typing_env.param_env), unpin: optimize && boxed_ty.is_unpin(tcx, typing_env),
global: this.ty.is_box_global(tcx), global: this.ty.is_box_global(tcx),
}); });
} }

View File

@ -1140,12 +1140,6 @@ pub struct TypingEnv<'tcx> {
} }
impl<'tcx> TypingEnv<'tcx> { impl<'tcx> TypingEnv<'tcx> {
// FIXME(#132279): This method should be removed but simplifies the
// transition.
pub fn from_param_env(param_env: ParamEnv<'tcx>) -> TypingEnv<'tcx> {
TypingEnv { typing_mode: TypingMode::from_param_env(param_env), param_env }
}
/// Create a typing environment with no where-clauses in scope /// Create a typing environment with no where-clauses in scope
/// where all opaque types and default associated items are revealed. /// where all opaque types and default associated items are revealed.
/// ///
@ -1192,7 +1186,6 @@ impl<'tcx> TypingEnv<'tcx> {
where where
T: TypeVisitable<TyCtxt<'tcx>>, T: TypeVisitable<TyCtxt<'tcx>>,
{ {
debug_assert!(!value.has_infer());
// FIXME(#132279): We should assert that the value does not contain any placeholders // 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 // 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 // currently use pseudo-canonical queries in the trait solver which replaces params with
@ -1215,7 +1208,7 @@ impl<'tcx> TypingEnv<'tcx> {
/// This should be created by using `infcx.pseudo_canonicalize_query(param_env, value)` /// This should be created by using `infcx.pseudo_canonicalize_query(param_env, value)`
/// or by using `typing_env.as_query_input(value)`. /// or by using `typing_env.as_query_input(value)`.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[derive(HashStable)] #[derive(HashStable, TypeVisitable, TypeFoldable)]
pub struct PseudoCanonicalInput<'tcx, T> { pub struct PseudoCanonicalInput<'tcx, T> {
pub typing_env: TypingEnv<'tcx>, pub typing_env: TypingEnv<'tcx>,
pub value: T, pub value: T,

View File

@ -1180,8 +1180,12 @@ impl<'tcx> Ty<'tcx> {
/// does copies even when the type actually doesn't satisfy the /// does copies even when the type actually doesn't satisfy the
/// full requirements for the `Copy` trait (cc #29149) -- this /// full requirements for the `Copy` trait (cc #29149) -- this
/// winds up being reported as an error during NLL borrow check. /// winds up being reported as an error during NLL borrow check.
pub fn is_copy_modulo_regions(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { pub fn is_copy_modulo_regions(
self.is_trivially_pure_clone_copy() || tcx.is_copy_raw(param_env.and(self)) self,
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
) -> bool {
self.is_trivially_pure_clone_copy() || tcx.is_copy_raw(typing_env.as_query_input(self))
} }
/// Checks whether values of this type `T` have a size known at /// Checks whether values of this type `T` have a size known at
@ -1190,8 +1194,8 @@ impl<'tcx> Ty<'tcx> {
/// over-approximation in generic contexts, where one can have /// over-approximation in generic contexts, where one can have
/// strange rules like `<T as Foo<'static>>::Bar: Sized` that /// strange rules like `<T as Foo<'static>>::Bar: Sized` that
/// actually carry lifetime requirements. /// actually carry lifetime requirements.
pub fn is_sized(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { pub fn is_sized(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool {
self.is_trivially_sized(tcx) || tcx.is_sized_raw(param_env.and(self)) self.is_trivially_sized(tcx) || tcx.is_sized_raw(typing_env.as_query_input(self))
} }
/// Checks whether values of this type `T` implement the `Freeze` /// Checks whether values of this type `T` implement the `Freeze`
@ -1201,8 +1205,8 @@ impl<'tcx> Ty<'tcx> {
/// optimization as well as the rules around static values. Note /// optimization as well as the rules around static values. Note
/// that the `Freeze` trait is not exposed to end users and is /// that the `Freeze` trait is not exposed to end users and is
/// effectively an implementation detail. /// effectively an implementation detail.
pub fn is_freeze(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { pub fn is_freeze(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool {
self.is_trivially_freeze() || tcx.is_freeze_raw(param_env.and(self)) self.is_trivially_freeze() || tcx.is_freeze_raw(typing_env.as_query_input(self))
} }
/// Fast path helper for testing if a type is `Freeze`. /// Fast path helper for testing if a type is `Freeze`.
@ -1241,8 +1245,8 @@ impl<'tcx> Ty<'tcx> {
} }
/// Checks whether values of this type `T` implement the `Unpin` trait. /// Checks whether values of this type `T` implement the `Unpin` trait.
pub fn is_unpin(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { pub fn is_unpin(self, tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>) -> bool {
self.is_trivially_unpin() || tcx.is_unpin_raw(param_env.and(self)) self.is_trivially_unpin() || tcx.is_unpin_raw(typing_env.as_query_input(self))
} }
/// Fast path helper for testing if a type is `Unpin`. /// Fast path helper for testing if a type is `Unpin`.

View File

@ -165,11 +165,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
if tcx.features().unsized_fn_params() { if tcx.features().unsized_fn_params() {
let ty = expr.ty; let ty = expr.ty;
let param_env = this.param_env; if !ty.is_sized(tcx, this.typing_env()) {
if !ty.is_sized(tcx, param_env) {
// !sized means !copy, so this is an unsized move // !sized means !copy, so this is an unsized move
assert!(!ty.is_copy_modulo_regions(tcx, param_env)); assert!(!ty.is_copy_modulo_regions(tcx, this.typing_env()));
// As described above, detect the case where we are passing a value of unsized // As described above, detect the case where we are passing a value of unsized
// type, and that value is coming from the deref of a box. // type, and that value is coming from the deref of a box.

View File

@ -148,6 +148,10 @@ struct BlockContext(Vec<BlockFrame>);
struct Builder<'a, 'tcx> { struct Builder<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
// FIXME(@lcnr): Why does this use an `infcx`, there should be
// no shared type inference going on here. I feel like it would
// clearer to manually construct one where necessary or to provide
// a nice API for non-type inference trait system checks.
infcx: InferCtxt<'tcx>, infcx: InferCtxt<'tcx>,
region_scope_tree: &'tcx region::ScopeTree, region_scope_tree: &'tcx region::ScopeTree,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,

View File

@ -11,7 +11,7 @@ use rustc_middle::span_bug;
use rustc_middle::thir::visit::Visitor; use rustc_middle::thir::visit::Visitor;
use rustc_middle::thir::*; use rustc_middle::thir::*;
use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::lint::Level; use rustc_session::lint::Level;
use rustc_session::lint::builtin::{DEPRECATED_SAFE_2024, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_session::lint::builtin::{DEPRECATED_SAFE_2024, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::def_id::{DefId, LocalDefId};
@ -37,7 +37,7 @@ struct UnsafetyVisitor<'a, 'tcx> {
/// of the LHS and the span of the assignment expression. /// of the LHS and the span of the assignment expression.
assignment_info: Option<Ty<'tcx>>, assignment_info: Option<Ty<'tcx>>,
in_union_destructure: bool, in_union_destructure: bool,
param_env: ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
inside_adt: bool, inside_adt: bool,
warnings: &'a mut Vec<UnusedUnsafeWarning>, warnings: &'a mut Vec<UnusedUnsafeWarning>,
@ -213,7 +213,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
body_target_features: self.body_target_features, body_target_features: self.body_target_features,
assignment_info: self.assignment_info, assignment_info: self.assignment_info,
in_union_destructure: false, in_union_destructure: false,
param_env: self.param_env, typing_env: self.typing_env,
inside_adt: false, inside_adt: false,
warnings: self.warnings, warnings: self.warnings,
suggest_unsafe_block: self.suggest_unsafe_block, suggest_unsafe_block: self.suggest_unsafe_block,
@ -370,7 +370,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
}; };
match rm { match rm {
Mutability::Not => { Mutability::Not => {
if !ty.is_freeze(self.tcx, self.param_env) { if !ty.is_freeze(self.tcx, self.typing_env) {
self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField); self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField);
} }
} }
@ -566,9 +566,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
&& adt_def.is_union() && adt_def.is_union()
{ {
if let Some(assigned_ty) = self.assignment_info { if let Some(assigned_ty) = self.assignment_info {
if assigned_ty if assigned_ty.needs_drop(self.tcx, self.typing_env) {
.needs_drop(self.tcx, ty::TypingEnv::from_param_env(self.param_env))
{
// This would be unsafe, but should be outright impossible since we // This would be unsafe, but should be outright impossible since we
// reject such unions. // reject such unions.
assert!( assert!(
@ -608,7 +606,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
if visitor.found { if visitor.found {
match borrow_kind { match borrow_kind {
BorrowKind::Fake(_) | BorrowKind::Shared BorrowKind::Fake(_) | BorrowKind::Shared
if !self.thir[arg].ty.is_freeze(self.tcx, self.param_env) => if !self.thir[arg].ty.is_freeze(self.tcx, self.typing_env) =>
{ {
self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField) self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField)
} }
@ -1026,7 +1024,8 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
body_target_features, body_target_features,
assignment_info: None, assignment_info: None,
in_union_destructure: false, in_union_destructure: false,
param_env: tcx.param_env(def), // FIXME(#132279): we're clearly in a body here.
typing_env: ty::TypingEnv::non_body_analysis(tcx, def),
inside_adt: false, inside_adt: false,
warnings: &mut warnings, warnings: &mut warnings,
suggest_unsafe_block: true, suggest_unsafe_block: true,

View File

@ -132,21 +132,16 @@ impl<'tcx> TerminatorClassifier<'tcx> for CallRecursion<'tcx> {
return false; return false;
} }
let caller = body.source.def_id(); let caller = body.source.def_id();
let param_env = tcx.param_env(caller); let typing_env = body.typing_env(tcx);
let func_ty = func.ty(body, tcx); let func_ty = func.ty(body, tcx);
if let ty::FnDef(callee, args) = *func_ty.kind() { if let ty::FnDef(callee, args) = *func_ty.kind() {
let Ok(normalized_args) = let Ok(normalized_args) = tcx.try_normalize_erasing_regions(typing_env, args) else {
tcx.try_normalize_erasing_regions(ty::TypingEnv::from_param_env(param_env), args)
else {
return false; return false;
}; };
let (callee, call_args) = if let Ok(Some(instance)) = Instance::try_resolve( let (callee, call_args) = if let Ok(Some(instance)) =
tcx, Instance::try_resolve(tcx, typing_env, callee, normalized_args)
ty::TypingEnv::from_param_env(param_env), {
callee,
normalized_args,
) {
(instance.def_id(), instance.args) (instance.def_id(), instance.args)
} else { } else {
(callee, normalized_args) (callee, normalized_args)

View File

@ -123,7 +123,7 @@ impl<'tcx> Cx<'tcx> {
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> { fn pattern_from_hir(&mut self, p: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p) pat_from_hir(self.tcx, self.typing_env(), self.typeck_results(), p)
} }
fn closure_env_param(&self, owner_def: LocalDefId, expr_id: HirId) -> Option<Param<'tcx>> { fn closure_env_param(&self, owner_def: LocalDefId, expr_id: HirId) -> Option<Param<'tcx>> {

View File

@ -7,6 +7,7 @@ use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, struct_span_code_e
use rustc_hir::def::*; use rustc_hir::def::*;
use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LocalDefId;
use rustc_hir::{self as hir, BindingMode, ByRef, HirId}; use rustc_hir::{self as hir, BindingMode, ByRef, HirId};
use rustc_infer::traits::Reveal;
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::middle::limits::get_limit_size; use rustc_middle::middle::limits::get_limit_size;
use rustc_middle::thir::visit::Visitor; use rustc_middle::thir::visit::Visitor;
@ -191,6 +192,15 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> {
} }
impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
fn typing_env(&self) -> ty::TypingEnv<'tcx> {
// FIXME(#132279): We're in a body, should handle opaques.
debug_assert_eq!(self.param_env.reveal(), Reveal::UserFacing);
ty::TypingEnv {
typing_mode: ty::TypingMode::non_body_analysis(),
param_env: self.param_env,
}
}
#[instrument(level = "trace", skip(self, f))] #[instrument(level = "trace", skip(self, f))]
fn with_let_source(&mut self, let_source: LetSource, f: impl FnOnce(&mut Self)) { fn with_let_source(&mut self, let_source: LetSource, f: impl FnOnce(&mut Self)) {
let old_let_source = self.let_source; let old_let_source = self.let_source;
@ -760,7 +770,7 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat:
return; return;
}; };
let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.param_env); let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env());
let sess = cx.tcx.sess; let sess = cx.tcx.sess;

View File

@ -2,11 +2,11 @@ use rustc_abi::{FieldIdx, VariantIdx};
use rustc_apfloat::Float; use rustc_apfloat::Float;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_index::Idx; use rustc_index::Idx;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::Obligation; use rustc_infer::traits::Obligation;
use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::thir::{FieldPat, Pat, PatKind}; use rustc_middle::thir::{FieldPat, Pat, PatKind};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode, ValTree}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, ValTree};
use rustc_middle::{mir, span_bug}; use rustc_middle::{mir, span_bug};
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::traits::ObligationCause; use rustc_trait_selection::traits::ObligationCause;
@ -35,10 +35,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
id: hir::HirId, id: hir::HirId,
span: Span, span: Span,
) -> Box<Pat<'tcx>> { ) -> Box<Pat<'tcx>> {
// FIXME(#132279): We likely want to be able to reveal the hidden types let mut convert = ConstToPat::new(self, id, span);
// of opaques defined in this function here.
let infcx = self.tcx.infer_ctxt().build(TypingMode::non_body_analysis());
let mut convert = ConstToPat::new(self, id, span, infcx);
match c.kind() { match c.kind() {
ty::ConstKind::Unevaluated(uv) => convert.unevaluated_to_pat(uv, ty), ty::ConstKind::Unevaluated(uv) => convert.unevaluated_to_pat(uv, ty),
@ -49,27 +46,20 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
} }
struct ConstToPat<'tcx> { struct ConstToPat<'tcx> {
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
span: Span, span: Span,
// inference context used for checking `T: Structural` bounds.
infcx: InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
treat_byte_string_as_slice: bool, treat_byte_string_as_slice: bool,
} }
impl<'tcx> ConstToPat<'tcx> { impl<'tcx> ConstToPat<'tcx> {
fn new( fn new(pat_ctxt: &PatCtxt<'_, 'tcx>, id: hir::HirId, span: Span) -> Self {
pat_ctxt: &PatCtxt<'_, 'tcx>,
id: hir::HirId,
span: Span,
infcx: InferCtxt<'tcx>,
) -> Self {
trace!(?pat_ctxt.typeck_results.hir_owner); trace!(?pat_ctxt.typeck_results.hir_owner);
ConstToPat { ConstToPat {
tcx: pat_ctxt.tcx,
typing_env: pat_ctxt.typing_env,
span, span,
infcx,
param_env: pat_ctxt.param_env,
treat_byte_string_as_slice: pat_ctxt treat_byte_string_as_slice: pat_ctxt
.typeck_results .typeck_results
.treat_byte_string_as_slice .treat_byte_string_as_slice
@ -77,16 +67,8 @@ impl<'tcx> ConstToPat<'tcx> {
} }
} }
fn tcx(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
fn typing_env(&self) -> ty::TypingEnv<'tcx> {
self.infcx.typing_env(self.param_env)
}
fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool { fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
ty.is_structural_eq_shallow(self.infcx.tcx) ty.is_structural_eq_shallow(self.tcx)
} }
fn unevaluated_to_pat( fn unevaluated_to_pat(
@ -105,22 +87,21 @@ impl<'tcx> ConstToPat<'tcx> {
// FIXME: `const_eval_resolve_for_typeck` should probably just set the env to `Reveal::All` // FIXME: `const_eval_resolve_for_typeck` should probably just set the env to `Reveal::All`
// instead of having this logic here // instead of having this logic here
let typing_env = let typing_env =
self.tcx().erase_regions(self.typing_env()).with_reveal_all_normalized(self.tcx()); self.tcx.erase_regions(self.typing_env).with_reveal_all_normalized(self.tcx);
let uv = self.tcx().erase_regions(uv); let uv = self.tcx.erase_regions(uv);
// try to resolve e.g. associated constants to their definition on an impl, and then // try to resolve e.g. associated constants to their definition on an impl, and then
// evaluate the const. // evaluate the const.
let valtree = match self.infcx.tcx.const_eval_resolve_for_typeck(typing_env, uv, self.span) let valtree = match self.tcx.const_eval_resolve_for_typeck(typing_env, uv, self.span) {
{
Ok(Ok(c)) => c, Ok(Ok(c)) => c,
Err(ErrorHandled::Reported(_, _)) => { Err(ErrorHandled::Reported(_, _)) => {
// Let's tell the use where this failing const occurs. // Let's tell the use where this failing const occurs.
let e = self.tcx().dcx().emit_err(CouldNotEvalConstPattern { span: self.span }); let e = self.tcx.dcx().emit_err(CouldNotEvalConstPattern { span: self.span });
return pat_from_kind(PatKind::Error(e)); return pat_from_kind(PatKind::Error(e));
} }
Err(ErrorHandled::TooGeneric(_)) => { Err(ErrorHandled::TooGeneric(_)) => {
let e = self let e = self
.tcx() .tcx
.dcx() .dcx()
.emit_err(ConstPatternDependsOnGenericParameter { span: self.span }); .emit_err(ConstPatternDependsOnGenericParameter { span: self.span });
return pat_from_kind(PatKind::Error(e)); return pat_from_kind(PatKind::Error(e));
@ -130,13 +111,13 @@ impl<'tcx> ConstToPat<'tcx> {
let e = match bad_ty.kind() { let e = match bad_ty.kind() {
ty::Adt(def, ..) => { ty::Adt(def, ..) => {
assert!(def.is_union()); assert!(def.is_union());
self.tcx().dcx().emit_err(UnionPattern { span: self.span }) self.tcx.dcx().emit_err(UnionPattern { span: self.span })
} }
ty::FnPtr(..) | ty::RawPtr(..) => { ty::FnPtr(..) | ty::RawPtr(..) => {
self.tcx().dcx().emit_err(PointerPattern { span: self.span }) self.tcx.dcx().emit_err(PointerPattern { span: self.span })
} }
_ => self _ => self
.tcx() .tcx
.dcx() .dcx()
.emit_err(InvalidPattern { span: self.span, non_sm_ty: bad_ty }), .emit_err(InvalidPattern { span: self.span, non_sm_ty: bad_ty }),
}; };
@ -151,7 +132,7 @@ impl<'tcx> ConstToPat<'tcx> {
// Always check for `PartialEq` if we had no other errors yet. // Always check for `PartialEq` if we had no other errors yet.
if !self.type_has_partial_eq_impl(ty) { if !self.type_has_partial_eq_impl(ty) {
let err = TypeNotPartialEq { span: self.span, non_peq_ty: ty }; let err = TypeNotPartialEq { span: self.span, non_peq_ty: ty };
let e = self.tcx().dcx().emit_err(err); let e = self.tcx.dcx().emit_err(err);
return pat_from_kind(PatKind::Error(e)); return pat_from_kind(PatKind::Error(e));
} }
} }
@ -161,18 +142,19 @@ impl<'tcx> ConstToPat<'tcx> {
#[instrument(level = "trace", skip(self), ret)] #[instrument(level = "trace", skip(self), ret)]
fn type_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool { fn type_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool {
let tcx = self.tcx(); let (infcx, param_env) = self.tcx.infer_ctxt().build_with_typing_env(self.typing_env);
// double-check there even *is* a semantic `PartialEq` to dispatch to. // double-check there even *is* a semantic `PartialEq` to dispatch to.
// //
// (If there isn't, then we can safely issue a hard // (If there isn't, then we can safely issue a hard
// error, because that's never worked, due to compiler // error, because that's never worked, due to compiler
// using `PartialEq::eq` in this scenario in the past.) // using `PartialEq::eq` in this scenario in the past.)
let partial_eq_trait_id = tcx.require_lang_item(hir::LangItem::PartialEq, Some(self.span)); let partial_eq_trait_id =
self.tcx.require_lang_item(hir::LangItem::PartialEq, Some(self.span));
let partial_eq_obligation = Obligation::new( let partial_eq_obligation = Obligation::new(
tcx, self.tcx,
ObligationCause::dummy(), ObligationCause::dummy(),
self.param_env, param_env,
ty::TraitRef::new(tcx, partial_eq_trait_id, [ty, ty]), ty::TraitRef::new(self.tcx, partial_eq_trait_id, [ty, ty]),
); );
// This *could* accept a type that isn't actually `PartialEq`, because region bounds get // This *could* accept a type that isn't actually `PartialEq`, because region bounds get
@ -181,7 +163,7 @@ impl<'tcx> ConstToPat<'tcx> {
// `PartialEq` for some lifetime but *not* for `'static`? If this ever becomes a problem // `PartialEq` for some lifetime but *not* for `'static`? If this ever becomes a problem
// we'll need to leave some sort of trace of this requirement in the MIR so that borrowck // we'll need to leave some sort of trace of this requirement in the MIR so that borrowck
// can ensure that the type really implements `PartialEq`. // can ensure that the type really implements `PartialEq`.
self.infcx.predicate_must_hold_modulo_regions(&partial_eq_obligation) infcx.predicate_must_hold_modulo_regions(&partial_eq_obligation)
} }
fn field_pats( fn field_pats(
@ -192,7 +174,7 @@ impl<'tcx> ConstToPat<'tcx> {
.map(|(idx, (val, ty))| { .map(|(idx, (val, ty))| {
let field = FieldIdx::new(idx); let field = FieldIdx::new(idx);
// Patterns can only use monomorphic types. // Patterns can only use monomorphic types.
let ty = self.tcx().normalize_erasing_regions(self.typing_env(), ty); let ty = self.tcx.normalize_erasing_regions(self.typing_env, ty);
FieldPat { field, pattern: self.valtree_to_pat(val, ty) } FieldPat { field, pattern: self.valtree_to_pat(val, ty) }
}) })
.collect() .collect()
@ -202,14 +184,12 @@ impl<'tcx> ConstToPat<'tcx> {
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]
fn valtree_to_pat(&self, cv: ValTree<'tcx>, ty: Ty<'tcx>) -> Box<Pat<'tcx>> { fn valtree_to_pat(&self, cv: ValTree<'tcx>, ty: Ty<'tcx>) -> Box<Pat<'tcx>> {
let span = self.span; let span = self.span;
let tcx = self.tcx(); let tcx = self.tcx;
let param_env = self.param_env;
let kind = match ty.kind() { let kind = match ty.kind() {
ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => { ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => {
// Extremely important check for all ADTs! Make sure they opted-in to be used in // Extremely important check for all ADTs! Make sure they opted-in to be used in
// patterns. // patterns.
debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty,); debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty);
let err = TypeNotStructural { span, non_sm_ty: ty }; let err = TypeNotStructural { span, non_sm_ty: ty };
let e = tcx.dcx().emit_err(err); let e = tcx.dcx().emit_err(err);
// We errored. Signal that in the pattern, so that follow up errors can be silenced. // We errored. Signal that in the pattern, so that follow up errors can be silenced.
@ -227,7 +207,7 @@ impl<'tcx> ConstToPat<'tcx> {
adt_def.variants()[variant_index] adt_def.variants()[variant_index]
.fields .fields
.iter() .iter()
.map(|field| field.ty(self.tcx(), args)), .map(|field| field.ty(self.tcx, args)),
), ),
), ),
} }
@ -235,14 +215,9 @@ impl<'tcx> ConstToPat<'tcx> {
ty::Adt(def, args) => { ty::Adt(def, args) => {
assert!(!def.is_union()); // Valtree construction would never succeed for unions. assert!(!def.is_union()); // Valtree construction would never succeed for unions.
PatKind::Leaf { PatKind::Leaf {
subpatterns: self.field_pats( subpatterns: self.field_pats(cv.unwrap_branch().iter().copied().zip(
cv.unwrap_branch().iter().copied().zip( def.non_enum_variant().fields.iter().map(|field| field.ty(self.tcx, args)),
def.non_enum_variant() )),
.fields
.iter()
.map(|field| field.ty(self.tcx(), args)),
),
),
} }
} }
ty::Tuple(fields) => PatKind::Leaf { ty::Tuple(fields) => PatKind::Leaf {
@ -276,7 +251,7 @@ impl<'tcx> ConstToPat<'tcx> {
// convert the dereferenced constant to a pattern that is the sub-pattern of the // convert the dereferenced constant to a pattern that is the sub-pattern of the
// deref pattern. // deref pattern.
_ => { _ => {
if !pointee_ty.is_sized(tcx, param_env) && !pointee_ty.is_slice() { if !pointee_ty.is_sized(tcx, self.typing_env) && !pointee_ty.is_slice() {
let err = UnsizedPattern { span, non_sm_ty: *pointee_ty }; let err = UnsizedPattern { span, non_sm_ty: *pointee_ty };
let e = tcx.dcx().emit_err(err); let e = tcx.dcx().emit_err(err);
// We errored. Signal that in the pattern, so that follow up errors can be silenced. // We errored. Signal that in the pattern, so that follow up errors can be silenced.

View File

@ -30,7 +30,7 @@ use crate::thir::util::UserAnnotatedTyHelpers;
struct PatCtxt<'a, 'tcx> { struct PatCtxt<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
typeck_results: &'a ty::TypeckResults<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>,
/// Used by the Rust 2024 migration lint. /// Used by the Rust 2024 migration lint.
@ -39,13 +39,13 @@ struct PatCtxt<'a, 'tcx> {
pub(super) fn pat_from_hir<'a, 'tcx>( pub(super) fn pat_from_hir<'a, 'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
typeck_results: &'a ty::TypeckResults<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>,
pat: &'tcx hir::Pat<'tcx>, pat: &'tcx hir::Pat<'tcx>,
) -> Box<Pat<'tcx>> { ) -> Box<Pat<'tcx>> {
let mut pcx = PatCtxt { let mut pcx = PatCtxt {
tcx, tcx,
param_env, typing_env,
typeck_results, typeck_results,
rust_2024_migration_suggestion: typeck_results rust_2024_migration_suggestion: typeck_results
.rust_2024_migration_desugared_pats() .rust_2024_migration_desugared_pats()
@ -242,7 +242,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
let lo = lo.unwrap_or(PatRangeBoundary::NegInfinity); let lo = lo.unwrap_or(PatRangeBoundary::NegInfinity);
let hi = hi.unwrap_or(PatRangeBoundary::PosInfinity); let hi = hi.unwrap_or(PatRangeBoundary::PosInfinity);
let cmp = lo.compare_with(hi, ty, self.tcx, ty::TypingEnv::from_param_env(self.param_env)); let cmp = lo.compare_with(hi, ty, self.tcx, self.typing_env);
let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty })); let mut kind = PatKind::Range(Box::new(PatRange { lo, hi, end, ty }));
match (end, cmp) { match (end, cmp) {
// `x..y` where `x < y`. // `x..y` where `x < y`.

View File

@ -3,7 +3,7 @@ use rustc_index::IndexVec;
use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::Session; use rustc_session::Session;
use tracing::{debug, trace}; use tracing::{debug, trace};
@ -25,9 +25,9 @@ impl<'tcx> crate::MirPass<'tcx> for CheckAlignment {
return; return;
} }
let typing_env = body.typing_env(tcx);
let basic_blocks = body.basic_blocks.as_mut(); let basic_blocks = body.basic_blocks.as_mut();
let local_decls = &mut body.local_decls; let local_decls = &mut body.local_decls;
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
// This pass inserts new blocks. Each insertion changes the Location for all // This pass inserts new blocks. Each insertion changes the Location for all
// statements/blocks after. Iterating or visiting the MIR in order would require updating // statements/blocks after. Iterating or visiting the MIR in order would require updating
@ -41,7 +41,7 @@ impl<'tcx> crate::MirPass<'tcx> for CheckAlignment {
let source_info = statement.source_info; let source_info = statement.source_info;
let mut finder = let mut finder =
PointerFinder { tcx, local_decls, param_env, pointers: Vec::new() }; PointerFinder { tcx, local_decls, typing_env, pointers: Vec::new() };
finder.visit_statement(statement, location); finder.visit_statement(statement, location);
for (local, ty) in finder.pointers { for (local, ty) in finder.pointers {
@ -65,7 +65,7 @@ impl<'tcx> crate::MirPass<'tcx> for CheckAlignment {
struct PointerFinder<'a, 'tcx> { struct PointerFinder<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
local_decls: &'a mut LocalDecls<'tcx>, local_decls: &'a mut LocalDecls<'tcx>,
param_env: ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
pointers: Vec<(Place<'tcx>, Ty<'tcx>)>, pointers: Vec<(Place<'tcx>, Ty<'tcx>)>,
} }
@ -107,7 +107,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PointerFinder<'a, 'tcx> {
let pointee_ty = let pointee_ty =
pointer_ty.builtin_deref(true).expect("no builtin_deref for an unsafe pointer"); pointer_ty.builtin_deref(true).expect("no builtin_deref for an unsafe pointer");
// Ideally we'd support this in the future, but for now we are limited to sized types. // Ideally we'd support this in the future, but for now we are limited to sized types.
if !pointee_ty.is_sized(self.tcx, self.param_env) { if !pointee_ty.is_sized(self.tcx, self.typing_env) {
debug!("Unsafe pointer, but pointee is not known to be sized: {:?}", pointer_ty); debug!("Unsafe pointer, but pointee is not known to be sized: {:?}", pointer_ty);
return; return;
} }

View File

@ -28,8 +28,8 @@ impl<'tcx> crate::MirPass<'tcx> for CopyProp {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
debug!(def_id = ?body.source.def_id()); debug!(def_id = ?body.source.def_id());
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); let typing_env = body.typing_env(tcx);
let ssa = SsaLocals::new(tcx, body, param_env); let ssa = SsaLocals::new(tcx, body, typing_env);
let fully_moved = fully_moved_locals(&ssa, body); let fully_moved = fully_moved_locals(&ssa, body);
debug!(?fully_moved); debug!(?fully_moved);

View File

@ -149,7 +149,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
map, map,
tcx, tcx,
local_decls: &body.local_decls, local_decls: &body.local_decls,
ecx: InterpCx::new(tcx, DUMMY_SP, typing_env.param_env, DummyMachine), ecx: InterpCx::new(tcx, DUMMY_SP, typing_env, DummyMachine),
typing_env, typing_env,
} }
} }

View File

@ -208,7 +208,7 @@ pub(super) fn deduced_param_attrs<'tcx>(
// blow-up in compile times: #113372 // blow-up in compile times: #113372
&& tcx && tcx
.normalize_erasing_regions(typing_env, local_decl.ty) .normalize_erasing_regions(typing_env, local_decl.ty)
.is_freeze(tcx, typing_env.param_env), .is_freeze(tcx, typing_env),
}, },
), ),
); );

View File

@ -120,12 +120,12 @@ impl<'tcx> crate::MirPass<'tcx> for GVN {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
debug!(def_id = ?body.source.def_id()); debug!(def_id = ?body.source.def_id());
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); let typing_env = body.typing_env(tcx);
let ssa = SsaLocals::new(tcx, body, param_env); let ssa = SsaLocals::new(tcx, body, typing_env);
// Clone dominators because we need them while mutating the body. // Clone dominators because we need them while mutating the body.
let dominators = body.basic_blocks.dominators().clone(); let dominators = body.basic_blocks.dominators().clone();
let mut state = VnState::new(tcx, body, param_env, &ssa, dominators, &body.local_decls); let mut state = VnState::new(tcx, body, typing_env, &ssa, dominators, &body.local_decls);
ssa.for_each_assignment_mut( ssa.for_each_assignment_mut(
body.basic_blocks.as_mut_preserves_cfg(), body.basic_blocks.as_mut_preserves_cfg(),
|local, value, location| { |local, value, location| {
@ -241,7 +241,6 @@ enum Value<'tcx> {
struct VnState<'body, 'tcx> { struct VnState<'body, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
ecx: InterpCx<'tcx, DummyMachine>, ecx: InterpCx<'tcx, DummyMachine>,
param_env: ty::ParamEnv<'tcx>,
local_decls: &'body LocalDecls<'tcx>, local_decls: &'body LocalDecls<'tcx>,
/// Value stored in each local. /// Value stored in each local.
locals: IndexVec<Local, Option<VnIndex>>, locals: IndexVec<Local, Option<VnIndex>>,
@ -266,7 +265,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
fn new( fn new(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
ssa: &'body SsaLocals, ssa: &'body SsaLocals,
dominators: Dominators<BasicBlock>, dominators: Dominators<BasicBlock>,
local_decls: &'body LocalDecls<'tcx>, local_decls: &'body LocalDecls<'tcx>,
@ -280,8 +279,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
+ 4 * body.basic_blocks.len(); + 4 * body.basic_blocks.len();
VnState { VnState {
tcx, tcx,
ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine), ecx: InterpCx::new(tcx, DUMMY_SP, typing_env, DummyMachine),
param_env,
local_decls, local_decls,
locals: IndexVec::from_elem(None, local_decls), locals: IndexVec::from_elem(None, local_decls),
rev_locals: IndexVec::with_capacity(num_values), rev_locals: IndexVec::with_capacity(num_values),
@ -296,7 +294,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
} }
fn typing_env(&self) -> ty::TypingEnv<'tcx> { fn typing_env(&self) -> ty::TypingEnv<'tcx> {
ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env: self.param_env } self.ecx.typing_env
} }
#[instrument(level = "trace", skip(self), ret)] #[instrument(level = "trace", skip(self), ret)]
@ -347,7 +345,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
// Only register the value if its type is `Sized`, as we will emit copies of it. // Only register the value if its type is `Sized`, as we will emit copies of it.
let is_sized = !self.feature_unsized_locals let is_sized = !self.feature_unsized_locals
|| self.local_decls[local].ty.is_sized(self.tcx, self.param_env); || self.local_decls[local].ty.is_sized(self.tcx, self.typing_env());
if is_sized { if is_sized {
self.rev_locals[value].push(local); self.rev_locals[value].push(local);
} }
@ -642,7 +640,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
let ty = place.ty(self.local_decls, self.tcx).ty; let ty = place.ty(self.local_decls, self.tcx).ty;
if let Some(Mutability::Not) = ty.ref_mutability() if let Some(Mutability::Not) = ty.ref_mutability()
&& let Some(pointee_ty) = ty.builtin_deref(true) && let Some(pointee_ty) = ty.builtin_deref(true)
&& pointee_ty.is_freeze(self.tcx, self.param_env) && pointee_ty.is_freeze(self.tcx, self.typing_env())
{ {
// An immutable borrow `_x` always points to the same value for the // An immutable borrow `_x` always points to the same value for the
// lifetime of the borrow, so we can merge all instances of `*_x`. // lifetime of the borrow, so we can merge all instances of `*_x`.
@ -1061,7 +1059,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
&& let ty::RawPtr(from_pointee_ty, from_mtbl) = cast_from.kind() && let ty::RawPtr(from_pointee_ty, from_mtbl) = cast_from.kind()
&& let ty::RawPtr(_, output_mtbl) = output_pointer_ty.kind() && let ty::RawPtr(_, output_mtbl) = output_pointer_ty.kind()
&& from_mtbl == output_mtbl && from_mtbl == output_mtbl
&& from_pointee_ty.is_sized(self.tcx, self.param_env) && from_pointee_ty.is_sized(self.tcx, self.typing_env())
{ {
fields[0] = *cast_value; fields[0] = *cast_value;
*data_pointer_ty = *cast_from; *data_pointer_ty = *cast_from;
@ -1383,7 +1381,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
&& let Value::Aggregate(AggregateTy::RawPtr { data_pointer_ty, .. }, _, fields) = && let Value::Aggregate(AggregateTy::RawPtr { data_pointer_ty, .. }, _, fields) =
self.get(value) self.get(value)
&& let ty::RawPtr(to_pointee, _) = to.kind() && let ty::RawPtr(to_pointee, _) = to.kind()
&& to_pointee.is_sized(self.tcx, self.param_env) && to_pointee.is_sized(self.tcx, self.typing_env())
{ {
from = *data_pointer_ty; from = *data_pointer_ty;
value = fields[0]; value = fields[0];

View File

@ -199,10 +199,7 @@ impl<'tcx> Inliner<'tcx> {
let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() }; let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() };
let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty; let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty;
for arg in args { for arg in args {
if !arg if !arg.node.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.typing_env)
.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 // We do not allow inlining functions with unsized params. Inlining these functions
// could create unsized locals, which are unsound and being phased out. // could create unsized locals, which are unsound and being phased out.

View File

@ -6,7 +6,7 @@ use rustc_hir::LangItem;
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::ty::layout::ValidityRequirement; use rustc_middle::ty::layout::ValidityRequirement;
use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, layout}; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, layout};
use rustc_span::sym; use rustc_span::sym;
use rustc_span::symbol::Symbol; use rustc_span::symbol::Symbol;
@ -34,7 +34,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify {
let ctx = InstSimplifyContext { let ctx = InstSimplifyContext {
tcx, tcx,
local_decls: &body.local_decls, local_decls: &body.local_decls,
param_env: tcx.param_env_reveal_all_normalized(body.source.def_id()), typing_env: body.typing_env(tcx),
}; };
let preserve_ub_checks = let preserve_ub_checks =
attr::contains_name(tcx.hir().krate_attrs(), sym::rustc_preserve_ub_checks); attr::contains_name(tcx.hir().krate_attrs(), sym::rustc_preserve_ub_checks);
@ -66,13 +66,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify {
struct InstSimplifyContext<'a, 'tcx> { struct InstSimplifyContext<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
local_decls: &'a LocalDecls<'tcx>, local_decls: &'a LocalDecls<'tcx>,
param_env: ParamEnv<'tcx>, typing_env: ty::TypingEnv<'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> { impl<'tcx> InstSimplifyContext<'_, 'tcx> {
@ -354,7 +348,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> {
} }
let known_is_valid = let known_is_valid =
intrinsic_assert_panics(self.tcx, self.typing_env(), args[0], intrinsic_name); intrinsic_assert_panics(self.tcx, self.typing_env, args[0], intrinsic_name);
match known_is_valid { match known_is_valid {
// We don't know the layout or it's not validity assertion at all, don't touch it // We don't know the layout or it's not validity assertion at all, don't touch it
None => {} None => {}

View File

@ -82,7 +82,7 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading {
let mut finder = TOFinder { let mut finder = TOFinder {
tcx, tcx,
typing_env, typing_env,
ecx: InterpCx::new(tcx, DUMMY_SP, typing_env.param_env, DummyMachine), ecx: InterpCx::new(tcx, DUMMY_SP, typing_env, DummyMachine),
body, body,
arena, arena,
map: Map::new(tcx, body, Some(MAX_PLACES)), map: Map::new(tcx, body, Some(MAX_PLACES)),

View File

@ -183,7 +183,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
// to runtime, so we have to manually specify the correct typing mode. // 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 typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id());
let can_const_prop = CanConstProp::check(tcx, typing_env, body); let can_const_prop = CanConstProp::check(tcx, typing_env, body);
let ecx = InterpCx::new(tcx, tcx.def_span(def_id), typing_env.param_env, DummyMachine); let ecx = InterpCx::new(tcx, tcx.def_span(def_id), typing_env, DummyMachine);
ConstPropagator { ConstPropagator {
ecx, ecx,
@ -451,7 +451,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
if rvalue.has_param() { if rvalue.has_param() {
return None; return None;
} }
if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.typing_env.param_env) { if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.typing_env) {
// the interpreter doesn't support unsized locals (only unsized arguments), // 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 // but rustc does (in a kinda broken way), so we have to skip them here
return None; return None;

View File

@ -85,8 +85,8 @@ impl<'tcx> crate::MirPass<'tcx> for ReferencePropagation {
} }
fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); let typing_env = body.typing_env(tcx);
let ssa = SsaLocals::new(tcx, body, param_env); let ssa = SsaLocals::new(tcx, body, typing_env);
let mut replacer = compute_replacement(tcx, body, &ssa); let mut replacer = compute_replacement(tcx, body, &ssa);
debug!(?replacer.targets); debug!(?replacer.targets);

View File

@ -13,7 +13,7 @@ use rustc_middle::bug;
use rustc_middle::middle::resolve_bound_vars::Set1; use rustc_middle::middle::resolve_bound_vars::Set1;
use rustc_middle::mir::visit::*; use rustc_middle::mir::visit::*;
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::ty::{ParamEnv, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
use tracing::{debug, instrument, trace}; use tracing::{debug, instrument, trace};
pub(super) struct SsaLocals { pub(super) struct SsaLocals {
@ -42,7 +42,7 @@ impl SsaLocals {
pub(super) fn new<'tcx>( pub(super) fn new<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
param_env: ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
) -> SsaLocals { ) -> SsaLocals {
let assignment_order = Vec::with_capacity(body.local_decls.len()); let assignment_order = Vec::with_capacity(body.local_decls.len());
@ -80,7 +80,7 @@ impl SsaLocals {
// have already been marked as non-SSA. // have already been marked as non-SSA.
debug!(?visitor.borrowed_locals); debug!(?visitor.borrowed_locals);
for local in visitor.borrowed_locals.iter() { for local in visitor.borrowed_locals.iter() {
if !body.local_decls[local].ty.is_freeze(tcx, param_env) { if !body.local_decls[local].ty.is_freeze(tcx, typing_env) {
visitor.assignments[local] = Set1::Many; visitor.assignments[local] = Set1::Many;
} }
} }

View File

@ -623,7 +623,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
if let Operand::Copy(place) = operand { if let Operand::Copy(place) = operand {
let ty = place.ty(&self.body.local_decls, self.tcx).ty; let ty = place.ty(&self.body.local_decls, self.tcx).ty;
if !ty.is_copy_modulo_regions(self.tcx, self.typing_env.param_env) { if !ty.is_copy_modulo_regions(self.tcx, self.typing_env) {
self.fail(location, format!("`Operand::Copy` with non-`Copy` type {ty}")); self.fail(location, format!("`Operand::Copy` with non-`Copy` type {ty}"));
} }
} }
@ -989,7 +989,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
} }
// FIXME: check `Thin` instead of `Sized` // FIXME: check `Thin` instead of `Sized`
if !in_pointee.is_sized(self.tcx, self.typing_env.param_env) { if !in_pointee.is_sized(self.tcx, self.typing_env) {
self.fail(location, "input pointer must be thin"); self.fail(location, "input pointer must be thin");
} }
} else { } else {
@ -1004,7 +1004,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
if !self.mir_assign_valid_types(metadata_ty, self.tcx.types.usize) { if !self.mir_assign_valid_types(metadata_ty, self.tcx.types.usize) {
self.fail(location, "slice metadata must be usize"); self.fail(location, "slice metadata must be usize");
} }
} else if pointee_ty.is_sized(self.tcx, self.typing_env.param_env) { } else if pointee_ty.is_sized(self.tcx, self.typing_env) {
if metadata_ty != self.tcx.types.unit { if metadata_ty != self.tcx.types.unit {
self.fail(location, "metadata for pointer-to-thin must be unit"); self.fail(location, "metadata for pointer-to-thin must be unit");
} }
@ -1294,7 +1294,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
if !self if !self
.tcx .tcx
.normalize_erasing_regions(self.typing_env, op_ty) .normalize_erasing_regions(self.typing_env, op_ty)
.is_sized(self.tcx, self.typing_env.param_env) .is_sized(self.tcx, self.typing_env)
{ {
self.fail( self.fail(
location, location,
@ -1304,7 +1304,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
if !self if !self
.tcx .tcx
.normalize_erasing_regions(self.typing_env, *target_type) .normalize_erasing_regions(self.typing_env, *target_type)
.is_sized(self.tcx, self.typing_env.param_env) .is_sized(self.tcx, self.typing_env)
{ {
self.fail( self.fail(
location, location,

View File

@ -1036,7 +1036,7 @@ fn find_vtable_types_for_unsizing<'tcx>(
let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| { let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| {
let typing_env = ty::TypingEnv::fully_monomorphized(); let typing_env = ty::TypingEnv::fully_monomorphized();
let type_has_metadata = |ty: Ty<'tcx>| -> bool { let type_has_metadata = |ty: Ty<'tcx>| -> bool {
if ty.is_sized(tcx.tcx, typing_env.param_env) { if ty.is_sized(tcx.tcx, typing_env) {
return false; return false;
} }
let tail = tcx.struct_tail_for_codegen(ty, typing_env); let tail = tcx.struct_tail_for_codegen(ty, typing_env);

View File

@ -468,7 +468,7 @@ const ACC_USE: u32 = 4;
struct Liveness<'a, 'tcx> { struct Liveness<'a, 'tcx> {
ir: &'a mut IrMaps<'tcx>, ir: &'a mut IrMaps<'tcx>,
typeck_results: &'a ty::TypeckResults<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
closure_min_captures: Option<&'tcx RootVariableMinCaptureList<'tcx>>, closure_min_captures: Option<&'tcx RootVariableMinCaptureList<'tcx>>,
successors: IndexVec<LiveNode, Option<LiveNode>>, successors: IndexVec<LiveNode, Option<LiveNode>>,
rwu_table: rwu_table::RWUTable, rwu_table: rwu_table::RWUTable,
@ -491,7 +491,8 @@ struct Liveness<'a, 'tcx> {
impl<'a, 'tcx> Liveness<'a, 'tcx> { impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn new(ir: &'a mut IrMaps<'tcx>, body_owner: LocalDefId) -> Liveness<'a, 'tcx> { fn new(ir: &'a mut IrMaps<'tcx>, body_owner: LocalDefId) -> Liveness<'a, 'tcx> {
let typeck_results = ir.tcx.typeck(body_owner); let typeck_results = ir.tcx.typeck(body_owner);
let param_env = ir.tcx.param_env(body_owner); // FIXME(#132279): we're in a body here.
let typing_env = ty::TypingEnv::non_body_analysis(ir.tcx, body_owner);
let closure_min_captures = typeck_results.closure_min_captures.get(&body_owner); let closure_min_captures = typeck_results.closure_min_captures.get(&body_owner);
let closure_ln = ir.add_live_node(ClosureNode); let closure_ln = ir.add_live_node(ClosureNode);
let exit_ln = ir.add_live_node(ExitNode); let exit_ln = ir.add_live_node(ExitNode);
@ -502,7 +503,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
Liveness { Liveness {
ir, ir,
typeck_results, typeck_results,
param_env, typing_env,
closure_min_captures, closure_min_captures,
successors: IndexVec::from_elem_n(None, num_live_nodes), successors: IndexVec::from_elem_n(None, num_live_nodes),
rwu_table: rwu_table::RWUTable::new(num_live_nodes, num_vars), rwu_table: rwu_table::RWUTable::new(num_live_nodes, num_vars),
@ -1297,7 +1298,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn check_is_ty_uninhabited(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNode { fn check_is_ty_uninhabited(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNode {
let ty = self.typeck_results.expr_ty(expr); let ty = self.typeck_results.expr_ty(expr);
let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id(); let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id();
if ty.is_inhabited_from(self.ir.tcx, m, ty::TypingEnv::from_param_env(self.param_env)) { if ty.is_inhabited_from(self.ir.tcx, m, self.typing_env) {
return succ; return succ;
} }
match self.ir.lnks[succ] { match self.ir.lnks[succ] {

View File

@ -15,7 +15,7 @@ use rustc_middle::ty::layout::{
}; };
use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths}; use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
use rustc_middle::ty::{ use rustc_middle::ty::{
GenericPredicates, Instance, List, ParamEnv, ScalarInt, TyCtxt, TypeVisitableExt, ValTree, GenericPredicates, Instance, List, ScalarInt, TyCtxt, TypeVisitableExt, ValTree,
}; };
use rustc_middle::{mir, ty}; use rustc_middle::{mir, ty};
use rustc_span::def_id::LOCAL_CRATE; use rustc_span::def_id::LOCAL_CRATE;
@ -713,7 +713,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
let instance = tables.instances[def]; let instance = tables.instances[def];
let tcx = tables.tcx; let tcx = tables.tcx;
let result = tcx.const_eval_instance( let result = tcx.const_eval_instance(
ParamEnv::reveal_all(), ty::TypingEnv::fully_monomorphized(),
instance, instance,
tcx.def_span(instance.def_id()), tcx.def_span(instance.def_id()),
); );

View File

@ -233,11 +233,11 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
let key = self.tcx.def_key(impl_def_id); let key = self.tcx.def_key(impl_def_id);
let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id }; let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id };
let mut param_env = self.tcx.param_env_reveal_all_normalized(impl_def_id); let mut typing_env = ty::TypingEnv::post_analysis(self.tcx, impl_def_id);
if !args.is_empty() { if !args.is_empty() {
param_env = EarlyBinder::bind(param_env).instantiate(self.tcx, args); typing_env.param_env =
EarlyBinder::bind(typing_env.param_env).instantiate(self.tcx, args);
} }
let typing_env = ty::TypingEnv { typing_mode: ty::TypingMode::PostAnalysis, param_env };
match &mut impl_trait_ref { match &mut impl_trait_ref {
Some(impl_trait_ref) => { Some(impl_trait_ref) => {

View File

@ -32,8 +32,10 @@ impl<'tcx> InferCtxt<'tcx> {
fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool {
let ty = self.resolve_vars_if_possible(ty); let ty = self.resolve_vars_if_possible(ty);
// FIXME(#132279): This should be removed as it causes us to incorrectly
// handle opaques in their defining scope.
if !(param_env, ty).has_infer() { if !(param_env, ty).has_infer() {
return ty.is_copy_modulo_regions(self.tcx, param_env); return ty.is_copy_modulo_regions(self.tcx, self.typing_env(param_env));
} }
let copy_def_id = self.tcx.require_lang_item(LangItem::Copy, None); let copy_def_id = self.tcx.require_lang_item(LangItem::Copy, None);

View File

@ -9,7 +9,6 @@ use rustc_data_structures::unord::UnordSet;
use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::DefineOpaqueTypes;
use rustc_middle::ty::{Region, RegionVid}; use rustc_middle::ty::{Region, RegionVid};
use tracing::debug; use tracing::debug;
use ty::TypingMode;
use super::*; use super::*;
use crate::errors::UnableToConstructConstantValue; use crate::errors::UnableToConstructConstantValue;
@ -71,7 +70,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
pub fn find_auto_trait_generics<A>( pub fn find_auto_trait_generics<A>(
&self, &self,
ty: Ty<'tcx>, ty: Ty<'tcx>,
orig_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
trait_did: DefId, trait_did: DefId,
mut auto_trait_callback: impl FnMut(AutoTraitInfo<'tcx>) -> A, mut auto_trait_callback: impl FnMut(AutoTraitInfo<'tcx>) -> A,
) -> AutoTraitResult<A> { ) -> AutoTraitResult<A> {
@ -79,7 +78,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
let trait_ref = ty::TraitRef::new(tcx, trait_did, [ty]); let trait_ref = ty::TraitRef::new(tcx, trait_did, [ty]);
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let (infcx, orig_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
let mut selcx = SelectionContext::new(&infcx); let mut selcx = SelectionContext::new(&infcx);
for polarity in [ty::PredicatePolarity::Positive, ty::PredicatePolarity::Negative] { for polarity in [ty::PredicatePolarity::Positive, ty::PredicatePolarity::Negative] {
let result = selcx.select(&Obligation::new( let result = selcx.select(&Obligation::new(
@ -89,17 +88,13 @@ impl<'tcx> AutoTraitFinder<'tcx> {
ty::TraitPredicate { trait_ref, polarity }, ty::TraitPredicate { trait_ref, polarity },
)); ));
if let Ok(Some(ImplSource::UserDefined(_))) = result { if let Ok(Some(ImplSource::UserDefined(_))) = result {
debug!( debug!("find_auto_trait_generics({trait_ref:?}): manual impl found, bailing out");
"find_auto_trait_generics({:?}): \
manual impl found, bailing out",
trait_ref
);
// If an explicit impl exists, it always takes priority over an auto impl // If an explicit impl exists, it always takes priority over an auto impl
return AutoTraitResult::ExplicitImpl; return AutoTraitResult::ExplicitImpl;
} }
} }
let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let (infcx, orig_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
let mut fresh_preds = FxIndexSet::default(); let mut fresh_preds = FxIndexSet::default();
// Due to the way projections are handled by SelectionContext, we need to run // Due to the way projections are handled by SelectionContext, we need to run

View File

@ -698,8 +698,8 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>(
/// used during analysis. /// used during analysis.
pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec<ty::Clause<'tcx>>) -> bool { pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec<ty::Clause<'tcx>>) -> bool {
debug!("impossible_predicates(predicates={:?})", predicates); debug!("impossible_predicates(predicates={:?})", predicates);
let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis); let (infcx, param_env) =
let param_env = ty::ParamEnv::reveal_all(); tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv::fully_monomorphized());
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
let predicates = ocx.normalize(&ObligationCause::dummy(), param_env, predicates); let predicates = ocx.normalize(&ObligationCause::dummy(), param_env, predicates);
for predicate in predicates { for predicate in predicates {

View File

@ -9,8 +9,7 @@ use rustc_infer::traits::util::PredicateSet;
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, TypingMode, Upcast, self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, Upcast, VtblEntry,
VtblEntry,
}; };
use rustc_span::{DUMMY_SP, Span, sym}; use rustc_span::{DUMMY_SP, Span, sym};
use smallvec::{SmallVec, smallvec}; use smallvec::{SmallVec, smallvec};
@ -442,8 +441,8 @@ fn trait_refs_are_compatible<'tcx>(
return false; return false;
} }
let infcx = tcx.infer_ctxt().build(TypingMode::PostAnalysis); let (infcx, param_env) =
let param_env = ty::ParamEnv::reveal_all(); tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv::fully_monomorphized());
let ocx = ObligationCtxt::new(&infcx); let ocx = ObligationCtxt::new(&infcx);
let hr_source_principal = let hr_source_principal =
ocx.normalize(&ObligationCause::dummy(), param_env, hr_vtable_principal); ocx.normalize(&ObligationCause::dummy(), param_env, hr_vtable_principal);

View File

@ -397,7 +397,7 @@ fn adjust_for_rust_scalar<'tcx>(
Some(kind) Some(kind)
} else if let Some(pointee) = drop_target_pointee { } else if let Some(pointee) = drop_target_pointee {
// The argument to `drop_in_place` is semantically equivalent to a mutable reference. // The argument to `drop_in_place` is semantically equivalent to a mutable reference.
Some(PointerKind::MutableRef { unpin: pointee.is_unpin(tcx, cx.typing_env.param_env) }) Some(PointerKind::MutableRef { unpin: pointee.is_unpin(tcx, cx.typing_env) })
} else { } else {
None None
}; };

View File

@ -3,34 +3,33 @@
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode}; use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_trait_selection::traits; use rustc_trait_selection::traits;
fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool {
is_item_raw(tcx, query, LangItem::Copy) is_item_raw(tcx, query, LangItem::Copy)
} }
fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool {
is_item_raw(tcx, query, LangItem::Sized) is_item_raw(tcx, query, LangItem::Sized)
} }
fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool {
is_item_raw(tcx, query, LangItem::Freeze) is_item_raw(tcx, query, LangItem::Freeze)
} }
fn is_unpin_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { fn is_unpin_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool {
is_item_raw(tcx, query, LangItem::Unpin) is_item_raw(tcx, query, LangItem::Unpin)
} }
fn is_item_raw<'tcx>( fn is_item_raw<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, query: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>,
item: LangItem, item: LangItem,
) -> bool { ) -> bool {
let (param_env, ty) = query.into_parts(); let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(query.typing_env);
let trait_def_id = tcx.require_lang_item(item, None); let trait_def_id = tcx.require_lang_item(item, None);
let infcx = tcx.infer_ctxt().build(TypingMode::from_param_env(param_env)); traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, query.value, trait_def_id)
traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id)
} }
pub(crate) fn provide(providers: &mut Providers) { pub(crate) fn provide(providers: &mut Providers) {

View File

@ -13,7 +13,7 @@ use rustc_span::sym;
use rustc_trait_selection::traits; use rustc_trait_selection::traits;
use rustc_type_ir::ClosureKind; use rustc_type_ir::ClosureKind;
use tracing::debug; use tracing::debug;
use traits::{Reveal, translate_args}; use traits::translate_args;
use crate::errors::UnexpectedFnPtrAssociatedItem; use crate::errors::UnexpectedFnPtrAssociatedItem;
@ -133,18 +133,6 @@ fn resolve_associated_item<'tcx>(
bug!("{:?} not found in {:?}", trait_item_id, impl_data.impl_def_id); bug!("{:?} not found in {:?}", trait_item_id, impl_data.impl_def_id);
}); });
let typing_env = typing_env.with_reveal_all_normalized(tcx);
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
let args = rcvr_args.rebase_onto(tcx, trait_def_id, impl_data.args);
let args = translate_args(
&infcx,
param_env,
impl_data.impl_def_id,
args,
leaf_def.defining_node,
);
let args = infcx.tcx.erase_regions(args);
// Since this is a trait item, we need to see if the item is either a trait default item // Since this is a trait item, we need to see if the item is either a trait default item
// or a specialization because we can't resolve those unless we can `Reveal::All`. // or a specialization because we can't resolve those unless we can `Reveal::All`.
// NOTE: This should be kept in sync with the similar code in // NOTE: This should be kept in sync with the similar code in
@ -157,16 +145,28 @@ fn resolve_associated_item<'tcx>(
// and the obligation is monomorphic, otherwise passes such as // and the obligation is monomorphic, otherwise passes such as
// transmute checking and polymorphic MIR optimizations could // transmute checking and polymorphic MIR optimizations could
// get a result which isn't correct for all monomorphizations. // get a result which isn't correct for all monomorphizations.
if param_env.reveal() == Reveal::All { match typing_env.typing_mode {
!trait_ref.still_further_specializable() ty::TypingMode::Coherence
} else { | ty::TypingMode::Analysis { defining_opaque_types: _ } => false,
false ty::TypingMode::PostAnalysis => !trait_ref.still_further_specializable(),
} }
}; };
if !eligible { if !eligible {
return Ok(None); return Ok(None);
} }
let typing_env = typing_env.with_reveal_all_normalized(tcx);
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
let args = rcvr_args.rebase_onto(tcx, trait_def_id, impl_data.args);
let args = translate_args(
&infcx,
param_env,
impl_data.impl_def_id,
args,
leaf_def.defining_node,
);
let args = infcx.tcx.erase_regions(args);
// HACK: We may have overlapping `dyn Trait` built-in impls and // HACK: We may have overlapping `dyn Trait` built-in impls and
// user-provided blanket impls. Detect that case here, and return // user-provided blanket impls. Detect that case here, and return
// ambiguity. // ambiguity.

View File

@ -105,7 +105,7 @@ fn map_error<'tcx>(
// This is sometimes not a compile error if there are trivially false where clauses. // This is sometimes not a compile error if there are trivially false where clauses.
// See `tests/ui/layout/trivial-bounds-sized.rs` for an example. // See `tests/ui/layout/trivial-bounds-sized.rs` for an example.
assert!(field.layout.is_unsized(), "invalid layout error {err:#?}"); assert!(field.layout.is_unsized(), "invalid layout error {err:#?}");
if !field.ty.is_sized(cx.tcx(), cx.typing_env.param_env) { if !field.ty.is_sized(cx.tcx(), cx.typing_env) {
cx.tcx().dcx().delayed_bug(format!( cx.tcx().dcx().delayed_bug(format!(
"encountered unexpected unsized field in layout of {ty:?}: {field:#?}" "encountered unexpected unsized field in layout of {ty:?}: {field:#?}"
)); ));
@ -236,7 +236,7 @@ fn layout_of_uncached<'tcx>(
} }
let pointee = tcx.normalize_erasing_regions(cx.typing_env, pointee); let pointee = tcx.normalize_erasing_regions(cx.typing_env, pointee);
if pointee.is_sized(tcx, cx.typing_env.param_env) { if pointee.is_sized(tcx, cx.typing_env) {
return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr))); return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr)));
} }
@ -594,8 +594,8 @@ fn layout_of_uncached<'tcx>(
let maybe_unsized = def.is_struct() let maybe_unsized = def.is_struct()
&& def.non_enum_variant().tail_opt().is_some_and(|last_field| { && def.non_enum_variant().tail_opt().is_some_and(|last_field| {
let param_env = tcx.param_env(def.did()); let typing_env = ty::TypingEnv::post_analysis(tcx, def.did());
!tcx.type_of(last_field.did).instantiate_identity().is_sized(tcx, param_env) !tcx.type_of(last_field.did).instantiate_identity().is_sized(tcx, typing_env)
}); });
let layout = cx let layout = cx
@ -620,11 +620,7 @@ fn layout_of_uncached<'tcx>(
// If the struct tail is sized and can be unsized, check that unsizing doesn't move the fields around. // If the struct tail is sized and can be unsized, check that unsizing doesn't move the fields around.
if cfg!(debug_assertions) if cfg!(debug_assertions)
&& maybe_unsized && maybe_unsized
&& def && def.non_enum_variant().tail().ty(tcx, args).is_sized(tcx, cx.typing_env)
.non_enum_variant()
.tail()
.ty(tcx, args)
.is_sized(tcx, cx.typing_env.param_env)
{ {
let mut variants = variants; let mut variants = variants;
let tail_replacement = cx.layout_of(Ty::new_slice(tcx, tcx.types.u8)).unwrap(); let tail_replacement = cx.layout_of(Ty::new_slice(tcx, tcx.types.u8)).unwrap();

View File

@ -186,7 +186,7 @@ where
} }
} }
_ if component.is_copy_modulo_regions(tcx, self.typing_env.param_env) => (), _ if component.is_copy_modulo_regions(tcx, self.typing_env) => (),
ty::Closure(_, args) => { ty::Closure(_, args) => {
for upvar in args.as_closure().upvar_tys() { for upvar in args.as_closure().upvar_tys() {

View File

@ -4,10 +4,8 @@ use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
use crate::fold::TypeFoldable; use crate::fold::TypeFoldable;
use crate::inherent::*;
use crate::relate::RelateResult; use crate::relate::RelateResult;
use crate::relate::combine::PredicateEmittingRelation; use crate::relate::combine::PredicateEmittingRelation;
use crate::solve::Reveal;
use crate::{self as ty, Interner}; use crate::{self as ty, Interner};
/// The current typing mode of an inference context. We unfortunately have some /// The current typing mode of an inference context. We unfortunately have some
@ -58,18 +56,6 @@ impl<I: Interner> TypingMode<I> {
pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> { pub fn analysis_in_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode<I> {
TypingMode::Analysis { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) } TypingMode::Analysis { defining_opaque_types: cx.opaque_types_defined_by(body_def_id) }
} }
/// FIXME(#132279): Using this function is questionable as the `param_env`
/// does not track `defining_opaque_types` and whether we're in coherence mode.
/// Many uses of this function should also use a not-yet implemented typing mode
/// which reveals already defined opaque types in the future. This function will
/// get completely removed at some point.
pub fn from_param_env(param_env: I::ParamEnv) -> TypingMode<I> {
match param_env.reveal() {
Reveal::UserFacing => TypingMode::non_body_analysis(),
Reveal::All => TypingMode::PostAnalysis,
}
}
} }
pub trait InferCtxtLike: Sized { pub trait InferCtxtLike: Sized {

View File

@ -21,7 +21,7 @@ pub(crate) fn synthesize_auto_trait_impls<'tcx>(
item_def_id: DefId, item_def_id: DefId,
) -> Vec<clean::Item> { ) -> Vec<clean::Item> {
let tcx = cx.tcx; let tcx = cx.tcx;
let param_env = tcx.param_env(item_def_id); let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id);
let ty = tcx.type_of(item_def_id).instantiate_identity(); let ty = tcx.type_of(item_def_id).instantiate_identity();
let finder = auto_trait::AutoTraitFinder::new(tcx); let finder = auto_trait::AutoTraitFinder::new(tcx);
@ -34,7 +34,7 @@ pub(crate) fn synthesize_auto_trait_impls<'tcx>(
cx, cx,
ty, ty,
trait_def_id, trait_def_id,
param_env, typing_env,
item_def_id, item_def_id,
&finder, &finder,
DiscardPositiveImpls::No, DiscardPositiveImpls::No,
@ -42,13 +42,13 @@ pub(crate) fn synthesize_auto_trait_impls<'tcx>(
}) })
.collect(); .collect();
// We are only interested in case the type *doesn't* implement the `Sized` trait. // We are only interested in case the type *doesn't* implement the `Sized` trait.
if !ty.is_sized(tcx, param_env) if !ty.is_sized(tcx, typing_env)
&& let Some(sized_trait_def_id) = tcx.lang_items().sized_trait() && let Some(sized_trait_def_id) = tcx.lang_items().sized_trait()
&& let Some(impl_item) = synthesize_auto_trait_impl( && let Some(impl_item) = synthesize_auto_trait_impl(
cx, cx,
ty, ty,
sized_trait_def_id, sized_trait_def_id,
param_env, typing_env,
item_def_id, item_def_id,
&finder, &finder,
DiscardPositiveImpls::Yes, DiscardPositiveImpls::Yes,
@ -64,7 +64,7 @@ fn synthesize_auto_trait_impl<'tcx>(
cx: &mut DocContext<'tcx>, cx: &mut DocContext<'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
trait_def_id: DefId, trait_def_id: DefId,
param_env: ty::ParamEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
item_def_id: DefId, item_def_id: DefId,
finder: &auto_trait::AutoTraitFinder<'tcx>, finder: &auto_trait::AutoTraitFinder<'tcx>,
discard_positive_impls: DiscardPositiveImpls, discard_positive_impls: DiscardPositiveImpls,
@ -76,7 +76,7 @@ fn synthesize_auto_trait_impl<'tcx>(
return None; return None;
} }
let result = finder.find_auto_trait_generics(ty, param_env, trait_def_id, |info| { let result = finder.find_auto_trait_generics(ty, typing_env, trait_def_id, |info| {
clean_param_env(cx, item_def_id, info.full_user_env, info.region_data, info.vid_to_region) clean_param_env(cx, item_def_id, info.full_user_env, info.region_data, info.vid_to_region)
}); });

View File

@ -1818,9 +1818,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
let ct = if let hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) = let ct = if let hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) =
const_arg.kind const_arg.kind
{ {
// Only anon consts can implicitly capture params. let typing_env = ty::TypingEnv::post_analysis(cx.tcx, *def_id);
// FIXME: is this correct behavior?
let typing_env = ty::TypingEnv::from_param_env(cx.tcx.param_env(*def_id));
cx.tcx.normalize_erasing_regions(typing_env, ct) cx.tcx.normalize_erasing_regions(typing_env, ct)
} else { } else {
ct ct

View File

@ -39,7 +39,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) {
(Mutability::Not, Mutability::Not) | (Mutability::Mut, Mutability::Mut)) (Mutability::Not, Mutability::Not) | (Mutability::Mut, Mutability::Mut))
// The `U` in `pointer::cast` have to be `Sized` // The `U` in `pointer::cast` have to be `Sized`
// as explained here: https://github.com/rust-lang/rust/issues/60602. // as explained here: https://github.com/rust-lang/rust/issues/60602.
&& to_pointee_ty.is_sized(cx.tcx, cx.param_env) && to_pointee_ty.is_sized(cx.tcx, cx.typing_env())
{ {
let mut app = Applicability::MachineApplicable; let mut app = Applicability::MachineApplicable;
let turbofish = match &cast_to_hir_ty.kind { let turbofish = match &cast_to_hir_ty.kind {

View File

@ -15,6 +15,7 @@ use rustc_hir::{
self as hir, BindingMode, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, Pat, self as hir, BindingMode, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, Pat,
PatKind, Path, QPath, TyKind, UnOp, PatKind, Path, QPath, TyKind, UnOp,
}; };
use rustc_hir::def_id::DefId;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypeckResults}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypeckResults};
@ -753,11 +754,10 @@ impl TyCoercionStability {
fn for_defined_ty<'tcx>(cx: &LateContext<'tcx>, ty: DefinedTy<'tcx>, for_return: bool) -> Self { fn for_defined_ty<'tcx>(cx: &LateContext<'tcx>, ty: DefinedTy<'tcx>, for_return: bool) -> Self {
match ty { match ty {
DefinedTy::Hir(ty) => Self::for_hir_ty(ty), DefinedTy::Hir(ty) => Self::for_hir_ty(ty),
DefinedTy::Mir(ty) => Self::for_mir_ty( DefinedTy::Mir { def_site_def_id, ty } => Self::for_mir_ty(
cx.tcx, cx.tcx,
// FIXME(#132279): convert `DefinedTy` to use `TypingEnv` instead. def_site_def_id,
ty::TypingEnv::from_param_env(ty.param_env), cx.tcx.instantiate_bound_regions_with_erased(ty),
cx.tcx.instantiate_bound_regions_with_erased(ty.value),
for_return, for_return,
), ),
} }
@ -824,12 +824,15 @@ impl TyCoercionStability {
} }
} }
fn for_mir_ty<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>, ty: Ty<'tcx>, for_return: bool) -> Self { fn for_mir_ty<'tcx>(tcx: TyCtxt<'tcx>, def_site_def_id: Option<DefId>, ty: Ty<'tcx>, for_return: bool) -> Self {
let ty::Ref(_, mut ty, _) = *ty.kind() else { let ty::Ref(_, mut ty, _) = *ty.kind() else {
return Self::None; return Self::None;
}; };
if let Some(def_id) = def_site_def_id {
let typing_env = ty::TypingEnv::non_body_analysis(tcx, def_id);
ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty); ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty);
}
loop { loop {
break match *ty.kind() { break match *ty.kind() {
ty::Ref(_, ref_ty, _) => { ty::Ref(_, ref_ty, _) => {
@ -1028,7 +1031,7 @@ fn report<'tcx>(
State::ExplicitDeref { mutability } => { State::ExplicitDeref { mutability } => {
if is_block_like(expr) if is_block_like(expr)
&& let ty::Ref(_, ty, _) = data.adjusted_ty.kind() && let ty::Ref(_, ty, _) = data.adjusted_ty.kind()
&& ty.is_sized(cx.tcx, cx.param_env) && ty.is_sized(cx.tcx, cx.typing_env())
{ {
// Rustc bug: auto deref doesn't work on block expression when targeting sized types. // Rustc bug: auto deref doesn't work on block expression when targeting sized types.
return; return;

View File

@ -454,13 +454,13 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r
&& cx.tcx.is_diagnostic_item(sym::PartialEq, def_id) && cx.tcx.is_diagnostic_item(sym::PartialEq, def_id)
&& !has_non_exhaustive_attr(cx.tcx, *adt) && !has_non_exhaustive_attr(cx.tcx, *adt)
&& !ty_implements_eq_trait(cx.tcx, ty, eq_trait_def_id) && !ty_implements_eq_trait(cx.tcx, ty, eq_trait_def_id)
&& let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id) && let typing_env = typing_env_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id)
&& let Some(local_def_id) = adt.did().as_local() && let Some(local_def_id) = adt.did().as_local()
// If all of our fields implement `Eq`, we can implement `Eq` too // If all of our fields implement `Eq`, we can implement `Eq` too
&& adt && adt
.all_fields() .all_fields()
.map(|f| f.ty(cx.tcx, args)) .map(|f| f.ty(cx.tcx, args))
.all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[])) .all(|ty| implements_trait_with_env(cx.tcx, typing_env, ty, eq_trait_def_id, None, &[]))
{ {
span_lint_hir_and_then( span_lint_hir_and_then(
cx, cx,
@ -485,7 +485,7 @@ fn ty_implements_eq_trait<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, eq_trait_id: De
} }
/// Creates the `ParamEnv` used for the give type's derived `Eq` impl. /// Creates the `ParamEnv` used for the give type's derived `Eq` impl.
fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> ParamEnv<'_> { fn typing_env_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> ty::TypingEnv<'_> {
// Initial map from generic index to param def. // Initial map from generic index to param def.
// Vec<(param_def, needs_eq)> // Vec<(param_def, needs_eq)>
let mut params = tcx let mut params = tcx
@ -506,7 +506,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
} }
} }
ParamEnv::new( let param_env = ParamEnv::new(
tcx.mk_clauses_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain( tcx.mk_clauses_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain(
params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| { params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| {
ClauseKind::Trait(TraitPredicate { ClauseKind::Trait(TraitPredicate {
@ -517,5 +517,9 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) ->
}), }),
)), )),
Reveal::UserFacing, Reveal::UserFacing,
) );
ty::TypingEnv {
typing_mode: ty::TypingMode::non_body_analysis(),
param_env,
}
} }

View File

@ -198,7 +198,7 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, tys: &mut DefIdSet)
// primitive types are never mutable // primitive types are never mutable
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false, ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false,
ty::Adt(adt, args) => { ty::Adt(adt, args) => {
tys.insert(adt.did()) && !ty.is_freeze(cx.tcx, cx.param_env) tys.insert(adt.did()) && !ty.is_freeze(cx.tcx, cx.typing_env())
|| matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::Rc | sym::Arc)) || matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::Rc | sym::Arc))
&& args.types().any(|ty| is_mutable_ty(cx, ty, tys)) && args.types().any(|ty| is_mutable_ty(cx, ty, tys))
}, },

View File

@ -80,7 +80,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq {
let has_interior_mutability = !cx let has_interior_mutability = !cx
.typeck_results() .typeck_results()
.node_type(canonical_id) .node_type(canonical_id)
.is_freeze(cx.tcx, cx.param_env); .is_freeze(cx.tcx, cx.typing_env());
if has_interior_mutability { if has_interior_mutability {
return; return;
} }

View File

@ -115,11 +115,11 @@ fn is_ref_iterable<'tcx>(
.tcx .tcx
.liberate_late_bound_regions(fn_id, cx.tcx.fn_sig(fn_id).skip_binder()) .liberate_late_bound_regions(fn_id, cx.tcx.fn_sig(fn_id).skip_binder())
&& let &[req_self_ty, req_res_ty] = &**sig.inputs_and_output && let &[req_self_ty, req_res_ty] = &**sig.inputs_and_output
&& let param_env = cx.tcx.param_env(fn_id) && let typing_env = ty::TypingEnv::non_body_analysis(cx.tcx, fn_id)
&& implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, Some(fn_id), &[]) && implements_trait_with_env(cx.tcx, typing_env, req_self_ty, trait_id, Some(fn_id), &[])
&& let Some(into_iter_ty) = && let Some(into_iter_ty) =
make_normalized_projection_with_regions(cx.tcx, param_env, trait_id, sym!(IntoIter), [req_self_ty]) make_normalized_projection_with_regions(cx.tcx, typing_env, trait_id, sym!(IntoIter), [req_self_ty])
&& let req_res_ty = normalize_with_regions(cx.tcx, param_env, req_res_ty) && let req_res_ty = normalize_with_regions(cx.tcx, typing_env, req_res_ty)
&& into_iter_ty == req_res_ty && into_iter_ty == req_res_ty
{ {
let adjustments = typeck.expr_adjustments(self_arg); let adjustments = typeck.expr_adjustments(self_arg);

View File

@ -148,7 +148,7 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name:
_ => {}, _ => {},
} }
} }
requires_copy |= !ty.is_copy_modulo_regions(cx.tcx, cx.param_env); requires_copy |= !ty.is_copy_modulo_regions(cx.tcx, cx.typing_env());
break; break;
} }
}, },
@ -158,9 +158,9 @@ pub(crate) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &Expr<'_>, name:
} }
if can_lint if can_lint
&& (!requires_copy || arg_ty.is_copy_modulo_regions(cx.tcx, cx.param_env)) && (!requires_copy || arg_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env()))
// This case could be handled, but a fair bit of care would need to be taken. // This case could be handled, but a fair bit of care would need to be taken.
&& (!requires_deref || arg_ty.is_freeze(cx.tcx, cx.param_env)) && (!requires_deref || arg_ty.is_freeze(cx.tcx, cx.typing_env()))
{ {
if requires_deref { if requires_deref {
edits.push((param.span.shrink_to_lo(), "&".into())); edits.push((param.span.shrink_to_lo(), "&".into()));

View File

@ -80,7 +80,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for MutVisitor<'_, 'tcx> {
"generally you want to avoid `&mut &mut _` if possible", "generally you want to avoid `&mut &mut _` if possible",
); );
} else if let ty::Ref(_, ty, hir::Mutability::Mut) = self.cx.typeck_results().expr_ty(e).kind() { } else if let ty::Ref(_, ty, hir::Mutability::Mut) = self.cx.typeck_results().expr_ty(e).kind() {
if ty.peel_refs().is_sized(self.cx.tcx, self.cx.param_env) { if ty.peel_refs().is_sized(self.cx.tcx, self.cx.typing_env()) {
span_lint_hir( span_lint_hir(
self.cx, self.cx,
MUT_MUT, MUT_MUT,

View File

@ -85,8 +85,8 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowsForGenericArgs<'tcx> {
&& use_cx.same_ctxt && use_cx.same_ctxt
&& !use_cx.is_ty_unified && !use_cx.is_ty_unified
&& let use_node = use_cx.use_node(cx) && let use_node = use_cx.use_node(cx)
&& let Some(DefinedTy::Mir(ty)) = use_node.defined_ty(cx) && let Some(DefinedTy::Mir { def_site_def_id: _, ty }) = use_node.defined_ty(cx)
&& let ty::Param(ty) = *ty.value.skip_binder().kind() && let ty::Param(param_ty) = *ty.skip_binder().kind()
&& let Some((hir_id, fn_id, i)) = match use_node { && let Some((hir_id, fn_id, i)) = match use_node {
ExprUseNode::MethodArg(_, _, 0) => None, ExprUseNode::MethodArg(_, _, 0) => None,
ExprUseNode::MethodArg(hir_id, None, i) => cx ExprUseNode::MethodArg(hir_id, None, i) => cx
@ -112,7 +112,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowsForGenericArgs<'tcx> {
fn_id, fn_id,
cx.typeck_results().node_args(hir_id), cx.typeck_results().node_args(hir_id),
i, i,
ty, param_ty,
expr, expr,
&self.msrv, &self.msrv,
) )

View File

@ -180,11 +180,16 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
if !is_self(arg) if !is_self(arg)
&& !ty.is_mutable_ptr() && !ty.is_mutable_ptr()
&& !is_copy(cx, ty) && !is_copy(cx, ty)
&& ty.is_sized(cx.tcx, cx.param_env) && ty.is_sized(cx.tcx, cx.typing_env())
&& !allowed_traits.iter().any(|&t| { && !allowed_traits.iter().any(|&t| {
implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, t, None, [Option::< implements_trait_with_env_from_iter(
ty::GenericArg<'tcx>, cx.tcx,
>::None]) cx.typing_env(),
ty,
t,
None,
[None::<ty::GenericArg<'tcx>>]
)
}) })
&& !implements_borrow_trait && !implements_borrow_trait
&& !all_borrowable_trait && !all_borrowable_trait

View File

@ -270,8 +270,8 @@ impl<'tcx> NonCopyConst<'tcx> {
instance, instance,
promoted: None, promoted: None,
}; };
let param_env = cx.tcx.param_env(def_id).with_reveal_all_normalized(cx.tcx); let typing_env = ty::TypingEnv::post_analysis(cx.tcx, def_id);
let result = cx.tcx.const_eval_global_id_for_typeck(param_env, cid, DUMMY_SP); let result = cx.tcx.const_eval_global_id_for_typeck(typing_env, cid, DUMMY_SP);
Self::is_value_unfrozen_raw(cx, result, ty) Self::is_value_unfrozen_raw(cx, result, ty)
} }
@ -294,7 +294,7 @@ impl<'tcx> NonCopyConst<'tcx> {
instance, instance,
promoted: None, promoted: None,
}; };
tcx.const_eval_global_id_for_typeck(typing_env.param_env, cid, span) tcx.const_eval_global_id_for_typeck(typing_env, cid, span)
}, },
Ok(None) => Err(ErrorHandled::TooGeneric(span)), Ok(None) => Err(ErrorHandled::TooGeneric(span)),
Err(err) => Err(ErrorHandled::Reported(err.into(), span)), Err(err) => Err(ErrorHandled::Reported(err.into(), span)),

View File

@ -251,7 +251,7 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex
{ {
let mut applicability = Applicability::MachineApplicable; let mut applicability = Applicability::MachineApplicable;
let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability); let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability);
let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env) let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.typing_env())
&& !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)); && !matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..));
let sugg = if let Some(else_inner) = r#else { let sugg = if let Some(else_inner) = r#else {
if eq_expr_value(cx, caller, peel_blocks(else_inner)) { if eq_expr_value(cx, caller, peel_blocks(else_inner)) {

View File

@ -27,7 +27,7 @@ pub(super) fn check<'tcx>(
|diag| { |diag| {
if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) { if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
if from_mutbl == to_mutbl if from_mutbl == to_mutbl
&& to_pointee_ty.is_sized(cx.tcx, cx.param_env) && to_pointee_ty.is_sized(cx.tcx, cx.typing_env())
&& msrv.meets(msrvs::POINTER_CAST) && msrv.meets(msrvs::POINTER_CAST)
{ {
diag.span_suggestion_verbose( diag.span_suggestion_verbose(

View File

@ -206,12 +206,12 @@ fn reduce_refs<'tcx>(cx: &LateContext<'tcx>, mut from_ty: Ty<'tcx>, mut to_ty: T
continue; continue;
}, },
(&(ty::Ref(_, unsized_ty, _) | ty::RawPtr(unsized_ty, _)), _) (&(ty::Ref(_, unsized_ty, _) | ty::RawPtr(unsized_ty, _)), _)
if !unsized_ty.is_sized(cx.tcx, cx.param_env) => if !unsized_ty.is_sized(cx.tcx, cx.typing_env()) =>
{ {
(true, false) (true, false)
}, },
(_, &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(unsized_ty, _))) (_, &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(unsized_ty, _)))
if !unsized_ty.is_sized(cx.tcx, cx.param_env) => if !unsized_ty.is_sized(cx.tcx, cx.typing_env()) =>
{ {
(false, true) (false, true)
}, },

View File

@ -60,7 +60,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>, qpath:
// here because `mod.rs` guarantees this lint is only run on types outside of bodies and // here because `mod.rs` guarantees this lint is only run on types outside of bodies and
// is not run on locals. // is not run on locals.
let ty = lower_ty(cx.tcx, hir_ty); let ty = lower_ty(cx.tcx, hir_ty);
if ty.has_escaping_bound_vars() || !ty.is_sized(cx.tcx, cx.param_env) { if ty.has_escaping_bound_vars() || !ty.is_sized(cx.tcx, cx.typing_env()) {
return false; return false;
} }
hir_ty.span hir_ty.span

View File

@ -37,7 +37,7 @@ pub(super) fn check<'tcx>(
&& let boxed_alloc_ty = last.args.get(1) && let boxed_alloc_ty = last.args.get(1)
&& let ty_ty = lower_ty(cx.tcx, boxed_ty) && let ty_ty = lower_ty(cx.tcx, boxed_ty)
&& !ty_ty.has_escaping_bound_vars() && !ty_ty.has_escaping_bound_vars()
&& ty_ty.is_sized(cx.tcx, cx.param_env) && ty_ty.is_sized(cx.tcx, cx.typing_env())
&& let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes()) && let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes())
&& ty_ty_size < box_size_threshold && ty_ty_size < box_size_threshold
// https://github.com/rust-lang/rust-clippy/issues/7114 // https://github.com/rust-lang/rust-clippy/issues/7114

Some files were not shown because too many files have changed in this diff Show More