move fn is_item_raw to TypingEnv

This commit is contained in:
lcnr 2024-11-19 16:13:55 +01:00
parent 89b6885529
commit 948cec0fad
60 changed files with 181 additions and 168 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -250,7 +250,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(

View File

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

View File

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

View File

@ -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);
} }
@ -1085,7 +1085,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
// Special check for CTFE validation, preventing `UnsafeCell` inside unions in immutable memory. // Special check for CTFE validation, preventing `UnsafeCell` inside unions in immutable memory.
if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) { if self.ctfe_mode.is_some_and(|c| !c.allow_immutable_unsafe_cell()) {
if !val.layout.is_zst() && !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) { if !val.layout.is_zst()
&& !val.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.typing_env())
{
if !self.in_mutable_memory(val) { if !self.in_mutable_memory(val) {
throw_validation_failure!(self.path, UnsafeCellInImmutable); throw_validation_failure!(self.path, UnsafeCellInImmutable);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1390,19 +1390,19 @@ rustc_queries! {
/// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`, /// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`,
/// `ty.is_copy()`, etc, since that will prune the environment where possible. /// `ty.is_copy()`, etc, since that will prune the environment where possible.
query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { query is_copy_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` is `Copy`", env.value } desc { "computing whether `{}` is `Copy`", env.value }
} }
/// Query backing `Ty::is_sized`. /// Query backing `Ty::is_sized`.
query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { query is_sized_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` is `Sized`", env.value } desc { "computing whether `{}` is `Sized`", env.value }
} }
/// Query backing `Ty::is_freeze`. /// Query backing `Ty::is_freeze`.
query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { query is_freeze_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` is freeze", env.value } desc { "computing whether `{}` is freeze", env.value }
} }
/// Query backing `Ty::is_unpin`. /// Query backing `Ty::is_unpin`.
query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { query is_unpin_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool {
desc { "computing whether `{}` is `Unpin`", env.value } desc { "computing whether `{}` is `Unpin`", env.value }
} }
/// Query backing `Ty::needs_drop`. /// Query backing `Ty::needs_drop`.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -203,8 +203,6 @@ impl<'tcx> ConstToPat<'tcx> {
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
@ -276,7 +274,9 @@ 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.infcx.typing_env(self.param_env))
&& !pointee_ty.is_slice()
{
let err = UnsizedPattern { span, non_sm_ty: *pointee_ty }; let err = UnsizedPattern { span, non_sm_ty: *pointee_ty };
let e = tcx.dcx().emit_err(err); let e = tcx.dcx().emit_err(err);
// We errored. Signal that in the pattern, so that follow up errors can be silenced. // We errored. Signal that in the pattern, so that follow up errors can be silenced.

View File

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

View File

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

View File

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

View File

@ -120,12 +120,13 @@ 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.param_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 +242,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>>,
@ -281,7 +281,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
VnState { VnState {
tcx, tcx,
ecx: InterpCx::new(tcx, DUMMY_SP, param_env, DummyMachine), ecx: InterpCx::new(tcx, DUMMY_SP, param_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 +295,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 +346,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 +641,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 +1060,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 +1382,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
&& let Value::Aggregate(AggregateTy::RawPtr { data_pointer_ty, .. }, _, fields) = && let Value::Aggregate(AggregateTy::RawPtr { data_pointer_ty, .. }, _, fields) =
self.get(value) self.get(value)
&& let ty::RawPtr(to_pointee, _) = to.kind() && let ty::RawPtr(to_pointee, _) = to.kind()
&& to_pointee.is_sized(self.tcx, self.param_env) && to_pointee.is_sized(self.tcx, self.typing_env())
{ {
from = *data_pointer_ty; from = *data_pointer_ty;
value = fields[0]; value = fields[0];

View File

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

View File

@ -451,7 +451,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
if rvalue.has_param() { if rvalue.has_param() {
return None; return None;
} }
if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.typing_env.param_env) { if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.typing_env) {
// the interpreter doesn't support unsized locals (only unsized arguments), // the interpreter doesn't support unsized locals (only unsized arguments),
// but rustc does (in a kinda broken way), so we have to skip them here // but rustc does (in a kinda broken way), so we have to skip them here
return None; return None;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -42,7 +42,7 @@ 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, ty::TypingEnv::from_param_env(param_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,

View File

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

View File

@ -1028,7 +1028,7 @@ fn report<'tcx>(
State::ExplicitDeref { mutability } => { State::ExplicitDeref { mutability } => {
if is_block_like(expr) if is_block_like(expr)
&& let ty::Ref(_, ty, _) = data.adjusted_ty.kind() && let ty::Ref(_, ty, _) = data.adjusted_ty.kind()
&& ty.is_sized(cx.tcx, cx.param_env) && ty.is_sized(cx.tcx, cx.typing_env())
{ {
// Rustc bug: auto deref doesn't work on block expression when targeting sized types. // Rustc bug: auto deref doesn't work on block expression when targeting sized types.
return; return;

View File

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

View File

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

View File

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

View File

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

View File

@ -180,7 +180,7 @@ 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(cx.tcx, cx.param_env, ty, t, None, [Option::<
ty::GenericArg<'tcx>, ty::GenericArg<'tcx>,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -82,7 +82,7 @@ impl UnnecessaryBoxReturns {
// It's sometimes useful to return Box<T> if T is unsized, so don't lint those. // It's sometimes useful to return Box<T> if T is unsized, so don't lint those.
// Also, don't lint if we know that T is very large, in which case returning // Also, don't lint if we know that T is very large, in which case returning
// a Box<T> may be beneficial. // a Box<T> may be beneficial.
if boxed_ty.is_sized(cx.tcx, cx.param_env) && approx_ty_size(cx, boxed_ty) <= self.maximum_size { if boxed_ty.is_sized(cx.tcx, cx.typing_env()) && approx_ty_size(cx, boxed_ty) <= self.maximum_size {
span_lint_and_then( span_lint_and_then(
cx, cx,
UNNECESSARY_BOX_RETURNS, UNNECESSARY_BOX_RETURNS,

View File

@ -38,7 +38,7 @@ pub use type_certainty::expr_type_is_certain;
/// Checks if the given type implements copy. /// Checks if the given type implements copy.
pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
ty.is_copy_modulo_regions(cx.tcx, cx.param_env) ty.is_copy_modulo_regions(cx.tcx, cx.typing_env())
} }
/// This checks whether a given type is known to implement Debug. /// This checks whether a given type is known to implement Debug.

View File

@ -12,7 +12,6 @@ use std::{cmp, mem};
use rustc_abi::{BackendRepr, Size}; use rustc_abi::{BackendRepr, Size};
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use rustc_middle::mir::{Mutability, RetagKind}; use rustc_middle::mir::{Mutability, RetagKind};
use rustc_middle::ty::layout::HasTypingEnv;
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use self::diagnostics::{RetagCause, RetagInfo}; use self::diagnostics::{RetagCause, RetagInfo};
@ -71,7 +70,7 @@ impl NewPermission {
access: None, access: None,
protector: None, protector: None,
} }
} else if pointee.is_unpin(*cx.tcx, cx.param_env()) { } else if pointee.is_unpin(*cx.tcx, cx.typing_env()) {
// A regular full mutable reference. On `FnEntry` this is `noalias` and `dereferenceable`. // A regular full mutable reference. On `FnEntry` this is `noalias` and `dereferenceable`.
NewPermission::Uniform { NewPermission::Uniform {
perm: Permission::Unique, perm: Permission::Unique,
@ -129,7 +128,7 @@ impl NewPermission {
fn from_box_ty<'tcx>(ty: Ty<'tcx>, kind: RetagKind, cx: &crate::MiriInterpCx<'tcx>) -> Self { fn from_box_ty<'tcx>(ty: Ty<'tcx>, kind: RetagKind, cx: &crate::MiriInterpCx<'tcx>) -> Self {
// `ty` is not the `Box` but the field of the Box with this pointer (due to allocator handling). // `ty` is not the `Box` but the field of the Box with this pointer (due to allocator handling).
let pointee = ty.builtin_deref(true).unwrap(); let pointee = ty.builtin_deref(true).unwrap();
if pointee.is_unpin(*cx.tcx, cx.param_env()) { if pointee.is_unpin(*cx.tcx, cx.typing_env()) {
// A regular box. On `FnEntry` this is `noalias`, but not `dereferenceable` (hence only // A regular box. On `FnEntry` this is `noalias`, but not `dereferenceable` (hence only
// a weak protector). // a weak protector).
NewPermission::Uniform { NewPermission::Uniform {
@ -608,7 +607,7 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> {
match new_perm { match new_perm {
NewPermission::Uniform { perm, .. } => NewPermission::Uniform { perm, .. } =>
write!(kind_str, "{perm:?} permission").unwrap(), write!(kind_str, "{perm:?} permission").unwrap(),
NewPermission::FreezeSensitive { freeze_perm, .. } if ty.is_freeze(*this.tcx, this.param_env()) => NewPermission::FreezeSensitive { freeze_perm, .. } if ty.is_freeze(*this.tcx, this.typing_env()) =>
write!(kind_str, "{freeze_perm:?} permission").unwrap(), write!(kind_str, "{freeze_perm:?} permission").unwrap(),
NewPermission::FreezeSensitive { freeze_perm, nonfreeze_perm, .. } => NewPermission::FreezeSensitive { freeze_perm, nonfreeze_perm, .. } =>
write!(kind_str, "{freeze_perm:?}/{nonfreeze_perm:?} permission for frozen/non-frozen parts").unwrap(), write!(kind_str, "{freeze_perm:?}/{nonfreeze_perm:?} permission for frozen/non-frozen parts").unwrap(),

View File

@ -1,6 +1,5 @@
use rustc_abi::{BackendRepr, Size}; use rustc_abi::{BackendRepr, Size};
use rustc_middle::mir::{Mutability, RetagKind}; use rustc_middle::mir::{Mutability, RetagKind};
use rustc_middle::ty::layout::HasTypingEnv;
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use rustc_span::def_id::DefId; use rustc_span::def_id::DefId;
@ -132,8 +131,8 @@ impl<'tcx> NewPermission {
kind: RetagKind, kind: RetagKind,
cx: &crate::MiriInterpCx<'tcx>, cx: &crate::MiriInterpCx<'tcx>,
) -> Option<Self> { ) -> Option<Self> {
let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.param_env()); let ty_is_freeze = pointee.is_freeze(*cx.tcx, cx.typing_env());
let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.param_env()); let ty_is_unpin = pointee.is_unpin(*cx.tcx, cx.typing_env());
let is_protected = kind == RetagKind::FnEntry; let is_protected = kind == RetagKind::FnEntry;
// As demonstrated by `tests/fail/tree_borrows/reservedim_spurious_write.rs`, // As demonstrated by `tests/fail/tree_borrows/reservedim_spurious_write.rs`,
// interior mutability and protectors interact poorly. // interior mutability and protectors interact poorly.
@ -164,10 +163,10 @@ impl<'tcx> NewPermission {
zero_size: bool, zero_size: bool,
) -> Option<Self> { ) -> Option<Self> {
let pointee = ty.builtin_deref(true).unwrap(); let pointee = ty.builtin_deref(true).unwrap();
pointee.is_unpin(*cx.tcx, cx.param_env()).then_some(()).map(|()| { pointee.is_unpin(*cx.tcx, cx.typing_env()).then_some(()).map(|()| {
// Regular `Unpin` box, give it `noalias` but only a weak protector // Regular `Unpin` box, give it `noalias` but only a weak protector
// because it is valid to deallocate it within the function. // because it is valid to deallocate it within the function.
let ty_is_freeze = ty.is_freeze(*cx.tcx, cx.param_env()); let ty_is_freeze = ty.is_freeze(*cx.tcx, cx.typing_env());
let protected = kind == RetagKind::FnEntry; let protected = kind == RetagKind::FnEntry;
let initial_state = Permission::new_reserved(ty_is_freeze, protected); let initial_state = Permission::new_reserved(ty_is_freeze, protected);
Self { Self {
@ -521,7 +520,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Note: if we were to inline `new_reserved` below we would find out that // Note: if we were to inline `new_reserved` below we would find out that
// `ty_is_freeze` is eventually unused because it appears in a `ty_is_freeze || true`. // `ty_is_freeze` is eventually unused because it appears in a `ty_is_freeze || true`.
// We are nevertheless including it here for clarity. // We are nevertheless including it here for clarity.
let ty_is_freeze = place.layout.ty.is_freeze(*this.tcx, this.param_env()); let ty_is_freeze = place.layout.ty.is_freeze(*this.tcx, this.typing_env());
// Retag it. With protection! That is the entire point. // Retag it. With protection! That is the entire point.
let new_perm = NewPermission { let new_perm = NewPermission {
initial_state: Permission::new_reserved(ty_is_freeze, /* protected */ true), initial_state: Permission::new_reserved(ty_is_freeze, /* protected */ true),