mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 22:34:05 +00:00
Use wide pointers consistenly across the compiler
This commit is contained in:
parent
f7c8928f03
commit
018ba0528f
@ -168,7 +168,7 @@ fn main() {
|
||||
|
||||
foo(I64X2([0, 0]));
|
||||
|
||||
transmute_fat_pointer();
|
||||
transmute_wide_pointer();
|
||||
|
||||
rust_call_abi();
|
||||
|
||||
@ -192,7 +192,7 @@ type TwoPtrs = i64;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
type TwoPtrs = i128;
|
||||
|
||||
fn transmute_fat_pointer() -> TwoPtrs {
|
||||
fn transmute_wide_pointer() -> TwoPtrs {
|
||||
unsafe { transmute::<_, TwoPtrs>("true !") }
|
||||
}
|
||||
|
||||
|
@ -713,17 +713,17 @@ fn codegen_stmt<'tcx>(
|
||||
let from_ty = operand.layout().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)
|
||||
.is_some_and(|pointee_ty| has_ptr_meta(fx.tcx, pointee_ty))
|
||||
}
|
||||
|
||||
if is_fat_ptr(fx, from_ty) {
|
||||
if is_fat_ptr(fx, to_ty) {
|
||||
// fat-ptr -> fat-ptr
|
||||
if is_wide_ptr(fx, from_ty) {
|
||||
if is_wide_ptr(fx, to_ty) {
|
||||
// wide-ptr -> wide-ptr
|
||||
lval.write_cvalue(fx, operand.cast_pointer_to(dest_layout));
|
||||
} else {
|
||||
// fat-ptr -> thin-ptr
|
||||
// wide-ptr -> thin-ptr
|
||||
let (ptr, _extra) = operand.load_scalar_pair(fx);
|
||||
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 {
|
||||
if ty.is_sized(tcx, ParamEnv::reveal_all()) {
|
||||
return false;
|
||||
|
@ -139,7 +139,7 @@ impl DebugContext {
|
||||
|
||||
pointer_type_id
|
||||
} else {
|
||||
// FIXME implement debuginfo for fat pointers
|
||||
// FIXME implement debuginfo for wide pointers
|
||||
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| {
|
||||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||
});
|
||||
require!(metadata.is_unit(), InvalidMonomorphization::CastFatPointer {
|
||||
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
|
||||
span,
|
||||
name,
|
||||
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| {
|
||||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||
});
|
||||
require!(metadata.is_unit(), InvalidMonomorphization::CastFatPointer {
|
||||
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
|
||||
span,
|
||||
name,
|
||||
ty: out_elem
|
||||
|
@ -207,7 +207,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
|
||||
// layout.
|
||||
if let Abi::Scalar(ref scalar) = self.abi {
|
||||
// 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) {
|
||||
return ty;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_middle::ty::Ty;
|
||||
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_session::config;
|
||||
pub(crate) use rustc_target::abi::call::*;
|
||||
|
@ -34,7 +34,7 @@ use super::utils::{
|
||||
};
|
||||
use crate::common::CodegenCx;
|
||||
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::{
|
||||
DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType, DebugEmissionKind,
|
||||
DebugNameTableKind,
|
||||
@ -161,7 +161,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
||||
unique_type_id: UniqueTypeId<'tcx>,
|
||||
) -> DINodeCreationResult<'ll> {
|
||||
// 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!(
|
||||
cx.size_and_align_of(ptr_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 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 => {
|
||||
// This is a thin pointer. Create a regular pointer type and give it the correct name.
|
||||
assert_eq!(
|
||||
@ -197,7 +197,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
||||
|
||||
DINodeCreationResult { di_node, already_stored_in_typemap: false }
|
||||
}
|
||||
Some(fat_pointer_kind) => {
|
||||
Some(wide_pointer_kind) => {
|
||||
type_map::build_type_with_children(
|
||||
cx,
|
||||
type_map::stub(
|
||||
@ -210,7 +210,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
||||
DIFlags::FlagZero,
|
||||
),
|
||||
|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
|
||||
// of it.
|
||||
// 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 addr_field = layout.field(cx, abi::FAT_PTR_ADDR);
|
||||
let extra_field = layout.field(cx, abi::FAT_PTR_EXTRA);
|
||||
let addr_field = layout.field(cx, abi::WIDE_PTR_ADDR);
|
||||
let extra_field = layout.field(cx, abi::WIDE_PTR_EXTRA);
|
||||
|
||||
let (addr_field_name, extra_field_name) = match fat_pointer_kind {
|
||||
FatPtrKind::Dyn => ("pointer", "vtable"),
|
||||
FatPtrKind::Slice => ("data_ptr", "length"),
|
||||
let (addr_field_name, extra_field_name) = match wide_pointer_kind {
|
||||
WidePtrKind::Dyn => ("pointer", "vtable"),
|
||||
WidePtrKind::Slice => ("data_ptr", "length"),
|
||||
};
|
||||
|
||||
assert_eq!(abi::FAT_PTR_ADDR, 0);
|
||||
assert_eq!(abi::FAT_PTR_EXTRA, 1);
|
||||
assert_eq!(abi::WIDE_PTR_ADDR, 0);
|
||||
assert_eq!(abi::WIDE_PTR_EXTRA, 1);
|
||||
|
||||
// The data pointer type is a regular, thin pointer, regardless of whether this
|
||||
// is a slice or a trait object.
|
||||
@ -258,7 +258,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
||||
owner,
|
||||
addr_field_name,
|
||||
(addr_field.size, addr_field.align.abi),
|
||||
layout.fields.offset(abi::FAT_PTR_ADDR),
|
||||
layout.fields.offset(abi::WIDE_PTR_ADDR),
|
||||
DIFlags::FlagZero,
|
||||
data_ptr_type_di_node,
|
||||
),
|
||||
@ -267,7 +267,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
|
||||
owner,
|
||||
extra_field_name,
|
||||
(extra_field.size, extra_field.align.abi),
|
||||
layout.fields.offset(abi::FAT_PTR_EXTRA),
|
||||
layout.fields.offset(abi::WIDE_PTR_EXTRA),
|
||||
DIFlags::FlagZero,
|
||||
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
|
||||
/// (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]`.
|
||||
///
|
||||
/// 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)]
|
||||
pub(crate) enum FatPtrKind {
|
||||
pub(crate) enum WidePtrKind {
|
||||
Slice,
|
||||
Dyn,
|
||||
}
|
||||
|
||||
/// 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 `pointee_ty` does not require a fat pointer (because it is Sized) then
|
||||
/// if the second field of the wide pointer is a length or a vtable-pointer.
|
||||
/// If `pointee_ty` does not require a wide pointer (because it is Sized) then
|
||||
/// the function returns `None`.
|
||||
pub(crate) fn fat_pointer_kind<'ll, 'tcx>(
|
||||
pub(crate) fn wide_pointer_kind<'ll, 'tcx>(
|
||||
cx: &CodegenCx<'ll, '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 layout = cx.layout_of(pointee_tail_ty);
|
||||
trace!(
|
||||
"fat_pointer_kind: {:?} has layout {:?} (is_unsized? {})",
|
||||
"wide_pointer_kind: {:?} has layout {:?} (is_unsized? {})",
|
||||
pointee_tail_ty,
|
||||
layout,
|
||||
layout.is_unsized()
|
||||
@ -76,8 +76,8 @@ pub(crate) fn fat_pointer_kind<'ll, 'tcx>(
|
||||
}
|
||||
|
||||
match *pointee_tail_ty.kind() {
|
||||
ty::Str | ty::Slice(_) => Some(FatPtrKind::Slice),
|
||||
ty::Dynamic(..) => Some(FatPtrKind::Dyn),
|
||||
ty::Str | ty::Slice(_) => Some(WidePtrKind::Slice),
|
||||
ty::Dynamic(..) => Some(WidePtrKind::Dyn),
|
||||
ty::Foreign(_) => {
|
||||
// Assert that pointers to foreign types really are thin:
|
||||
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
|
||||
// at the beginning of the function.
|
||||
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| {
|
||||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||
});
|
||||
require!(metadata.is_unit(), InvalidMonomorphization::CastFatPointer {
|
||||
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
|
||||
span,
|
||||
name,
|
||||
ty: in_elem
|
||||
@ -2200,7 +2200,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
|
||||
let metadata = p_ty.ptr_metadata_ty(bx.tcx, |ty| {
|
||||
bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty)
|
||||
});
|
||||
require!(metadata.is_unit(), InvalidMonomorphization::CastFatPointer {
|
||||
require!(metadata.is_unit(), InvalidMonomorphization::CastWidePointer {
|
||||
span,
|
||||
name,
|
||||
ty: out_elem
|
||||
|
@ -199,7 +199,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
||||
// layout.
|
||||
if let Abi::Scalar(scalar) = self.abi {
|
||||
// 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) {
|
||||
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_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}`
|
||||
|
||||
|
@ -916,8 +916,8 @@ pub enum InvalidMonomorphization<'tcx> {
|
||||
ret_ty: Ty<'tcx>,
|
||||
},
|
||||
|
||||
#[diag(codegen_ssa_invalid_monomorphization_cast_fat_pointer, code = E0511)]
|
||||
CastFatPointer {
|
||||
#[diag(codegen_ssa_invalid_monomorphization_cast_wide_pointer, code = E0511)]
|
||||
CastWidePointer {
|
||||
#[primary_span]
|
||||
span: Span,
|
||||
name: Symbol,
|
||||
|
@ -133,9 +133,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
enum LocalRef<'tcx, V> {
|
||||
Place(PlaceRef<'tcx, V>),
|
||||
/// `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
|
||||
/// 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>),
|
||||
/// The backend [`OperandValue`] has already been generated.
|
||||
Operand(OperandRef<'tcx, V>),
|
||||
@ -429,7 +429,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
// Unsized indirect qrguments
|
||||
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
|
||||
// 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);
|
||||
llarg_idx += 1;
|
||||
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,
|
||||
/// as returned by [`LayoutTypeCodegenMethods::immediate_backend_type`].
|
||||
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
|
||||
/// [`LayoutTypeCodegenMethods::is_backend_scalar_pair`] returns `true`.
|
||||
|
@ -38,10 +38,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
ref source,
|
||||
_,
|
||||
) => {
|
||||
// The destination necessarily contains a fat pointer, so if
|
||||
// it's a scalar pair, it's a fat pointer or newtype thereof.
|
||||
// The destination necessarily contains a wide pointer, so if
|
||||
// it's a scalar pair, it's a wide pointer or newtype thereof.
|
||||
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.
|
||||
let temp = self.codegen_rvalue_operand(bx, rvalue);
|
||||
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) {
|
||||
OperandValue::Pair(data_ptr, meta)
|
||||
} 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)
|
||||
}
|
||||
} else {
|
||||
@ -622,7 +622,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
(
|
||||
OperandValue::Pair(lhs_addr, lhs_extra),
|
||||
OperandValue::Pair(rhs_addr, rhs_extra),
|
||||
) => self.codegen_fat_ptr_binop(
|
||||
) => self.codegen_wide_ptr_binop(
|
||||
bx,
|
||||
op,
|
||||
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,
|
||||
bx: &mut Bx,
|
||||
op: mir::BinOp,
|
||||
@ -1021,7 +1021,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
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>> {
|
||||
assert!(src.layout.ty.is_any_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 {
|
||||
// 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));
|
||||
} 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!(cast_to.size, self.pointer_size());
|
||||
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:
|
||||
|
||||
@ -7,18 +7,18 @@ let v = core::ptr::null::<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
|
||||
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
|
||||
behind some kind of pointer that contains additional information. For example,
|
||||
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
|
||||
[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"
|
||||
// These are scalar types which directly match a "machine" type
|
||||
// Yes: Integers, floats, "thin" pointers
|
||||
// No: char, "fat" pointers, compound types
|
||||
// No: char, "wide" pointers, compound types
|
||||
match element_ty.kind() {
|
||||
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
|
||||
|
@ -424,7 +424,7 @@ pub(crate) fn coerce_unsized_info<'tcx>(
|
||||
// Here `U = [i32; 3]` and `V = [i32]`. At runtime,
|
||||
// when this coercion occurs, we would be changing the
|
||||
// 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
|
||||
// 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_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
|
||||
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
|
||||
only exist behind some kind of pointers that contain additional
|
||||
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.
|
||||
|
||||
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
|
||||
/// 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.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, TypeVisitable, TypeFoldable)]
|
||||
enum PointerKind<'tcx> {
|
||||
@ -162,7 +162,7 @@ enum CastError<'tcx> {
|
||||
src_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,
|
||||
IllegalCast,
|
||||
NeedDeref,
|
||||
@ -172,12 +172,12 @@ enum CastError<'tcx> {
|
||||
NonScalar,
|
||||
UnknownExprPtrKind,
|
||||
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"
|
||||
/// 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.
|
||||
IntToFatCast(Option<&'static str>),
|
||||
IntToWideCast(Option<&'static str>),
|
||||
ForeignNonExhaustiveAdt,
|
||||
}
|
||||
|
||||
@ -545,14 +545,14 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
err.emit();
|
||||
}
|
||||
CastError::SizedUnsizedCast => {
|
||||
fcx.dcx().emit_err(errors::CastThinPointerToFatPointer {
|
||||
fcx.dcx().emit_err(errors::CastThinPointerToWidePointer {
|
||||
span: self.span,
|
||||
expr_ty: self.expr_ty,
|
||||
cast_ty: fcx.ty_to_string(self.cast_ty),
|
||||
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 cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
|
||||
let expr_ty = fcx.ty_to_string(self.expr_ty);
|
||||
@ -861,7 +861,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
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 {
|
||||
return Err(CastError::UnknownCastPtrKind);
|
||||
};
|
||||
@ -1054,10 +1054,10 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
match fcx.pointer_kind(m_cast.ty, self.span)? {
|
||||
None => Err(CastError::UnknownCastPtrKind),
|
||||
Some(PointerKind::Thin) => Ok(CastKind::AddrPtrCast),
|
||||
Some(PointerKind::VTable(_)) => Err(CastError::IntToFatCast(Some("a vtable"))),
|
||||
Some(PointerKind::Length) => Err(CastError::IntToFatCast(Some("a length"))),
|
||||
Some(PointerKind::VTable(_)) => Err(CastError::IntToWideCast(Some("a vtable"))),
|
||||
Some(PointerKind::Length) => Err(CastError::IntToWideCast(Some("a length"))),
|
||||
Some(PointerKind::OfAlias(_) | PointerKind::OfParam(_)) => {
|
||||
Err(CastError::IntToFatCast(None))
|
||||
Err(CastError::IntToWideCast(None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -699,8 +699,8 @@ pub(crate) struct ReplaceWithName {
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_cast_thin_pointer_to_fat_pointer, code = E0607)]
|
||||
pub(crate) struct CastThinPointerToFatPointer<'tcx> {
|
||||
#[diag(hir_typeck_cast_thin_pointer_to_wide_pointer, code = E0607)]
|
||||
pub(crate) struct CastThinPointerToWidePointer<'tcx> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
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
|
||||
/// 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:
|
||||
///
|
||||
/// let x: &[isize] = &[1, 2, 3];
|
||||
|
@ -413,7 +413,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => {
|
||||
if oprnd.is_syntactic_place_expr() {
|
||||
// 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.
|
||||
ExpectHasType(*ty)
|
||||
} else {
|
||||
|
@ -25,10 +25,10 @@ pub enum PointerCoercion {
|
||||
ArrayToPointer,
|
||||
|
||||
/// Unsize a pointer/reference value, e.g., `&[T; n]` to
|
||||
/// `&[T]`. Note that the source could be a thin or fat pointer.
|
||||
/// This will do things like convert thin pointers to fat
|
||||
/// `&[T]`. Note that the source could be a thin or wide pointer.
|
||||
/// This will do things like convert thin pointers to wide
|
||||
/// 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
|
||||
/// done (in fact, we don't know that, because it might depend on
|
||||
/// 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 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 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.
|
||||
///
|
||||
@ -312,7 +312,7 @@ pub enum SizeSkeleton<'tcx> {
|
||||
/// that another SizeSkeleton is of equal size.
|
||||
Generic(ty::Const<'tcx>),
|
||||
|
||||
/// A potentially-fat pointer.
|
||||
/// A potentially-wide pointer.
|
||||
Pointer {
|
||||
/// If true, this pointer is never null.
|
||||
non_zero: bool,
|
||||
@ -785,11 +785,11 @@ where
|
||||
bug!("TyAndLayout::field({:?}): not applicable", this)
|
||||
}
|
||||
|
||||
// Potentially-fat pointers.
|
||||
// Potentially-wide pointers.
|
||||
ty::Ref(_, pointee, _) | ty::RawPtr(pointee, _) => {
|
||||
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
|
||||
// (which may have no non-DST form), and will work as long
|
||||
// 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())
|
||||
}
|
||||
|
||||
/// 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.
|
||||
pub fn ptr_metadata_ty_or_tail(
|
||||
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.
|
||||
pub fn ptr_metadata_ty(
|
||||
self,
|
||||
|
@ -1137,7 +1137,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||
(UnOp::PtrMetadata, Value::Aggregate(AggregateTy::RawPtr { .. }, _, fields)) => {
|
||||
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,
|
||||
Value::Cast {
|
||||
@ -1421,7 +1421,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||
|
||||
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.
|
||||
while let Value::Address { place: borrowed, .. } = self.get(inner)
|
||||
&& let [PlaceElem::Deref] = borrowed.projection[..]
|
||||
@ -1430,7 +1430,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||
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)
|
||||
&& let CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) = kind
|
||||
&& let Some(from) = from.builtin_deref(true)
|
||||
|
@ -119,7 +119,7 @@
|
||||
//!
|
||||
//! #### Unsizing Casts
|
||||
//! 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
|
||||
//! pointers to these functions even if they never get called anywhere. This can
|
||||
//! 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;
|
||||
|
||||
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
|
||||
// can build the appropriate vtable.
|
||||
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
|
||||
/// 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
|
||||
/// 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`
|
||||
/// 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
|
||||
/// 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.
|
||||
pub fn make_indirect(&mut self) {
|
||||
match self.mode {
|
||||
|
@ -135,7 +135,7 @@ impl<'a> Layout<'a> {
|
||||
/// Note that the layout is NOT guaranteed to always be identical
|
||||
/// to that obtained from `layout_of(ty)`, as we need to produce
|
||||
/// 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)]
|
||||
pub struct TyAndLayout<'a, 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>(
|
||||
cx: LayoutCx<'tcx>,
|
||||
attrs: &mut ArgAttributes,
|
||||
@ -810,7 +810,7 @@ fn make_thin_self_ptr<'tcx>(
|
||||
layout: TyAndLayout<'tcx>,
|
||||
) -> TyAndLayout<'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`
|
||||
// FIXME (mikeyhew) change this to use &own if it is ever added to the language
|
||||
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`.
|
||||
// To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
|
||||
// get a built-in pointer type
|
||||
let mut fat_pointer_layout = layout;
|
||||
while !fat_pointer_layout.ty.is_unsafe_ptr() && !fat_pointer_layout.ty.is_ref() {
|
||||
fat_pointer_layout = fat_pointer_layout
|
||||
let mut wide_pointer_layout = layout;
|
||||
while !wide_pointer_layout.ty.is_unsafe_ptr() && !wide_pointer_layout.ty.is_ref() {
|
||||
wide_pointer_layout = wide_pointer_layout
|
||||
.non_1zst_field(cx)
|
||||
.expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type")
|
||||
.1
|
||||
}
|
||||
|
||||
fat_pointer_layout.ty
|
||||
wide_pointer_layout.ty
|
||||
};
|
||||
|
||||
// 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);
|
||||
|
||||
TyAndLayout {
|
||||
ty: fat_pointer_ty,
|
||||
ty: wide_pointer_ty,
|
||||
|
||||
// NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing the `Result`
|
||||
// should always work because the type is always `*mut ()`.
|
||||
|
@ -946,10 +946,10 @@ pub enum PointerCoercion {
|
||||
ArrayToPointer,
|
||||
|
||||
/// Unsize a pointer/reference value, e.g., `&[T; n]` to
|
||||
/// `&[T]`. Note that the source could be a thin or fat pointer.
|
||||
/// This will do things like convert thin pointers to fat
|
||||
/// `&[T]`. Note that the source could be a thin or wide pointer.
|
||||
/// This will do things like convert thin pointers to wide
|
||||
/// 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.
|
||||
Unsize,
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ LL | p as usize;
|
||||
|
|
||||
= 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
|
||||
|
|
||||
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
|
||||
|
|
||||
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
|
||||
|
|
||||
LL | v as *const [u8];
|
||||
|
@ -81,7 +81,7 @@ help: dereference the expression
|
||||
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
|
||||
|
|
||||
LL | v as *const [u8];
|
||||
|
@ -1,6 +1,6 @@
|
||||
fn cast_thin_to_fat(x: *const ()) {
|
||||
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() {}
|
||||
|
@ -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
|
||||
|
|
||||
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`
|
||||
|
||||
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
|
||||
|
|
||||
LL | let _ = v as *const [u8];
|
||||
|
Loading…
Reference in New Issue
Block a user