mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 00:03:43 +00:00
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:
commit
70e814bd9e
@ -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
|
||||||
|
@ -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(),
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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 => {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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,35 +652,35 @@ 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(),
|
"dynamic call on non-`dyn` type {}",
|
||||||
"dynamic call on non-`dyn` type {}",
|
receiver_tail
|
||||||
receiver_tail
|
)
|
||||||
)
|
|
||||||
};
|
|
||||||
assert!(receiver_place.layout.is_unsized());
|
|
||||||
|
|
||||||
// Get the required information from the vtable.
|
|
||||||
let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?;
|
|
||||||
let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?;
|
|
||||||
|
|
||||||
// It might be surprising that we use a pointer as the receiver even if this
|
|
||||||
// is a by-val case; this works because by-val passing of an unsized `dyn
|
|
||||||
// Trait` to a function is actually desugared to a pointer.
|
|
||||||
(receiver_trait.principal(), dyn_ty, receiver_place.ptr())
|
|
||||||
};
|
};
|
||||||
|
assert!(receiver_place.layout.is_unsized());
|
||||||
|
|
||||||
|
// Get the required information from the vtable.
|
||||||
|
let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?;
|
||||||
|
let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?;
|
||||||
|
|
||||||
|
// It might be surprising that we use a pointer as the receiver even if this
|
||||||
|
// is a by-val case; this works because by-val passing of an unsized `dyn
|
||||||
|
// Trait` to a function is actually desugared to a pointer.
|
||||||
|
(receiver_trait.principal(), dyn_ty, receiver_place.ptr())
|
||||||
|
};
|
||||||
|
|
||||||
// Now determine the actual method to call. Usually we use the easy way of just
|
// Now determine the actual method to call. Usually we use the easy way of just
|
||||||
// looking up the method at index `idx`.
|
// looking up the method at index `idx`.
|
||||||
@ -704,7 +704,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
|
|
||||||
let concrete_method = Instance::expect_resolve_for_vtable(
|
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(),
|
||||||
|
@ -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(_)) => {
|
||||||
|
@ -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(..) => {},
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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"),
|
||||||
|
@ -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),
|
||||||
|
@ -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(),
|
||||||
|
@ -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)?;
|
||||||
|
@ -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));
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -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))
|
||||||
|
@ -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),
|
||||||
|
@ -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) {
|
||||||
|
@ -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,
|
||||||
param_env: ty::ParamEnv::empty(),
|
typing_env: ty::TypingEnv {
|
||||||
|
typing_mode: ty::TypingMode::non_body_analysis(),
|
||||||
|
param_env: ty::ParamEnv::empty(),
|
||||||
|
},
|
||||||
get_operand_ty: Box::new(|e| bug!("asm operand in global asm: {e:?}")),
|
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()
|
||||||
|
@ -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" }
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -105,8 +105,12 @@ 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(
|
||||||
.check_asm(asm, enclosing_id);
|
self.tcx,
|
||||||
|
self.infcx.typing_env(self.param_env),
|
||||||
|
get_operand_ty,
|
||||||
|
)
|
||||||
|
.check_asm(asm, enclosing_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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! {
|
||||||
|
@ -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)
|
||||||
|
@ -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 =
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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>;
|
||||||
|
|
||||||
|
@ -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`.
|
||||||
|
@ -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(
|
||||||
|
@ -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),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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`.
|
||||||
|
@ -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.
|
||||||
|
@ -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>,
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
@ -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>> {
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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`.
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -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];
|
||||||
|
@ -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.
|
||||||
|
@ -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 => {}
|
||||||
|
@ -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)),
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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] {
|
||||||
|
@ -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()),
|
||||||
);
|
);
|
||||||
|
@ -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) => {
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
|
@ -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) {
|
||||||
|
@ -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.
|
||||||
|
@ -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();
|
||||||
|
@ -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() {
|
||||||
|
@ -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 {
|
||||||
|
@ -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)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty);
|
if let Some(def_id) = def_site_def_id {
|
||||||
|
let typing_env = ty::TypingEnv::non_body_analysis(tcx, def_id);
|
||||||
|
ty = tcx.try_normalize_erasing_regions(typing_env, ty).unwrap_or(ty);
|
||||||
|
}
|
||||||
loop {
|
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;
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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))
|
||||||
},
|
},
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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()));
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
|
@ -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
|
||||||
|
@ -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)),
|
||||||
|
@ -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)) {
|
||||||
|
@ -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(
|
||||||
|
@ -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)
|
||||||
},
|
},
|
||||||
|
@ -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
|
||||||
|
@ -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
Loading…
Reference in New Issue
Block a user