Rollup merge of #103625 - WaffleLapkin:no_tyctxt_dogs_allowed, r=compiler-errors

Accept `TyCtxt` instead of `TyCtxtAt` in `Ty::is_*` functions

Functions in answer:

- `Ty::is_freeze`
- `Ty::is_sized`
- `Ty::is_unpin`
- `Ty::is_copy_modulo_regions`

This allows to remove a lot of useless `.at(DUMMY_SP)`, making the code a bit nicer :3

r? `@compiler-errors`
This commit is contained in:
Guillaume Gomez 2022-10-29 14:18:03 +02:00 committed by GitHub
commit 2414a4c31a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
45 changed files with 191 additions and 172 deletions

View file

@ -1783,7 +1783,7 @@ 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.at(span), self.param_env) { if !erased_ty.is_sized(tcx, self.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

@ -770,11 +770,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(null_op, ty) => { Rvalue::NullaryOp(null_op, ty) => {
assert!( assert!(lval.layout().ty.is_sized(fx.tcx, ParamEnv::reveal_all()));
lval.layout()
.ty
.is_sized(fx.tcx.at(stmt.source_info.span), ParamEnv::reveal_all())
);
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

@ -5,7 +5,6 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::interpret::{ use rustc_middle::mir::interpret::{
read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar, read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
}; };
use rustc_span::DUMMY_SP;
use cranelift_module::*; use cranelift_module::*;
@ -291,7 +290,7 @@ fn data_id_for_static(
let is_mutable = if tcx.is_mutable_static(def_id) { let is_mutable = if tcx.is_mutable_static(def_id) {
true true
} else { } else {
!ty.is_freeze(tcx.at(DUMMY_SP), ParamEnv::reveal_all()) !ty.is_freeze(tcx, ParamEnv::reveal_all())
}; };
let align = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().align.pref.bytes(); let align = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().align.pref.bytes();

View file

@ -5,7 +5,6 @@ use crate::common::TypeKind;
use crate::mir::place::PlaceRef; use crate::mir::place::PlaceRef;
use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use rustc_span::DUMMY_SP;
use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg}; use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg};
use rustc_target::abi::{AddressSpace, Integer}; use rustc_target::abi::{AddressSpace, Integer};
@ -75,16 +74,16 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
} }
fn type_is_sized(&self, ty: Ty<'tcx>) -> bool { fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
ty.is_sized(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all()) ty.is_sized(self.tcx(), ty::ParamEnv::reveal_all())
} }
fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
ty.is_freeze(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all()) ty.is_freeze(self.tcx(), ty::ParamEnv::reveal_all())
} }
fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool { fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
let param_env = ty::ParamEnv::reveal_all(); let param_env = ty::ParamEnv::reveal_all();
if ty.is_sized(self.tcx().at(DUMMY_SP), param_env) { if ty.is_sized(self.tcx(), param_env) {
return false; return false;
} }

View file

@ -212,7 +212,7 @@ fn create_pointee_place<'tcx>(
) -> MPlaceTy<'tcx> { ) -> MPlaceTy<'tcx> {
let tcx = ecx.tcx.tcx; let tcx = ecx.tcx.tcx;
if !ty.is_sized(ecx.tcx, ty::ParamEnv::empty()) { if !ty.is_sized(*ecx.tcx, ty::ParamEnv::empty()) {
// We need to create `Allocation`s for custom DSTs // We need to create `Allocation`s for custom DSTs
let (unsized_inner_ty, num_elems) = get_info_on_unsized_field(ty, valtree, tcx); let (unsized_inner_ty, num_elems) = get_info_on_unsized_field(ty, valtree, tcx);
@ -398,7 +398,7 @@ fn valtree_into_mplace<'tcx>(
let mut place_inner = match ty.kind() { let mut place_inner = match ty.kind() {
ty::Str | ty::Slice(_) => ecx.mplace_index(&place, i as u64).unwrap(), ty::Str | ty::Slice(_) => ecx.mplace_index(&place, i as u64).unwrap(),
_ if !ty.is_sized(ecx.tcx, ty::ParamEnv::empty()) _ if !ty.is_sized(*ecx.tcx, ty::ParamEnv::empty())
&& i == branches.len() - 1 => && i == branches.len() - 1 =>
{ {
// Note: For custom DSTs we need to manually process the last unsized field. // Note: For custom DSTs we need to manually process the last unsized field.

View file

@ -468,7 +468,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, '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.param_env)
} }
pub fn load_mir( pub fn load_mir(

View file

@ -114,7 +114,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval:
if let InternMode::Static(mutability) = mode { if let InternMode::Static(mutability) = mode {
// For this, we need to take into account `UnsafeCell`. When `ty` is `None`, we assume // For this, we need to take into account `UnsafeCell`. When `ty` is `None`, we assume
// no interior mutability. // no interior mutability.
let frozen = ty.map_or(true, |ty| ty.is_freeze(ecx.tcx, ecx.param_env)); let frozen = ty.map_or(true, |ty| ty.is_freeze(*ecx.tcx, ecx.param_env));
// For statics, allocation mutability is the combination of place mutability and // For statics, allocation mutability is the combination of place mutability and
// type mutability. // type mutability.
// The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere. // The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere.

View file

@ -15,7 +15,6 @@ use rustc_middle::mir::interpret::InterpError;
use rustc_middle::ty; use rustc_middle::ty;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_span::symbol::{sym, Symbol}; use rustc_span::symbol::{sym, Symbol};
use rustc_span::DUMMY_SP;
use rustc_target::abi::{Abi, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange}; use rustc_target::abi::{Abi, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange};
use std::hash::Hash; use std::hash::Hash;
@ -726,7 +725,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
// Special check preventing `UnsafeCell` inside unions in the inner part of constants. // Special check preventing `UnsafeCell` inside unions in the inner part of constants.
if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { inner: true, .. })) { if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { inner: true, .. })) {
if !op.layout.ty.is_freeze(self.ecx.tcx.at(DUMMY_SP), self.ecx.param_env) { if !op.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) {
throw_validation_failure!(self.path, { "`UnsafeCell` in a `const`" }); throw_validation_failure!(self.path, { "`UnsafeCell` in a `const`" });
} }
} }

View file

@ -8,7 +8,6 @@ use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty}; use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::{ use rustc_trait_selection::traits::{
self, ImplSource, Obligation, ObligationCause, SelectionContext, self, ImplSource, Obligation, ObligationCause, SelectionContext,
}; };
@ -92,7 +91,7 @@ impl Qualif for HasMutInterior {
} }
fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool { fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
!ty.is_freeze(cx.tcx.at(DUMMY_SP), cx.param_env) !ty.is_freeze(cx.tcx, cx.param_env)
} }
fn in_adt_inherently<'tcx>( fn in_adt_inherently<'tcx>(

View file

@ -8,7 +8,6 @@ use rustc_middle::mir::{self, BasicBlock, Local, Location, Statement, StatementK
use rustc_mir_dataflow::fmt::DebugWithContext; use rustc_mir_dataflow::fmt::DebugWithContext;
use rustc_mir_dataflow::JoinSemiLattice; use rustc_mir_dataflow::JoinSemiLattice;
use rustc_mir_dataflow::{Analysis, AnalysisDomain, CallReturnPlaces}; use rustc_mir_dataflow::{Analysis, AnalysisDomain, CallReturnPlaces};
use rustc_span::DUMMY_SP;
use std::fmt; use std::fmt;
use std::marker::PhantomData; use std::marker::PhantomData;
@ -120,10 +119,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.param_env)
.ty(self.ccx.body, self.ccx.tcx)
.ty
.is_freeze(self.ccx.tcx.at(DUMMY_SP), self.ccx.param_env)
} }
} }

View file

@ -235,9 +235,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
// `Operand::Copy` is only supposed to be used with `Copy` types. // `Operand::Copy` is only supposed to be used with `Copy` types.
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;
let span = self.body.source_info(location).span;
if !ty.is_copy_modulo_regions(self.tcx.at(span), self.param_env) { if !ty.is_copy_modulo_regions(self.tcx, self.param_env) {
self.fail(location, format!("`Operand::Copy` with non-`Copy` type {}", ty)); self.fail(location, format!("`Operand::Copy` with non-`Copy` type {}", ty));
} }
} }

View file

@ -114,7 +114,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
_ => { _ => {
// Fallback case: allow `ManuallyDrop` and things that are `Copy`. // Fallback case: allow `ManuallyDrop` and things that are `Copy`.
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.at(span), param_env) || ty.is_copy_modulo_regions(tcx, param_env)
} }
} }
} }

View file

@ -33,7 +33,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
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.at(DUMMY_SP), self.param_env) { if ty.is_sized(self.tcx, self.param_env) {
return true; return true;
} }
if let ty::Foreign(..) = ty.kind() { if let ty::Foreign(..) = ty.kind() {
@ -128,7 +128,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.at(expr.span), self.param_env) { if !ty.is_copy_modulo_regions(self.tcx, self.param_env) {
let msg = "arguments for inline assembly must be copyable"; let msg = "arguments for inline assembly must be copyable";
let mut err = self.tcx.sess.struct_span_err(expr.span, msg); let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
err.note(&format!("`{ty}` does not implement the Copy trait")); err.note(&format!("`{ty}` does not implement the Copy trait"));

View file

@ -752,7 +752,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
return; return;
} }
let param_env = ty::ParamEnv::empty(); let param_env = ty::ParamEnv::empty();
if ty.is_copy_modulo_regions(cx.tcx.at(item.span), param_env) { if ty.is_copy_modulo_regions(cx.tcx, param_env) {
return; return;
} }
if can_type_implement_copy( if can_type_implement_copy(

View file

@ -11,7 +11,7 @@ use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable}; use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
use rustc_span::source_map; use rustc_span::source_map;
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol, DUMMY_SP}; use rustc_span::{Span, Symbol};
use rustc_target::abi::{Abi, WrappingRange}; use rustc_target::abi::{Abi, WrappingRange};
use rustc_target::abi::{Integer, TagEncoding, Variants}; use rustc_target::abi::{Integer, TagEncoding, Variants};
use rustc_target::spec::abi::Abi as SpecAbi; use rustc_target::spec::abi::Abi as SpecAbi;
@ -931,7 +931,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
match *ty.kind() { match *ty.kind() {
ty::Adt(def, substs) => { ty::Adt(def, substs) => {
if def.is_box() && matches!(self.mode, CItemKind::Definition) { if def.is_box() && matches!(self.mode, CItemKind::Definition) {
if ty.boxed_ty().is_sized(tcx.at(DUMMY_SP), self.cx.param_env) { if ty.boxed_ty().is_sized(tcx, self.cx.param_env) {
return FfiSafe; return FfiSafe;
} else { } else {
return FfiUnsafe { return FfiUnsafe {
@ -1082,7 +1082,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _)
if { if {
matches!(self.mode, CItemKind::Definition) matches!(self.mode, CItemKind::Definition)
&& ty.is_sized(self.cx.tcx.at(DUMMY_SP), self.cx.param_env) && ty.is_sized(self.cx.tcx, self.cx.param_env)
} => } =>
{ {
FfiSafe FfiSafe

View file

@ -830,7 +830,7 @@ where
} else { } else {
match mt { match mt {
hir::Mutability::Not => { hir::Mutability::Not => {
if ty.is_freeze(tcx.at(DUMMY_SP), cx.param_env()) { if ty.is_freeze(tcx, cx.param_env()) {
PointerKind::Frozen PointerKind::Frozen
} else { } else {
PointerKind::SharedMutable PointerKind::SharedMutable
@ -841,7 +841,7 @@ where
// noalias, as another pointer to the structure can be obtained, that // noalias, as another pointer to the structure can be obtained, that
// is not based-on the original reference. We consider all !Unpin // is not based-on the original reference. We consider all !Unpin
// types to be potentially self-referential here. // types to be potentially self-referential here.
if ty.is_unpin(tcx.at(DUMMY_SP), cx.param_env()) { if ty.is_unpin(tcx, cx.param_env()) {
PointerKind::UniqueBorrowed PointerKind::UniqueBorrowed
} else { } else {
PointerKind::UniqueBorrowedPinned PointerKind::UniqueBorrowedPinned

View file

@ -2,7 +2,6 @@
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::ty::layout::IntegerExt; use crate::ty::layout::IntegerExt;
use crate::ty::query::TyCtxtAt;
use crate::ty::{ use crate::ty::{
self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitable, TypeVisitable,
@ -821,12 +820,8 @@ 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( pub fn is_copy_modulo_regions(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
self, self.is_trivially_pure_clone_copy() || tcx.is_copy_raw(param_env.and(self))
tcx_at: TyCtxtAt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> bool {
self.is_trivially_pure_clone_copy() || tcx_at.is_copy_raw(param_env.and(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
@ -835,8 +830,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_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { pub fn is_sized(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
self.is_trivially_sized(tcx_at.tcx) || tcx_at.is_sized_raw(param_env.and(self)) self.is_trivially_sized(tcx) || tcx.is_sized_raw(param_env.and(self))
} }
/// Checks whether values of this type `T` implement the `Freeze` /// Checks whether values of this type `T` implement the `Freeze`
@ -846,8 +841,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_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { pub fn is_freeze(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
self.is_trivially_freeze() || tcx_at.is_freeze_raw(param_env.and(self)) self.is_trivially_freeze() || tcx.is_freeze_raw(param_env.and(self))
} }
/// Fast path helper for testing if a type is `Freeze`. /// Fast path helper for testing if a type is `Freeze`.
@ -886,8 +881,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_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { pub fn is_unpin(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
self.is_trivially_unpin() || tcx_at.is_unpin_raw(param_env.and(self)) self.is_trivially_unpin() || tcx.is_unpin_raw(param_env.and(self))
} }
/// Fast path helper for testing if a type is `Unpin`. /// Fast path helper for testing if a type is `Unpin`.

View file

@ -153,12 +153,11 @@ 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 span = expr.span;
let param_env = this.param_env; let param_env = this.param_env;
if !ty.is_sized(tcx.at(span), param_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.at(span), param_env)); assert!(!ty.is_copy_modulo_regions(tcx, param_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

@ -260,7 +260,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
}; };
match borrow_kind { match borrow_kind {
BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique => { BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique => {
if !ty.is_freeze(self.tcx.at(pat.span), self.param_env) { if !ty.is_freeze(self.tcx, self.param_env) {
self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField); self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField);
} }
} }
@ -457,9 +457,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
if visitor.found { if visitor.found {
match borrow_kind { match borrow_kind {
BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique
if !self.thir[arg] if !self.thir[arg].ty.is_freeze(self.tcx, self.param_env) =>
.ty
.is_freeze(self.tcx.at(self.thir[arg].span), self.param_env) =>
{ {
self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField) self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField)
} }

View file

@ -1004,8 +1004,8 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>(
} }
/// Check if a by-value binding is by-value. That is, check if the binding's type is not `Copy`. /// Check if a by-value binding is by-value. That is, check if the binding's type is not `Copy`.
fn is_binding_by_move(cx: &MatchVisitor<'_, '_, '_>, hir_id: HirId, span: Span) -> bool { fn is_binding_by_move(cx: &MatchVisitor<'_, '_, '_>, hir_id: HirId) -> bool {
!cx.typeck_results.node_type(hir_id).is_copy_modulo_regions(cx.tcx.at(span), cx.param_env) !cx.typeck_results.node_type(hir_id).is_copy_modulo_regions(cx.tcx, cx.param_env)
} }
/// Check that there are no borrow or move conflicts in `binding @ subpat` patterns. /// Check that there are no borrow or move conflicts in `binding @ subpat` patterns.
@ -1031,7 +1031,7 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa
// Get the binding move, extract the mutability if by-ref. // Get the binding move, extract the mutability if by-ref.
let mut_outer = match typeck_results.extract_binding_mode(sess, pat.hir_id, pat.span) { let mut_outer = match typeck_results.extract_binding_mode(sess, pat.hir_id, pat.span) {
Some(ty::BindByValue(_)) if is_binding_by_move(cx, pat.hir_id, pat.span) => { Some(ty::BindByValue(_)) if is_binding_by_move(cx, pat.hir_id) => {
// We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`. // We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`.
let mut conflicts_ref = Vec::new(); let mut conflicts_ref = Vec::new();
sub.each_binding(|_, hir_id, span, _| { sub.each_binding(|_, hir_id, span, _| {
@ -1070,7 +1070,7 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa
(Mutability::Mut, Mutability::Mut) => conflicts_mut_mut.push((span, name)), // 2x `ref mut`. (Mutability::Mut, Mutability::Mut) => conflicts_mut_mut.push((span, name)), // 2x `ref mut`.
_ => conflicts_mut_ref.push((span, name)), // `ref` + `ref mut` in either direction. _ => conflicts_mut_ref.push((span, name)), // `ref` + `ref mut` in either direction.
}, },
Some(ty::BindByValue(_)) if is_binding_by_move(cx, hir_id, span) => { Some(ty::BindByValue(_)) if is_binding_by_move(cx, hir_id) => {
conflicts_move.push((span, name)) // `ref mut?` + by-move conflict. conflicts_move.push((span, name)) // `ref mut?` + by-move conflict.
} }
Some(ty::BindByValue(_)) | None => {} // `ref mut?` + by-copy is fine. Some(ty::BindByValue(_)) | None => {} // `ref mut?` + by-copy is fine.

View file

@ -506,7 +506,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.at(span), param_env) { if !pointee_ty.is_sized(tcx, param_env) {
// `tcx.deref_mir_constant()` below will ICE with an unsized type // `tcx.deref_mir_constant()` below will ICE with an unsized type
// (except slices, which are handled in a separate arm above). // (except slices, which are handled in a separate arm above).
let msg = format!("cannot use unsized non-slice type `{}` in constant patterns", pointee_ty); let msg = format!("cannot use unsized non-slice type `{}` in constant patterns", pointee_ty);
@ -534,7 +534,7 @@ impl<'tcx> ConstToPat<'tcx> {
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => {
PatKind::Constant { value: cv } PatKind::Constant { value: cv }
} }
ty::RawPtr(pointee) if pointee.ty.is_sized(tcx.at(span), param_env) => { ty::RawPtr(pointee) if pointee.ty.is_sized(tcx, param_env) => {
PatKind::Constant { value: cv } PatKind::Constant { value: cv }
} }
// FIXME: these can have very surprising behaviour where optimization levels or other // FIXME: these can have very surprising behaviour where optimization levels or other

View file

@ -312,7 +312,7 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
} else if !place } else if !place
.ty(self.body, self.tcx) .ty(self.body, self.tcx)
.ty .ty
.is_freeze(self.tcx.at(self.source_info.span), self.param_env) .is_freeze(self.tcx, self.param_env)
{ {
UnsafetyViolationDetails::BorrowOfLayoutConstrainedField UnsafetyViolationDetails::BorrowOfLayoutConstrainedField
} else { } else {

View file

@ -633,7 +633,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
} }
if !rvalue if !rvalue
.ty(&self.ecx.frame().body.local_decls, *self.ecx.tcx) .ty(&self.ecx.frame().body.local_decls, *self.ecx.tcx)
.is_sized(self.ecx.tcx, self.param_env) .is_sized(*self.ecx.tcx, self.param_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

View file

@ -500,7 +500,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
} }
if !rvalue if !rvalue
.ty(&self.ecx.frame().body.local_decls, *self.ecx.tcx) .ty(&self.ecx.frame().body.local_decls, *self.ecx.tcx)
.is_sized(self.ecx.tcx, self.param_env) .is_sized(*self.ecx.tcx, self.param_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

View file

@ -11,7 +11,6 @@ use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::{Body, Local, Location, Operand, Terminator, TerminatorKind, RETURN_PLACE}; use rustc_middle::mir::{Body, Local, Location, Operand, Terminator, TerminatorKind, RETURN_PLACE};
use rustc_middle::ty::{self, DeducedParamAttrs, ParamEnv, Ty, TyCtxt}; use rustc_middle::ty::{self, DeducedParamAttrs, ParamEnv, Ty, TyCtxt};
use rustc_session::config::OptLevel; use rustc_session::config::OptLevel;
use rustc_span::DUMMY_SP;
/// A visitor that determines which arguments have been mutated. We can't use the mutability field /// A visitor that determines which arguments have been mutated. We can't use the mutability field
/// on LocalDecl for this because it has no meaning post-optimization. /// on LocalDecl for this because it has no meaning post-optimization.
@ -232,7 +231,7 @@ pub fn deduced_param_attrs<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx [Ded
body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map( body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map(
|(arg_index, local_decl)| DeducedParamAttrs { |(arg_index, local_decl)| DeducedParamAttrs {
read_only: !deduce_read_only.mutable_args.contains(arg_index) read_only: !deduce_read_only.mutable_args.contains(arg_index)
&& local_decl.ty.is_freeze(tcx.at(DUMMY_SP), ParamEnv::reveal_all()), && local_decl.ty.is_freeze(tcx, ParamEnv::reveal_all()),
}, },
), ),
); );

View file

@ -312,7 +312,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -
let param_env = tcx.param_env(def_id); let param_env = tcx.param_env(def_id);
let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty); let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
let is_copy = self_ty.is_copy_modulo_regions(tcx.at(builder.span), param_env); let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env);
let dest = Place::return_place(); let dest = Place::return_place();
let src = tcx.mk_place_deref(Place::from(Local::new(1 + 0))); let src = tcx.mk_place_deref(Place::from(Local::new(1 + 0)));

View file

@ -1067,7 +1067,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 param_env = ty::ParamEnv::reveal_all(); let param_env = ty::ParamEnv::reveal_all();
let type_has_metadata = |ty: Ty<'tcx>| -> bool { let type_has_metadata = |ty: Ty<'tcx>| -> bool {
if ty.is_sized(tcx.at(DUMMY_SP), param_env) { if ty.is_sized(tcx, param_env) {
return false; return false;
} }
let tail = tcx.struct_tail_erasing_lifetimes(ty, param_env); let tail = tcx.struct_tail_erasing_lifetimes(ty, param_env);

View file

@ -69,7 +69,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
let ty = self.resolve_vars_if_possible(ty); let ty = self.resolve_vars_if_possible(ty);
if !(param_env, ty).needs_infer() { if !(param_env, ty).needs_infer() {
return ty.is_copy_modulo_regions(self.tcx.at(span), param_env); return ty.is_copy_modulo_regions(self.tcx, 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

@ -4,7 +4,7 @@ use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::traits::CodegenObligationError; use rustc_middle::traits::CodegenObligationError;
use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitable}; use rustc_middle::ty::{self, Instance, TyCtxt, TypeVisitable};
use rustc_span::{sym, DUMMY_SP}; use rustc_span::sym;
use rustc_trait_selection::traits; use rustc_trait_selection::traits;
use traits::{translate_substs, Reveal}; use traits::{translate_substs, Reveal};
@ -236,7 +236,7 @@ fn resolve_associated_item<'tcx>(
if name == sym::clone { if name == sym::clone {
let self_ty = trait_ref.self_ty(); let self_ty = trait_ref.self_ty();
let is_copy = self_ty.is_copy_modulo_regions(tcx.at(DUMMY_SP), param_env); let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env);
match self_ty.kind() { match self_ty.kind() {
_ if is_copy => (), _ if is_copy => (),
ty::Generator(..) ty::Generator(..)

View file

@ -399,7 +399,7 @@ fn layout_of_uncached<'tcx>(
} }
let pointee = tcx.normalize_erasing_regions(param_env, pointee); let pointee = tcx.normalize_erasing_regions(param_env, pointee);
if pointee.is_sized(tcx.at(DUMMY_SP), param_env) { if pointee.is_sized(tcx, param_env) {
return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr))); return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr)));
} }
@ -755,8 +755,7 @@ fn layout_of_uncached<'tcx>(
} else { } else {
let param_env = tcx.param_env(def.did()); let param_env = tcx.param_env(def.did());
let last_field = def.variant(v).fields.last().unwrap(); let last_field = def.variant(v).fields.last().unwrap();
let always_sized = let always_sized = tcx.type_of(last_field.did).is_sized(tcx, param_env);
tcx.type_of(last_field.did).is_sized(tcx.at(DUMMY_SP), param_env);
if !always_sized { StructKind::MaybeUnsized } else { StructKind::AlwaysSized } if !always_sized { StructKind::MaybeUnsized } else { StructKind::AlwaysSized }
}; };

View file

@ -109,7 +109,7 @@ where
for component in components { for component in components {
match *component.kind() { match *component.kind() {
_ if component.is_copy_modulo_regions(tcx.at(DUMMY_SP), self.param_env) => (), _ if component.is_copy_modulo_regions(tcx, self.param_env) => (),
ty::Closure(_, substs) => { ty::Closure(_, substs) => {
queue_type(self, substs.as_closure().tupled_upvars_ty()); queue_type(self, substs.as_closure().tupled_upvars_ty());

View file

@ -148,7 +148,7 @@ where
}) })
.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.at(rustc_span::DUMMY_SP), param_env) { if !ty.is_sized(tcx, param_env) {
// In case `#![no_core]` is used, `sized_trait` returns nothing. // In case `#![no_core]` is used, `sized_trait` returns nothing.
if let Some(item) = tcx.lang_items().sized_trait().and_then(|sized_trait_did| { if let Some(item) = tcx.lang_items().sized_trait().and_then(|sized_trait_did| {
self.generate_for_trait(ty, sized_trait_did, param_env, item_def_id, &f, true) self.generate_for_trait(ty, sized_trait_did, param_env, item_def_id, &f, true)

View file

@ -26,7 +26,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Option<RustcVer
(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.
if to_pointee_ty.is_sized(cx.tcx.at(expr.span), cx.param_env); if to_pointee_ty.is_sized(cx.tcx, cx.param_env);
then { then {
let mut applicability = Applicability::MachineApplicable; let mut applicability = Applicability::MachineApplicable;
let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut applicability); let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut applicability);

View file

@ -29,7 +29,7 @@ use rustc_middle::ty::{
}; };
use rustc_semver::RustcVersion; use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP}; use rustc_span::{symbol::sym, Span, Symbol};
use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause}; use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause};
use std::collections::VecDeque; use std::collections::VecDeque;
@ -990,7 +990,7 @@ fn binding_ty_auto_deref_stability<'tcx>(
cx.typeck_results().node_type(ty.ty.hir_id), cx.typeck_results().node_type(ty.ty.hir_id),
binder_args, binder_args,
)) ))
.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()), .is_sized(cx.tcx, cx.param_env.without_caller_bounds()),
) )
} }
}, },
@ -1005,7 +1005,7 @@ fn binding_ty_auto_deref_stability<'tcx>(
cx.typeck_results().node_type(ty.ty.hir_id), cx.typeck_results().node_type(ty.ty.hir_id),
binder_args, binder_args,
)) ))
.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()), .is_sized(cx.tcx, cx.param_env.without_caller_bounds()),
), ),
TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => { TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => {
Position::ReborrowStable(precedence) Position::ReborrowStable(precedence)
@ -1297,7 +1297,7 @@ impl<'tcx> TyPosition<'tcx> {
fn position_for_result(self, cx: &LateContext<'tcx>) -> Position { fn position_for_result(self, cx: &LateContext<'tcx>) -> Position {
match (self.position, self.ty) { match (self.position, self.ty) {
(Position::ReborrowStable(precedence), Some(ty)) => { (Position::ReborrowStable(precedence), Some(ty)) => {
Position::DerefStable(precedence, ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env)) Position::DerefStable(precedence, ty.is_sized(cx.tcx, cx.param_env))
}, },
(position, _) => position, (position, _) => position,
} }
@ -1348,7 +1348,7 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
| ty::Tuple(_) | ty::Tuple(_)
| ty::Projection(_) => Position::DerefStable( | ty::Projection(_) => Position::DerefStable(
precedence, precedence,
ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()), ty.is_sized(cx.tcx, cx.param_env.without_caller_bounds()),
) )
.into(), .into(),
}; };

View file

@ -188,7 +188,7 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &m
// 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, substs) => { ty::Adt(adt, substs) => {
tys.insert(adt.did()) && !ty.is_freeze(cx.tcx.at(span), cx.param_env) tys.insert(adt.did()) && !ty.is_freeze(cx.tcx, cx.param_env)
|| KNOWN_WRAPPER_TYS || KNOWN_WRAPPER_TYS
.iter() .iter()
.any(|&sym| cx.tcx.is_diagnostic_item(sym, adt.did())) .any(|&sym| cx.tcx.is_diagnostic_item(sym, adt.did()))

View file

@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq {
let span = stmt.span.to(if_.span); let span = stmt.span.to(if_.span);
let has_interior_mutability = !cx.typeck_results().node_type(canonical_id).is_freeze( let has_interior_mutability = !cx.typeck_results().node_type(canonical_id).is_freeze(
cx.tcx.at(span), cx.tcx,
cx.param_env, cx.param_env,
); );
if has_interior_mutability { return; } if has_interior_mutability { return; }

View file

@ -136,12 +136,14 @@ fn check_ty<'tcx>(cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) {
/// [`Hash`] or [`Ord`]. /// [`Hash`] or [`Ord`].
fn is_interior_mutable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span) -> bool { fn is_interior_mutable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span) -> bool {
match *ty.kind() { match *ty.kind() {
Ref(_, inner_ty, mutbl) => mutbl == hir::Mutability::Mut || is_interior_mutable_type(cx, inner_ty, span), Ref(_, inner_ty, mutbl) => {
mutbl == hir::Mutability::Mut || is_interior_mutable_type(cx, inner_ty, span)
}
Slice(inner_ty) => is_interior_mutable_type(cx, inner_ty, span), Slice(inner_ty) => is_interior_mutable_type(cx, inner_ty, span),
Array(inner_ty, size) => { Array(inner_ty, size) => {
size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0) size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0)
&& is_interior_mutable_type(cx, inner_ty, span) && is_interior_mutable_type(cx, inner_ty, span)
}, }
Tuple(fields) => fields.iter().any(|ty| is_interior_mutable_type(cx, ty, span)), Tuple(fields) => fields.iter().any(|ty| is_interior_mutable_type(cx, ty, span)),
Adt(def, substs) => { Adt(def, substs) => {
// Special case for collections in `std` who's impl of `Hash` or `Ord` delegates to // Special case for collections in `std` who's impl of `Hash` or `Ord` delegates to
@ -167,9 +169,9 @@ fn is_interior_mutable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Sp
} else { } else {
!ty.has_escaping_bound_vars() !ty.has_escaping_bound_vars()
&& cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && cx.tcx.layout_of(cx.param_env.and(ty)).is_ok()
&& !ty.is_freeze(cx.tcx.at(span), cx.param_env) && !ty.is_freeze(cx.tcx, cx.param_env)
} }
}, }
_ => false, _ => false,
} }
} }

View file

@ -19,7 +19,7 @@ use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::{self, TypeVisitable}; use rustc_middle::ty::{self, TypeVisitable};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::kw; use rustc_span::symbol::kw;
use rustc_span::{sym, Span, DUMMY_SP}; use rustc_span::{sym, Span};
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits; use rustc_trait_selection::traits;
use rustc_trait_selection::traits::misc::can_type_implement_copy; use rustc_trait_selection::traits::misc::can_type_implement_copy;
@ -184,7 +184,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
if !is_self(arg); if !is_self(arg);
if !ty.is_mutable_ptr(); if !ty.is_mutable_ptr();
if !is_copy(cx, ty); if !is_copy(cx, ty);
if ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env); if ty.is_sized(cx.tcx, cx.param_env);
if !allowed_traits.iter().any(|&t| implements_trait(cx, ty, t, &[])); if !allowed_traits.iter().any(|&t| implements_trait(cx, ty, t, &[]));
if !implements_borrow_trait; if !implements_borrow_trait;
if !all_borrowable_trait; if !all_borrowable_trait;

View file

@ -20,7 +20,7 @@ use rustc_middle::mir::interpret::{ConstValue, ErrorHandled};
use rustc_middle::ty::adjustment::Adjust; use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{sym, InnerSpan, Span, DUMMY_SP}; use rustc_span::{sym, InnerSpan, Span};
// FIXME: this is a correctness problem but there's no suitable // FIXME: this is a correctness problem but there's no suitable
// warn-by-default category. // warn-by-default category.
@ -136,7 +136,7 @@ fn is_unfrozen<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
// since it works when a pointer indirection involves (`Cell<*const T>`). // since it works when a pointer indirection involves (`Cell<*const T>`).
// Making up a `ParamEnv` where every generic params and assoc types are `Freeze`is another option; // Making up a `ParamEnv` where every generic params and assoc types are `Freeze`is another option;
// but I'm not sure whether it's a decent way, if possible. // but I'm not sure whether it's a decent way, if possible.
cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx.at(DUMMY_SP), cx.param_env) cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx, cx.param_env)
} }
fn is_value_unfrozen_raw<'tcx>( fn is_value_unfrozen_raw<'tcx>(

View file

@ -94,7 +94,7 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex
then { then {
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.at(caller.span), cx.param_env) && let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_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

@ -5,7 +5,6 @@ use rustc_hir::Expr;
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_middle::ty::SubstsRef; use rustc_middle::ty::SubstsRef;
use rustc_middle::ty::{self, IntTy, Ty, TypeAndMut, UintTy}; use rustc_middle::ty::{self, IntTy, Ty, TypeAndMut, UintTy};
use rustc_span::DUMMY_SP;
#[expect(clippy::too_many_lines)] #[expect(clippy::too_many_lines)]
pub(super) fn check<'tcx>( pub(super) fn check<'tcx>(
@ -28,24 +27,32 @@ pub(super) fn check<'tcx>(
// `Repr(C)` <-> unordered type. // `Repr(C)` <-> unordered type.
// If the first field of the `Repr(C)` type matches then the transmute is ok // If the first field of the `Repr(C)` type matches then the transmute is ok
(ReducedTy::OrderedFields(_, Some(from_sub_ty)), ReducedTy::UnorderedFields(to_sub_ty)) (
| (ReducedTy::UnorderedFields(from_sub_ty), ReducedTy::OrderedFields(_, Some(to_sub_ty))) => { ReducedTy::OrderedFields(_, Some(from_sub_ty)),
ReducedTy::UnorderedFields(to_sub_ty),
)
| (
ReducedTy::UnorderedFields(from_sub_ty),
ReducedTy::OrderedFields(_, Some(to_sub_ty)),
) => {
from_ty = from_sub_ty; from_ty = from_sub_ty;
to_ty = to_sub_ty; to_ty = to_sub_ty;
continue; continue;
}, }
(ReducedTy::OrderedFields(_, Some(from_sub_ty)), ReducedTy::Other(to_sub_ty)) if reduced_tys.to_fat_ptr => { (ReducedTy::OrderedFields(_, Some(from_sub_ty)), ReducedTy::Other(to_sub_ty))
if reduced_tys.to_fat_ptr =>
{
from_ty = from_sub_ty; from_ty = from_sub_ty;
to_ty = to_sub_ty; to_ty = to_sub_ty;
continue; continue;
}, }
(ReducedTy::Other(from_sub_ty), ReducedTy::OrderedFields(_, Some(to_sub_ty))) (ReducedTy::Other(from_sub_ty), ReducedTy::OrderedFields(_, Some(to_sub_ty)))
if reduced_tys.from_fat_ptr => if reduced_tys.from_fat_ptr =>
{ {
from_ty = from_sub_ty; from_ty = from_sub_ty;
to_ty = to_sub_ty; to_ty = to_sub_ty;
continue; continue;
}, }
// ptr <-> ptr // ptr <-> ptr
(ReducedTy::Other(from_sub_ty), ReducedTy::Other(to_sub_ty)) (ReducedTy::Other(from_sub_ty), ReducedTy::Other(to_sub_ty))
@ -55,19 +62,19 @@ pub(super) fn check<'tcx>(
from_ty = from_sub_ty; from_ty = from_sub_ty;
to_ty = to_sub_ty; to_ty = to_sub_ty;
continue; continue;
}, }
// fat ptr <-> (*size, *size) // fat ptr <-> (*size, *size)
(ReducedTy::Other(_), ReducedTy::UnorderedFields(to_ty)) (ReducedTy::Other(_), ReducedTy::UnorderedFields(to_ty))
if reduced_tys.from_fat_ptr && is_size_pair(to_ty) => if reduced_tys.from_fat_ptr && is_size_pair(to_ty) =>
{ {
return false; return false;
}, }
(ReducedTy::UnorderedFields(from_ty), ReducedTy::Other(_)) (ReducedTy::UnorderedFields(from_ty), ReducedTy::Other(_))
if reduced_tys.to_fat_ptr && is_size_pair(from_ty) => if reduced_tys.to_fat_ptr && is_size_pair(from_ty) =>
{ {
return false; return false;
}, }
// fat ptr -> some struct | some struct -> fat ptr // fat ptr -> some struct | some struct -> fat ptr
(ReducedTy::Other(_), _) if reduced_tys.from_fat_ptr => { (ReducedTy::Other(_), _) if reduced_tys.from_fat_ptr => {
@ -78,12 +85,14 @@ pub(super) fn check<'tcx>(
&format!("transmute from `{from_ty_orig}` which has an undefined layout"), &format!("transmute from `{from_ty_orig}` which has an undefined layout"),
|diag| { |diag| {
if from_ty_orig.peel_refs() != from_ty.peel_refs() { if from_ty_orig.peel_refs() != from_ty.peel_refs() {
diag.note(&format!("the contained type `{from_ty}` has an undefined layout")); diag.note(&format!(
"the contained type `{from_ty}` has an undefined layout"
));
} }
}, },
); );
return true; return true;
}, }
(_, ReducedTy::Other(_)) if reduced_tys.to_fat_ptr => { (_, ReducedTy::Other(_)) if reduced_tys.to_fat_ptr => {
span_lint_and_then( span_lint_and_then(
cx, cx,
@ -92,14 +101,18 @@ pub(super) fn check<'tcx>(
&format!("transmute to `{to_ty_orig}` which has an undefined layout"), &format!("transmute to `{to_ty_orig}` which has an undefined layout"),
|diag| { |diag| {
if to_ty_orig.peel_refs() != to_ty.peel_refs() { if to_ty_orig.peel_refs() != to_ty.peel_refs() {
diag.note(&format!("the contained type `{to_ty}` has an undefined layout")); diag.note(&format!(
"the contained type `{to_ty}` has an undefined layout"
));
} }
}, },
); );
return true; return true;
}, }
(ReducedTy::UnorderedFields(from_ty), ReducedTy::UnorderedFields(to_ty)) if from_ty != to_ty => { (ReducedTy::UnorderedFields(from_ty), ReducedTy::UnorderedFields(to_ty))
if from_ty != to_ty =>
{
let same_adt_did = if let (ty::Adt(from_def, from_subs), ty::Adt(to_def, to_subs)) let same_adt_did = if let (ty::Adt(from_def, from_subs), ty::Adt(to_def, to_subs))
= (from_ty.kind(), to_ty.kind()) = (from_ty.kind(), to_ty.kind())
&& from_def == to_def && from_def == to_def
@ -126,19 +139,25 @@ pub(super) fn check<'tcx>(
)); ));
} else { } else {
if from_ty_orig.peel_refs() != from_ty { if from_ty_orig.peel_refs() != from_ty {
diag.note(&format!("the contained type `{from_ty}` has an undefined layout")); diag.note(&format!(
"the contained type `{from_ty}` has an undefined layout"
));
} }
if to_ty_orig.peel_refs() != to_ty { if to_ty_orig.peel_refs() != to_ty {
diag.note(&format!("the contained type `{to_ty}` has an undefined layout")); diag.note(&format!(
"the contained type `{to_ty}` has an undefined layout"
));
} }
} }
}, },
); );
return true; return true;
}, }
( (
ReducedTy::UnorderedFields(from_ty), ReducedTy::UnorderedFields(from_ty),
ReducedTy::Other(_) | ReducedTy::OrderedFields(..) | ReducedTy::TypeErasure { raw_ptr_only: true }, ReducedTy::Other(_)
| ReducedTy::OrderedFields(..)
| ReducedTy::TypeErasure { raw_ptr_only: true },
) => { ) => {
span_lint_and_then( span_lint_and_then(
cx, cx,
@ -147,14 +166,18 @@ pub(super) fn check<'tcx>(
&format!("transmute from `{from_ty_orig}` which has an undefined layout"), &format!("transmute from `{from_ty_orig}` which has an undefined layout"),
|diag| { |diag| {
if from_ty_orig.peel_refs() != from_ty { if from_ty_orig.peel_refs() != from_ty {
diag.note(&format!("the contained type `{from_ty}` has an undefined layout")); diag.note(&format!(
"the contained type `{from_ty}` has an undefined layout"
));
} }
}, },
); );
return true; return true;
}, }
( (
ReducedTy::Other(_) | ReducedTy::OrderedFields(..) | ReducedTy::TypeErasure { raw_ptr_only: true }, ReducedTy::Other(_)
| ReducedTy::OrderedFields(..)
| ReducedTy::TypeErasure { raw_ptr_only: true },
ReducedTy::UnorderedFields(to_ty), ReducedTy::UnorderedFields(to_ty),
) => { ) => {
span_lint_and_then( span_lint_and_then(
@ -164,19 +187,25 @@ pub(super) fn check<'tcx>(
&format!("transmute into `{to_ty_orig}` which has an undefined layout"), &format!("transmute into `{to_ty_orig}` which has an undefined layout"),
|diag| { |diag| {
if to_ty_orig.peel_refs() != to_ty { if to_ty_orig.peel_refs() != to_ty {
diag.note(&format!("the contained type `{to_ty}` has an undefined layout")); diag.note(&format!(
"the contained type `{to_ty}` has an undefined layout"
));
} }
}, },
); );
return true; return true;
}, }
( (
ReducedTy::OrderedFields(..) | ReducedTy::Other(_) | ReducedTy::TypeErasure { raw_ptr_only: true }, ReducedTy::OrderedFields(..)
ReducedTy::OrderedFields(..) | ReducedTy::Other(_) | ReducedTy::TypeErasure { raw_ptr_only: true }, | ReducedTy::Other(_)
| ReducedTy::TypeErasure { raw_ptr_only: true },
ReducedTy::OrderedFields(..)
| ReducedTy::Other(_)
| ReducedTy::TypeErasure { raw_ptr_only: true },
) )
| (ReducedTy::UnorderedFields(_), ReducedTy::UnorderedFields(_)) => { | (ReducedTy::UnorderedFields(_), ReducedTy::UnorderedFields(_)) => {
break; break;
}, }
} }
} }
@ -194,42 +223,38 @@ struct ReducedTys<'tcx> {
} }
/// Remove references so long as both types are references. /// Remove references so long as both types are references.
fn reduce_refs<'tcx>(cx: &LateContext<'tcx>, mut from_ty: Ty<'tcx>, mut to_ty: Ty<'tcx>) -> ReducedTys<'tcx> { fn reduce_refs<'tcx>(
cx: &LateContext<'tcx>,
mut from_ty: Ty<'tcx>,
mut to_ty: Ty<'tcx>,
) -> ReducedTys<'tcx> {
let mut from_raw_ptr = false; let mut from_raw_ptr = false;
let mut to_raw_ptr = false; let mut to_raw_ptr = false;
let (from_fat_ptr, to_fat_ptr) = loop { let (from_fat_ptr, to_fat_ptr) =
break match (from_ty.kind(), to_ty.kind()) { loop {
( break match (from_ty.kind(), to_ty.kind()) {
&(ty::Ref(_, from_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: from_sub_ty, .. })), (
&(ty::Ref(_, to_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: to_sub_ty, .. })), &(ty::Ref(_, from_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: from_sub_ty, .. })),
) => { &(ty::Ref(_, to_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: to_sub_ty, .. })),
from_raw_ptr = matches!(*from_ty.kind(), ty::RawPtr(_)); ) => {
from_ty = from_sub_ty; from_raw_ptr = matches!(*from_ty.kind(), ty::RawPtr(_));
to_raw_ptr = matches!(*to_ty.kind(), ty::RawPtr(_)); from_ty = from_sub_ty;
to_ty = to_sub_ty; to_raw_ptr = matches!(*to_ty.kind(), ty::RawPtr(_));
continue; to_ty = to_sub_ty;
}, continue;
(&(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })), _) }
if !unsized_ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env) => (
{ &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })),
(true, false) _,
}, ) if !unsized_ty.is_sized(cx.tcx, cx.param_env) => (true, false),
(_, &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. }))) (
if !unsized_ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env) => _,
{ &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })),
(false, true) ) if !unsized_ty.is_sized(cx.tcx, cx.param_env) => (false, true),
}, _ => (false, false),
_ => (false, false), };
}; };
}; ReducedTys { from_ty, to_ty, from_raw_ptr, to_raw_ptr, from_fat_ptr, to_fat_ptr }
ReducedTys {
from_ty,
to_ty,
from_raw_ptr,
to_raw_ptr,
from_fat_ptr,
to_fat_ptr,
}
} }
enum ReducedTy<'tcx> { enum ReducedTy<'tcx> {
@ -252,11 +277,11 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
return match *ty.kind() { return match *ty.kind() {
ty::Array(sub_ty, _) if matches!(sub_ty.kind(), ty::Int(_) | ty::Uint(_)) => { ty::Array(sub_ty, _) if matches!(sub_ty.kind(), ty::Int(_) | ty::Uint(_)) => {
ReducedTy::TypeErasure { raw_ptr_only: false } ReducedTy::TypeErasure { raw_ptr_only: false }
}, }
ty::Array(sub_ty, _) | ty::Slice(sub_ty) => { ty::Array(sub_ty, _) | ty::Slice(sub_ty) => {
ty = sub_ty; ty = sub_ty;
continue; continue;
}, }
ty::Tuple(args) if args.is_empty() => ReducedTy::TypeErasure { raw_ptr_only: false }, ty::Tuple(args) if args.is_empty() => ReducedTy::TypeErasure { raw_ptr_only: false },
ty::Tuple(args) => { ty::Tuple(args) => {
let mut iter = args.iter(); let mut iter = args.iter();
@ -268,7 +293,7 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
continue; continue;
} }
ReducedTy::UnorderedFields(ty) ReducedTy::UnorderedFields(ty)
}, }
ty::Adt(def, substs) if def.is_struct() => { ty::Adt(def, substs) if def.is_struct() => {
let mut iter = def let mut iter = def
.non_enum_variant() .non_enum_variant()
@ -287,10 +312,12 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
} else { } else {
ReducedTy::UnorderedFields(ty) ReducedTy::UnorderedFields(ty)
} }
}, }
ty::Adt(def, _) if def.is_enum() && (def.variants().is_empty() || is_c_void(cx, ty)) => { ty::Adt(def, _)
if def.is_enum() && (def.variants().is_empty() || is_c_void(cx, ty)) =>
{
ReducedTy::TypeErasure { raw_ptr_only: false } ReducedTy::TypeErasure { raw_ptr_only: false }
}, }
// TODO: Check if the conversion to or from at least one of a union's fields is valid. // TODO: Check if the conversion to or from at least one of a union's fields is valid.
ty::Adt(def, _) if def.is_union() => ReducedTy::TypeErasure { raw_ptr_only: false }, ty::Adt(def, _) if def.is_union() => ReducedTy::TypeErasure { raw_ptr_only: false },
ty::Foreign(_) | ty::Param(_) => ReducedTy::TypeErasure { raw_ptr_only: false }, ty::Foreign(_) | ty::Param(_) => ReducedTy::TypeErasure { raw_ptr_only: false },
@ -329,7 +356,11 @@ fn same_except_params<'tcx>(subs1: SubstsRef<'tcx>, subs2: SubstsRef<'tcx>) -> b
for (ty1, ty2) in subs1.types().zip(subs2.types()).filter(|(ty1, ty2)| ty1 != ty2) { for (ty1, ty2) in subs1.types().zip(subs2.types()).filter(|(ty1, ty2)| ty1 != ty2) {
match (ty1.kind(), ty2.kind()) { match (ty1.kind(), ty2.kind()) {
(ty::Param(_), _) | (_, ty::Param(_)) => (), (ty::Param(_), _) | (_, ty::Param(_)) => (),
(ty::Adt(adt1, subs1), ty::Adt(adt2, subs2)) if adt1 == adt2 && same_except_params(subs1, subs2) => (), (ty::Adt(adt1, subs1), ty::Adt(adt2, subs2))
if adt1 == adt2 && same_except_params(subs1, subs2) =>
{
()
}
_ => return false, _ => return false,
} }
} }

View file

@ -9,7 +9,12 @@ use rustc_span::symbol::sym;
use super::{utils, REDUNDANT_ALLOCATION}; use super::{utils, REDUNDANT_ALLOCATION};
pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool { pub(super) fn check(
cx: &LateContext<'_>,
hir_ty: &hir::Ty<'_>,
qpath: &QPath<'_>,
def_id: DefId,
) -> bool {
let mut applicability = Applicability::MaybeIncorrect; let mut applicability = Applicability::MaybeIncorrect;
let outer_sym = if Some(def_id) == cx.tcx.lang_items().owned_box() { let outer_sym = if Some(def_id) == cx.tcx.lang_items().owned_box() {
"Box" "Box"
@ -29,7 +34,12 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
hir_ty.span, hir_ty.span,
&format!("usage of `{outer_sym}<{generic_snippet}>`"), &format!("usage of `{outer_sym}<{generic_snippet}>`"),
|diag| { |diag| {
diag.span_suggestion(hir_ty.span, "try", format!("{generic_snippet}"), applicability); diag.span_suggestion(
hir_ty.span,
"try",
format!("{generic_snippet}"),
applicability,
);
diag.note(&format!( diag.note(&format!(
"`{generic_snippet}` is already a pointer, `{outer_sym}<{generic_snippet}>` allocates a pointer on the heap" "`{generic_snippet}` is already a pointer, `{outer_sym}<{generic_snippet}>` allocates a pointer on the heap"
)); ));
@ -55,11 +65,11 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
// Reallocation of a fat pointer causes it to become thin. `hir_ty_to_ty` is safe to use // Reallocation of a fat pointer causes it to become thin. `hir_ty_to_ty` is safe to use
// 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.
if !hir_ty_to_ty(cx.tcx, ty).is_sized(cx.tcx.at(ty.span), cx.param_env) { if !hir_ty_to_ty(cx.tcx, ty).is_sized(cx.tcx, cx.param_env) {
return false; return false;
} }
ty.span ty.span
}, }
None => return false, None => return false,
}; };
if inner_sym == outer_sym { if inner_sym == outer_sym {

View file

@ -40,7 +40,7 @@ pub(super) fn check(
}); });
let ty_ty = hir_ty_to_ty(cx.tcx, boxed_ty); let ty_ty = hir_ty_to_ty(cx.tcx, boxed_ty);
if !ty_ty.has_escaping_bound_vars(); if !ty_ty.has_escaping_bound_vars();
if ty_ty.is_sized(cx.tcx.at(ty.span), cx.param_env); if ty_ty.is_sized(cx.tcx, cx.param_env);
if let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes()); if let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes());
if ty_ty_size <= box_size_threshold; if ty_ty_size <= box_size_threshold;
then { then {

View file

@ -18,7 +18,7 @@ use rustc_middle::ty::{
}; };
use rustc_middle::ty::{GenericArg, GenericArgKind}; use rustc_middle::ty::{GenericArg, GenericArgKind};
use rustc_span::symbol::Ident; use rustc_span::symbol::Ident;
use rustc_span::{sym, Span, Symbol, DUMMY_SP}; use rustc_span::{sym, Span, Symbol};
use rustc_target::abi::{Size, VariantIdx}; use rustc_target::abi::{Size, VariantIdx};
use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::query::normalize::AtExt; use rustc_trait_selection::traits::query::normalize::AtExt;
@ -28,7 +28,7 @@ use crate::{match_def_path, path_res, paths};
// 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.at(DUMMY_SP), cx.param_env) ty.is_copy_modulo_regions(cx.tcx, cx.param_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

@ -16,7 +16,6 @@ use rustc_middle::ty::{
layout::{HasParamEnv, LayoutOf}, layout::{HasParamEnv, LayoutOf},
Ty, Ty,
}; };
use rustc_span::DUMMY_SP;
use rustc_target::abi::Abi; use rustc_target::abi::Abi;
use rustc_target::abi::Size; use rustc_target::abi::Size;
use smallvec::SmallVec; use smallvec::SmallVec;
@ -714,12 +713,12 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
let mut kind_str = format!("{kind}"); let mut kind_str = format!("{kind}");
match kind { match kind {
RefKind::Unique { two_phase: false } RefKind::Unique { two_phase: false }
if !ty.is_unpin(this.tcx.at(DUMMY_SP), this.param_env()) => if !ty.is_unpin(*this.tcx, this.param_env()) =>
{ {
write!(kind_str, " (!Unpin pointee type {ty})").unwrap() write!(kind_str, " (!Unpin pointee type {ty})").unwrap()
}, },
RefKind::Shared RefKind::Shared
if !ty.is_freeze(this.tcx.at(DUMMY_SP), this.param_env()) => if !ty.is_freeze(*this.tcx, this.param_env()) =>
{ {
write!(kind_str, " (!Freeze pointee type {ty})").unwrap() write!(kind_str, " (!Freeze pointee type {ty})").unwrap()
}, },
@ -834,7 +833,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
// There could be existing unique pointers reborrowed from them that should remain valid! // There could be existing unique pointers reborrowed from them that should remain valid!
let perm = match kind { let perm = match kind {
RefKind::Unique { two_phase: false } RefKind::Unique { two_phase: false }
if place.layout.ty.is_unpin(this.tcx.at(DUMMY_SP), this.param_env()) => if place.layout.ty.is_unpin(*this.tcx, this.param_env()) =>
{ {
// Only if the type is unpin do we actually enforce uniqueness // Only if the type is unpin do we actually enforce uniqueness
Permission::Unique Permission::Unique