]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #74124 - ehuss:fix-doc-dry-run-up-to-date, r=Mark-Simulacrum
authorbors <bors@rust-lang.org>
Wed, 8 Jul 2020 09:47:41 +0000 (09:47 +0000)
committerbors <bors@rust-lang.org>
Wed, 8 Jul 2020 09:47:41 +0000 (09:47 +0000)
Fix occasional bootstrap panic in docs.

I am occasionally running into this panic when running `x.py`:

> thread 'main' panicked at 'source "/Users/eric/Proj/rust/rust/build/x86_64-apple-darwin/md-doc/unstable-book" failed to get metadata: No such file or directory (os error 2)', src/build_helper/lib.rs:173:19

I have not been able to figure out the exact sequence of commands that leads to this error (I tried for quite a while to reproduce it). I think it may involve updating my tree, but I am uncertain.  An artificial way to trigger it is to build the documentation, and then delete the `md-doc` directory manually.

The cause is that bootstrap does a "dry run" before every command, and in this case `up_to_date` panics because the destination exists (`build/x86_64-apple-darwin/doc/unstable-book/index.html `) but the source does not (`build/x86_64-apple-darwin/md-doc/unstable-book`).

I am uncertain if it is important that the last line `builder.run(…)` needs to be called during the dry run. This patch seems to fix the issue, though.

src/librustc_error_codes/error_codes/E0432.md
src/librustc_mir/interpret/validity.rs
src/librustc_mir/interpret/visitor.rs
src/libstd/sys/unix/args.rs
src/libstd/sys/unix/stack_overflow.rs
src/libstd/sys/unix/thread.rs
src/test/ui/consts/const-eval/double_check2.stderr
src/test/ui/consts/const-eval/ub-enum.stderr
src/test/ui/consts/const-eval/union-ub.rs
src/test/ui/consts/const-eval/union-ub.stderr

index b562a85b785ff37ec3bb5e3756cd191e83a7d4ca..a6e2acac5d2952368bd6b06d11b38be7a6a22588 100644 (file)
@@ -6,14 +6,20 @@ Erroneous code example:
 use something::Foo; // error: unresolved import `something::Foo`.
 ```
 
-Paths in `use` statements are relative to the crate root. To import items
-relative to the current and parent modules, use the `self::` and `super::`
-prefixes, respectively. Also verify that you didn't misspell the import
-name and that the import exists in the module from where you tried to
-import it. Example:
+In Rust 2015, paths in `use` statements are relative to the crate root. To
+import items relative to the current and parent modules, use the `self::` and
+`super::` prefixes, respectively.
+
+In Rust 2018, paths in `use` statements are relative to the current module
+unless they begin with the name of a crate or a literal `crate::`, in which
+case they start from the crate root. As in Rust 2015 code, the `self::` and
+`super::` prefixes refer to the current and parent modules respectively.
+
+Also verify that you didn't misspell the import name and that the import exists
+in the module from where you tried to import it. Example:
 
 ```
-use self::something::Foo; // ok!
+use self::something::Foo; // Ok.
 
 mod something {
     pub struct Foo;
@@ -21,12 +27,21 @@ mod something {
 # fn main() {}
 ```
 
-Or, if you tried to use a module from an external crate, you may have missed
-the `extern crate` declaration (which is usually placed in the crate root):
+If you tried to use a module from an external crate and are using Rust 2015,
+you may have missed the `extern crate` declaration (which is usually placed in
+the crate root):
 
-```
-extern crate core; // Required to use the `core` crate
+```edition2015
+extern crate core; // Required to use the `core` crate in Rust 2015.
 
 use core::any;
 # fn main() {}
 ```
+
+In Rust 2018 the `extern crate` declaration is not required and you can instead
+just `use` it:
+
+```edition2018
+use core::any; // No extern crate required in Rust 2018.
+# fn main() {}
+```
index 3bb9ba37120582fda0f770298e2daa4ba3c84c98..ab836595a7acc57e39f6ebc5bc8aba4386212bad 100644 (file)
@@ -276,19 +276,21 @@ fn aggregate_field_path_elem(&mut self, layout: TyAndLayout<'tcx>, field: usize)
         }
     }
 
-    fn visit_elem(
+    fn with_elem<R>(
         &mut self,
-        new_op: OpTy<'tcx, M::PointerTag>,
         elem: PathElem,
-    ) -> InterpResult<'tcx> {
+        f: impl FnOnce(&mut Self) -> InterpResult<'tcx, R>,
+    ) -> InterpResult<'tcx, R> {
         // Remember the old state
         let path_len = self.path.len();
-        // Perform operation
+        // Record new element
         self.path.push(elem);
-        self.visit_value(new_op)?;
+        // Perform operation
+        let r = f(self)?;
         // Undo changes
         self.path.truncate(path_len);
-        Ok(())
+        // Done
+        Ok(r)
     }
 
     fn check_wide_ptr_meta(
@@ -366,7 +368,7 @@ fn check_safe_pointer(
         let place = try_validation!(
             self.ecx.ref_to_mplace(value),
             self.path,
-            err_ub!(InvalidUninitBytes { .. }) => { "uninitialized {}", kind },
+            err_ub!(InvalidUninitBytes(None)) => { "uninitialized {}", kind },
         );
         if place.layout.is_unsized() {
             self.check_wide_ptr_meta(place.meta, place.layout)?;
@@ -477,7 +479,8 @@ fn try_visit_primitive(
                 try_validation!(
                     value.to_bool(),
                     self.path,
-                    err_ub!(InvalidBool(..)) => { "{}", value } expected { "a boolean" },
+                    err_ub!(InvalidBool(..)) | err_ub!(InvalidUninitBytes(None)) =>
+                        { "{}", value } expected { "a boolean" },
                 );
                 Ok(true)
             }
@@ -486,7 +489,8 @@ fn try_visit_primitive(
                 try_validation!(
                     value.to_char(),
                     self.path,
-                    err_ub!(InvalidChar(..)) => { "{}", value } expected { "a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)" },
+                    err_ub!(InvalidChar(..)) | err_ub!(InvalidUninitBytes(None)) =>
+                        { "{}", value } expected { "a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)" },
                 );
                 Ok(true)
             }
@@ -515,7 +519,7 @@ fn try_visit_primitive(
                 let place = try_validation!(
                     self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?),
                     self.path,
-                    err_ub!(InvalidUninitBytes { .. } ) => { "uninitialized raw pointer" },
+                    err_ub!(InvalidUninitBytes(None)) => { "uninitialized raw pointer" },
                 );
                 if place.layout.is_unsized() {
                     self.check_wide_ptr_meta(place.meta, place.layout)?;
@@ -537,6 +541,7 @@ fn try_visit_primitive(
                     self.path,
                     err_ub!(DanglingIntPointer(..)) |
                     err_ub!(InvalidFunctionPointer(..)) |
+                    err_ub!(InvalidUninitBytes(None)) |
                     err_unsup!(ReadBytesAsPointer) =>
                         { "{}", value } expected { "a function pointer" },
                 );
@@ -593,7 +598,7 @@ fn visit_scalar(
         let value = try_validation!(
             value.not_undef(),
             self.path,
-            err_ub!(InvalidUninitBytes { .. }) => { "{}", value }
+            err_ub!(InvalidUninitBytes(None)) => { "{}", value }
                 expected { "something {}", wrapping_range_format(valid_range, max_hi) },
         );
         let bits = match value.to_bits_or_ptr(op.layout.size, self.ecx) {
@@ -646,6 +651,25 @@ fn ecx(&self) -> &InterpCx<'mir, 'tcx, M> {
         &self.ecx
     }
 
+    fn read_discriminant(
+        &mut self,
+        op: OpTy<'tcx, M::PointerTag>,
+    ) -> InterpResult<'tcx, VariantIdx> {
+        self.with_elem(PathElem::EnumTag, move |this| {
+            Ok(try_validation!(
+                this.ecx.read_discriminant(op),
+                this.path,
+                err_ub!(InvalidTag(val)) =>
+                    { "{}", val } expected { "a valid enum tag" },
+                err_ub!(InvalidUninitBytes(None)) =>
+                    { "uninitialized bytes" } expected { "a valid enum tag" },
+                err_unsup!(ReadPointerAsBytes) =>
+                    { "a pointer" } expected { "a valid enum tag" },
+            )
+            .1)
+        })
+    }
+
     #[inline]
     fn visit_field(
         &mut self,
@@ -654,7 +678,7 @@ fn visit_field(
         new_op: OpTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx> {
         let elem = self.aggregate_field_path_elem(old_op.layout, field);
-        self.visit_elem(new_op, elem)
+        self.with_elem(elem, move |this| this.visit_value(new_op))
     }
 
     #[inline]
@@ -670,7 +694,7 @@ fn visit_variant(
             ty::Generator(..) => PathElem::GeneratorState(variant_id),
             _ => bug!("Unexpected type with variant: {:?}", old_op.layout.ty),
         };
-        self.visit_elem(new_op, name)
+        self.with_elem(name, move |this| this.visit_value(new_op))
     }
 
     #[inline(always)]
@@ -693,15 +717,8 @@ fn visit_value(&mut self, op: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> {
         // Sanity check: `builtin_deref` does not know any pointers that are not primitive.
         assert!(op.layout.ty.builtin_deref(true).is_none());
 
-        // Recursively walk the type. Translate some possible errors to something nicer.
-        try_validation!(
-            self.walk_value(op),
-            self.path,
-            err_ub!(InvalidTag(val)) =>
-                { "{}", val } expected { "a valid enum tag" },
-            err_unsup!(ReadPointerAsBytes) =>
-                { "a pointer" } expected { "plain (non-pointer) bytes" },
-        );
+        // Recursively walk the value at its type.
+        self.walk_value(op)?;
 
         // *After* all of this, check the ABI.  We need to check the ABI to handle
         // types like `NonNull` where the `Scalar` info is more restrictive than what
@@ -816,6 +833,10 @@ fn visit_aggregate(
 
                                 throw_validation_failure!(self.path, { "uninitialized bytes" })
                             }
+                            err_unsup!(ReadPointerAsBytes) => {
+                                throw_validation_failure!(self.path, { "a pointer" } expected { "plain (non-pointer) bytes" })
+                            }
+
                             // Propagate upwards (that will also check for unexpected errors).
                             _ => return Err(err),
                         }
index 903aa377a3d7ddd74c2f1b778a81417056cfa90e..6c53df40a7c9a6c732ea2753e7e1cab0d856778d 100644 (file)
@@ -125,6 +125,15 @@ pub trait $visitor_trait_name<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized {
             fn ecx(&$($mutability)? self)
                 -> &$($mutability)? InterpCx<'mir, 'tcx, M>;
 
+            /// `read_discriminant` can be hooked for better error messages.
+            #[inline(always)]
+            fn read_discriminant(
+                &mut self,
+                op: OpTy<'tcx, M::PointerTag>,
+            ) -> InterpResult<'tcx, VariantIdx> {
+                Ok(self.ecx().read_discriminant(op)?.1)
+            }
+
             // Recursive actions, ready to be overloaded.
             /// Visits the given value, dispatching as appropriate to more specialized visitors.
             #[inline(always)]
@@ -245,7 +254,7 @@ fn walk_value(&mut self, v: Self::V) -> InterpResult<'tcx>
                     // with *its* fields.
                     Variants::Multiple { .. } => {
                         let op = v.to_op(self.ecx())?;
-                        let idx = self.ecx().read_discriminant(op)?.1;
+                        let idx = self.read_discriminant(op)?;
                         let inner = v.project_downcast(self.ecx(), idx)?;
                         trace!("walk_value: variant layout: {:#?}", inner.layout());
                         // recurse with the inner type
index 773fab36be22127a7b62a367a7c98e3d4636e78d..5b712e202423236757516b6d5b9359447e9b9f93 100644 (file)
@@ -78,19 +78,20 @@ mod imp {
     use crate::marker::PhantomData;
     use crate::os::unix::prelude::*;
     use crate::ptr;
+    use crate::sync::atomic::{AtomicIsize, AtomicPtr, Ordering};
 
     use crate::sys_common::mutex::Mutex;
 
-    static mut ARGC: isize = 0;
-    static mut ARGV: *const *const u8 = ptr::null();
+    static ARGC: AtomicIsize = AtomicIsize::new(0);
+    static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
     // We never call `ENV_LOCK.init()`, so it is UB to attempt to
     // acquire this mutex reentrantly!
     static LOCK: Mutex = Mutex::new();
 
     unsafe fn really_init(argc: isize, argv: *const *const u8) {
         let _guard = LOCK.lock();
-        ARGC = argc;
-        ARGV = argv;
+        ARGC.store(argc, Ordering::Relaxed);
+        ARGV.store(argv as *mut _, Ordering::Relaxed);
     }
 
     #[inline(always)]
@@ -126,8 +127,8 @@ extern "C" fn init_wrapper(
 
     pub unsafe fn cleanup() {
         let _guard = LOCK.lock();
-        ARGC = 0;
-        ARGV = ptr::null();
+        ARGC.store(0, Ordering::Relaxed);
+        ARGV.store(ptr::null_mut(), Ordering::Relaxed);
     }
 
     pub fn args() -> Args {
@@ -137,9 +138,11 @@ pub fn args() -> Args {
     fn clone() -> Vec<OsString> {
         unsafe {
             let _guard = LOCK.lock();
-            (0..ARGC)
+            let argc = ARGC.load(Ordering::Relaxed);
+            let argv = ARGV.load(Ordering::Relaxed);
+            (0..argc)
                 .map(|i| {
-                    let cstr = CStr::from_ptr(*ARGV.offset(i) as *const libc::c_char);
+                    let cstr = CStr::from_ptr(*argv.offset(i) as *const libc::c_char);
                     OsStringExt::from_vec(cstr.to_bytes().to_vec())
                 })
                 .collect()
index 5e10357835056c59b2e5c5715f0c5552b9826c57..c74fc2b5903161d08e46a7181e9dc81149889294 100644 (file)
@@ -48,6 +48,7 @@ mod imp {
     use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE};
     use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV};
 
+    use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
     use crate::sys::unix::os::page_size;
     use crate::sys_common::thread_info;
 
@@ -113,8 +114,8 @@ unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize {
         }
     }
 
-    static mut MAIN_ALTSTACK: *mut libc::c_void = ptr::null_mut();
-    static mut NEED_ALTSTACK: bool = false;
+    static MAIN_ALTSTACK: AtomicPtr<libc::c_void> = AtomicPtr::new(ptr::null_mut());
+    static NEED_ALTSTACK: AtomicBool = AtomicBool::new(false);
 
     pub unsafe fn init() {
         let mut action: sigaction = mem::zeroed();
@@ -125,17 +126,17 @@ pub unsafe fn init() {
                 action.sa_flags = SA_SIGINFO | SA_ONSTACK;
                 action.sa_sigaction = signal_handler as sighandler_t;
                 sigaction(signal, &action, ptr::null_mut());
-                NEED_ALTSTACK = true;
+                NEED_ALTSTACK.store(true, Ordering::Relaxed);
             }
         }
 
         let handler = make_handler();
-        MAIN_ALTSTACK = handler._data;
+        MAIN_ALTSTACK.store(handler._data, Ordering::Relaxed);
         mem::forget(handler);
     }
 
     pub unsafe fn cleanup() {
-        Handler { _data: MAIN_ALTSTACK };
+        Handler { _data: MAIN_ALTSTACK.load(Ordering::Relaxed) };
     }
 
     unsafe fn get_stackp() -> *mut libc::c_void {
@@ -176,7 +177,7 @@ unsafe fn get_stack() -> libc::stack_t {
     }
 
     pub unsafe fn make_handler() -> Handler {
-        if !NEED_ALTSTACK {
+        if !NEED_ALTSTACK.load(Ordering::Relaxed) {
             return Handler::null();
         }
         let mut stack = mem::zeroed();
index 7b3d69dcaa015fe0ddf16603dd6424c38d0a9c2c..c1bda6b430e13d6fcf4c8212d0be386ad5ea4ff4 100644 (file)
@@ -246,10 +246,11 @@ pub mod guard {
     use libc::{MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE};
 
     use crate::ops::Range;
+    use crate::sync::atomic::{AtomicUsize, Ordering};
     use crate::sys::os;
 
     // This is initialized in init() and only read from after
-    static mut PAGE_SIZE: usize = 0;
+    static PAGE_SIZE: AtomicUsize = AtomicUsize::new(0);
 
     pub type Guard = Range<usize>;
 
@@ -275,7 +276,7 @@ unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
 
         let stackaddr = if libc::pthread_main_np() == 1 {
             // main thread
-            current_stack.ss_sp as usize - current_stack.ss_size + PAGE_SIZE
+            current_stack.ss_sp as usize - current_stack.ss_size + PAGE_SIZE.load(Ordering::Relaxed)
         } else {
             // new thread
             current_stack.ss_sp as usize - current_stack.ss_size
@@ -310,7 +311,8 @@ unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
 
     // Precondition: PAGE_SIZE is initialized.
     unsafe fn get_stack_start_aligned() -> Option<*mut libc::c_void> {
-        assert!(PAGE_SIZE != 0);
+        let page_size = PAGE_SIZE.load(Ordering::Relaxed);
+        assert!(page_size != 0);
         let stackaddr = get_stack_start()?;
 
         // Ensure stackaddr is page aligned! A parent process might
@@ -319,16 +321,17 @@ unsafe fn get_stack_start_aligned() -> Option<*mut libc::c_void> {
         // stackaddr < stackaddr + stacksize, so if stackaddr is not
         // page-aligned, calculate the fix such that stackaddr <
         // new_page_aligned_stackaddr < stackaddr + stacksize
-        let remainder = (stackaddr as usize) % PAGE_SIZE;
+        let remainder = (stackaddr as usize) % page_size;
         Some(if remainder == 0 {
             stackaddr
         } else {
-            ((stackaddr as usize) + PAGE_SIZE - remainder) as *mut libc::c_void
+            ((stackaddr as usize) + page_size - remainder) as *mut libc::c_void
         })
     }
 
     pub unsafe fn init() -> Option<Guard> {
-        PAGE_SIZE = os::page_size();
+        let page_size = os::page_size();
+        PAGE_SIZE.store(page_size, Ordering::Relaxed);
 
         let stackaddr = get_stack_start_aligned()?;
 
@@ -344,7 +347,7 @@ pub unsafe fn init() -> Option<Guard> {
             // faulting, so our handler can report "stack overflow", and
             // trust that the kernel's own stack guard will work.
             let stackaddr = stackaddr as usize;
-            Some(stackaddr - PAGE_SIZE..stackaddr)
+            Some(stackaddr - page_size..stackaddr)
         } else {
             // Reallocate the last page of the stack.
             // This ensures SIGBUS will be raised on
@@ -356,7 +359,7 @@ pub unsafe fn init() -> Option<Guard> {
             // no permissions at all. See issue #50313.
             let result = mmap(
                 stackaddr,
-                PAGE_SIZE,
+                page_size,
                 PROT_READ | PROT_WRITE,
                 MAP_PRIVATE | MAP_ANON | MAP_FIXED,
                 -1,
@@ -366,7 +369,7 @@ pub unsafe fn init() -> Option<Guard> {
                 panic!("failed to allocate a guard page");
             }
 
-            let result = mprotect(stackaddr, PAGE_SIZE, PROT_NONE);
+            let result = mprotect(stackaddr, page_size, PROT_NONE);
             if result != 0 {
                 panic!("failed to protect the guard page");
             }
@@ -374,14 +377,14 @@ pub unsafe fn init() -> Option<Guard> {
             let guardaddr = stackaddr as usize;
             let offset = if cfg!(target_os = "freebsd") { 2 } else { 1 };
 
-            Some(guardaddr..guardaddr + offset * PAGE_SIZE)
+            Some(guardaddr..guardaddr + offset * page_size)
         }
     }
 
     #[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "solaris"))]
     pub unsafe fn current() -> Option<Guard> {
         let stackaddr = get_stack_start()? as usize;
-        Some(stackaddr - PAGE_SIZE..stackaddr)
+        Some(stackaddr - PAGE_SIZE.load(Ordering::Relaxed)..stackaddr)
     }
 
     #[cfg(any(
@@ -413,7 +416,7 @@ pub unsafe fn current() -> Option<Guard> {
             ret = if cfg!(target_os = "freebsd") {
                 // FIXME does freebsd really fault *below* the guard addr?
                 let guardaddr = stackaddr - guardsize;
-                Some(guardaddr - PAGE_SIZE..guardaddr)
+                Some(guardaddr - PAGE_SIZE.load(Ordering::Relaxed)..guardaddr)
             } else if cfg!(target_os = "netbsd") {
                 Some(stackaddr - guardsize..stackaddr)
             } else if cfg!(all(target_os = "linux", target_env = "gnu")) {
index 93dd9a53ec99f95c3595d875e208dc49bf181652..513b71f0c6fdcf973572ad517ada9b1890c9a9b8 100644 (file)
@@ -5,7 +5,7 @@ LL | / static FOO: (&Foo, &Bar) = unsafe {(
 LL | |     Union { u8: &BAR }.foo,
 LL | |     Union { u8: &BAR }.bar,
 LL | | )};
-   | |___^ type validation failed: encountered 0x05 at .1.<deref>, but expected a valid enum tag
+   | |___^ type validation failed: encountered 0x05 at .1.<deref>.<enum-tag>, but expected a valid enum tag
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
index 1f7593c6db9b6b25f66bd958265cf92a7ff1ff12..217bfb628a018673d4590618f07a08f31e39c910 100644 (file)
@@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:24:1
    |
 LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x00000001, but expected a valid enum tag
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x00000001 at .<enum-tag>, but expected a valid enum tag
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
@@ -26,7 +26,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:42:1
    |
 LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x00000000, but expected a valid enum tag
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x00000000 at .<enum-tag>, but expected a valid enum tag
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
index 848826e6ef7f2f6d2cf67670c58a913d36cadff0..512359f5b1c38c82992c1009aba4ce054c836234 100644 (file)
@@ -2,6 +2,7 @@
 
 #[repr(C)]
 union DummyUnion {
+    unit: (),
     u8: u8,
     bool: bool,
 }
@@ -30,6 +31,8 @@ union Bar {
 // the value is not valid for bools
 const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool};
 //~^ ERROR it is undefined behavior to use this value
+const UNINIT_BOOL: bool = unsafe { DummyUnion { unit: () }.bool};
+//~^ ERROR it is undefined behavior to use this value
 
 // The value is not valid for any union variant, but that's fine
 // unions are just a convenient way to transmute bits around
index fd3e66765c61bf01cf57438dd9221deef514c970..e8869d0d76c1cf8c0d042db378f526f5b1b4c6a5 100644 (file)
@@ -1,11 +1,19 @@
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/union-ub.rs:31:1
+  --> $DIR/union-ub.rs:32:1
    |
 LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool};
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x2a, but expected a boolean
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
-error: aborting due to previous error
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/union-ub.rs:34:1
+   |
+LL | const UNINIT_BOOL: bool = unsafe { DummyUnion { unit: () }.bool};
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected a boolean
+   |
+   = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.