]> git.lizzy.rs Git - rust.git/commitdiff
Make const_eval_raw query return just an AllocId
authorRalf Jung <post@ralfj.de>
Tue, 6 Nov 2018 13:17:40 +0000 (14:17 +0100)
committerRalf Jung <post@ralfj.de>
Mon, 19 Nov 2018 21:42:46 +0000 (22:42 +0100)
18 files changed:
src/librustc/ich/impls_ty.rs
src/librustc/mir/interpret/error.rs
src/librustc/mir/interpret/mod.rs
src/librustc/mir/interpret/value.rs
src/librustc/ty/query/mod.rs
src/librustc_mir/const_eval.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/transform/const_prop.rs
src/test/ui/consts/const-err4.rs
src/test/ui/consts/const-err4.stderr
src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs
src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr
src/test/ui/consts/const-eval/union-const-eval-field.rs
src/test/ui/consts/const-eval/union-const-eval-field.stderr
src/test/ui/consts/const-eval/union-ice.rs
src/test/ui/consts/const-eval/union-ice.stderr

index 64685446e8fe14383a52e610b2fa96a5911eedde..679107160a6fc4a4785d6aea8639d401363cdd4a 100644 (file)
@@ -317,6 +317,10 @@ impl<'tcx> for enum mir::interpret::ConstValue<'tcx> [ mir::interpret::ConstValu
         ByRef(id, alloc, offset),
     }
 );
+impl_stable_hash_for!(struct ::mir::interpret::RawConst<'tcx> {
+    alloc_id,
+    ty,
+});
 
 impl_stable_hash_for! {
     impl<Tag> for struct mir::interpret::Pointer<Tag> {
index f1c95e0f00024a57204a55a8dfb0ce82b0947aa8..f1ac4b210583e6d935b6cc9983cf4284d798f171 100644 (file)
@@ -16,7 +16,7 @@
 use ty::layout::{Size, Align, LayoutError};
 use rustc_target::spec::abi::Abi;
 
-use super::{Pointer, InboundsCheck, ScalarMaybeUndef};
+use super::{RawConst, Pointer, InboundsCheck, ScalarMaybeUndef};
 
 use backtrace::Backtrace;
 
@@ -46,6 +46,7 @@ pub fn assert_reported(self) {
     }
 }
 
+pub type ConstEvalRawResult<'tcx> = Result<RawConst<'tcx>, ErrorHandled>;
 pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
 
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
index ec25431bd1ffe505ad1b40ea817cfe90a63af481..9369b6e56f1d018f3992c096ccc648da1dedcc62 100644 (file)
@@ -22,10 +22,10 @@ macro_rules! err {
 
 pub use self::error::{
     EvalError, EvalResult, EvalErrorKind, AssertMessage, ConstEvalErr, struct_error,
-    FrameInfo, ConstEvalResult, ErrorHandled,
+    FrameInfo, ConstEvalRawResult, ConstEvalResult, ErrorHandled,
 };
 
-pub use self::value::{Scalar, ConstValue, ScalarMaybeUndef};
+pub use self::value::{Scalar, ScalarMaybeUndef, RawConst, ConstValue};
 
 pub use self::allocation::{
     InboundsCheck, Allocation, AllocationExtra,
index 47c42c9431a210325e7e8ab9130268c22411ca83..4bcba9d54674e3f7f610b59ab4bfaa2c26170b01 100644 (file)
 
 use std::fmt;
 
-use ty::layout::{HasDataLayout, Size};
-use ty::subst::Substs;
-use hir::def_id::DefId;
+use crate::ty::{Ty, subst::Substs, layout::{HasDataLayout, Size}};
+use crate::hir::def_id::DefId;
 
 use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate};
 
+/// Represents the result of a raw const operation, pre-validation.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)]
+pub struct RawConst<'tcx> {
+    // the value lives here, at offset 0, and that allocation definitely is a `AllocType::Memory`
+    // (so you can use `AllocMap::unwrap_memory`).
+    pub alloc_id: AllocId,
+    pub ty: Ty<'tcx>,
+}
+
 /// Represents a constant value in Rust. Scalar and ScalarPair are optimizations which
 /// matches the LocalValue optimizations for easy conversions between Value and ConstValue.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
@@ -23,6 +31,7 @@ pub enum ConstValue<'tcx> {
     /// Never returned from the `const_eval` query, but the HIR contains these frequently in order
     /// to allow HIR creation to happen for everything before needing to be able to run constant
     /// evaluation
+    /// FIXME: The query should then return a type that does not even have this variant.
     Unevaluated(DefId, &'tcx Substs<'tcx>),
 
     /// Used only for types with layout::abi::Scalar ABI and ZSTs
index 89e7f4db502bb73138e73cdc1a23e0733d298dfe..22bd1e26ba3eea36d86e2e30da850cbd1c44b178 100644 (file)
@@ -27,7 +27,7 @@
 use middle::lib_features::LibFeatures;
 use middle::lang_items::{LanguageItems, LangItem};
 use middle::exported_symbols::{SymbolExportLevel, ExportedSymbol};
-use mir::interpret::ConstEvalResult;
+use mir::interpret::{ConstEvalRawResult, ConstEvalResult};
 use mir::mono::CodegenUnit;
 use mir;
 use mir::interpret::GlobalId;
         /// validation. Please add a comment to every use site explaining why using `const_eval`
         /// isn't sufficient
         [] fn const_eval_raw: const_eval_raw_dep_node(ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
-            -> ConstEvalResult<'tcx>,
+            -> ConstEvalRawResult<'tcx>,
 
         /// Results of evaluating const items or constants embedded in
         /// other items (such as enum variant explicit discriminants).
index 51046399ec2017bed8a78d95f84f155f6fc38bd1..4e727de535822dfd9af4a22d73a7201034f7fa96 100644 (file)
@@ -31,8 +31,8 @@
 use syntax::ast::Mutability;
 use syntax::source_map::{Span, DUMMY_SP};
 
-use interpret::{self,
-    PlaceTy, MemPlace, OpTy, Operand, Immediate, Scalar, ConstValue, Pointer,
+use crate::interpret::{self,
+    PlaceTy, MPlaceTy, MemPlace, OpTy, Operand, Immediate, Scalar, RawConst, ConstValue, Pointer,
     EvalResult, EvalError, EvalErrorKind, GlobalId, EvalContext, StackPopCleanup,
     Allocation, AllocId, MemoryKind,
     snapshot, RefTracking,
@@ -94,11 +94,13 @@ pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
     cid: GlobalId<'tcx>,
     mir: &'mir mir::Mir<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-) -> EvalResult<'tcx, OpTy<'tcx>> {
+) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
     let mut ecx = mk_borrowck_eval_cx(tcx, cid.instance, mir, DUMMY_SP).unwrap();
     eval_body_using_ecx(&mut ecx, cid, Some(mir), param_env)
 }
 
+// FIXME: This thing is a bad hack. We should get rid of it.  Ideally constants are always
+// in an allocation.
 pub fn op_to_const<'tcx>(
     ecx: &CompileTimeEvalContext<'_, '_, 'tcx>,
     op: OpTy<'tcx>,
@@ -150,7 +152,7 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
     cid: GlobalId<'tcx>,
     mir: Option<&'mir mir::Mir<'tcx>>,
     param_env: ty::ParamEnv<'tcx>,
-) -> (EvalResult<'tcx, OpTy<'tcx>>, CompileTimeEvalContext<'a, 'mir, 'tcx>) {
+) -> (EvalResult<'tcx, MPlaceTy<'tcx>>, CompileTimeEvalContext<'a, 'mir, 'tcx>) {
     // we start out with the best span we have
     // and try improving it down the road when more information is available
     let span = tcx.def_span(cid.instance.def_id());
@@ -166,7 +168,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
     cid: GlobalId<'tcx>,
     mir: Option<&'mir mir::Mir<'tcx>>,
     param_env: ty::ParamEnv<'tcx>,
-) -> EvalResult<'tcx, OpTy<'tcx>> {
+) -> EvalResult<'tcx, MPlaceTy<'tcx>> {
     debug!("eval_body_using_ecx: {:?}, {:?}", cid, param_env);
     let tcx = ecx.tcx.tcx;
     let mut mir = match mir {
@@ -206,7 +208,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
     ecx.memory.intern_static(ret.ptr.to_ptr()?.alloc_id, mutability)?;
 
     debug!("eval_body_using_ecx done: {:?}", *ret);
-    Ok(ret.into())
+    Ok(ret)
 }
 
 impl<'tcx> Into<EvalError<'tcx>> for ConstEvalError {
@@ -534,15 +536,17 @@ pub fn error_to_const_error<'a, 'mir, 'tcx>(
     ConstEvalErr { error: error.kind, stacktrace, span: ecx.tcx.span }
 }
 
-fn validate_const<'a, 'tcx>(
+fn validate_and_turn_into_const<'a, 'tcx>(
     tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
-    constant: &'tcx ty::Const<'tcx>,
+    constant: RawConst<'tcx>,
     key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
 ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
     let cid = key.value;
     let ecx = mk_eval_cx(tcx, cid.instance, key.param_env).unwrap();
     let val = (|| {
-        let op = ecx.const_to_op(constant)?;
+        let op = ecx.raw_const_to_mplace(constant)?.into();
+        // FIXME: Once the visitor infrastructure landed, change validation to
+        // work directly on `MPlaceTy`.
         let mut ref_tracking = RefTracking::new(op);
         while let Some((op, path)) = ref_tracking.todo.pop() {
             ecx.validate_operand(
@@ -552,7 +556,10 @@ fn validate_const<'a, 'tcx>(
                 /* const_mode */ true,
             )?;
         }
-        Ok(constant)
+        // Now that we validated, turn this into a proper constant
+        let def_id = cid.instance.def.def_id();
+        let normalize = tcx.is_static(def_id).is_none() && cid.promoted.is_none();
+        op_to_const(&ecx, op, normalize)
     })();
 
     val.map_err(|error| {
@@ -591,14 +598,14 @@ pub fn const_eval_provider<'a, 'tcx>(
         }
     }
     tcx.const_eval_raw(key).and_then(|val| {
-        validate_const(tcx, val, key)
+        validate_and_turn_into_const(tcx, val, key)
     })
 }
 
 pub fn const_eval_raw_provider<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
-) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
+) -> ::rustc::mir::interpret::ConstEvalRawResult<'tcx> {
     // Because the constant is computed twice (once per value of `Reveal`), we are at risk of
     // reporting the same error twice here. To resolve this, we check whether we can evaluate the
     // constant in the more restrictive `Reveal::UserFacing`, which most likely already was
@@ -648,16 +655,11 @@ pub fn const_eval_raw_provider<'a, 'tcx>(
     };
 
     let (res, ecx) = eval_body_and_ecx(tcx, cid, None, key.param_env);
-    res.and_then(|op| {
-        let normalize = tcx.is_static(def_id).is_none() && cid.promoted.is_none();
-        if !normalize {
-            // Sanity check: These must always be a MemPlace
-            match op.op {
-                Operand::Indirect(_) => { /* all is good */ },
-                Operand::Immediate(_) => bug!("const eval gave us an Immediate"),
-            }
-        }
-        op_to_const(&ecx, op, normalize)
+    res.and_then(|place| {
+        Ok(RawConst {
+            alloc_id: place.to_ptr().expect("we allocated this ptr!").alloc_id,
+            ty: place.layout.ty
+        })
     }).map_err(|error| {
         let err = error_to_const_error(&ecx, error);
         // errors in statics are always emitted as fatal errors
index c5a242f334c90ebedca7b1fc14bfcd7b150ace62..7dd42c6664968c3099af4f802e700e1dacda6ea3 100644 (file)
@@ -28,7 +28,7 @@
 use syntax::ast::Mutability;
 
 use super::{
-    Pointer, AllocId, Allocation, ConstValue, GlobalId, AllocationExtra, InboundsCheck,
+    Pointer, AllocId, Allocation, GlobalId, AllocationExtra, InboundsCheck,
     EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic,
     Machine, AllocMap, MayLeak, ScalarMaybeUndef, ErrorHandled,
 };
@@ -374,14 +374,11 @@ fn get_static_alloc(
                 ErrorHandled::Reported => EvalErrorKind::ReferencedConstant.into(),
                 ErrorHandled::TooGeneric => EvalErrorKind::TooGeneric.into(),
             }
-        }).map(|const_val| {
-            if let ConstValue::ByRef(_, allocation, _) = const_val.val {
-                // We got tcx memory. Let the machine figure out whether and how to
-                // turn that into memory with the right pointer tag.
-                M::adjust_static_allocation(allocation)
-            } else {
-                bug!("Matching on non-ByRef static")
-            }
+        }).map(|raw_const| {
+            let allocation = tcx.alloc_map.lock().unwrap_memory(raw_const.alloc_id);
+            // We got tcx memory. Let the machine figure out whether and how to
+            // turn that into memory with the right pointer tag.
+            M::adjust_static_allocation(allocation)
         })
     }
 
index b7910ad3bce9ed1adf8ece1a301320b9131c4942..16f1e487f59a1e40522c0b94e53b0053bb7ed0cb 100644 (file)
@@ -536,7 +536,8 @@ pub(super) fn eval_operands(
     }
 
     // Also used e.g. when miri runs into a constant.
-    pub(super) fn const_value_to_op(
+    // FIXME: Can we avoid converting with ConstValue and Const?  We should be using RawConst.
+    fn const_value_to_op(
         &self,
         val: ConstValue<'tcx>,
     ) -> EvalResult<'tcx, Operand<M::PointerTag>> {
index fa76eeb2fedd580a99233cd760233f4100bc28c2..104d66f7bde21c555e934d4c7b0bd4ac93f3f61d 100644 (file)
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx};
 
-use rustc::mir::interpret::{
-    GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic
-};
 use super::{
+    GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic,
     EvalContext, Machine, AllocMap, AllocationExtra,
-    Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind
+    RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind
 };
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
@@ -981,6 +979,19 @@ pub fn place_to_op(
         Ok(OpTy { op, layout: place.layout })
     }
 
+    pub fn raw_const_to_mplace(
+        &self,
+        raw: RawConst<'tcx>,
+    ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
+        // This must be an allocation in `tcx`
+        assert!(self.tcx.alloc_map.lock().get(raw.alloc_id).is_some());
+        let layout = self.layout_of(raw.ty)?;
+        Ok(MPlaceTy::from_aligned_ptr(
+            Pointer::new(raw.alloc_id, Size::ZERO).with_default_tag(),
+            layout,
+        ))
+    }
+
     /// Turn a place with a `dyn Trait` type into a place with the actual dynamic type.
     /// Also return some more information so drop doesn't have to run the same code twice.
     pub(super) fn unpack_dyn_trait(&self, mplace: MPlaceTy<'tcx, M::PointerTag>)
index 885d70dc4304dee3e3cd02c3118df7555aab58b6..6b8233c941e8bb90fb4e43bb76e4c73142016ca9 100644 (file)
@@ -309,7 +309,7 @@ fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option
                     eval_promoted(this.tcx, cid, this.mir, this.param_env)
                 })?;
                 trace!("evaluated promoted {:?} to {:?}", promoted, res);
-                Some((res, source_info.span))
+                Some((res.into(), source_info.span))
             },
             _ => None,
         }
index 0bbc254453cff6b20b91bc50e7be15ea7247c1f8..129177e9a1ae92b550c3f3e87e791797ef3a378e 100644 (file)
@@ -16,7 +16,7 @@ union Foo {
 
 enum Bar {
     Boo = [unsafe { Foo { b: () }.a }; 4][3],
-    //~^ ERROR evaluation of constant value failed
+    //~^ ERROR it is undefined behavior to use this value
 }
 
 fn main() {
index bb50f38062ee995349ad340781c69f73f408eac3..2f58712be28f671170beceae6c06b4e2d7635588 100644 (file)
@@ -1,8 +1,10 @@
-error[E0080]: evaluation of constant value failed
+error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-err4.rs:18:11
    |
 LL |     Boo = [unsafe { Foo { b: () }.a }; 4][3],
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempted to read undefined bytes
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain bits
+   |
+   = 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
 
 error: aborting due to previous error
 
index 23e1ab013ef3e991f773940cfb1908fd44ec51c3..cc5ddb4401644b8f7ad407070d43a9b4fea07d83 100644 (file)
@@ -37,7 +37,7 @@ fn main() {
     //~^ ERROR it is undefined behavior to use this value
 
     const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 };
-    //~^ ERROR any use of this value will cause an error
+    //~^ ERROR it is undefined behavior to use this value
 
     const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 };
     //~^ ERROR any use of this value will cause an error
@@ -52,7 +52,7 @@ fn main() {
     //~^ ERROR it is undefined behavior to use this value
 
     const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 };
-    //~^ ERROR any use of this value will cause an error
+    //~^ ERROR it is undefined behavior to use this value
 
     const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 };
     //~^ ERROR any use of this value will cause an error
index 0126743eedecba9ced796711dfebdbad95645730..60079193ee8e4917b03a5b274fea899fed0337fd 100644 (file)
@@ -40,11 +40,13 @@ LL |     const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uin
    |
    = 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
 
-error: any use of this value will cause an error
+error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:39:5
    |
 LL |     const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempted to read undefined bytes
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain bits
+   |
+   = 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
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:42:5
@@ -78,11 +80,13 @@ LL |     const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int
    |
    = 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
 
-error: any use of this value will cause an error
+error[E0080]: it is undefined behavior to use this value
   --> $DIR/const-pointer-values-in-various-types.rs:54:5
    |
 LL |     const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempted to read undefined bytes
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain bits
+   |
+   = 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
 
 error: any use of this value will cause an error
   --> $DIR/const-pointer-values-in-various-types.rs:57:5
index c0bfbc17629fc3cfcb0f6a665e0c7078446b26a2..2bdad3af889dcf0f3a1bb409c959dc5d1e382b33 100644 (file)
@@ -34,7 +34,8 @@ const fn read_field2() -> Field2 {
 }
 
 const fn read_field3() -> Field3 {
-    const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR any use of this value
+    const FIELD3: Field3 = unsafe { UNION.field3 };
+    //~^ ERROR it is undefined behavior to use this value
     FIELD3
 }
 
index 565cd916ffcb110244724ffd24d96b31e5dbd1e0..035a95a14c831ebcefe9c6579b5bd53b3e113b63 100644 (file)
@@ -1,10 +1,11 @@
-error: any use of this value will cause an error
+error[E0080]: it is undefined behavior to use this value
   --> $DIR/union-const-eval-field.rs:37:5
    |
-LL |     const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR any use of this value
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempted to read undefined bytes
+LL |     const FIELD3: Field3 = unsafe { UNION.field3 };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain bits
    |
-   = note: #[deny(const_err)] on by default
+   = 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
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0080`.
index 0e4f1e09171de97213808d5929a62416d84a205e..6bd63472b212a287805c5426772825c2c8f21c70 100644 (file)
@@ -20,7 +20,7 @@ union DummyUnion {
 
 const UNION: DummyUnion = DummyUnion { field1: 1065353216 };
 
-const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR will cause an error
+const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR it is undefined behavior to use this value
 
 const FIELD_PATH: Struct = Struct { //~ ERROR it is undefined behavior to use this value
     a: 42,
index 98c2c1472aae016c6005ee0760b8167e1ad82e0b..a6b49e0cda3a317bc47433f90438943d9f3bc63b 100644 (file)
@@ -1,10 +1,10 @@
-error: any use of this value will cause an error
+error[E0080]: it is undefined behavior to use this value
   --> $DIR/union-ice.rs:23:1
    |
-LL | const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR will cause an error
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempted to read undefined bytes
+LL | const FIELD3: Field3 = unsafe { UNION.field3 }; //~ ERROR it is undefined behavior to use this value
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected initialized plain bits
    |
-   = note: #[deny(const_err)] on by default
+   = 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
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/union-ice.rs:25:1