mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Auto merge of #62946 - RalfJung:miri_type_dispatch_first, r=oli-obk
Miri: dispatch first on the type Based on the fact that Miri now always has intptrcast available, we can change binops and casts to first check the type of the source operand and then decide based on that what to do, instead of considering the value (pointer vs bits) first.
This commit is contained in:
commit
8e917f4838
@ -1863,6 +1863,12 @@ impl<'tcx> TyS<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Tests if this is any kind of primitive pointer type (reference, raw pointer, fn pointer).
|
||||
#[inline]
|
||||
pub fn is_any_ptr(&self) -> bool {
|
||||
self.is_region_ptr() || self.is_unsafe_ptr() || self.is_fn_ptr()
|
||||
}
|
||||
|
||||
/// Returns `true` if this type is an `Arc<T>`.
|
||||
#[inline]
|
||||
pub fn is_arc(&self) -> bool {
|
||||
|
@ -20,10 +20,10 @@ use rustc_data_structures::fx::FxHashMap;
|
||||
use syntax::source_map::{Span, DUMMY_SP};
|
||||
|
||||
use crate::interpret::{self,
|
||||
PlaceTy, MPlaceTy, OpTy, ImmTy, Immediate, Scalar,
|
||||
PlaceTy, MPlaceTy, OpTy, ImmTy, Immediate, Scalar, Pointer,
|
||||
RawConst, ConstValue,
|
||||
InterpResult, InterpErrorInfo, GlobalId, InterpCx, StackPopCleanup,
|
||||
Allocation, AllocId, MemoryKind,
|
||||
Allocation, AllocId, MemoryKind, Memory,
|
||||
snapshot, RefTracking, intern_const_alloc_recursive,
|
||||
};
|
||||
|
||||
@ -397,7 +397,16 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
||||
)
|
||||
}
|
||||
|
||||
fn ptr_op(
|
||||
fn ptr_to_int(
|
||||
_mem: &Memory<'mir, 'tcx, Self>,
|
||||
_ptr: Pointer,
|
||||
) -> InterpResult<'tcx, u64> {
|
||||
Err(
|
||||
ConstEvalError::NeedsRfc("pointer-to-integer cast".to_string()).into(),
|
||||
)
|
||||
}
|
||||
|
||||
fn binary_ptr_op(
|
||||
_ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
_bin_op: mir::BinOp,
|
||||
_left: ImmTy<'tcx>,
|
||||
|
@ -7,22 +7,13 @@ use syntax::symbol::sym;
|
||||
use rustc_apfloat::ieee::{Single, Double};
|
||||
use rustc_apfloat::{Float, FloatConvert};
|
||||
use rustc::mir::interpret::{
|
||||
Scalar, InterpResult, Pointer, PointerArithmetic,
|
||||
Scalar, InterpResult, PointerArithmetic,
|
||||
};
|
||||
use rustc::mir::CastKind;
|
||||
|
||||
use super::{InterpCx, Machine, PlaceTy, OpTy, Immediate, FnVal};
|
||||
use super::{InterpCx, Machine, PlaceTy, OpTy, ImmTy, Immediate, FnVal};
|
||||
|
||||
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
|
||||
match ty.sty {
|
||||
ty::RawPtr(ty::TypeAndMut { ty, .. }) |
|
||||
ty::Ref(_, ty, _) => !self.type_is_sized(ty),
|
||||
ty::Adt(def, _) if def.is_box() => !self.type_is_sized(ty.boxed_ty()),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cast(
|
||||
&mut self,
|
||||
src: OpTy<'tcx, M::PointerTag>,
|
||||
@ -37,40 +28,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
|
||||
Misc | Pointer(PointerCast::MutToConstPointer) => {
|
||||
let src = self.read_immediate(src)?;
|
||||
|
||||
if self.type_is_fat_ptr(src.layout.ty) {
|
||||
match (*src, self.type_is_fat_ptr(dest.layout.ty)) {
|
||||
// pointers to extern types
|
||||
(Immediate::Scalar(_),_) |
|
||||
// slices and trait objects to other slices/trait objects
|
||||
(Immediate::ScalarPair(..), true) => {
|
||||
// No change to immediate
|
||||
self.write_immediate(*src, dest)?;
|
||||
}
|
||||
// slices and trait objects to thin pointers (dropping the metadata)
|
||||
(Immediate::ScalarPair(data, _), false) => {
|
||||
self.write_scalar(data, dest)?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match src.layout.variants {
|
||||
layout::Variants::Single { index } => {
|
||||
if let Some(discr) =
|
||||
src.layout.ty.discriminant_for_variant(*self.tcx, index)
|
||||
{
|
||||
// Cast from a univariant enum
|
||||
assert!(src.layout.is_zst());
|
||||
return self.write_scalar(
|
||||
Scalar::from_uint(discr.val, dest.layout.size),
|
||||
dest);
|
||||
}
|
||||
}
|
||||
layout::Variants::Multiple { .. } => {},
|
||||
}
|
||||
|
||||
let dest_val = self.cast_scalar(src.to_scalar()?, src.layout, dest.layout)?;
|
||||
self.write_scalar(dest_val, dest)?;
|
||||
}
|
||||
let res = self.cast_immediate(src, dest.layout)?;
|
||||
self.write_immediate(res, dest)?;
|
||||
}
|
||||
|
||||
Pointer(PointerCast::ReifyFnPointer) => {
|
||||
@ -126,36 +85,76 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn cast_scalar(
|
||||
fn cast_immediate(
|
||||
&self,
|
||||
val: Scalar<M::PointerTag>,
|
||||
src_layout: TyLayout<'tcx>,
|
||||
src: ImmTy<'tcx, M::PointerTag>,
|
||||
dest_layout: TyLayout<'tcx>,
|
||||
) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
|
||||
) -> InterpResult<'tcx, Immediate<M::PointerTag>> {
|
||||
use rustc::ty::TyKind::*;
|
||||
trace!("Casting {:?}: {:?} to {:?}", val, src_layout.ty, dest_layout.ty);
|
||||
trace!("Casting {:?}: {:?} to {:?}", *src, src.layout.ty, dest_layout.ty);
|
||||
|
||||
match src_layout.ty.sty {
|
||||
match src.layout.ty.sty {
|
||||
// Floating point
|
||||
Float(FloatTy::F32) => self.cast_from_float(val.to_f32()?, dest_layout.ty),
|
||||
Float(FloatTy::F64) => self.cast_from_float(val.to_f64()?, dest_layout.ty),
|
||||
// Integer(-like), including fn ptr casts and casts from enums that
|
||||
// are represented as integers (this excludes univariant enums, which
|
||||
// are handled in `cast` directly).
|
||||
_ => {
|
||||
Float(FloatTy::F32) =>
|
||||
return Ok(self.cast_from_float(src.to_scalar()?.to_f32()?, dest_layout.ty)?.into()),
|
||||
Float(FloatTy::F64) =>
|
||||
return Ok(self.cast_from_float(src.to_scalar()?.to_f64()?, dest_layout.ty)?.into()),
|
||||
// The rest is integer/pointer-"like", including fn ptr casts and casts from enums that
|
||||
// are represented as integers.
|
||||
_ =>
|
||||
assert!(
|
||||
src_layout.ty.is_bool() || src_layout.ty.is_char() ||
|
||||
src_layout.ty.is_enum() || src_layout.ty.is_integral() ||
|
||||
src_layout.ty.is_unsafe_ptr() || src_layout.ty.is_fn_ptr() ||
|
||||
src_layout.ty.is_region_ptr(),
|
||||
"Unexpected cast from type {:?}", src_layout.ty
|
||||
);
|
||||
match val.to_bits_or_ptr(src_layout.size, self) {
|
||||
Err(ptr) => self.cast_from_ptr(ptr, src_layout, dest_layout),
|
||||
Ok(data) => self.cast_from_int(data, src_layout, dest_layout),
|
||||
src.layout.ty.is_bool() || src.layout.ty.is_char() ||
|
||||
src.layout.ty.is_enum() || src.layout.ty.is_integral() ||
|
||||
src.layout.ty.is_any_ptr(),
|
||||
"Unexpected cast from type {:?}", src.layout.ty
|
||||
)
|
||||
}
|
||||
|
||||
// Handle cast from a univariant (ZST) enum.
|
||||
match src.layout.variants {
|
||||
layout::Variants::Single { index } => {
|
||||
if let Some(discr) =
|
||||
src.layout.ty.discriminant_for_variant(*self.tcx, index)
|
||||
{
|
||||
assert!(src.layout.is_zst());
|
||||
return Ok(Scalar::from_uint(discr.val, dest_layout.size).into());
|
||||
}
|
||||
}
|
||||
layout::Variants::Multiple { .. } => {},
|
||||
}
|
||||
|
||||
// Handle casting the metadata away from a fat pointer.
|
||||
if src.layout.ty.is_unsafe_ptr() && dest_layout.ty.is_unsafe_ptr() &&
|
||||
dest_layout.size != src.layout.size
|
||||
{
|
||||
assert_eq!(src.layout.size, 2*self.memory.pointer_size());
|
||||
assert_eq!(dest_layout.size, self.memory.pointer_size());
|
||||
assert!(dest_layout.ty.is_unsafe_ptr());
|
||||
match *src {
|
||||
Immediate::ScalarPair(data, _) =>
|
||||
return Ok(data.into()),
|
||||
Immediate::Scalar(..) =>
|
||||
bug!(
|
||||
"{:?} input to a fat-to-thin cast ({:?} -> {:?})",
|
||||
*src, src.layout.ty, dest_layout.ty
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
// Handle casting any ptr to raw ptr (might be a fat ptr).
|
||||
if src.layout.ty.is_any_ptr() && dest_layout.ty.is_unsafe_ptr()
|
||||
{
|
||||
// The only possible size-unequal case was handled above.
|
||||
assert_eq!(src.layout.size, dest_layout.size);
|
||||
return Ok(*src);
|
||||
}
|
||||
|
||||
// For all remaining casts, we either
|
||||
// (a) cast a raw ptr to usize, or
|
||||
// (b) cast from an integer-like (including bool, char, enums).
|
||||
// In both cases we want the bits.
|
||||
let bits = self.force_bits(src.to_scalar()?, src.layout.size)?;
|
||||
Ok(self.cast_from_int(bits, src.layout, dest_layout)?.into())
|
||||
}
|
||||
|
||||
fn cast_from_int(
|
||||
@ -236,31 +235,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
}
|
||||
}
|
||||
|
||||
fn cast_from_ptr(
|
||||
&self,
|
||||
ptr: Pointer<M::PointerTag>,
|
||||
src_layout: TyLayout<'tcx>,
|
||||
dest_layout: TyLayout<'tcx>,
|
||||
) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
|
||||
use rustc::ty::TyKind::*;
|
||||
|
||||
match dest_layout.ty.sty {
|
||||
// Casting to a reference or fn pointer is not permitted by rustc,
|
||||
// no need to support it here.
|
||||
RawPtr(_) => Ok(ptr.into()),
|
||||
Int(_) | Uint(_) => {
|
||||
let size = self.memory.pointer_size();
|
||||
|
||||
match self.force_bits(Scalar::Ptr(ptr), size) {
|
||||
Ok(bits) => self.cast_from_int(bits, src_layout, dest_layout),
|
||||
Err(_) if dest_layout.size == size => Ok(ptr.into()),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
_ => bug!("invalid MIR: ptr to {:?} cast", dest_layout.ty)
|
||||
}
|
||||
}
|
||||
|
||||
fn unsize_into_ptr(
|
||||
&mut self,
|
||||
src: OpTy<'tcx, M::PointerTag>,
|
||||
|
@ -165,11 +165,10 @@ pub trait Machine<'mir, 'tcx>: Sized {
|
||||
def_id: DefId,
|
||||
) -> InterpResult<'tcx, Cow<'tcx, Allocation>>;
|
||||
|
||||
/// Called for all binary operations on integer(-like) types when one operand is a pointer
|
||||
/// value, and for the `Offset` operation that is inherently about pointers.
|
||||
/// Called for all binary operations where the LHS has pointer type.
|
||||
///
|
||||
/// Returns a (value, overflowed) pair if the operation succeeded
|
||||
fn ptr_op(
|
||||
fn binary_ptr_op(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
bin_op: mir::BinOp,
|
||||
left: ImmTy<'tcx, Self::PointerTag>,
|
||||
@ -234,7 +233,6 @@ pub trait Machine<'mir, 'tcx>: Sized {
|
||||
extra: Self::FrameExtra,
|
||||
) -> InterpResult<'tcx>;
|
||||
|
||||
#[inline(always)]
|
||||
fn int_to_ptr(
|
||||
_mem: &Memory<'mir, 'tcx, Self>,
|
||||
int: u64,
|
||||
@ -246,11 +244,8 @@ pub trait Machine<'mir, 'tcx>: Sized {
|
||||
}).into())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn ptr_to_int(
|
||||
_mem: &Memory<'mir, 'tcx, Self>,
|
||||
_ptr: Pointer<Self::PointerTag>,
|
||||
) -> InterpResult<'tcx, u64> {
|
||||
throw_unsup!(ReadPointerAsBytes)
|
||||
}
|
||||
) -> InterpResult<'tcx, u64>;
|
||||
}
|
||||
|
@ -32,12 +32,21 @@ pub enum Immediate<Tag=(), Id=AllocId> {
|
||||
ScalarPair(ScalarMaybeUndef<Tag, Id>, ScalarMaybeUndef<Tag, Id>),
|
||||
}
|
||||
|
||||
impl<'tcx, Tag> Immediate<Tag> {
|
||||
#[inline]
|
||||
pub fn from_scalar(val: Scalar<Tag>) -> Self {
|
||||
Immediate::Scalar(ScalarMaybeUndef::Scalar(val))
|
||||
impl<Tag> From<ScalarMaybeUndef<Tag>> for Immediate<Tag> {
|
||||
#[inline(always)]
|
||||
fn from(val: ScalarMaybeUndef<Tag>) -> Self {
|
||||
Immediate::Scalar(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Tag> From<Scalar<Tag>> for Immediate<Tag> {
|
||||
#[inline(always)]
|
||||
fn from(val: Scalar<Tag>) -> Self {
|
||||
Immediate::Scalar(val.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, Tag> Immediate<Tag> {
|
||||
pub fn new_slice(
|
||||
val: Scalar<Tag>,
|
||||
len: u64,
|
||||
@ -182,7 +191,7 @@ impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag>
|
||||
{
|
||||
#[inline]
|
||||
pub fn from_scalar(val: Scalar<Tag>, layout: TyLayout<'tcx>) -> Self {
|
||||
ImmTy { imm: Immediate::from_scalar(val), layout }
|
||||
ImmTy { imm: val.into(), layout }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -240,7 +249,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let ptr = match self.check_mplace_access(mplace, None)? {
|
||||
Some(ptr) => ptr,
|
||||
None => return Ok(Some(ImmTy { // zero-sized type
|
||||
imm: Immediate::Scalar(Scalar::zst().into()),
|
||||
imm: Scalar::zst().into(),
|
||||
layout: mplace.layout,
|
||||
})),
|
||||
};
|
||||
@ -251,7 +260,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
.get(ptr.alloc_id)?
|
||||
.read_scalar(self, ptr, mplace.layout.size)?;
|
||||
Ok(Some(ImmTy {
|
||||
imm: Immediate::Scalar(scalar),
|
||||
imm: scalar.into(),
|
||||
layout: mplace.layout,
|
||||
}))
|
||||
}
|
||||
@ -354,7 +363,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let field = field.try_into().unwrap();
|
||||
let field_layout = op.layout.field(self, field)?;
|
||||
if field_layout.is_zst() {
|
||||
let immediate = Immediate::Scalar(Scalar::zst().into());
|
||||
let immediate = Scalar::zst().into();
|
||||
return Ok(OpTy { op: Operand::Immediate(immediate), layout: field_layout });
|
||||
}
|
||||
let offset = op.layout.fields.offset(field);
|
||||
@ -364,7 +373,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
// extract fields from types with `ScalarPair` ABI
|
||||
Immediate::ScalarPair(a, b) => {
|
||||
let val = if offset.bytes() == 0 { a } else { b };
|
||||
Immediate::Scalar(val)
|
||||
Immediate::from(val)
|
||||
},
|
||||
Immediate::Scalar(val) =>
|
||||
bug!("field access on non aggregate {:#?}, {:#?}", val, op.layout),
|
||||
@ -401,7 +410,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
Deref => self.deref_operand(base)?.into(),
|
||||
Subslice { .. } | ConstantIndex { .. } | Index(_) => if base.layout.is_zst() {
|
||||
OpTy {
|
||||
op: Operand::Immediate(Immediate::Scalar(Scalar::zst().into())),
|
||||
op: Operand::Immediate(Scalar::zst().into()),
|
||||
// the actual index doesn't matter, so we just pick a convenient one like 0
|
||||
layout: base.layout.field(self, 0)?,
|
||||
}
|
||||
@ -425,7 +434,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let layout = self.layout_of_local(frame, local, layout)?;
|
||||
let op = if layout.is_zst() {
|
||||
// Do not read from ZST, they might not be initialized
|
||||
Operand::Immediate(Immediate::Scalar(Scalar::zst().into()))
|
||||
Operand::Immediate(Scalar::zst().into())
|
||||
} else {
|
||||
frame.locals[local].access()?
|
||||
};
|
||||
@ -556,7 +565,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
Operand::Indirect(MemPlace::from_ptr(ptr, align))
|
||||
},
|
||||
ConstValue::Scalar(x) =>
|
||||
Operand::Immediate(Immediate::Scalar(tag_scalar(x).into())),
|
||||
Operand::Immediate(tag_scalar(x).into()),
|
||||
ConstValue::Slice { data, start, end } => {
|
||||
// We rely on mutability being set correctly in `data` to prevent writes
|
||||
// where none should happen.
|
||||
|
@ -290,30 +290,29 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
FloatTy::F64 => self.binary_float_op(bin_op, left.to_f64()?, right.to_f64()?),
|
||||
})
|
||||
}
|
||||
_ => {
|
||||
// Must be integer(-like) types. Don't forget about == on fn pointers.
|
||||
_ if left.layout.ty.is_integral() => {
|
||||
// the RHS type can be different, e.g. for shifts -- but it has to be integral, too
|
||||
assert!(
|
||||
left.layout.ty.is_integral() ||
|
||||
left.layout.ty.is_unsafe_ptr() || left.layout.ty.is_fn_ptr(),
|
||||
"Unexpected LHS type {:?} for BinOp {:?}", left.layout.ty, bin_op);
|
||||
assert!(
|
||||
right.layout.ty.is_integral() ||
|
||||
right.layout.ty.is_unsafe_ptr() || right.layout.ty.is_fn_ptr(),
|
||||
"Unexpected RHS type {:?} for BinOp {:?}", right.layout.ty, bin_op);
|
||||
right.layout.ty.is_integral(),
|
||||
"Unexpected types for BinOp: {:?} {:?} {:?}",
|
||||
left.layout.ty, bin_op, right.layout.ty
|
||||
);
|
||||
|
||||
// Handle operations that support pointer values
|
||||
if left.to_scalar_ptr()?.is_ptr() ||
|
||||
right.to_scalar_ptr()?.is_ptr() ||
|
||||
bin_op == mir::BinOp::Offset
|
||||
{
|
||||
return M::ptr_op(self, bin_op, left, right);
|
||||
}
|
||||
|
||||
// Everything else only works with "proper" bits
|
||||
let l = left.to_bits().expect("we checked is_ptr");
|
||||
let r = right.to_bits().expect("we checked is_ptr");
|
||||
let l = self.force_bits(left.to_scalar()?, left.layout.size)?;
|
||||
let r = self.force_bits(right.to_scalar()?, right.layout.size)?;
|
||||
self.binary_int_op(bin_op, l, left.layout, r, right.layout)
|
||||
}
|
||||
_ if left.layout.ty.is_any_ptr() => {
|
||||
// The RHS type must be the same *or an integer type* (for `Offset`).
|
||||
assert!(
|
||||
right.layout.ty == left.layout.ty || right.layout.ty.is_integral(),
|
||||
"Unexpected types for BinOp: {:?} {:?} {:?}",
|
||||
left.layout.ty, bin_op, right.layout.ty
|
||||
);
|
||||
|
||||
M::binary_ptr_op(self, bin_op, left, right)
|
||||
}
|
||||
_ => bug!("Invalid MIR: bad LHS type for binop: {:?}", left.layout.ty),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ use rustc_target::spec::abi::Abi;
|
||||
|
||||
use super::{
|
||||
InterpResult, PointerArithmetic, Scalar,
|
||||
InterpCx, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup, FnVal,
|
||||
InterpCx, Machine, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup, FnVal,
|
||||
};
|
||||
|
||||
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
@ -460,7 +460,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
// Adjust receiver argument.
|
||||
args[0] = OpTy::from(ImmTy {
|
||||
layout: this_receiver_ptr,
|
||||
imm: Immediate::Scalar(receiver_place.ptr.into())
|
||||
imm: receiver_place.ptr.into()
|
||||
});
|
||||
trace!("Patched self operand to {:#?}", args[0]);
|
||||
// recurse with concrete function
|
||||
|
@ -19,7 +19,7 @@ fn main() {
|
||||
// _3 = const Scalar(AllocId(1).0x0) : fn();
|
||||
// _2 = move _3 as usize (Misc);
|
||||
// ...
|
||||
// _1 = const Scalar(AllocId(1).0x0) : *const fn();
|
||||
// _1 = move _2 as *const fn() (Misc);
|
||||
// ...
|
||||
// }
|
||||
// END rustc.main.ConstProp.after.mir
|
||||
|
@ -4,8 +4,8 @@ fn main() {}
|
||||
|
||||
// unconst and bad, will thus error in miri
|
||||
const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR any use of this
|
||||
// unconst and fine
|
||||
const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
|
||||
// unconst and bad, will thus error in miri
|
||||
const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR any use of this
|
||||
// unconst and fine
|
||||
const Y: usize = unsafe { 42usize as *const i32 as usize + 1 };
|
||||
// unconst and bad, will thus error in miri
|
||||
|
@ -8,13 +8,21 @@ LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 };
|
||||
|
|
||||
= note: `#[deny(const_err)]` on by default
|
||||
|
||||
error: any use of this value will cause an error
|
||||
--> $DIR/const_raw_ptr_ops.rs:8:27
|
||||
|
|
||||
LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
|
||||
| --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
|
||||
| |
|
||||
| "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
|
||||
|
||||
error: any use of this value will cause an error
|
||||
--> $DIR/const_raw_ptr_ops.rs:12:28
|
||||
|
|
||||
LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 };
|
||||
| ---------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
|
||||
| ---------------------------^^^^^^^^^^^^^^^^^^^^^^^^^-------
|
||||
| |
|
||||
| "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
|
||||
| "pointer-to-integer cast" needs an rfc before being allowed inside constants
|
||||
|
||||
error: any use of this value will cause an error
|
||||
--> $DIR/const_raw_ptr_ops.rs:16:26
|
||||
@ -32,5 +40,5 @@ LL | const Z3: i32 = unsafe { *(44 as *const i32) };
|
||||
| |
|
||||
| a memory access tried to interpret some bytes as a pointer
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
fn main() {
|
||||
[(); { &loop { break } as *const _ as usize } ];
|
||||
//~^ ERROR casting pointers to integers in constants is unstable
|
||||
//~| ERROR it is undefined behavior to use this value
|
||||
//~| ERROR evaluation of constant value failed
|
||||
}
|
||||
|
@ -7,13 +7,11 @@ LL | [(); { &loop { break } as *const _ as usize } ];
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/51910
|
||||
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/issue-52442.rs:2:11
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/issue-52442.rs:2:13
|
||||
|
|
||||
LL | [(); { &loop { break } as *const _ as usize } ];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -5,11 +5,9 @@ fn main() {
|
||||
let _: [u8; 0] = [4; {
|
||||
match &1 as *const i32 as usize {
|
||||
//~^ ERROR casting pointers to integers in constants
|
||||
//~| NOTE for more information, see
|
||||
//~| ERROR constant contains unimplemented expression type
|
||||
0 => 42, //~ ERROR constant contains unimplemented expression type
|
||||
//~^ NOTE "pointer arithmetic or comparison" needs an rfc before being allowed
|
||||
//~| ERROR evaluation of constant value failed
|
||||
0 => 42, //~ ERROR constant contains unimplemented expression type
|
||||
n => n,
|
||||
}
|
||||
}];
|
||||
|
@ -20,10 +20,10 @@ LL | 0 => 42,
|
||||
| ^
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/match-test-ptr-null.rs:10:13
|
||||
--> $DIR/match-test-ptr-null.rs:6:15
|
||||
|
|
||||
LL | 0 => 42,
|
||||
| ^ "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
|
||||
LL | match &1 as *const i32 as usize {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
@ -2,6 +2,6 @@
|
||||
|
||||
const BAR: *mut () = ((|| 3) as fn() -> i32) as *mut ();
|
||||
pub const FOO: usize = unsafe { BAR as usize };
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
//~^ ERROR any use of this value will cause an error
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,11 +1,12 @@
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/issue-51559.rs:4:1
|
||||
error: any use of this value will cause an error
|
||||
--> $DIR/issue-51559.rs:4:33
|
||||
|
|
||||
LL | pub const FOO: usize = unsafe { BAR as usize };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
|
||||
| --------------------------------^^^^^^^^^^^^---
|
||||
| |
|
||||
| "pointer-to-integer cast" needs an rfc before being allowed inside constants
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
||||
= note: `#[deny(const_err)]` on by default
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
@ -1,4 +1,4 @@
|
||||
fn main() {
|
||||
let _ = [0; (&0 as *const i32) as usize]; //~ ERROR casting pointers to integers in constants
|
||||
//~^ ERROR it is undefined behavior to use this value
|
||||
//~^ ERROR evaluation of constant value failed
|
||||
}
|
||||
|
@ -7,13 +7,11 @@ LL | let _ = [0; (&0 as *const i32) as usize];
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/51910
|
||||
= help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/issue-52023-array-size-pointer-cast.rs:2:17
|
||||
|
|
||||
LL | let _ = [0; (&0 as *const i32) as usize];
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes
|
||||
|
|
||||
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user