mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Rollup merge of #131202 - Urgau:wide-ptrs-compiler, r=jieyouxu
Use wide pointers consistenly across the compiler This PR replace every use of "fat pointer" for the more recent "wide pointer" terminology. Since some time T-lang as preferred the "wide pointer" terminology, as can be seen on [the last RFCs](https://github.com/search?q=repo%3Arust-lang%2Frfcs+%22wide+pointer%22&type=code), on some [lints](https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#ambiguous-wide-pointer-comparisons), but also in [the reference](https://doc.rust-lang.org/stable/reference/expressions/operator-expr.html?highlight=wide%20pointer#pointer-to-pointer-cast). Currently we have a [mix of both](https://github.com/search?q=repo%3Arust-lang%2Frust+%22wide+pointer%22&type=code) (including in error messages), which isn't great, but with this PR no more. r? `@jieyouxu` (feel free to re-roll)
This commit is contained in:
commit
ba94a2ada1
@ -168,7 +168,7 @@ fn main() {
|
|||||||
|
|
||||||
foo(I64X2([0, 0]));
|
foo(I64X2([0, 0]));
|
||||||
|
|
||||||
transmute_fat_pointer();
|
transmute_wide_pointer();
|
||||||
|
|
||||||
rust_call_abi();
|
rust_call_abi();
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ type TwoPtrs = i64;
|
|||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
type TwoPtrs = i128;
|
type TwoPtrs = i128;
|
||||||
|
|
||||||
fn transmute_fat_pointer() -> TwoPtrs {
|
fn transmute_wide_pointer() -> TwoPtrs {
|
||||||
unsafe { transmute::<_, TwoPtrs>("true !") }
|
unsafe { transmute::<_, TwoPtrs>("true !") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -713,17 +713,17 @@ fn codegen_stmt<'tcx>(
|
|||||||
let from_ty = operand.layout().ty;
|
let from_ty = operand.layout().ty;
|
||||||
let to_ty = fx.monomorphize(to_ty);
|
let to_ty = fx.monomorphize(to_ty);
|
||||||
|
|
||||||
fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
|
fn is_wide_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||||
ty.builtin_deref(true)
|
ty.builtin_deref(true)
|
||||||
.is_some_and(|pointee_ty| has_ptr_meta(fx.tcx, pointee_ty))
|
.is_some_and(|pointee_ty| has_ptr_meta(fx.tcx, pointee_ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_fat_ptr(fx, from_ty) {
|
if is_wide_ptr(fx, from_ty) {
|
||||||
if is_fat_ptr(fx, to_ty) {
|
if is_wide_ptr(fx, to_ty) {
|
||||||
// fat-ptr -> fat-ptr
|
// wide-ptr -> wide-ptr
|
||||||
lval.write_cvalue(fx, operand.cast_pointer_to(dest_layout));
|
lval.write_cvalue(fx, operand.cast_pointer_to(dest_layout));
|
||||||
} else {
|
} else {
|
||||||
// fat-ptr -> thin-ptr
|
// wide-ptr -> thin-ptr
|
||||||
let (ptr, _extra) = operand.load_scalar_pair(fx);
|
let (ptr, _extra) = operand.load_scalar_pair(fx);
|
||||||
lval.write_cvalue(fx, CValue::by_val(ptr, dest_layout))
|
lval.write_cvalue(fx, CValue::by_val(ptr, dest_layout))
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ fn clif_pair_type_from_ty<'tcx>(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is a pointer to this type a fat ptr?
|
/// Is a pointer to this type a wide ptr?
|
||||||
pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
pub(crate) fn has_ptr_meta<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
|
||||||
if ty.is_sized(tcx, ParamEnv::reveal_all()) {
|
if ty.is_sized(tcx, ParamEnv::reveal_all()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -139,7 +139,7 @@ impl DebugContext {
|
|||||||
|
|
||||||
pointer_type_id
|
pointer_type_id
|
||||||
} else {
|
} else {
|
||||||
// FIXME implement debuginfo for fat pointers
|
// FIXME implement debuginfo for wide pointers
|
||||||
self.placeholder_for_type(tcx, type_dbg, ptr_type)
|
self.placeholder_for_type(tcx, type_dbg, ptr_type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -478,7 +478,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||||||
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||||
});
|
});
|
||||||
require!(metadata.is_unit(), InvalidMonomorphization::CastFatPointer {
|
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
|
||||||
span,
|
span,
|
||||||
name,
|
name,
|
||||||
ty: in_elem
|
ty: in_elem
|
||||||
@ -493,7 +493,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
|
|||||||
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||||
});
|
});
|
||||||
require!(metadata.is_unit(), InvalidMonomorphization::CastFatPointer {
|
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
|
||||||
span,
|
span,
|
||||||
name,
|
name,
|
||||||
ty: out_elem
|
ty: out_elem
|
||||||
|
@ -207,7 +207,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
|
|||||||
// layout.
|
// layout.
|
||||||
if let Abi::Scalar(ref scalar) = self.abi {
|
if let Abi::Scalar(ref scalar) = self.abi {
|
||||||
// Use a different cache for scalars because pointers to DSTs
|
// Use a different cache for scalars because pointers to DSTs
|
||||||
// can be either fat or thin (data pointers of fat pointers).
|
// can be either wide or thin (data pointers of wide pointers).
|
||||||
if let Some(&ty) = cx.scalar_types.borrow().get(&self.ty) {
|
if let Some(&ty) = cx.scalar_types.borrow().get(&self.ty) {
|
||||||
return ty;
|
return ty;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
|
|||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_middle::ty::Ty;
|
use rustc_middle::ty::Ty;
|
||||||
use rustc_middle::ty::layout::LayoutOf;
|
use rustc_middle::ty::layout::LayoutOf;
|
||||||
pub(crate) use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
|
pub(crate) use rustc_middle::ty::layout::{WIDE_PTR_ADDR, WIDE_PTR_EXTRA};
|
||||||
use rustc_middle::{bug, ty};
|
use rustc_middle::{bug, ty};
|
||||||
use rustc_session::config;
|
use rustc_session::config;
|
||||||
pub(crate) use rustc_target::abi::call::*;
|
pub(crate) use rustc_target::abi::call::*;
|
||||||
|
@ -34,7 +34,7 @@ use super::utils::{
|
|||||||
};
|
};
|
||||||
use crate::common::CodegenCx;
|
use crate::common::CodegenCx;
|
||||||
use crate::debuginfo::metadata::type_map::build_type_with_children;
|
use crate::debuginfo::metadata::type_map::build_type_with_children;
|
||||||
use crate::debuginfo::utils::{FatPtrKind, fat_pointer_kind};
|
use crate::debuginfo::utils::{WidePtrKind, wide_pointer_kind};
|
||||||
use crate::llvm::debuginfo::{
|
use crate::llvm::debuginfo::{
|
||||||
DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType, DebugEmissionKind,
|
DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType, DebugEmissionKind,
|
||||||
DebugNameTableKind,
|
DebugNameTableKind,
|
||||||
@ -161,7 +161,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||||||
unique_type_id: UniqueTypeId<'tcx>,
|
unique_type_id: UniqueTypeId<'tcx>,
|
||||||
) -> DINodeCreationResult<'ll> {
|
) -> DINodeCreationResult<'ll> {
|
||||||
// The debuginfo generated by this function is only valid if `ptr_type` is really just
|
// The debuginfo generated by this function is only valid if `ptr_type` is really just
|
||||||
// a (fat) pointer. Make sure it is not called for e.g. `Box<T, NonZSTAllocator>`.
|
// a (wide) pointer. Make sure it is not called for e.g. `Box<T, NonZSTAllocator>`.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cx.size_and_align_of(ptr_type),
|
cx.size_and_align_of(ptr_type),
|
||||||
cx.size_and_align_of(Ty::new_mut_ptr(cx.tcx, pointee_type))
|
cx.size_and_align_of(Ty::new_mut_ptr(cx.tcx, pointee_type))
|
||||||
@ -174,7 +174,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||||||
let data_layout = &cx.tcx.data_layout;
|
let data_layout = &cx.tcx.data_layout;
|
||||||
let ptr_type_debuginfo_name = compute_debuginfo_type_name(cx.tcx, ptr_type, true);
|
let ptr_type_debuginfo_name = compute_debuginfo_type_name(cx.tcx, ptr_type, true);
|
||||||
|
|
||||||
match fat_pointer_kind(cx, pointee_type) {
|
match wide_pointer_kind(cx, pointee_type) {
|
||||||
None => {
|
None => {
|
||||||
// This is a thin pointer. Create a regular pointer type and give it the correct name.
|
// This is a thin pointer. Create a regular pointer type and give it the correct name.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -197,7 +197,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||||||
|
|
||||||
DINodeCreationResult { di_node, already_stored_in_typemap: false }
|
DINodeCreationResult { di_node, already_stored_in_typemap: false }
|
||||||
}
|
}
|
||||||
Some(fat_pointer_kind) => {
|
Some(wide_pointer_kind) => {
|
||||||
type_map::build_type_with_children(
|
type_map::build_type_with_children(
|
||||||
cx,
|
cx,
|
||||||
type_map::stub(
|
type_map::stub(
|
||||||
@ -210,7 +210,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||||||
DIFlags::FlagZero,
|
DIFlags::FlagZero,
|
||||||
),
|
),
|
||||||
|cx, owner| {
|
|cx, owner| {
|
||||||
// FIXME: If this fat pointer is a `Box` then we don't want to use its
|
// FIXME: If this wide pointer is a `Box` then we don't want to use its
|
||||||
// type layout and instead use the layout of the raw pointer inside
|
// type layout and instead use the layout of the raw pointer inside
|
||||||
// of it.
|
// of it.
|
||||||
// The proper way to handle this is to not treat Box as a pointer
|
// The proper way to handle this is to not treat Box as a pointer
|
||||||
@ -227,16 +227,16 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let layout = cx.layout_of(layout_type);
|
let layout = cx.layout_of(layout_type);
|
||||||
let addr_field = layout.field(cx, abi::FAT_PTR_ADDR);
|
let addr_field = layout.field(cx, abi::WIDE_PTR_ADDR);
|
||||||
let extra_field = layout.field(cx, abi::FAT_PTR_EXTRA);
|
let extra_field = layout.field(cx, abi::WIDE_PTR_EXTRA);
|
||||||
|
|
||||||
let (addr_field_name, extra_field_name) = match fat_pointer_kind {
|
let (addr_field_name, extra_field_name) = match wide_pointer_kind {
|
||||||
FatPtrKind::Dyn => ("pointer", "vtable"),
|
WidePtrKind::Dyn => ("pointer", "vtable"),
|
||||||
FatPtrKind::Slice => ("data_ptr", "length"),
|
WidePtrKind::Slice => ("data_ptr", "length"),
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(abi::FAT_PTR_ADDR, 0);
|
assert_eq!(abi::WIDE_PTR_ADDR, 0);
|
||||||
assert_eq!(abi::FAT_PTR_EXTRA, 1);
|
assert_eq!(abi::WIDE_PTR_EXTRA, 1);
|
||||||
|
|
||||||
// The data pointer type is a regular, thin pointer, regardless of whether this
|
// The data pointer type is a regular, thin pointer, regardless of whether this
|
||||||
// is a slice or a trait object.
|
// is a slice or a trait object.
|
||||||
@ -258,7 +258,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||||||
owner,
|
owner,
|
||||||
addr_field_name,
|
addr_field_name,
|
||||||
(addr_field.size, addr_field.align.abi),
|
(addr_field.size, addr_field.align.abi),
|
||||||
layout.fields.offset(abi::FAT_PTR_ADDR),
|
layout.fields.offset(abi::WIDE_PTR_ADDR),
|
||||||
DIFlags::FlagZero,
|
DIFlags::FlagZero,
|
||||||
data_ptr_type_di_node,
|
data_ptr_type_di_node,
|
||||||
),
|
),
|
||||||
@ -267,7 +267,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
|||||||
owner,
|
owner,
|
||||||
extra_field_name,
|
extra_field_name,
|
||||||
(extra_field.size, extra_field.align.abi),
|
(extra_field.size, extra_field.align.abi),
|
||||||
layout.fields.offset(abi::FAT_PTR_EXTRA),
|
layout.fields.offset(abi::WIDE_PTR_EXTRA),
|
||||||
DIFlags::FlagZero,
|
DIFlags::FlagZero,
|
||||||
type_di_node(cx, extra_field.ty),
|
type_di_node(cx, extra_field.ty),
|
||||||
),
|
),
|
||||||
@ -391,7 +391,7 @@ fn build_dyn_type_di_node<'ll, 'tcx>(
|
|||||||
///
|
///
|
||||||
/// NOTE: We currently emit just emit the debuginfo for the element type here
|
/// NOTE: We currently emit just emit the debuginfo for the element type here
|
||||||
/// (i.e. `T` for slices and `u8` for `str`), so that we end up with
|
/// (i.e. `T` for slices and `u8` for `str`), so that we end up with
|
||||||
/// `*const T` for the `data_ptr` field of the corresponding fat-pointer
|
/// `*const T` for the `data_ptr` field of the corresponding wide-pointer
|
||||||
/// debuginfo of `&[T]`.
|
/// debuginfo of `&[T]`.
|
||||||
///
|
///
|
||||||
/// It would be preferable and more accurate if we emitted a DIArray of T
|
/// It would be preferable and more accurate if we emitted a DIArray of T
|
||||||
|
@ -49,23 +49,23 @@ pub(crate) fn get_namespace_for_item<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub(crate) enum FatPtrKind {
|
pub(crate) enum WidePtrKind {
|
||||||
Slice,
|
Slice,
|
||||||
Dyn,
|
Dyn,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines if `pointee_ty` is slice-like or trait-object-like, i.e.
|
/// Determines if `pointee_ty` is slice-like or trait-object-like, i.e.
|
||||||
/// if the second field of the fat pointer is a length or a vtable-pointer.
|
/// if the second field of the wide pointer is a length or a vtable-pointer.
|
||||||
/// If `pointee_ty` does not require a fat pointer (because it is Sized) then
|
/// If `pointee_ty` does not require a wide pointer (because it is Sized) then
|
||||||
/// the function returns `None`.
|
/// the function returns `None`.
|
||||||
pub(crate) fn fat_pointer_kind<'ll, 'tcx>(
|
pub(crate) fn wide_pointer_kind<'ll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
pointee_ty: Ty<'tcx>,
|
pointee_ty: Ty<'tcx>,
|
||||||
) -> Option<FatPtrKind> {
|
) -> Option<WidePtrKind> {
|
||||||
let pointee_tail_ty = cx.tcx.struct_tail_for_codegen(pointee_ty, cx.param_env());
|
let pointee_tail_ty = cx.tcx.struct_tail_for_codegen(pointee_ty, cx.param_env());
|
||||||
let layout = cx.layout_of(pointee_tail_ty);
|
let layout = cx.layout_of(pointee_tail_ty);
|
||||||
trace!(
|
trace!(
|
||||||
"fat_pointer_kind: {:?} has layout {:?} (is_unsized? {})",
|
"wide_pointer_kind: {:?} has layout {:?} (is_unsized? {})",
|
||||||
pointee_tail_ty,
|
pointee_tail_ty,
|
||||||
layout,
|
layout,
|
||||||
layout.is_unsized()
|
layout.is_unsized()
|
||||||
@ -76,8 +76,8 @@ pub(crate) fn fat_pointer_kind<'ll, 'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
match *pointee_tail_ty.kind() {
|
match *pointee_tail_ty.kind() {
|
||||||
ty::Str | ty::Slice(_) => Some(FatPtrKind::Slice),
|
ty::Str | ty::Slice(_) => Some(WidePtrKind::Slice),
|
||||||
ty::Dynamic(..) => Some(FatPtrKind::Dyn),
|
ty::Dynamic(..) => Some(WidePtrKind::Dyn),
|
||||||
ty::Foreign(_) => {
|
ty::Foreign(_) => {
|
||||||
// Assert that pointers to foreign types really are thin:
|
// Assert that pointers to foreign types really are thin:
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -90,7 +90,7 @@ pub(crate) fn fat_pointer_kind<'ll, 'tcx>(
|
|||||||
// For all other pointee types we should already have returned None
|
// For all other pointee types we should already have returned None
|
||||||
// at the beginning of the function.
|
// at the beginning of the function.
|
||||||
panic!(
|
panic!(
|
||||||
"fat_pointer_kind() - Encountered unexpected `pointee_tail_ty`: {pointee_tail_ty:?}"
|
"wide_pointer_kind() - Encountered unexpected `pointee_tail_ty`: {pointee_tail_ty:?}"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2185,7 +2185,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||||||
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||||
});
|
});
|
||||||
require!(metadata.is_unit(), InvalidMonomorphization::CastFatPointer {
|
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
|
||||||
span,
|
span,
|
||||||
name,
|
name,
|
||||||
ty: in_elem
|
ty: in_elem
|
||||||
@ -2200,7 +2200,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
|||||||
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||||
});
|
});
|
||||||
require!(metadata.is_unit(), InvalidMonomorphization::CastFatPointer {
|
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
|
||||||
span,
|
span,
|
||||||
name,
|
name,
|
||||||
ty: out_elem
|
ty: out_elem
|
||||||
|
@ -199,7 +199,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
|||||||
// layout.
|
// layout.
|
||||||
if let Abi::Scalar(scalar) = self.abi {
|
if let Abi::Scalar(scalar) = self.abi {
|
||||||
// Use a different cache for scalars because pointers to DSTs
|
// Use a different cache for scalars because pointers to DSTs
|
||||||
// can be either fat or thin (data pointers of fat pointers).
|
// can be either wide or thin (data pointers of wide pointers).
|
||||||
if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) {
|
if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) {
|
||||||
return llty;
|
return llty;
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphizati
|
|||||||
|
|
||||||
codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
|
codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
|
||||||
|
|
||||||
codegen_ssa_invalid_monomorphization_cast_fat_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast fat pointer `{$ty}`
|
codegen_ssa_invalid_monomorphization_cast_wide_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast wide pointer `{$ty}`
|
||||||
|
|
||||||
codegen_ssa_invalid_monomorphization_expected_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}`
|
codegen_ssa_invalid_monomorphization_expected_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}`
|
||||||
|
|
||||||
|
@ -916,8 +916,8 @@ pub enum InvalidMonomorphization<'tcx> {
|
|||||||
ret_ty: Ty<'tcx>,
|
ret_ty: Ty<'tcx>,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[diag(codegen_ssa_invalid_monomorphization_cast_fat_pointer, code = E0511)]
|
#[diag(codegen_ssa_invalid_monomorphization_cast_wide_pointer, code = E0511)]
|
||||||
CastFatPointer {
|
CastWidePointer {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
span: Span,
|
span: Span,
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
|
@ -133,9 +133,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
enum LocalRef<'tcx, V> {
|
enum LocalRef<'tcx, V> {
|
||||||
Place(PlaceRef<'tcx, V>),
|
Place(PlaceRef<'tcx, V>),
|
||||||
/// `UnsizedPlace(p)`: `p` itself is a thin pointer (indirect place).
|
/// `UnsizedPlace(p)`: `p` itself is a thin pointer (indirect place).
|
||||||
/// `*p` is the fat pointer that references the actual unsized place.
|
/// `*p` is the wide pointer that references the actual unsized place.
|
||||||
/// Every time it is initialized, we have to reallocate the place
|
/// Every time it is initialized, we have to reallocate the place
|
||||||
/// and update the fat pointer. That's the reason why it is indirect.
|
/// and update the wide pointer. That's the reason why it is indirect.
|
||||||
UnsizedPlace(PlaceRef<'tcx, V>),
|
UnsizedPlace(PlaceRef<'tcx, V>),
|
||||||
/// The backend [`OperandValue`] has already been generated.
|
/// The backend [`OperandValue`] has already been generated.
|
||||||
Operand(OperandRef<'tcx, V>),
|
Operand(OperandRef<'tcx, V>),
|
||||||
@ -429,7 +429,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||||||
// Unsized indirect qrguments
|
// Unsized indirect qrguments
|
||||||
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
|
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
|
||||||
// As the storage for the indirect argument lives during
|
// As the storage for the indirect argument lives during
|
||||||
// the whole function call, we just copy the fat pointer.
|
// the whole function call, we just copy the wide pointer.
|
||||||
let llarg = bx.get_param(llarg_idx);
|
let llarg = bx.get_param(llarg_idx);
|
||||||
llarg_idx += 1;
|
llarg_idx += 1;
|
||||||
let llextra = bx.get_param(llarg_idx);
|
let llextra = bx.get_param(llarg_idx);
|
||||||
|
@ -41,7 +41,7 @@ pub enum OperandValue<V> {
|
|||||||
/// The backend value in this variant must be the *immediate* backend type,
|
/// The backend value in this variant must be the *immediate* backend type,
|
||||||
/// as returned by [`LayoutTypeCodegenMethods::immediate_backend_type`].
|
/// as returned by [`LayoutTypeCodegenMethods::immediate_backend_type`].
|
||||||
Immediate(V),
|
Immediate(V),
|
||||||
/// A pair of immediate LLVM values. Used by fat pointers too.
|
/// A pair of immediate LLVM values. Used by wide pointers too.
|
||||||
///
|
///
|
||||||
/// An `OperandValue` *must* be this variant for any type for which
|
/// An `OperandValue` *must* be this variant for any type for which
|
||||||
/// [`LayoutTypeCodegenMethods::is_backend_scalar_pair`] returns `true`.
|
/// [`LayoutTypeCodegenMethods::is_backend_scalar_pair`] returns `true`.
|
||||||
|
@ -38,10 +38,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
ref source,
|
ref source,
|
||||||
_,
|
_,
|
||||||
) => {
|
) => {
|
||||||
// The destination necessarily contains a fat pointer, so if
|
// The destination necessarily contains a wide pointer, so if
|
||||||
// it's a scalar pair, it's a fat pointer or newtype thereof.
|
// it's a scalar pair, it's a wide pointer or newtype thereof.
|
||||||
if bx.cx().is_backend_scalar_pair(dest.layout) {
|
if bx.cx().is_backend_scalar_pair(dest.layout) {
|
||||||
// Into-coerce of a thin pointer to a fat pointer -- just
|
// Into-coerce of a thin pointer to a wide pointer -- just
|
||||||
// use the operand path.
|
// use the operand path.
|
||||||
let temp = self.codegen_rvalue_operand(bx, rvalue);
|
let temp = self.codegen_rvalue_operand(bx, rvalue);
|
||||||
temp.val.store(bx, dest);
|
temp.val.store(bx, dest);
|
||||||
@ -519,7 +519,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
if bx.cx().is_backend_scalar_pair(cast) {
|
if bx.cx().is_backend_scalar_pair(cast) {
|
||||||
OperandValue::Pair(data_ptr, meta)
|
OperandValue::Pair(data_ptr, meta)
|
||||||
} else {
|
} else {
|
||||||
// Cast of fat-ptr to thin-ptr is an extraction of data-ptr.
|
// Cast of wide-ptr to thin-ptr is an extraction of data-ptr.
|
||||||
OperandValue::Immediate(data_ptr)
|
OperandValue::Immediate(data_ptr)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -622,7 +622,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
(
|
(
|
||||||
OperandValue::Pair(lhs_addr, lhs_extra),
|
OperandValue::Pair(lhs_addr, lhs_extra),
|
||||||
OperandValue::Pair(rhs_addr, rhs_extra),
|
OperandValue::Pair(rhs_addr, rhs_extra),
|
||||||
) => self.codegen_fat_ptr_binop(
|
) => self.codegen_wide_ptr_binop(
|
||||||
bx,
|
bx,
|
||||||
op,
|
op,
|
||||||
lhs_addr,
|
lhs_addr,
|
||||||
@ -984,7 +984,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen_fat_ptr_binop(
|
fn codegen_wide_ptr_binop(
|
||||||
&mut self,
|
&mut self,
|
||||||
bx: &mut Bx,
|
bx: &mut Bx,
|
||||||
op: mir::BinOp,
|
op: mir::BinOp,
|
||||||
@ -1021,7 +1021,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
bx.or(lhs, rhs)
|
bx.or(lhs, rhs)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
bug!("unexpected fat ptr binop");
|
bug!("unexpected wide ptr binop");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,12 +204,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||||||
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
|
) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
|
||||||
assert!(src.layout.ty.is_any_ptr());
|
assert!(src.layout.ty.is_any_ptr());
|
||||||
assert!(cast_to.ty.is_unsafe_ptr());
|
assert!(cast_to.ty.is_unsafe_ptr());
|
||||||
// Handle casting any ptr to raw ptr (might be a fat ptr).
|
// Handle casting any ptr to raw ptr (might be a wide ptr).
|
||||||
if cast_to.size == src.layout.size {
|
if cast_to.size == src.layout.size {
|
||||||
// Thin or fat pointer that just has the ptr kind of target type changed.
|
// Thin or wide pointer that just has the ptr kind of target type changed.
|
||||||
return interp_ok(ImmTy::from_immediate(**src, cast_to));
|
return interp_ok(ImmTy::from_immediate(**src, cast_to));
|
||||||
} else {
|
} else {
|
||||||
// Casting the metadata away from a fat ptr.
|
// Casting the metadata away from a wide ptr.
|
||||||
assert_eq!(src.layout.size, 2 * self.pointer_size());
|
assert_eq!(src.layout.size, 2 * self.pointer_size());
|
||||||
assert_eq!(cast_to.size, self.pointer_size());
|
assert_eq!(cast_to.size, self.pointer_size());
|
||||||
assert!(src.layout.ty.is_unsafe_ptr());
|
assert!(src.layout.ty.is_unsafe_ptr());
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
A cast between a thin and a fat pointer was attempted.
|
A cast between a thin and a wide pointer was attempted.
|
||||||
|
|
||||||
Erroneous code example:
|
Erroneous code example:
|
||||||
|
|
||||||
@ -7,18 +7,18 @@ let v = core::ptr::null::<u8>();
|
|||||||
v as *const [u8];
|
v as *const [u8];
|
||||||
```
|
```
|
||||||
|
|
||||||
First: what are thin and fat pointers?
|
First: what are thin and wide pointers?
|
||||||
|
|
||||||
Thin pointers are "simple" pointers: they are purely a reference to a memory
|
Thin pointers are "simple" pointers: they are purely a reference to a memory
|
||||||
address.
|
address.
|
||||||
|
|
||||||
Fat pointers are pointers referencing Dynamically Sized Types (also called
|
Wide pointers are pointers referencing Dynamically Sized Types (also called
|
||||||
DSTs). DSTs don't have a statically known size, therefore they can only exist
|
DSTs). DSTs don't have a statically known size, therefore they can only exist
|
||||||
behind some kind of pointer that contains additional information. For example,
|
behind some kind of pointer that contains additional information. For example,
|
||||||
slices and trait objects are DSTs. In the case of slices, the additional
|
slices and trait objects are DSTs. In the case of slices, the additional
|
||||||
information the fat pointer holds is their size.
|
information the wide pointer holds is their size.
|
||||||
|
|
||||||
To fix this error, don't try to cast directly between thin and fat pointers.
|
To fix this error, don't try to cast directly between thin and wide pointers.
|
||||||
|
|
||||||
For more information about type casts, take a look at the section of the
|
For more information about type casts, take a look at the section of the
|
||||||
[The Rust Reference][1] on type cast expressions.
|
[The Rust Reference][1] on type cast expressions.
|
||||||
|
@ -1105,7 +1105,7 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
|
|||||||
// Check that we use types valid for use in the lanes of a SIMD "vector register"
|
// Check that we use types valid for use in the lanes of a SIMD "vector register"
|
||||||
// These are scalar types which directly match a "machine" type
|
// These are scalar types which directly match a "machine" type
|
||||||
// Yes: Integers, floats, "thin" pointers
|
// Yes: Integers, floats, "thin" pointers
|
||||||
// No: char, "fat" pointers, compound types
|
// No: char, "wide" pointers, compound types
|
||||||
match element_ty.kind() {
|
match element_ty.kind() {
|
||||||
ty::Param(_) => (), // pass struct<T>([T; 4]) through, let monomorphization catch errors
|
ty::Param(_) => (), // pass struct<T>([T; 4]) through, let monomorphization catch errors
|
||||||
ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _) => (), // struct([u8; 4]) is ok
|
ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _) => (), // struct([u8; 4]) is ok
|
||||||
|
@ -424,7 +424,7 @@ pub(crate) fn coerce_unsized_info<'tcx>(
|
|||||||
// Here `U = [i32; 3]` and `V = [i32]`. At runtime,
|
// Here `U = [i32; 3]` and `V = [i32]`. At runtime,
|
||||||
// when this coercion occurs, we would be changing the
|
// when this coercion occurs, we would be changing the
|
||||||
// field `ptr` from a thin pointer of type `*mut [i32;
|
// field `ptr` from a thin pointer of type `*mut [i32;
|
||||||
// 3]` to a fat pointer of type `*mut [i32]` (with
|
// 3]` to a wide pointer of type `*mut [i32]` (with
|
||||||
// extra data `3`). **The purpose of this check is to
|
// extra data `3`). **The purpose of this check is to
|
||||||
// make sure that we know how to do this conversion.**
|
// make sure that we know how to do this conversion.**
|
||||||
//
|
//
|
||||||
|
@ -23,17 +23,17 @@ hir_typeck_cannot_cast_to_bool = cannot cast `{$expr_ty}` as `bool`
|
|||||||
|
|
||||||
hir_typeck_cast_enum_drop = cannot cast enum `{$expr_ty}` into integer `{$cast_ty}` because it implements `Drop`
|
hir_typeck_cast_enum_drop = cannot cast enum `{$expr_ty}` into integer `{$cast_ty}` because it implements `Drop`
|
||||||
|
|
||||||
hir_typeck_cast_thin_pointer_to_fat_pointer = cannot cast thin pointer `{$expr_ty}` to fat pointer `{$cast_ty}`
|
hir_typeck_cast_thin_pointer_to_wide_pointer = cannot cast thin pointer `{$expr_ty}` to wide pointer `{$cast_ty}`
|
||||||
.teach_help = Thin pointers are "simple" pointers: they are purely a reference to a
|
.teach_help = Thin pointers are "simple" pointers: they are purely a reference to a
|
||||||
memory address.
|
memory address.
|
||||||
|
|
||||||
Fat pointers are pointers referencing "Dynamically Sized Types" (also
|
Wide pointers are pointers referencing "Dynamically Sized Types" (also
|
||||||
called DST). DST don't have a statically known size, therefore they can
|
called DST). DST don't have a statically known size, therefore they can
|
||||||
only exist behind some kind of pointers that contain additional
|
only exist behind some kind of pointers that contain additional
|
||||||
information. Slices and trait objects are DSTs. In the case of slices,
|
information. Slices and trait objects are DSTs. In the case of slices,
|
||||||
the additional information the fat pointer holds is their size.
|
the additional information the wide pointer holds is their size.
|
||||||
|
|
||||||
To fix this error, don't try to cast directly between thin and fat
|
To fix this error, don't try to cast directly between thin and wide
|
||||||
pointers.
|
pointers.
|
||||||
|
|
||||||
For more information about casts, take a look at The Book:
|
For more information about casts, take a look at The Book:
|
||||||
|
@ -66,7 +66,7 @@ pub(crate) struct CastCheck<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The kind of pointer and associated metadata (thin, length or vtable) - we
|
/// The kind of pointer and associated metadata (thin, length or vtable) - we
|
||||||
/// only allow casts between fat pointers if their metadata have the same
|
/// only allow casts between wide pointers if their metadata have the same
|
||||||
/// kind.
|
/// kind.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, TypeVisitable, TypeFoldable)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, TypeVisitable, TypeFoldable)]
|
||||||
enum PointerKind<'tcx> {
|
enum PointerKind<'tcx> {
|
||||||
@ -162,7 +162,7 @@ enum CastError<'tcx> {
|
|||||||
src_kind: PointerKind<'tcx>,
|
src_kind: PointerKind<'tcx>,
|
||||||
dst_kind: PointerKind<'tcx>,
|
dst_kind: PointerKind<'tcx>,
|
||||||
},
|
},
|
||||||
/// Cast of thin to fat raw ptr (e.g., `*const () as *const [u8]`).
|
/// Cast of thin to wide raw ptr (e.g., `*const () as *const [u8]`).
|
||||||
SizedUnsizedCast,
|
SizedUnsizedCast,
|
||||||
IllegalCast,
|
IllegalCast,
|
||||||
NeedDeref,
|
NeedDeref,
|
||||||
@ -172,12 +172,12 @@ enum CastError<'tcx> {
|
|||||||
NonScalar,
|
NonScalar,
|
||||||
UnknownExprPtrKind,
|
UnknownExprPtrKind,
|
||||||
UnknownCastPtrKind,
|
UnknownCastPtrKind,
|
||||||
/// Cast of int to (possibly) fat raw pointer.
|
/// Cast of int to (possibly) wide raw pointer.
|
||||||
///
|
///
|
||||||
/// Argument is the specific name of the metadata in plain words, such as "a vtable"
|
/// Argument is the specific name of the metadata in plain words, such as "a vtable"
|
||||||
/// or "a length". If this argument is None, then the metadata is unknown, for example,
|
/// or "a length". If this argument is None, then the metadata is unknown, for example,
|
||||||
/// when we're typechecking a type parameter with a ?Sized bound.
|
/// when we're typechecking a type parameter with a ?Sized bound.
|
||||||
IntToFatCast(Option<&'static str>),
|
IntToWideCast(Option<&'static str>),
|
||||||
ForeignNonExhaustiveAdt,
|
ForeignNonExhaustiveAdt,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,14 +545,14 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
CastError::SizedUnsizedCast => {
|
CastError::SizedUnsizedCast => {
|
||||||
fcx.dcx().emit_err(errors::CastThinPointerToFatPointer {
|
fcx.dcx().emit_err(errors::CastThinPointerToWidePointer {
|
||||||
span: self.span,
|
span: self.span,
|
||||||
expr_ty: self.expr_ty,
|
expr_ty: self.expr_ty,
|
||||||
cast_ty: fcx.ty_to_string(self.cast_ty),
|
cast_ty: fcx.ty_to_string(self.cast_ty),
|
||||||
teach: fcx.tcx.sess.teach(E0607),
|
teach: fcx.tcx.sess.teach(E0607),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
CastError::IntToFatCast(known_metadata) => {
|
CastError::IntToWideCast(known_metadata) => {
|
||||||
let expr_if_nightly = fcx.tcx.sess.is_nightly_build().then_some(self.expr_span);
|
let expr_if_nightly = fcx.tcx.sess.is_nightly_build().then_some(self.expr_span);
|
||||||
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
|
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
|
||||||
let expr_ty = fcx.ty_to_string(self.expr_ty);
|
let expr_ty = fcx.ty_to_string(self.expr_ty);
|
||||||
@ -861,7 +861,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||||||
return Ok(CastKind::PtrPtrCast);
|
return Ok(CastKind::PtrPtrCast);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can't cast to fat pointer if source pointer kind is unknown
|
// We can't cast to wide pointer if source pointer kind is unknown
|
||||||
let Some(src_kind) = src_kind else {
|
let Some(src_kind) = src_kind else {
|
||||||
return Err(CastError::UnknownCastPtrKind);
|
return Err(CastError::UnknownCastPtrKind);
|
||||||
};
|
};
|
||||||
@ -1054,10 +1054,10 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||||||
match fcx.pointer_kind(m_cast.ty, self.span)? {
|
match fcx.pointer_kind(m_cast.ty, self.span)? {
|
||||||
None => Err(CastError::UnknownCastPtrKind),
|
None => Err(CastError::UnknownCastPtrKind),
|
||||||
Some(PointerKind::Thin) => Ok(CastKind::AddrPtrCast),
|
Some(PointerKind::Thin) => Ok(CastKind::AddrPtrCast),
|
||||||
Some(PointerKind::VTable(_)) => Err(CastError::IntToFatCast(Some("a vtable"))),
|
Some(PointerKind::VTable(_)) => Err(CastError::IntToWideCast(Some("a vtable"))),
|
||||||
Some(PointerKind::Length) => Err(CastError::IntToFatCast(Some("a length"))),
|
Some(PointerKind::Length) => Err(CastError::IntToWideCast(Some("a length"))),
|
||||||
Some(PointerKind::OfAlias(_) | PointerKind::OfParam(_)) => {
|
Some(PointerKind::OfAlias(_) | PointerKind::OfParam(_)) => {
|
||||||
Err(CastError::IntToFatCast(None))
|
Err(CastError::IntToWideCast(None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -699,8 +699,8 @@ pub(crate) struct ReplaceWithName {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(hir_typeck_cast_thin_pointer_to_fat_pointer, code = E0607)]
|
#[diag(hir_typeck_cast_thin_pointer_to_wide_pointer, code = E0607)]
|
||||||
pub(crate) struct CastThinPointerToFatPointer<'tcx> {
|
pub(crate) struct CastThinPointerToWidePointer<'tcx> {
|
||||||
#[primary_span]
|
#[primary_span]
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub expr_ty: Ty<'tcx>,
|
pub expr_ty: Ty<'tcx>,
|
||||||
|
@ -55,7 +55,7 @@ impl<'a, 'tcx> Expectation<'tcx> {
|
|||||||
/// be checked higher up, as is the case with `&expr` and `box expr`), but
|
/// be checked higher up, as is the case with `&expr` and `box expr`), but
|
||||||
/// is useful in determining the concrete type.
|
/// is useful in determining the concrete type.
|
||||||
///
|
///
|
||||||
/// The primary use case is where the expected type is a fat pointer,
|
/// The primary use case is where the expected type is a wide pointer,
|
||||||
/// like `&[isize]`. For example, consider the following statement:
|
/// like `&[isize]`. For example, consider the following statement:
|
||||||
///
|
///
|
||||||
/// let x: &[isize] = &[1, 2, 3];
|
/// let x: &[isize] = &[1, 2, 3];
|
||||||
|
@ -413,7 +413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => {
|
ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => {
|
||||||
if oprnd.is_syntactic_place_expr() {
|
if oprnd.is_syntactic_place_expr() {
|
||||||
// Places may legitimately have unsized types.
|
// Places may legitimately have unsized types.
|
||||||
// For example, dereferences of a fat pointer and
|
// For example, dereferences of a wide pointer and
|
||||||
// the last field of a struct can be unsized.
|
// the last field of a struct can be unsized.
|
||||||
ExpectHasType(*ty)
|
ExpectHasType(*ty)
|
||||||
} else {
|
} else {
|
||||||
|
@ -25,10 +25,10 @@ pub enum PointerCoercion {
|
|||||||
ArrayToPointer,
|
ArrayToPointer,
|
||||||
|
|
||||||
/// Unsize a pointer/reference value, e.g., `&[T; n]` to
|
/// Unsize a pointer/reference value, e.g., `&[T; n]` to
|
||||||
/// `&[T]`. Note that the source could be a thin or fat pointer.
|
/// `&[T]`. Note that the source could be a thin or wide pointer.
|
||||||
/// This will do things like convert thin pointers to fat
|
/// This will do things like convert thin pointers to wide
|
||||||
/// pointers, or convert structs containing thin pointers to
|
/// pointers, or convert structs containing thin pointers to
|
||||||
/// structs containing fat pointers, or convert between fat
|
/// structs containing wide pointers, or convert between wide
|
||||||
/// pointers. We don't store the details of how the transform is
|
/// pointers. We don't store the details of how the transform is
|
||||||
/// done (in fact, we don't know that, because it might depend on
|
/// done (in fact, we don't know that, because it might depend on
|
||||||
/// the precise type parameters). We just store the target
|
/// the precise type parameters). We just store the target
|
||||||
|
@ -164,17 +164,17 @@ impl Primitive {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The first half of a fat pointer.
|
/// The first half of a wide pointer.
|
||||||
///
|
///
|
||||||
/// - For a trait object, this is the address of the box.
|
/// - For a trait object, this is the address of the box.
|
||||||
/// - For a slice, this is the base address.
|
/// - For a slice, this is the base address.
|
||||||
pub const FAT_PTR_ADDR: usize = 0;
|
pub const WIDE_PTR_ADDR: usize = 0;
|
||||||
|
|
||||||
/// The second half of a fat pointer.
|
/// The second half of a wide pointer.
|
||||||
///
|
///
|
||||||
/// - For a trait object, this is the address of the vtable.
|
/// - For a trait object, this is the address of the vtable.
|
||||||
/// - For a slice, this is the length.
|
/// - For a slice, this is the length.
|
||||||
pub const FAT_PTR_EXTRA: usize = 1;
|
pub const WIDE_PTR_EXTRA: usize = 1;
|
||||||
|
|
||||||
/// The maximum supported number of lanes in a SIMD vector.
|
/// The maximum supported number of lanes in a SIMD vector.
|
||||||
///
|
///
|
||||||
@ -312,7 +312,7 @@ pub enum SizeSkeleton<'tcx> {
|
|||||||
/// that another SizeSkeleton is of equal size.
|
/// that another SizeSkeleton is of equal size.
|
||||||
Generic(ty::Const<'tcx>),
|
Generic(ty::Const<'tcx>),
|
||||||
|
|
||||||
/// A potentially-fat pointer.
|
/// A potentially-wide pointer.
|
||||||
Pointer {
|
Pointer {
|
||||||
/// If true, this pointer is never null.
|
/// If true, this pointer is never null.
|
||||||
non_zero: bool,
|
non_zero: bool,
|
||||||
@ -785,11 +785,11 @@ where
|
|||||||
bug!("TyAndLayout::field({:?}): not applicable", this)
|
bug!("TyAndLayout::field({:?}): not applicable", this)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Potentially-fat pointers.
|
// Potentially-wide pointers.
|
||||||
ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
|
ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
|
||||||
assert!(i < this.fields.count());
|
assert!(i < this.fields.count());
|
||||||
|
|
||||||
// Reuse the fat `*T` type as its own thin pointer data field.
|
// Reuse the wide `*T` type as its own thin pointer data field.
|
||||||
// This provides information about, e.g., DST struct pointees
|
// This provides information about, e.g., DST struct pointees
|
||||||
// (which may have no non-DST form), and will work as long
|
// (which may have no non-DST form), and will work as long
|
||||||
// as the `Abi` or `FieldsShape` is checked by users.
|
// as the `Abi` or `FieldsShape` is checked by users.
|
||||||
|
@ -1589,7 +1589,7 @@ impl<'tcx> Ty<'tcx> {
|
|||||||
.map_bound(|fn_sig| fn_sig.output().no_bound_vars().unwrap())
|
.map_bound(|fn_sig| fn_sig.output().no_bound_vars().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the type of metadata for (potentially fat) pointers to this type,
|
/// Returns the type of metadata for (potentially wide) pointers to this type,
|
||||||
/// or the struct tail if the metadata type cannot be determined.
|
/// or the struct tail if the metadata type cannot be determined.
|
||||||
pub fn ptr_metadata_ty_or_tail(
|
pub fn ptr_metadata_ty_or_tail(
|
||||||
self,
|
self,
|
||||||
@ -1648,7 +1648,7 @@ impl<'tcx> Ty<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the type of metadata for (potentially fat) pointers to this type.
|
/// Returns the type of metadata for (potentially wide) pointers to this type.
|
||||||
/// Causes an ICE if the metadata type cannot be determined.
|
/// Causes an ICE if the metadata type cannot be determined.
|
||||||
pub fn ptr_metadata_ty(
|
pub fn ptr_metadata_ty(
|
||||||
self,
|
self,
|
||||||
|
@ -1137,7 +1137,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||||||
(UnOp::PtrMetadata, Value::Aggregate(AggregateTy::RawPtr { .. }, _, fields)) => {
|
(UnOp::PtrMetadata, Value::Aggregate(AggregateTy::RawPtr { .. }, _, fields)) => {
|
||||||
return Some(fields[1]);
|
return Some(fields[1]);
|
||||||
}
|
}
|
||||||
// We have an unsizing cast, which assigns the length to fat pointer metadata.
|
// We have an unsizing cast, which assigns the length to wide pointer metadata.
|
||||||
(
|
(
|
||||||
UnOp::PtrMetadata,
|
UnOp::PtrMetadata,
|
||||||
Value::Cast {
|
Value::Cast {
|
||||||
@ -1421,7 +1421,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||||||
|
|
||||||
let mut inner = self.simplify_place_value(place, location)?;
|
let mut inner = self.simplify_place_value(place, location)?;
|
||||||
|
|
||||||
// The length information is stored in the fat pointer.
|
// The length information is stored in the wide pointer.
|
||||||
// Reborrowing copies length information from one pointer to the other.
|
// Reborrowing copies length information from one pointer to the other.
|
||||||
while let Value::Address { place: borrowed, .. } = self.get(inner)
|
while let Value::Address { place: borrowed, .. } = self.get(inner)
|
||||||
&& let [PlaceElem::Deref] = borrowed.projection[..]
|
&& let [PlaceElem::Deref] = borrowed.projection[..]
|
||||||
@ -1430,7 +1430,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||||||
inner = borrowed;
|
inner = borrowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have an unsizing cast, which assigns the length to fat pointer metadata.
|
// We have an unsizing cast, which assigns the length to wide pointer metadata.
|
||||||
if let Value::Cast { kind, from, to, .. } = self.get(inner)
|
if let Value::Cast { kind, from, to, .. } = self.get(inner)
|
||||||
&& let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) = kind
|
&& let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) = kind
|
||||||
&& let Some(from) = from.builtin_deref(true)
|
&& let Some(from) = from.builtin_deref(true)
|
||||||
|
@ -119,7 +119,7 @@
|
|||||||
//!
|
//!
|
||||||
//! #### Unsizing Casts
|
//! #### Unsizing Casts
|
||||||
//! A subtle way of introducing use edges is by casting to a trait object.
|
//! A subtle way of introducing use edges is by casting to a trait object.
|
||||||
//! Since the resulting fat-pointer contains a reference to a vtable, we need to
|
//! Since the resulting wide-pointer contains a reference to a vtable, we need to
|
||||||
//! instantiate all dyn-compatible methods of the trait, as we need to store
|
//! instantiate all dyn-compatible methods of the trait, as we need to store
|
||||||
//! pointers to these functions even if they never get called anywhere. This can
|
//! pointers to these functions even if they never get called anywhere. This can
|
||||||
//! be seen as a special case of taking a function reference.
|
//! be seen as a special case of taking a function reference.
|
||||||
@ -661,7 +661,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
|
|||||||
let span = self.body.source_info(location).span;
|
let span = self.body.source_info(location).span;
|
||||||
|
|
||||||
match *rvalue {
|
match *rvalue {
|
||||||
// When doing an cast from a regular pointer to a fat pointer, we
|
// When doing an cast from a regular pointer to a wide pointer, we
|
||||||
// have to instantiate all methods of the trait being cast to, so we
|
// have to instantiate all methods of the trait being cast to, so we
|
||||||
// can build the appropriate vtable.
|
// can build the appropriate vtable.
|
||||||
mir::Rvalue::Cast(
|
mir::Rvalue::Cast(
|
||||||
@ -985,7 +985,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxtAt<'tcx>, instance: Instance<'tcx>) -
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Then the output of this function would be (SomeStruct, SomeTrait) since for
|
/// Then the output of this function would be (SomeStruct, SomeTrait) since for
|
||||||
/// constructing the `target` fat-pointer we need the vtable for that pair.
|
/// constructing the `target` wide-pointer we need the vtable for that pair.
|
||||||
///
|
///
|
||||||
/// Things can get more complicated though because there's also the case where
|
/// Things can get more complicated though because there's also the case where
|
||||||
/// the unsized type occurs as a field:
|
/// the unsized type occurs as a field:
|
||||||
@ -999,7 +999,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxtAt<'tcx>, instance: Instance<'tcx>) -
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// In this case, if `T` is sized, `&ComplexStruct<T>` is a thin pointer. If `T`
|
/// In this case, if `T` is sized, `&ComplexStruct<T>` is a thin pointer. If `T`
|
||||||
/// is unsized, `&SomeStruct` is a fat pointer, and the vtable it points to is
|
/// is unsized, `&SomeStruct` is a wide pointer, and the vtable it points to is
|
||||||
/// for the pair of `T` (which is a trait) and the concrete type that `T` was
|
/// for the pair of `T` (which is a trait) and the concrete type that `T` was
|
||||||
/// originally coerced from:
|
/// originally coerced from:
|
||||||
///
|
///
|
||||||
|
@ -637,7 +637,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pass this argument indirectly, by passing a (thin or fat) pointer to the argument instead.
|
/// Pass this argument indirectly, by passing a (thin or wide) pointer to the argument instead.
|
||||||
/// This is valid for both sized and unsized arguments.
|
/// This is valid for both sized and unsized arguments.
|
||||||
pub fn make_indirect(&mut self) {
|
pub fn make_indirect(&mut self) {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
|
@ -135,7 +135,7 @@ impl<'a> Layout<'a> {
|
|||||||
/// Note that the layout is NOT guaranteed to always be identical
|
/// Note that the layout is NOT guaranteed to always be identical
|
||||||
/// to that obtained from `layout_of(ty)`, as we need to produce
|
/// to that obtained from `layout_of(ty)`, as we need to produce
|
||||||
/// layouts for which Rust types do not exist, such as enum variants
|
/// layouts for which Rust types do not exist, such as enum variants
|
||||||
/// or synthetic fields of enums (i.e., discriminants) and fat pointers.
|
/// or synthetic fields of enums (i.e., discriminants) and wide pointers.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
|
||||||
pub struct TyAndLayout<'a, Ty> {
|
pub struct TyAndLayout<'a, Ty> {
|
||||||
pub ty: Ty,
|
pub ty: Ty,
|
||||||
|
@ -357,7 +357,7 @@ fn fn_abi_of_instance<'tcx>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle safe Rust thin and fat pointers.
|
// Handle safe Rust thin and wide pointers.
|
||||||
fn adjust_for_rust_scalar<'tcx>(
|
fn adjust_for_rust_scalar<'tcx>(
|
||||||
cx: LayoutCx<'tcx>,
|
cx: LayoutCx<'tcx>,
|
||||||
attrs: &mut ArgAttributes,
|
attrs: &mut ArgAttributes,
|
||||||
@ -810,7 +810,7 @@ fn make_thin_self_ptr<'tcx>(
|
|||||||
layout: TyAndLayout<'tcx>,
|
layout: TyAndLayout<'tcx>,
|
||||||
) -> TyAndLayout<'tcx> {
|
) -> TyAndLayout<'tcx> {
|
||||||
let tcx = cx.tcx();
|
let tcx = cx.tcx();
|
||||||
let fat_pointer_ty = if layout.is_unsized() {
|
let wide_pointer_ty = if layout.is_unsized() {
|
||||||
// unsized `self` is passed as a pointer to `self`
|
// unsized `self` is passed as a pointer to `self`
|
||||||
// FIXME (mikeyhew) change this to use &own if it is ever added to the language
|
// FIXME (mikeyhew) change this to use &own if it is ever added to the language
|
||||||
Ty::new_mut_ptr(tcx, layout.ty)
|
Ty::new_mut_ptr(tcx, layout.ty)
|
||||||
@ -825,15 +825,15 @@ fn make_thin_self_ptr<'tcx>(
|
|||||||
// elsewhere in the compiler as a method on a `dyn Trait`.
|
// elsewhere in the compiler as a method on a `dyn Trait`.
|
||||||
// To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
|
// To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
|
||||||
// get a built-in pointer type
|
// get a built-in pointer type
|
||||||
let mut fat_pointer_layout = layout;
|
let mut wide_pointer_layout = layout;
|
||||||
while !fat_pointer_layout.ty.is_unsafe_ptr() && !fat_pointer_layout.ty.is_ref() {
|
while !wide_pointer_layout.ty.is_unsafe_ptr() && !wide_pointer_layout.ty.is_ref() {
|
||||||
fat_pointer_layout = fat_pointer_layout
|
wide_pointer_layout = wide_pointer_layout
|
||||||
.non_1zst_field(cx)
|
.non_1zst_field(cx)
|
||||||
.expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type")
|
.expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type")
|
||||||
.1
|
.1
|
||||||
}
|
}
|
||||||
|
|
||||||
fat_pointer_layout.ty
|
wide_pointer_layout.ty
|
||||||
};
|
};
|
||||||
|
|
||||||
// we now have a type like `*mut RcBox<dyn Trait>`
|
// we now have a type like `*mut RcBox<dyn Trait>`
|
||||||
@ -842,7 +842,7 @@ fn make_thin_self_ptr<'tcx>(
|
|||||||
let unit_ptr_ty = Ty::new_mut_ptr(tcx, tcx.types.unit);
|
let unit_ptr_ty = Ty::new_mut_ptr(tcx, tcx.types.unit);
|
||||||
|
|
||||||
TyAndLayout {
|
TyAndLayout {
|
||||||
ty: fat_pointer_ty,
|
ty: wide_pointer_ty,
|
||||||
|
|
||||||
// NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing the `Result`
|
// NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing the `Result`
|
||||||
// should always work because the type is always `*mut ()`.
|
// should always work because the type is always `*mut ()`.
|
||||||
|
@ -946,10 +946,10 @@ pub enum PointerCoercion {
|
|||||||
ArrayToPointer,
|
ArrayToPointer,
|
||||||
|
|
||||||
/// Unsize a pointer/reference value, e.g., `&[T; n]` to
|
/// Unsize a pointer/reference value, e.g., `&[T; n]` to
|
||||||
/// `&[T]`. Note that the source could be a thin or fat pointer.
|
/// `&[T]`. Note that the source could be a thin or wide pointer.
|
||||||
/// This will do things like convert thin pointers to fat
|
/// This will do things like convert thin pointers to wide
|
||||||
/// pointers, or convert structs containing thin pointers to
|
/// pointers, or convert structs containing thin pointers to
|
||||||
/// structs containing fat pointers, or convert between fat
|
/// structs containing wide pointers, or convert between wide
|
||||||
/// pointers.
|
/// pointers.
|
||||||
Unsize,
|
Unsize,
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ LL | p as usize;
|
|||||||
|
|
|
|
||||||
= help: cast through a thin pointer first
|
= help: cast through a thin pointer first
|
||||||
|
|
||||||
error[E0607]: cannot cast thin pointer `*const i32` to fat pointer `*const [i32]`
|
error[E0607]: cannot cast thin pointer `*const i32` to wide pointer `*const [i32]`
|
||||||
--> $DIR/fat-ptr-cast.rs:19:5
|
--> $DIR/fat-ptr-cast.rs:19:5
|
||||||
|
|
|
|
||||||
LL | q as *const [i32];
|
LL | q as *const [i32];
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
error[E0607]: cannot cast thin pointer `*const [i64; 0]` to fat pointer `*const [u8]`
|
error[E0607]: cannot cast thin pointer `*const [i64; 0]` to wide pointer `*const [u8]`
|
||||||
--> $DIR/slice_elem_ty_mismatch_in_unsizing_cast.rs:1:31
|
--> $DIR/slice_elem_ty_mismatch_in_unsizing_cast.rs:1:31
|
||||||
|
|
|
|
||||||
LL | const FOO: &str = unsafe { &*(1_usize as *const [i64; 0] as *const [u8] as *const str) };
|
LL | const FOO: &str = unsafe { &*(1_usize as *const [i64; 0] as *const [u8] as *const str) };
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
|
error[E0607]: cannot cast thin pointer `*const u8` to wide pointer `*const [u8]`
|
||||||
--> $DIR/E0607.rs:3:5
|
--> $DIR/E0607.rs:3:5
|
||||||
|
|
|
|
||||||
LL | v as *const [u8];
|
LL | v as *const [u8];
|
||||||
|
@ -81,7 +81,7 @@ help: dereference the expression
|
|||||||
LL | let y: u32 = *x as u32;
|
LL | let y: u32 = *x as u32;
|
||||||
| +
|
| +
|
||||||
|
|
||||||
error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
|
error[E0607]: cannot cast thin pointer `*const u8` to wide pointer `*const [u8]`
|
||||||
--> $DIR/error-festival.rs:41:5
|
--> $DIR/error-festival.rs:41:5
|
||||||
|
|
|
|
||||||
LL | v as *const [u8];
|
LL | v as *const [u8];
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
fn cast_thin_to_fat(x: *const ()) {
|
fn cast_thin_to_fat(x: *const ()) {
|
||||||
x as *const [u8];
|
x as *const [u8];
|
||||||
//~^ ERROR: cannot cast thin pointer `*const ()` to fat pointer `*const [u8]`
|
//~^ ERROR: cannot cast thin pointer `*const ()` to wide pointer `*const [u8]`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
error[E0607]: cannot cast thin pointer `*const ()` to fat pointer `*const [u8]`
|
error[E0607]: cannot cast thin pointer `*const ()` to wide pointer `*const [u8]`
|
||||||
--> $DIR/issue-31511.rs:2:5
|
--> $DIR/issue-31511.rs:2:5
|
||||||
|
|
|
|
||||||
LL | x as *const [u8];
|
LL | x as *const [u8];
|
||||||
|
@ -158,7 +158,7 @@ LL | let _ = 42usize as *const [u8];
|
|||||||
| |
|
| |
|
||||||
| consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`
|
| consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`
|
||||||
|
|
||||||
error[E0607]: cannot cast thin pointer `*const u8` to fat pointer `*const [u8]`
|
error[E0607]: cannot cast thin pointer `*const u8` to wide pointer `*const [u8]`
|
||||||
--> $DIR/cast-rfc0401.rs:52:13
|
--> $DIR/cast-rfc0401.rs:52:13
|
||||||
|
|
|
|
||||||
LL | let _ = v as *const [u8];
|
LL | let _ = v as *const [u8];
|
||||||
|
Loading…
Reference in New Issue
Block a user