mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Rollup merge of #124957 - compiler-errors:builtin-deref, r=michaelwoerister
Make `Ty::builtin_deref` just return a `Ty` Nowhere in the compiler are we using the mutability part of the `TyAndMut` that we used to return.
This commit is contained in:
commit
9a9ec90567
@ -1483,10 +1483,9 @@ fn suggest_ampmut<'tcx>(
|
||||
} else {
|
||||
// otherwise, suggest that the user annotates the binding; we provide the
|
||||
// type of the local.
|
||||
let ty_mut = decl_ty.builtin_deref(true).unwrap();
|
||||
assert_eq!(ty_mut.mutbl, hir::Mutability::Not);
|
||||
let ty = decl_ty.builtin_deref(true).unwrap();
|
||||
|
||||
(false, span, format!("{}mut {}", if decl_ty.is_ref() { "&" } else { "*" }, ty_mut.ty))
|
||||
(false, span, format!("{}mut {}", if decl_ty.is_ref() { "&" } else { "*" }, ty))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,7 +400,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
|
||||
} else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
|
||||
let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
|
||||
let normalized_ty = self.cx.normalize(unnormalized_ty, locations);
|
||||
let literal_ty = constant.const_.ty().builtin_deref(true).unwrap().ty;
|
||||
let literal_ty = constant.const_.ty().builtin_deref(true).unwrap();
|
||||
|
||||
if let Err(terr) = self.cx.eq_types(
|
||||
literal_ty,
|
||||
@ -637,7 +637,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
||||
match pi {
|
||||
ProjectionElem::Deref => {
|
||||
let deref_ty = base_ty.builtin_deref(true);
|
||||
PlaceTy::from_ty(deref_ty.map(|t| t.ty).unwrap_or_else(|| {
|
||||
PlaceTy::from_ty(deref_ty.unwrap_or_else(|| {
|
||||
span_mirbug_and_err!(self, place, "deref of non-pointer {:?}", base_ty)
|
||||
}))
|
||||
}
|
||||
|
@ -670,11 +670,8 @@ fn codegen_stmt<'tcx>(
|
||||
let to_ty = fx.monomorphize(to_ty);
|
||||
|
||||
fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
ty.builtin_deref(true).is_some_and(
|
||||
|ty::TypeAndMut { ty: pointee_ty, mutbl: _ }| {
|
||||
has_ptr_meta(fx.tcx, pointee_ty)
|
||||
},
|
||||
)
|
||||
ty.builtin_deref(true)
|
||||
.is_some_and(|pointee_ty| has_ptr_meta(fx.tcx, pointee_ty))
|
||||
}
|
||||
|
||||
if is_fat_ptr(fx, from_ty) {
|
||||
|
@ -586,7 +586,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
||||
intrinsic_args!(fx, args => (base, offset); intrinsic);
|
||||
let offset = offset.load_scalar(fx);
|
||||
|
||||
let pointee_ty = base.layout().ty.builtin_deref(true).unwrap().ty;
|
||||
let pointee_ty = base.layout().ty.builtin_deref(true).unwrap();
|
||||
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
|
||||
let ptr_diff = if pointee_size != 1 {
|
||||
fx.bcx.ins().imul_imm(offset, pointee_size as i64)
|
||||
@ -610,7 +610,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
||||
let val = val.load_scalar(fx);
|
||||
let count = count.load_scalar(fx);
|
||||
|
||||
let pointee_ty = dst.layout().ty.builtin_deref(true).unwrap().ty;
|
||||
let pointee_ty = dst.layout().ty.builtin_deref(true).unwrap();
|
||||
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
|
||||
let count = if pointee_size != 1 {
|
||||
fx.bcx.ins().imul_imm(count, pointee_size as i64)
|
||||
@ -715,7 +715,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
|
||||
|
||||
// Cranelift treats loads as volatile by default
|
||||
// FIXME correctly handle unaligned_volatile_load
|
||||
let inner_layout = fx.layout_of(ptr.layout().ty.builtin_deref(true).unwrap().ty);
|
||||
let inner_layout = fx.layout_of(ptr.layout().ty.builtin_deref(true).unwrap());
|
||||
let val = CValue::by_ref(Pointer::new(ptr.load_scalar(fx)), inner_layout);
|
||||
ret.write_cvalue(fx, val);
|
||||
}
|
||||
|
@ -974,7 +974,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
||||
intrinsic_args!(fx, args => (ptr, offset); intrinsic);
|
||||
|
||||
let (lane_count, ptr_lane_ty) = ptr.layout().ty.simd_size_and_type(fx.tcx);
|
||||
let pointee_ty = ptr_lane_ty.builtin_deref(true).unwrap().ty;
|
||||
let pointee_ty = ptr_lane_ty.builtin_deref(true).unwrap();
|
||||
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
|
||||
let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
|
||||
let ret_lane_layout = fx.layout_of(ret_lane_ty);
|
||||
|
@ -95,7 +95,7 @@ mod prelude {
|
||||
pub(crate) use rustc_middle::mir::{self, *};
|
||||
pub(crate) use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||
pub(crate) use rustc_middle::ty::{
|
||||
self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut, UintTy,
|
||||
self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, UintTy,
|
||||
};
|
||||
pub(crate) use rustc_span::Span;
|
||||
pub(crate) use rustc_target::abi::{Abi, FieldIdx, Scalar, Size, VariantIdx, FIRST_VARIANT};
|
||||
|
@ -388,12 +388,8 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
|
||||
in_lhs: CValue<'tcx>,
|
||||
in_rhs: CValue<'tcx>,
|
||||
) -> CValue<'tcx> {
|
||||
let is_thin_ptr = in_lhs
|
||||
.layout()
|
||||
.ty
|
||||
.builtin_deref(true)
|
||||
.map(|TypeAndMut { ty, mutbl: _ }| !has_ptr_meta(fx.tcx, ty))
|
||||
.unwrap_or(true);
|
||||
let is_thin_ptr =
|
||||
in_lhs.layout().ty.builtin_deref(true).map(|ty| !has_ptr_meta(fx.tcx, ty)).unwrap_or(true);
|
||||
|
||||
if is_thin_ptr {
|
||||
match bin_op {
|
||||
@ -404,7 +400,7 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
|
||||
codegen_compare_bin_op(fx, bin_op, false, lhs, rhs)
|
||||
}
|
||||
BinOp::Offset => {
|
||||
let pointee_ty = in_lhs.layout().ty.builtin_deref(true).unwrap().ty;
|
||||
let pointee_ty = in_lhs.layout().ty.builtin_deref(true).unwrap();
|
||||
let (base, offset) = (in_lhs, in_rhs.load_scalar(fx));
|
||||
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
|
||||
let ptr_diff = fx.bcx.ins().imul_imm(offset, pointee_size as i64);
|
||||
|
@ -127,7 +127,7 @@ pub(crate) fn coerce_unsized_into<'tcx>(
|
||||
let dst_ty = dst.layout().ty;
|
||||
let mut coerce_ptr = || {
|
||||
let (base, info) =
|
||||
if fx.layout_of(src.layout().ty.builtin_deref(true).unwrap().ty).is_unsized() {
|
||||
if fx.layout_of(src.layout().ty.builtin_deref(true).unwrap()).is_unsized() {
|
||||
let (old_base, old_info) = src.load_scalar_pair(fx);
|
||||
unsize_ptr(fx, old_base, src.layout(), dst.layout(), Some(old_info))
|
||||
} else {
|
||||
|
@ -819,7 +819,7 @@ impl<'tcx> CPlace<'tcx> {
|
||||
}
|
||||
|
||||
pub(crate) fn place_deref(self, fx: &mut FunctionCx<'_, '_, 'tcx>) -> CPlace<'tcx> {
|
||||
let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap().ty);
|
||||
let inner_layout = fx.layout_of(self.layout().ty.builtin_deref(true).unwrap());
|
||||
if has_ptr_meta(fx.tcx, inner_layout.ty) {
|
||||
let (addr, extra) = self.to_cvalue(fx).load_scalar_pair(fx);
|
||||
CPlace::for_ptr_with_extra(Pointer::new(addr), extra, inner_layout)
|
||||
|
@ -59,7 +59,7 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
|
||||
|
||||
if let ty::Ref(_, ty, _) = arg.layout().ty.kind() {
|
||||
if ty.is_dyn_star() {
|
||||
let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap().ty);
|
||||
let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap());
|
||||
let dyn_star = CPlace::for_ptr(Pointer::new(arg.load_scalar(fx)), inner_layout);
|
||||
let ptr = dyn_star.place_field(fx, FieldIdx::ZERO).to_ptr();
|
||||
let vtable =
|
||||
|
@ -583,7 +583,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||
let element_type_index = unsafe { llvm::LLVMRustGetElementTypeArgIndex(callsite) };
|
||||
if element_type_index >= 0 {
|
||||
let arg_ty = self.args[element_type_index as usize].layout.ty;
|
||||
let pointee_ty = arg_ty.builtin_deref(true).expect("Must be pointer argument").ty;
|
||||
let pointee_ty = arg_ty.builtin_deref(true).expect("Must be pointer argument");
|
||||
let element_type_attr = unsafe {
|
||||
llvm::LLVMRustCreateElementTypeAttr(bx.llcx, bx.layout_of(pointee_ty).llvm_type(bx))
|
||||
};
|
||||
|
@ -2387,7 +2387,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||
let pointee = in_elem.builtin_deref(true).unwrap_or_else(|| {
|
||||
span_bug!(span, "must be called with a vector of pointer types as first argument")
|
||||
});
|
||||
let layout = bx.layout_of(pointee.ty);
|
||||
let layout = bx.layout_of(pointee);
|
||||
let ptrs = args[0].immediate();
|
||||
// The second argument must be a ptr-sized integer.
|
||||
// (We don't care about the signedness, this is wrapping anyway.)
|
||||
|
@ -1060,7 +1060,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
|
||||
// Make sure that we've actually unwrapped the rcvr down
|
||||
// to a pointer or ref to `dyn* Trait`.
|
||||
if !op.layout.ty.builtin_deref(true).unwrap().ty.is_dyn_star() {
|
||||
if !op.layout.ty.builtin_deref(true).unwrap().is_dyn_star() {
|
||||
span_bug!(span, "can't codegen a virtual call on {:#?}", op);
|
||||
}
|
||||
let place = op.deref(bx.cx());
|
||||
|
@ -120,7 +120,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
|
||||
{
|
||||
fn deref(&self, bx: &mut Bx) -> Self {
|
||||
bx.cx().layout_of(
|
||||
self.ty.builtin_deref(true).unwrap_or_else(|| bug!("cannot deref `{}`", self.ty)).ty,
|
||||
self.ty.builtin_deref(true).unwrap_or_else(|| bug!("cannot deref `{}`", self.ty)),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -215,8 +215,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
|
||||
.layout
|
||||
.ty
|
||||
.builtin_deref(true)
|
||||
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", self))
|
||||
.ty;
|
||||
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", self));
|
||||
|
||||
let (llptr, llextra) = match self.val {
|
||||
OperandValue::Immediate(llptr) => (llptr, None),
|
||||
@ -455,8 +454,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
|
||||
.layout
|
||||
.ty
|
||||
.builtin_deref(true)
|
||||
.unwrap_or_else(|| bug!("indirect_dest has non-pointer type: {:?}", indirect_dest))
|
||||
.ty;
|
||||
.unwrap_or_else(|| bug!("indirect_dest has non-pointer type: {:?}", indirect_dest));
|
||||
|
||||
let OperandValue::Ref(PlaceValue { llval: llptr, llextra: Some(llextra), .. }) = self
|
||||
else {
|
||||
|
@ -868,8 +868,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
mir::BinOp::Offset => {
|
||||
let pointee_type = input_ty
|
||||
.builtin_deref(true)
|
||||
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", input_ty))
|
||||
.ty;
|
||||
.unwrap_or_else(|| bug!("deref of non-pointer {:?}", input_ty));
|
||||
let pointee_layout = bx.cx().layout_of(pointee_type);
|
||||
if pointee_layout.is_zst() {
|
||||
// `Offset` works in terms of the size of pointee,
|
||||
|
@ -222,7 +222,7 @@ pub(super) fn op_to_const<'tcx>(
|
||||
// This codepath solely exists for `valtree_to_const_value` to not need to generate
|
||||
// a `ConstValue::Indirect` for wide references, so it is tightly restricted to just
|
||||
// that case.
|
||||
let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap().ty; // `false` = no raw ptrs
|
||||
let pointee_ty = imm.layout.ty.builtin_deref(false).unwrap(); // `false` = no raw ptrs
|
||||
debug_assert!(
|
||||
matches!(
|
||||
ecx.tcx.struct_tail_without_normalization(pointee_ty).kind(),
|
||||
|
@ -605,7 +605,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
nonoverlapping: bool,
|
||||
) -> InterpResult<'tcx> {
|
||||
let count = self.read_target_usize(count)?;
|
||||
let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?;
|
||||
let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap())?;
|
||||
let (size, align) = (layout.size, layout.align.abi);
|
||||
// `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max),
|
||||
// but no actual allocation can be big enough for the difference to be noticeable.
|
||||
@ -649,7 +649,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
byte: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
count: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let layout = self.layout_of(dst.layout.ty.builtin_deref(true).unwrap().ty)?;
|
||||
let layout = self.layout_of(dst.layout.ty.builtin_deref(true).unwrap())?;
|
||||
|
||||
let dst = self.read_pointer(dst)?;
|
||||
let byte = self.read_scalar(byte)?.to_u8()?;
|
||||
@ -688,7 +688,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
lhs: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
rhs: &OpTy<'tcx, <M as Machine<'mir, 'tcx>>::Provenance>,
|
||||
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
|
||||
let layout = self.layout_of(lhs.layout.ty.builtin_deref(true).unwrap().ty)?;
|
||||
let layout = self.layout_of(lhs.layout.ty.builtin_deref(true).unwrap())?;
|
||||
assert!(layout.is_sized());
|
||||
|
||||
let get_bytes = |this: &InterpCx<'mir, 'tcx, M>,
|
||||
|
@ -357,7 +357,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
Offset => {
|
||||
let ptr = left.to_scalar().to_pointer(self)?;
|
||||
let offset_count = right.to_scalar().to_target_isize(self)?;
|
||||
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty;
|
||||
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap();
|
||||
|
||||
// We cannot overflow i64 as a type's size must be <= isize::MAX.
|
||||
let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap();
|
||||
|
@ -415,7 +415,7 @@ where
|
||||
val: &ImmTy<'tcx, M::Provenance>,
|
||||
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> {
|
||||
let pointee_type =
|
||||
val.layout.ty.builtin_deref(true).expect("`ref_to_mplace` called on non-ptr type").ty;
|
||||
val.layout.ty.builtin_deref(true).expect("`ref_to_mplace` called on non-ptr type");
|
||||
let layout = self.layout_of(pointee_type)?;
|
||||
let (ptr, meta) = val.to_scalar_and_meta();
|
||||
|
||||
|
@ -1291,7 +1291,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
)) => {
|
||||
let src_ty = src.ty(&self.body.local_decls, self.tcx);
|
||||
let op_src_ty = if let Some(src_deref) = src_ty.builtin_deref(true) {
|
||||
src_deref.ty
|
||||
src_deref
|
||||
} else {
|
||||
self.fail(
|
||||
location,
|
||||
@ -1301,7 +1301,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
};
|
||||
let dst_ty = dst.ty(&self.body.local_decls, self.tcx);
|
||||
let op_dst_ty = if let Some(dst_deref) = dst_ty.builtin_deref(true) {
|
||||
dst_deref.ty
|
||||
dst_deref
|
||||
} else {
|
||||
self.fail(
|
||||
location,
|
||||
|
@ -115,7 +115,7 @@ fn might_permit_raw_init_lax<'tcx>(
|
||||
|
||||
// Special magic check for references and boxes (i.e., special pointer types).
|
||||
if let Some(pointee) = this.ty.builtin_deref(false) {
|
||||
let pointee = cx.layout_of(pointee.ty)?;
|
||||
let pointee = cx.layout_of(pointee)?;
|
||||
// We need to ensure that the LLVM attributes `aligned` and `dereferenceable(size)` are satisfied.
|
||||
if pointee.align.abi.bytes() > 1 {
|
||||
// 0x01-filling is not aligned.
|
||||
|
@ -68,28 +68,27 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
|
||||
}
|
||||
|
||||
// Otherwise, deref if type is derefable:
|
||||
let (kind, new_ty) = if let Some(ty::TypeAndMut { ty, .. }) =
|
||||
self.state.cur_ty.builtin_deref(self.include_raw_pointers)
|
||||
{
|
||||
debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
|
||||
// NOTE: we may still need to normalize the built-in deref in case
|
||||
// we have some type like `&<Ty as Trait>::Assoc`, since users of
|
||||
// autoderef expect this type to have been structurally normalized.
|
||||
if self.infcx.next_trait_solver()
|
||||
&& let ty::Alias(..) = ty.kind()
|
||||
{
|
||||
let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
|
||||
self.state.obligations.extend(obligations);
|
||||
(AutoderefKind::Builtin, normalized_ty)
|
||||
let (kind, new_ty) =
|
||||
if let Some(ty) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) {
|
||||
debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
|
||||
// NOTE: we may still need to normalize the built-in deref in case
|
||||
// we have some type like `&<Ty as Trait>::Assoc`, since users of
|
||||
// autoderef expect this type to have been structurally normalized.
|
||||
if self.infcx.next_trait_solver()
|
||||
&& let ty::Alias(..) = ty.kind()
|
||||
{
|
||||
let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
|
||||
self.state.obligations.extend(obligations);
|
||||
(AutoderefKind::Builtin, normalized_ty)
|
||||
} else {
|
||||
(AutoderefKind::Builtin, ty)
|
||||
}
|
||||
} else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
|
||||
// The overloaded deref check already normalizes the pointee type.
|
||||
(AutoderefKind::Overloaded, ty)
|
||||
} else {
|
||||
(AutoderefKind::Builtin, ty)
|
||||
}
|
||||
} else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
|
||||
// The overloaded deref check already normalizes the pointee type.
|
||||
(AutoderefKind::Overloaded, ty)
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
return None;
|
||||
};
|
||||
|
||||
self.state.steps.push((self.state.cur_ty, kind));
|
||||
debug!(
|
||||
|
@ -624,10 +624,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
/// returns a type of `&T`, but the actual type we assign to the
|
||||
/// *expression* is `T`. So this function just peels off the return
|
||||
/// type by one layer to yield `T`.
|
||||
pub(crate) fn make_overloaded_place_return_type(
|
||||
&self,
|
||||
method: MethodCallee<'tcx>,
|
||||
) -> ty::TypeAndMut<'tcx> {
|
||||
pub(crate) fn make_overloaded_place_return_type(&self, method: MethodCallee<'tcx>) -> Ty<'tcx> {
|
||||
// extract method return type, which will be &T;
|
||||
let ret_ty = method.sig.output();
|
||||
|
||||
|
@ -207,7 +207,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
||||
// but what we want here is the type of the underlying value being borrowed.
|
||||
// So peel off one-level, turning the &T into T.
|
||||
match base_ty.builtin_deref(false) {
|
||||
Some(t) => Ok(t.ty),
|
||||
Some(ty) => Ok(ty),
|
||||
None => {
|
||||
debug!("By-ref binding of non-derefable type");
|
||||
Err(())
|
||||
@ -485,7 +485,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
|
||||
) -> McResult<PlaceWithHirId<'tcx>> {
|
||||
let base_curr_ty = base_place.place.ty();
|
||||
let deref_ty = match base_curr_ty.builtin_deref(true) {
|
||||
Some(mt) => mt.ty,
|
||||
Some(pointee_ty) => pointee_ty,
|
||||
None => {
|
||||
debug!("explicit deref of non-derefable type: {:?}", base_curr_ty);
|
||||
return Err(());
|
||||
|
@ -918,8 +918,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
inner: &Pat<'_>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
if let PatKind::Binding(..) = inner.kind
|
||||
&& let Some(mt) = self.shallow_resolve(expected).builtin_deref(true)
|
||||
&& let ty::Dynamic(..) = mt.ty.kind()
|
||||
&& let Some(pointee_ty) = self.shallow_resolve(expected).builtin_deref(true)
|
||||
&& let ty::Dynamic(..) = pointee_ty.kind()
|
||||
{
|
||||
// This is "x = dyn SomeTrait" being reduced from
|
||||
// "let &x = &dyn SomeTrait" or "let box x = Box<dyn SomeTrait>", an error.
|
||||
|
@ -19,8 +19,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
oprnd_expr: &'tcx hir::Expr<'tcx>,
|
||||
oprnd_ty: Ty<'tcx>,
|
||||
) -> Option<Ty<'tcx>> {
|
||||
if let Some(mt) = oprnd_ty.builtin_deref(true) {
|
||||
return Some(mt.ty);
|
||||
if let Some(ty) = oprnd_ty.builtin_deref(true) {
|
||||
return Some(ty);
|
||||
}
|
||||
|
||||
let ok = self.try_overloaded_deref(expr.span, oprnd_ty)?;
|
||||
@ -36,7 +36,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
} else {
|
||||
span_bug!(expr.span, "input to deref is not a ref?");
|
||||
}
|
||||
let ty = self.make_overloaded_place_return_type(method).ty;
|
||||
let ty = self.make_overloaded_place_return_type(method);
|
||||
self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
|
||||
Some(ty)
|
||||
}
|
||||
@ -173,7 +173,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
self.write_method_call_and_enforce_effects(expr.hir_id, expr.span, method);
|
||||
|
||||
return Some((input_ty, self.make_overloaded_place_return_type(method).ty));
|
||||
return Some((input_ty, self.make_overloaded_place_return_type(method)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -342,8 +342,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
.borrow()
|
||||
.expr_ty_adjusted(base_expr)
|
||||
.builtin_deref(false)
|
||||
.expect("place op takes something that is not a ref")
|
||||
.ty;
|
||||
.expect("place op takes something that is not a ref");
|
||||
|
||||
let arg_ty = match op {
|
||||
PlaceOp::Deref => None,
|
||||
|
@ -78,13 +78,9 @@ impl<'tcx> PlaceTy<'tcx> {
|
||||
}
|
||||
let answer = match *elem {
|
||||
ProjectionElem::Deref => {
|
||||
let ty = self
|
||||
.ty
|
||||
.builtin_deref(true)
|
||||
.unwrap_or_else(|| {
|
||||
bug!("deref projection of non-dereferenceable ty {:?}", self)
|
||||
})
|
||||
.ty;
|
||||
let ty = self.ty.builtin_deref(true).unwrap_or_else(|| {
|
||||
bug!("deref projection of non-dereferenceable ty {:?}", self)
|
||||
});
|
||||
PlaceTy::from_ty(ty)
|
||||
}
|
||||
ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => {
|
||||
|
@ -2164,13 +2164,11 @@ impl<'tcx> Ty<'tcx> {
|
||||
///
|
||||
/// The parameter `explicit` indicates if this is an *explicit* dereference.
|
||||
/// Some types -- notably unsafe ptrs -- can only be dereferenced explicitly.
|
||||
pub fn builtin_deref(self, explicit: bool) -> Option<TypeAndMut<'tcx>> {
|
||||
match self.kind() {
|
||||
Adt(def, _) if def.is_box() => {
|
||||
Some(TypeAndMut { ty: self.boxed_ty(), mutbl: hir::Mutability::Not })
|
||||
}
|
||||
Ref(_, ty, mutbl) => Some(TypeAndMut { ty: *ty, mutbl: *mutbl }),
|
||||
RawPtr(ty, mutbl) if explicit => Some(TypeAndMut { ty: *ty, mutbl: *mutbl }),
|
||||
pub fn builtin_deref(self, explicit: bool) -> Option<Ty<'tcx>> {
|
||||
match *self.kind() {
|
||||
Adt(def, _) if def.is_box() => Some(self.boxed_ty()),
|
||||
Ref(_, ty, _) => Some(ty),
|
||||
RawPtr(ty, _) if explicit => Some(ty),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ impl<'tcx, 'a> Visitor<'tcx> for PointerFinder<'tcx, 'a> {
|
||||
}
|
||||
|
||||
let pointee_ty =
|
||||
pointer_ty.builtin_deref(true).expect("no builtin_deref for an unsafe pointer").ty;
|
||||
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.
|
||||
if !pointee_ty.is_sized(self.tcx, self.param_env) {
|
||||
debug!("Unsafe pointer, but pointee is not known to be sized: {:?}", pointer_ty);
|
||||
|
@ -202,7 +202,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
|
||||
if let Some(target_len) = self.map().find_len(target.as_ref())
|
||||
&& let operand_ty = operand.ty(self.local_decls, self.tcx)
|
||||
&& let Some(operand_ty) = operand_ty.builtin_deref(true)
|
||||
&& let ty::Array(_, len) = operand_ty.ty.kind()
|
||||
&& let ty::Array(_, len) = operand_ty.kind()
|
||||
&& let Some(len) = Const::Ty(*len).try_eval_scalar_int(self.tcx, self.param_env)
|
||||
{
|
||||
state.insert_value_idx(target_len, FlatSet::Elem(len.into()), self.map());
|
||||
|
@ -594,7 +594,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||
let ty = place.ty(self.local_decls, self.tcx).ty;
|
||||
if let Some(Mutability::Not) = ty.ref_mutability()
|
||||
&& let Some(pointee_ty) = ty.builtin_deref(true)
|
||||
&& pointee_ty.ty.is_freeze(self.tcx, self.param_env)
|
||||
&& pointee_ty.is_freeze(self.tcx, self.param_env)
|
||||
{
|
||||
// An immutable borrow `_x` always points to the same value for the
|
||||
// lifetime of the borrow, so we can merge all instances of `*_x`.
|
||||
@ -1133,9 +1133,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||
if let Value::Cast { kind, from, to, .. } = self.get(inner)
|
||||
&& let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize) = kind
|
||||
&& let Some(from) = from.builtin_deref(true)
|
||||
&& let ty::Array(_, len) = from.ty.kind()
|
||||
&& let ty::Array(_, len) = from.kind()
|
||||
&& let Some(to) = to.builtin_deref(true)
|
||||
&& let ty::Slice(..) = to.ty.kind()
|
||||
&& let ty::Slice(..) = to.kind()
|
||||
{
|
||||
return self.insert_constant(Const::from_ty_const(*len, self.tcx));
|
||||
}
|
||||
|
@ -79,8 +79,8 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
|
||||
// add everything that may involve a vtable.
|
||||
let source_ty = operand.ty(self.body, self.tcx);
|
||||
let may_involve_vtable = match (
|
||||
source_ty.builtin_deref(true).map(|t| t.ty.kind()),
|
||||
target_ty.builtin_deref(true).map(|t| t.ty.kind()),
|
||||
source_ty.builtin_deref(true).map(|t| t.kind()),
|
||||
target_ty.builtin_deref(true).map(|t| t.kind()),
|
||||
) {
|
||||
(Some(ty::Array(..)), Some(ty::Str | ty::Slice(..))) => false, // &str/&[T] unsizing
|
||||
_ => true,
|
||||
|
@ -48,9 +48,9 @@ fn compute_slice_length<'tcx>(
|
||||
let operand_ty = operand.ty(body, tcx);
|
||||
debug!(?operand_ty);
|
||||
if let Some(operand_ty) = operand_ty.builtin_deref(true)
|
||||
&& let ty::Array(_, len) = operand_ty.ty.kind()
|
||||
&& let ty::Array(_, len) = operand_ty.kind()
|
||||
&& let Some(cast_ty) = cast_ty.builtin_deref(true)
|
||||
&& let ty::Slice(..) = cast_ty.ty.kind()
|
||||
&& let ty::Slice(..) = cast_ty.kind()
|
||||
{
|
||||
slice_lengths[local] = Some(*len);
|
||||
}
|
||||
|
@ -630,8 +630,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
||||
let pointee_ty = ct
|
||||
.ty()
|
||||
.builtin_deref(true)
|
||||
.expect("tried to dereference on non-ptr type")
|
||||
.ty;
|
||||
.expect("tried to dereference on non-ptr type");
|
||||
// FIXME(const_generics): add an assert that we only do this for valtrees.
|
||||
let dereferenced_const = self.tcx.mk_ct_from_kind(ct.kind(), pointee_ty);
|
||||
dereferenced_const.print(self)?;
|
||||
|
@ -6,7 +6,7 @@ use rustc_errors::{Applicability, Diag};
|
||||
use rustc_hir::intravisit::{walk_expr, Visitor};
|
||||
use rustc_hir::{Arm, Expr, ExprKind, MatchSource};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_middle::ty::{GenericArgKind, Ty, TypeAndMut};
|
||||
use rustc_middle::ty::{GenericArgKind, Ty};
|
||||
use rustc_span::Span;
|
||||
|
||||
use super::SIGNIFICANT_DROP_IN_SCRUTINEE;
|
||||
@ -234,9 +234,9 @@ impl<'a, 'tcx> SigDropHelper<'a, 'tcx> {
|
||||
}
|
||||
let ty = self.sig_drop_checker.get_type(expr);
|
||||
if ty.is_ref() {
|
||||
// We checked that the type was ref, so builtin_deref will return Some TypeAndMut,
|
||||
// but let's avoid any chance of an ICE
|
||||
if let Some(TypeAndMut { ty, .. }) = ty.builtin_deref(true) {
|
||||
// We checked that the type was ref, so builtin_deref will return Some,
|
||||
// but let's avoid any chance of an ICE.
|
||||
if let Some(ty) = ty.builtin_deref(true) {
|
||||
if ty.is_trivially_pure_clone_copy() {
|
||||
self.replace_current_sig_drop(expr.span, false, LintSuggestion::MoveAndDerefToCopy);
|
||||
} else if allow_move_and_clone {
|
||||
|
@ -70,7 +70,7 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
|
||||
let without_deref = symmetric_partial_eq(cx, arg_ty, other_ty).unwrap_or_default();
|
||||
let with_deref = arg_ty
|
||||
.builtin_deref(true)
|
||||
.and_then(|tam| symmetric_partial_eq(cx, tam.ty, other_ty))
|
||||
.and_then(|ty| symmetric_partial_eq(cx, ty, other_ty))
|
||||
.unwrap_or_default();
|
||||
|
||||
if !with_deref.is_implemented() && !without_deref.is_implemented() {
|
||||
|
@ -134,7 +134,7 @@ fn check_rvalue<'tcx>(
|
||||
) => Err((span, "function pointer casts are not allowed in const fn".into())),
|
||||
Rvalue::Cast(CastKind::PointerCoercion(PointerCoercion::Unsize), op, cast_ty) => {
|
||||
let pointee_ty = if let Some(deref_ty) = cast_ty.builtin_deref(true) {
|
||||
deref_ty.ty
|
||||
deref_ty
|
||||
} else {
|
||||
// We cannot allow this for now.
|
||||
return Err((span, "unsizing casts are only allowed for references right now".into()));
|
||||
|
@ -136,7 +136,7 @@ impl NewPermission {
|
||||
cx: &crate::MiriInterpCx<'_, 'tcx>,
|
||||
) -> Self {
|
||||
// `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().ty;
|
||||
let pointee = ty.builtin_deref(true).unwrap();
|
||||
if pointee.is_unpin(*cx.tcx, cx.param_env()) {
|
||||
// A regular box. On `FnEntry` this is `noalias`, but not `dereferenceable` (hence only
|
||||
// a weak protector).
|
||||
|
@ -173,7 +173,7 @@ impl<'tcx> NewPermission {
|
||||
cx: &crate::MiriInterpCx<'_, 'tcx>,
|
||||
zero_size: bool,
|
||||
) -> Option<Self> {
|
||||
let pointee = ty.builtin_deref(true).unwrap().ty;
|
||||
let pointee = ty.builtin_deref(true).unwrap();
|
||||
pointee.is_unpin(*cx.tcx, cx.param_env()).then_some(()).map(|()| {
|
||||
// Regular `Unpin` box, give it `noalias` but only a weak protector
|
||||
// because it is valid to deallocate it within the function.
|
||||
|
@ -117,7 +117,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
|
||||
"write_bytes" | "volatile_set_memory" => {
|
||||
let [ptr, val_byte, count] = check_arg_count(args)?;
|
||||
let ty = ptr.layout.ty.builtin_deref(true).unwrap().ty;
|
||||
let ty = ptr.layout.ty.builtin_deref(true).unwrap();
|
||||
let ty_layout = this.layout_of(ty)?;
|
||||
let val_byte = this.read_scalar(val_byte)?.to_u8()?;
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
|
@ -267,7 +267,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
Op::WrappingOffset => {
|
||||
let ptr = left.to_scalar().to_pointer(this)?;
|
||||
let offset_count = right.to_scalar().to_target_isize(this)?;
|
||||
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty;
|
||||
let pointee_ty = left.layout.ty.builtin_deref(true).unwrap();
|
||||
|
||||
let pointee_size = i64::try_from(this.layout_of(pointee_ty)?.size.bytes()).unwrap();
|
||||
let offset_bytes = offset_count.wrapping_mul(pointee_size);
|
||||
|
@ -378,8 +378,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||
.builtin_deref(true)
|
||||
.ok_or_else(|| err_ub_format!(
|
||||
"wrong signature used for `pthread_key_create`: first argument must be a raw pointer."
|
||||
))?
|
||||
.ty;
|
||||
))?;
|
||||
let key_layout = this.layout_of(key_type)?;
|
||||
|
||||
// Create key and write it into the memory where `key_ptr` wants it.
|
||||
|
Loading…
Reference in New Issue
Block a user