From 44a927ad626620f0cde3216a256423b7a41d54c9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 24 Jul 2019 16:08:01 +0200 Subject: [PATCH 01/13] cast: no need to catch errors any more, force_bits should succeed --- src/librustc_mir/interpret/cast.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index a481a3b37b717..e1842e72e3c82 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -250,12 +250,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { 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), - } + let bits = self.force_bits(Scalar::Ptr(ptr), size)?; + self.cast_from_int(bits, src_layout, dest_layout) } _ => bug!("invalid MIR: ptr to {:?} cast", dest_layout.ty) } From 48b87c6f275069e5c885b54e3d968056a5563db9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 24 Jul 2019 16:08:50 +0200 Subject: [PATCH 02/13] operator: implement binary_op strictly by first checking the type, then dispatching further; call ptr_op machine hook only for pointer types --- src/librustc_mir/const_eval.rs | 2 +- src/librustc_mir/interpret/machine.rs | 5 ++-- src/librustc_mir/interpret/operator.rs | 39 +++++++++++++------------- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 1b92e4992ffb1..813b7f7fa9c30 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -397,7 +397,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, ) } - fn ptr_op( + fn binary_ptr_op( _ecx: &InterpCx<'mir, 'tcx, Self>, _bin_op: mir::BinOp, _left: ImmTy<'tcx>, diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 78902b1016634..4a0cc24cf1e95 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -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>, diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index a942da5771b00..504bd0a67bc48 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -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. - 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); + _ if left.layout.ty.is_integral() => { + // the RHS type can be different, e.g. for shifts -- but it has to be integral, too 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); - - // 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); - } + right.layout.ty.is_integral(), + "Unexpected types for BinOp: {:?} {:?} {:?}", + left.layout.ty, bin_op, right.layout.ty + ); - // 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_unsafe_ptr() || left.layout.ty.is_fn_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), } } From ec1e71895aa450606d99d7705dac20d689a330d1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 24 Jul 2019 19:01:12 +0200 Subject: [PATCH 03/13] turn cast_immediate into its own function --- src/librustc_mir/interpret/cast.rs | 75 ++++++++++++++------------- src/librustc_mir/interpret/operand.rs | 14 +++++ 2 files changed, 54 insertions(+), 35 deletions(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index e1842e72e3c82..7e752e2edc4a4 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -11,7 +11,7 @@ use rustc::mir::interpret::{ }; 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 { @@ -37,40 +37,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,6 +94,43 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(()) } + fn cast_immediate( + &self, + src: ImmTy<'tcx, M::PointerTag>, + dest_layout: TyLayout<'tcx>, + ) -> InterpResult<'tcx, Immediate> { + if self.type_is_fat_ptr(src.layout.ty) { + return 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 + Ok(*src) + } + // slices and trait objects to thin pointers (dropping the metadata) + (Immediate::ScalarPair(data, _), false) => { + Ok(data.into()) + } + }; + } 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 Ok(Scalar::from_uint(discr.val, dest_layout.size).into()); + } + } + layout::Variants::Multiple { .. } => {}, + } + + return Ok(self.cast_scalar(src.to_scalar()?, src.layout, dest_layout)?.into()); + } + } + fn cast_scalar( &self, val: Scalar, diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index e64a474b4ca71..4742d53d0ba4a 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -32,6 +32,20 @@ pub enum Immediate { ScalarPair(ScalarMaybeUndef, ScalarMaybeUndef), } +impl From> for Immediate { + #[inline(always)] + fn from(val: ScalarMaybeUndef) -> Self { + Immediate::Scalar(val) + } +} + +impl From> for Immediate { + #[inline(always)] + fn from(val: Scalar) -> Self { + Immediate::Scalar(val.into()) + } +} + impl<'tcx, Tag> Immediate { #[inline] pub fn from_scalar(val: Scalar) -> Self { From b318bcfa784cead43a8b5aa553dcc4999e46b32e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 24 Jul 2019 20:05:53 +0200 Subject: [PATCH 04/13] refactor cast_immediate to dispatch on the type first, and on the value second --- src/librustc_mir/interpret/cast.rs | 110 ++++++++++++----------------- 1 file changed, 46 insertions(+), 64 deletions(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 7e752e2edc4a4..4758e7ff170bd 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -14,15 +14,6 @@ use rustc::mir::CastKind; 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>, @@ -99,68 +90,59 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { src: ImmTy<'tcx, M::PointerTag>, dest_layout: TyLayout<'tcx>, ) -> InterpResult<'tcx, Immediate> { - if self.type_is_fat_ptr(src.layout.ty) { - return 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 - Ok(*src) - } - // slices and trait objects to thin pointers (dropping the metadata) - (Immediate::ScalarPair(data, _), false) => { - Ok(data.into()) - } - }; - } 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 Ok(Scalar::from_uint(discr.val, dest_layout.size).into()); - } - } - layout::Variants::Multiple { .. } => {}, - } - - return Ok(self.cast_scalar(src.to_scalar()?, src.layout, dest_layout)?.into()); - } - } - - fn cast_scalar( - &self, - val: Scalar, - src_layout: TyLayout<'tcx>, - dest_layout: TyLayout<'tcx>, - ) -> InterpResult<'tcx, Scalar> { 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_unsafe_ptr() || src.layout.ty.is_fn_ptr() || + src.layout.ty.is_region_ptr(), + "Unexpected cast from type {:?}", src.layout.ty + ) + } + + // Handle cast the metadata away from a fat pointer. + if dest_layout.size != src.layout.size { + assert_eq!(dest_layout.size, self.memory.pointer_size()); + return match *src { + Immediate::ScalarPair(data, _) => Ok(data.into()), + Immediate::Scalar(..) => + bug!( + "{:?} input to a fat-to-thin cast ({:?} -> {:?})", + *src, src.layout.ty, dest_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 all the rest. + let val = src.to_scalar()?; + Ok(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)?, + }.into()) } fn cast_from_int( From 780e1fc5df22d5b6971553048f1ad7dbc0bb41ec Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 24 Jul 2019 20:20:55 +0200 Subject: [PATCH 05/13] use From to convert scalars to immediates --- src/librustc_mir/interpret/operand.rs | 21 ++++++++------------- src/librustc_mir/interpret/terminator.rs | 4 ++-- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 4742d53d0ba4a..7b75627ee1400 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -47,11 +47,6 @@ impl From> for Immediate { } impl<'tcx, Tag> Immediate { - #[inline] - pub fn from_scalar(val: Scalar) -> Self { - Immediate::Scalar(ScalarMaybeUndef::Scalar(val)) - } - pub fn new_slice( val: Scalar, len: u64, @@ -196,7 +191,7 @@ impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag> { #[inline] pub fn from_scalar(val: Scalar, layout: TyLayout<'tcx>) -> Self { - ImmTy { imm: Immediate::from_scalar(val), layout } + ImmTy { imm: val.into(), layout } } #[inline] @@ -254,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, })), }; @@ -265,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, })) } @@ -368,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); @@ -378,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), @@ -415,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)?, } @@ -439,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()? }; @@ -570,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. diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index d4bc8f460e894..4282687dad0f7 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -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 From 26c55ec0505e1337780b1ee2bad58dc672714bb5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 24 Jul 2019 20:09:18 +0200 Subject: [PATCH 06/13] fix casts from fat pointers --- src/librustc_mir/interpret/cast.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 4758e7ff170bd..72def95de895d 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -111,9 +111,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) } - // Handle cast the metadata away from a fat pointer. - if dest_layout.size != src.layout.size { + // 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()); return match *src { Immediate::ScalarPair(data, _) => Ok(data.into()), Immediate::Scalar(..) => @@ -124,6 +128,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; } + // Handle casting reference to raw ptr or raw to other raw (might be a fat ptr). + if (src.layout.ty.is_region_ptr() || src.layout.ty.is_unsafe_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); + } + // Handle cast from a univariant (ZST) enum match src.layout.variants { layout::Variants::Single { index } => { From 7885fac7e904568d58eae4ef34239a3c41241aa8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 25 Jul 2019 00:06:47 +0200 Subject: [PATCH 07/13] improve error when CTFE does ptr-int-cast; update tests --- src/librustc_mir/const_eval.rs | 13 +++++++++++-- src/librustc_mir/interpret/machine.rs | 6 +----- src/test/ui/consts/const-eval/const_raw_ptr_ops.rs | 4 ++-- .../ui/consts/const-eval/const_raw_ptr_ops.stderr | 14 +++++++++++--- src/test/ui/consts/const-eval/issue-52442.rs | 2 +- src/test/ui/consts/const-eval/issue-52442.stderr | 8 +++----- .../ui/consts/const-eval/match-test-ptr-null.rs | 5 ++--- .../consts/const-eval/match-test-ptr-null.stderr | 12 ++++++------ 8 files changed, 37 insertions(+), 27 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 813b7f7fa9c30..54cf56258f9f2 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -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,6 +397,15 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, ) } + 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, diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 4a0cc24cf1e95..a9794982fe50b 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -233,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, @@ -245,11 +244,8 @@ pub trait Machine<'mir, 'tcx>: Sized { }).into()) } - #[inline(always)] fn ptr_to_int( _mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer, - ) -> InterpResult<'tcx, u64> { - throw_unsup!(ReadPointerAsBytes) - } + ) -> InterpResult<'tcx, u64>; } diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs index 44266682a5c6c..9be1374f85d99 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs @@ -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 diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr index a12575b3975b6..2cba833a74896 100644 --- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr +++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr @@ -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 diff --git a/src/test/ui/consts/const-eval/issue-52442.rs b/src/test/ui/consts/const-eval/issue-52442.rs index 2989b200b2fc4..ea24578c7dd0c 100644 --- a/src/test/ui/consts/const-eval/issue-52442.rs +++ b/src/test/ui/consts/const-eval/issue-52442.rs @@ -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 } diff --git a/src/test/ui/consts/const-eval/issue-52442.stderr b/src/test/ui/consts/const-eval/issue-52442.stderr index 88c94d917fe0e..5bd4979bdb33c 100644 --- a/src/test/ui/consts/const-eval/issue-52442.stderr +++ b/src/test/ui/consts/const-eval/issue-52442.stderr @@ -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 diff --git a/src/test/ui/consts/const-eval/match-test-ptr-null.rs b/src/test/ui/consts/const-eval/match-test-ptr-null.rs index 50757afaf5651..9c930221e73e3 100644 --- a/src/test/ui/consts/const-eval/match-test-ptr-null.rs +++ b/src/test/ui/consts/const-eval/match-test-ptr-null.rs @@ -1,3 +1,4 @@ + fn main() { // Make sure match uses the usual pointer comparison code path -- i.e., it should complain // that pointer comparison is disallowed, not that parts of a pointer are accessed as raw @@ -5,11 +6,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, } }]; diff --git a/src/test/ui/consts/const-eval/match-test-ptr-null.stderr b/src/test/ui/consts/const-eval/match-test-ptr-null.stderr index d8a3bac5ce689..9bb561f31ebb0 100644 --- a/src/test/ui/consts/const-eval/match-test-ptr-null.stderr +++ b/src/test/ui/consts/const-eval/match-test-ptr-null.stderr @@ -1,5 +1,5 @@ error[E0658]: casting pointers to integers in constants is unstable - --> $DIR/match-test-ptr-null.rs:6:15 + --> $DIR/match-test-ptr-null.rs:7:15 | LL | match &1 as *const i32 as usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,22 +8,22 @@ LL | match &1 as *const i32 as usize { = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable error[E0019]: constant contains unimplemented expression type - --> $DIR/match-test-ptr-null.rs:6:15 + --> $DIR/match-test-ptr-null.rs:7:15 | LL | match &1 as *const i32 as usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0019]: constant contains unimplemented expression type - --> $DIR/match-test-ptr-null.rs:10:13 + --> $DIR/match-test-ptr-null.rs:11:13 | LL | 0 => 42, | ^ error[E0080]: evaluation of constant value failed - --> $DIR/match-test-ptr-null.rs:10:13 + --> $DIR/match-test-ptr-null.rs:7: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 From 144e5e99b5854c15bb9908a61e38b23f66fb6b46 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 25 Jul 2019 00:22:05 +0200 Subject: [PATCH 08/13] get rid of some remaining type-based dispatching in cast code --- src/librustc_mir/interpret/cast.rs | 70 +++++++++++------------------- 1 file changed, 25 insertions(+), 45 deletions(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 72def95de895d..fb4329ee0e32a 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -7,7 +7,7 @@ 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; @@ -111,6 +111,19 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) } + // 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 @@ -118,8 +131,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { 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()); - return match *src { - Immediate::ScalarPair(data, _) => Ok(data.into()), + match *src { + Immediate::ScalarPair(data, _) => + return Ok(data.into()), Immediate::Scalar(..) => bug!( "{:?} input to a fat-to-thin cast ({:?} -> {:?})", @@ -128,8 +142,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; } - // Handle casting reference to raw ptr or raw to other raw (might be a fat ptr). - if (src.layout.ty.is_region_ptr() || src.layout.ty.is_unsafe_ptr()) && + // Handle casting any ptr to raw ptr (might be a fat ptr). + if (src.layout.ty.is_region_ptr() || src.layout.ty.is_unsafe_ptr() || src.layout.ty.is_fn_ptr()) && dest_layout.ty.is_unsafe_ptr() { // The only possible size-unequal case was handled above. @@ -137,25 +151,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return Ok(*src); } - // 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 all the rest. - let val = src.to_scalar()?; - Ok(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)?, - }.into()) + // 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,27 +237,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - fn cast_from_ptr( - &self, - ptr: Pointer, - src_layout: TyLayout<'tcx>, - dest_layout: TyLayout<'tcx>, - ) -> InterpResult<'tcx, Scalar> { - 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(); - let bits = self.force_bits(Scalar::Ptr(ptr), size)?; - self.cast_from_int(bits, src_layout, dest_layout) - } - _ => bug!("invalid MIR: ptr to {:?} cast", dest_layout.ty) - } - } - fn unsize_into_ptr( &mut self, src: OpTy<'tcx, M::PointerTag>, From 7b30612c9bf8731abeb42eff684ae15f46a0656d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 25 Jul 2019 01:02:41 +0200 Subject: [PATCH 09/13] add is_any_ptr type test; this also helps pacify tidy --- src/librustc/ty/sty.rs | 6 ++++++ src/librustc_mir/interpret/cast.rs | 6 ++---- src/librustc_mir/interpret/operator.rs | 2 +- src/test/ui/consts/const-eval/match-test-ptr-null.rs | 1 - 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 77b8ebba21669..14da3875cdd79 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -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`. #[inline] pub fn is_arc(&self) -> bool { diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index fb4329ee0e32a..edddbc8850063 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -105,8 +105,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { 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(), + src.layout.ty.is_any_ptr(), "Unexpected cast from type {:?}", src.layout.ty ) } @@ -143,8 +142,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } // Handle casting any ptr to raw ptr (might be a fat ptr). - if (src.layout.ty.is_region_ptr() || src.layout.ty.is_unsafe_ptr() || src.layout.ty.is_fn_ptr()) && - dest_layout.ty.is_unsafe_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); diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index 504bd0a67bc48..24bb712410089 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -302,7 +302,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { 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_unsafe_ptr() || left.layout.ty.is_fn_ptr() => { + _ 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(), diff --git a/src/test/ui/consts/const-eval/match-test-ptr-null.rs b/src/test/ui/consts/const-eval/match-test-ptr-null.rs index 9c930221e73e3..5b89b0262aca5 100644 --- a/src/test/ui/consts/const-eval/match-test-ptr-null.rs +++ b/src/test/ui/consts/const-eval/match-test-ptr-null.rs @@ -1,4 +1,3 @@ - fn main() { // Make sure match uses the usual pointer comparison code path -- i.e., it should complain // that pointer comparison is disallowed, not that parts of a pointer are accessed as raw From 5fa443ddee30bd2489d0368ee553c416ccc48a5b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 25 Jul 2019 09:08:00 +0200 Subject: [PATCH 10/13] trailing full stops Co-Authored-By: Mazdak Farrokhzad --- src/librustc_mir/interpret/cast.rs | 2 +- src/librustc_mir/interpret/operator.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index edddbc8850063..1dbf1d0940557 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -110,7 +110,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) } - // Handle cast from a univariant (ZST) enum + // Handle cast from a univariant (ZST) enum. match src.layout.variants { layout::Variants::Single { index } => { if let Some(discr) = diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index 24bb712410089..02dc3c01036d0 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -303,7 +303,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { 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`) + // 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: {:?} {:?} {:?}", From f06a27488011138062ee515a17494bce88088407 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 25 Jul 2019 09:11:53 +0200 Subject: [PATCH 11/13] bless all the things --- src/test/ui/consts/const-eval/match-test-ptr-null.stderr | 8 ++++---- src/test/ui/issues/issue-52023-array-size-pointer-cast.rs | 2 +- .../ui/issues/issue-52023-array-size-pointer-cast.stderr | 6 ++---- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/test/ui/consts/const-eval/match-test-ptr-null.stderr b/src/test/ui/consts/const-eval/match-test-ptr-null.stderr index 9bb561f31ebb0..3d34ac4266270 100644 --- a/src/test/ui/consts/const-eval/match-test-ptr-null.stderr +++ b/src/test/ui/consts/const-eval/match-test-ptr-null.stderr @@ -1,5 +1,5 @@ error[E0658]: casting pointers to integers in constants is unstable - --> $DIR/match-test-ptr-null.rs:7:15 + --> $DIR/match-test-ptr-null.rs:6:15 | LL | match &1 as *const i32 as usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,19 +8,19 @@ LL | match &1 as *const i32 as usize { = help: add `#![feature(const_raw_ptr_to_usize_cast)]` to the crate attributes to enable error[E0019]: constant contains unimplemented expression type - --> $DIR/match-test-ptr-null.rs:7:15 + --> $DIR/match-test-ptr-null.rs:6:15 | LL | match &1 as *const i32 as usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0019]: constant contains unimplemented expression type - --> $DIR/match-test-ptr-null.rs:11:13 + --> $DIR/match-test-ptr-null.rs:10:13 | LL | 0 => 42, | ^ error[E0080]: evaluation of constant value failed - --> $DIR/match-test-ptr-null.rs:7:15 + --> $DIR/match-test-ptr-null.rs:6:15 | LL | match &1 as *const i32 as usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants diff --git a/src/test/ui/issues/issue-52023-array-size-pointer-cast.rs b/src/test/ui/issues/issue-52023-array-size-pointer-cast.rs index 63f1128f10642..d12b483ba4473 100644 --- a/src/test/ui/issues/issue-52023-array-size-pointer-cast.rs +++ b/src/test/ui/issues/issue-52023-array-size-pointer-cast.rs @@ -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 } diff --git a/src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr b/src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr index 2db6f42405c17..68ee53754161c 100644 --- a/src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr +++ b/src/test/ui/issues/issue-52023-array-size-pointer-cast.stderr @@ -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 From 0f97583e68f26eb1a1957886ea1fa8fa17288b92 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 25 Jul 2019 10:47:11 +0200 Subject: [PATCH 12/13] const_prop no longer does ptr-to-int casts --- src/test/mir-opt/const_prop/reify_fn_ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/mir-opt/const_prop/reify_fn_ptr.rs b/src/test/mir-opt/const_prop/reify_fn_ptr.rs index 809eb19ade899..7e36b2a6b1b39 100644 --- a/src/test/mir-opt/const_prop/reify_fn_ptr.rs +++ b/src/test/mir-opt/const_prop/reify_fn_ptr.rs @@ -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 From b9db95edb1136de4230bb2e130c4e09b06f7f3a7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 1 Aug 2019 09:12:48 +0200 Subject: [PATCH 13/13] fix rebase fallout --- src/test/ui/consts/issue-51559.rs | 2 +- src/test/ui/consts/issue-51559.stderr | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/test/ui/consts/issue-51559.rs b/src/test/ui/consts/issue-51559.rs index 429947269385b..69f0d8df0aa4a 100644 --- a/src/test/ui/consts/issue-51559.rs +++ b/src/test/ui/consts/issue-51559.rs @@ -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() {} diff --git a/src/test/ui/consts/issue-51559.stderr b/src/test/ui/consts/issue-51559.stderr index 917c54ddaef1e..4d50ec818bce7 100644 --- a/src/test/ui/consts/issue-51559.stderr +++ b/src/test/ui/consts/issue-51559.stderr @@ -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`.