about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-11-27 10:35:00 +0000
committerbors <bors@rust-lang.org>2022-11-27 10:35:00 +0000
commitdf04d28163cc42e2c5b1072abe68460f904e42be (patch)
tree332ecf0df1e53bf06a2b9fe766dfa952f88fb828 /src
parent5ac7e08aaf10d2882c6addcf220872c9390ed91e (diff)
parent208bb933e7a6d8820646e3e367e2bf188d85e485 (diff)
Auto merge of #103917 - oli-obk:layout_math, r=RalfJung,lcnr
Various cleanups around scalar layout restrictions

Pulled out of https://github.com/rust-lang/rust/pull/103724
Diffstat (limited to 'src')
-rw-r--r--src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr13
-rw-r--r--src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr13
-rw-r--r--src/test/ui/consts/const-eval/ub-nonnull.rs9
-rw-r--r--src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr5
-rw-r--r--src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr5
-rw-r--r--src/test/ui/layout/valid_range_oob.rs15
-rw-r--r--src/test/ui/layout/valid_range_oob.stderr6
-rw-r--r--src/test/ui/lint/invalid_value.stderr69
8 files changed, 115 insertions, 20 deletions
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr b/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr
index dbd05b8f424..b24e0cc37aa 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr
@@ -65,6 +65,17 @@ LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
                14 00 00 00                                     │ ....
            }
 
-error: aborting due to 7 previous errors
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-nonnull.rs:50:1
+   |
+LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 8, align: 4) {
+               00 00 00 00 ╾─alloc26─╼                         │ ....╾──╼
+           }
+
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr b/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr
index 5a1ac09bd35..92b8d017c0b 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr
@@ -65,6 +65,17 @@ LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
                14 00 00 00                                     │ ....
            }
 
-error: aborting due to 7 previous errors
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-nonnull.rs:50:1
+   |
+LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 16, align: 8) {
+               00 00 00 00 00 00 00 00 ╾───────alloc26───────╼ │ ........╾──────╼
+           }
+
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs
index d22a99cd01e..49092582267 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.rs
+++ b/src/test/ui/consts/const-eval/ub-nonnull.rs
@@ -1,5 +1,5 @@
 // stderr-per-bitwidth
-#![feature(rustc_attrs)]
+#![feature(rustc_attrs, ptr_metadata)]
 #![allow(invalid_value)] // make sure we cannot allow away the errors tested here
 
 use std::mem;
@@ -47,4 +47,11 @@ struct RestrictedRange2(u32);
 const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
 //~^ ERROR it is undefined behavior to use this value
 
+const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
+//~^ ERROR it is undefined behavior to use this value
+    let x: &dyn Send = &42;
+    let meta = std::ptr::metadata(x);
+    mem::transmute((0_usize, meta))
+};
+
 fn main() {}
diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
index 63639729a2a..8b4d845b30e 100644
--- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
+++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
@@ -40,6 +40,11 @@ LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
    |                                          this code causes undefined behavior when executed
    |                                          help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
+note: in this struct field
+  --> $DIR/validate_uninhabited_zsts.rs:16:22
+   |
+LL |     pub struct Empty(Void);
+   |                      ^^^^
 note: enums with no inhabited variants have no valid value
   --> $DIR/validate_uninhabited_zsts.rs:13:5
    |
diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
index 63639729a2a..8b4d845b30e 100644
--- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
+++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
@@ -40,6 +40,11 @@ LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
    |                                          this code causes undefined behavior when executed
    |                                          help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
+note: in this struct field
+  --> $DIR/validate_uninhabited_zsts.rs:16:22
+   |
+LL |     pub struct Empty(Void);
+   |                      ^^^^
 note: enums with no inhabited variants have no valid value
   --> $DIR/validate_uninhabited_zsts.rs:13:5
    |
diff --git a/src/test/ui/layout/valid_range_oob.rs b/src/test/ui/layout/valid_range_oob.rs
new file mode 100644
index 00000000000..74aa47fe405
--- /dev/null
+++ b/src/test/ui/layout/valid_range_oob.rs
@@ -0,0 +1,15 @@
+// failure-status: 101
+// normalize-stderr-test "note: .*\n\n" -> ""
+// normalize-stderr-test "thread 'rustc' panicked.*\n" -> ""
+// rustc-env:RUST_BACKTRACE=0
+
+#![feature(rustc_attrs)]
+
+#[rustc_layout_scalar_valid_range_end(257)]
+struct Foo(i8);
+
+// Need to do in a constant, as runtime codegen
+// does not compute the layout of `Foo` in check builds.
+const FOO: Foo = unsafe { Foo(1) };
+
+fn main() {}
diff --git a/src/test/ui/layout/valid_range_oob.stderr b/src/test/ui/layout/valid_range_oob.stderr
new file mode 100644
index 00000000000..7398f01643f
--- /dev/null
+++ b/src/test/ui/layout/valid_range_oob.stderr
@@ -0,0 +1,6 @@
+error: internal compiler error: unexpected panic
+
+query stack during panic:
+#0 [layout_of] computing layout of `Foo`
+#1 [eval_to_allocation_raw] const-evaluating + checking `FOO`
+end of query stack
diff --git a/src/test/ui/lint/invalid_value.stderr b/src/test/ui/lint/invalid_value.stderr
index 76afb765f0f..5370660d6c1 100644
--- a/src/test/ui/lint/invalid_value.stderr
+++ b/src/test/ui/lint/invalid_value.stderr
@@ -34,7 +34,8 @@ LL |         let _val: Wrap<&'static T> = mem::zeroed();
    |                                      this code causes undefined behavior when executed
    |                                      help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: references must be non-null (in this struct field)
+   = note: `Wrap<&T>` must be non-null
+note: because references must be non-null (in this struct field)
   --> $DIR/invalid_value.rs:17:18
    |
 LL | struct Wrap<T> { wrapped: T }
@@ -49,7 +50,8 @@ LL |         let _val: Wrap<&'static T> = mem::uninitialized();
    |                                      this code causes undefined behavior when executed
    |                                      help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: references must be non-null (in this struct field)
+   = note: `Wrap<&T>` must be non-null
+note: because references must be non-null (in this struct field)
   --> $DIR/invalid_value.rs:17:18
    |
 LL | struct Wrap<T> { wrapped: T }
@@ -97,7 +99,7 @@ LL |         let _val: (i32, !) = mem::uninitialized();
    |                              this code causes undefined behavior when executed
    |                              help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: integers must not be uninitialized
+   = note: integers must be initialized
 
 error: the type `Void` does not permit zero-initialization
   --> $DIR/invalid_value.rs:71:26
@@ -160,7 +162,8 @@ LL |         let _val: Ref = mem::zeroed();
    |                         this code causes undefined behavior when executed
    |                         help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: references must be non-null (in this struct field)
+   = note: `Ref` must be non-null
+note: because references must be non-null (in this struct field)
   --> $DIR/invalid_value.rs:14:12
    |
 LL | struct Ref(&'static i32);
@@ -175,7 +178,8 @@ LL |         let _val: Ref = mem::uninitialized();
    |                         this code causes undefined behavior when executed
    |                         help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: references must be non-null (in this struct field)
+   = note: `Ref` must be non-null
+note: because references must be non-null (in this struct field)
   --> $DIR/invalid_value.rs:14:12
    |
 LL | struct Ref(&'static i32);
@@ -212,7 +216,8 @@ LL |         let _val: Wrap<fn()> = mem::zeroed();
    |                                this code causes undefined behavior when executed
    |                                help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: function pointers must be non-null (in this struct field)
+   = note: `Wrap<fn()>` must be non-null
+note: because function pointers must be non-null (in this struct field)
   --> $DIR/invalid_value.rs:17:18
    |
 LL | struct Wrap<T> { wrapped: T }
@@ -227,7 +232,8 @@ LL |         let _val: Wrap<fn()> = mem::uninitialized();
    |                                this code causes undefined behavior when executed
    |                                help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: function pointers must be non-null (in this struct field)
+   = note: `Wrap<fn()>` must be non-null
+note: because function pointers must be non-null (in this struct field)
   --> $DIR/invalid_value.rs:17:18
    |
 LL | struct Wrap<T> { wrapped: T }
@@ -242,7 +248,8 @@ LL |         let _val: WrapEnum<fn()> = mem::zeroed();
    |                                    this code causes undefined behavior when executed
    |                                    help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: function pointers must be non-null (in this field of the only potentially inhabited enum variant)
+   = note: `WrapEnum<fn()>` must be non-null
+note: because function pointers must be non-null (in this field of the only potentially inhabited enum variant)
   --> $DIR/invalid_value.rs:18:28
    |
 LL | enum WrapEnum<T> { Wrapped(T) }
@@ -257,7 +264,8 @@ LL |         let _val: WrapEnum<fn()> = mem::uninitialized();
    |                                    this code causes undefined behavior when executed
    |                                    help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: function pointers must be non-null (in this field of the only potentially inhabited enum variant)
+   = note: `WrapEnum<fn()>` must be non-null
+note: because function pointers must be non-null (in this field of the only potentially inhabited enum variant)
   --> $DIR/invalid_value.rs:18:28
    |
 LL | enum WrapEnum<T> { Wrapped(T) }
@@ -272,7 +280,12 @@ LL |         let _val: Wrap<(RefPair, i32)> = mem::zeroed();
    |                                          this code causes undefined behavior when executed
    |                                          help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: references must be non-null (in this struct field)
+note: `RefPair` must be non-null (in this struct field)
+  --> $DIR/invalid_value.rs:17:18
+   |
+LL | struct Wrap<T> { wrapped: T }
+   |                  ^^^^^^^^^^
+note: because references must be non-null (in this struct field)
   --> $DIR/invalid_value.rs:15:16
    |
 LL | struct RefPair((&'static i32, i32));
@@ -287,7 +300,12 @@ LL |         let _val: Wrap<(RefPair, i32)> = mem::uninitialized();
    |                                          this code causes undefined behavior when executed
    |                                          help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: references must be non-null (in this struct field)
+note: `RefPair` must be non-null (in this struct field)
+  --> $DIR/invalid_value.rs:17:18
+   |
+LL | struct Wrap<T> { wrapped: T }
+   |                  ^^^^^^^^^^
+note: because references must be non-null (in this struct field)
   --> $DIR/invalid_value.rs:15:16
    |
 LL | struct RefPair((&'static i32, i32));
@@ -314,6 +332,7 @@ LL |         let _val: NonNull<i32> = mem::uninitialized();
    |                                  help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
    = note: `std::ptr::NonNull<i32>` must be non-null
+   = note: raw pointers must be initialized
 
 error: the type `(NonZeroU32, i32)` does not permit zero-initialization
   --> $DIR/invalid_value.rs:95:39
@@ -336,6 +355,7 @@ LL |         let _val: (NonZeroU32, i32) = mem::uninitialized();
    |                                       help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
    = note: `std::num::NonZeroU32` must be non-null
+   = note: integers must be initialized
 
 error: the type `*const dyn Send` does not permit zero-initialization
   --> $DIR/invalid_value.rs:98:37
@@ -420,7 +440,8 @@ LL |         let _val: OneFruitNonZero = mem::zeroed();
    |                                     this code causes undefined behavior when executed
    |                                     help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant)
+   = note: `OneFruitNonZero` must be non-null
+note: because `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant)
   --> $DIR/invalid_value.rs:39:12
    |
 LL |     Banana(NonZeroU32),
@@ -435,11 +456,13 @@ LL |         let _val: OneFruitNonZero = mem::uninitialized();
    |                                     this code causes undefined behavior when executed
    |                                     help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-note: `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant)
+   = note: `OneFruitNonZero` must be non-null
+note: because `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant)
   --> $DIR/invalid_value.rs:39:12
    |
 LL |     Banana(NonZeroU32),
    |            ^^^^^^^^^^
+   = note: integers must be initialized
 
 error: the type `bool` does not permit being left uninitialized
   --> $DIR/invalid_value.rs:112:26
@@ -461,6 +484,7 @@ LL |         let _val: Wrap<char> = mem::uninitialized();
    |                                this code causes undefined behavior when executed
    |                                help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
+   = note: `Wrap<char>` must be initialized inside its custom valid range
 note: characters must be a valid Unicode codepoint (in this struct field)
   --> $DIR/invalid_value.rs:17:18
    |
@@ -477,6 +501,11 @@ LL |         let _val: NonBig = mem::uninitialized();
    |                            help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
    = note: `NonBig` must be initialized inside its custom valid range
+note: integers must be initialized (in this struct field)
+  --> $DIR/invalid_value.rs:23:26
+   |
+LL | pub(crate) struct NonBig(u64);
+   |                          ^^^
 
 error: the type `Fruit` does not permit being left uninitialized
   --> $DIR/invalid_value.rs:121:27
@@ -513,7 +542,7 @@ LL |         let _val: i32 = mem::uninitialized();
    |                         this code causes undefined behavior when executed
    |                         help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: integers must not be uninitialized
+   = note: integers must be initialized
 
 error: the type `f32` does not permit being left uninitialized
   --> $DIR/invalid_value.rs:130:25
@@ -524,7 +553,7 @@ LL |         let _val: f32 = mem::uninitialized();
    |                         this code causes undefined behavior when executed
    |                         help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: floats must not be uninitialized
+   = note: floats must be initialized
 
 error: the type `*const ()` does not permit being left uninitialized
   --> $DIR/invalid_value.rs:133:31
@@ -535,7 +564,7 @@ LL |         let _val: *const () = mem::uninitialized();
    |                               this code causes undefined behavior when executed
    |                               help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: raw pointers must not be uninitialized
+   = note: raw pointers must be initialized
 
 error: the type `*const [()]` does not permit being left uninitialized
   --> $DIR/invalid_value.rs:136:33
@@ -546,7 +575,7 @@ LL |         let _val: *const [()] = mem::uninitialized();
    |                                 this code causes undefined behavior when executed
    |                                 help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: raw pointers must not be uninitialized
+   = note: raw pointers must be initialized
 
 error: the type `WrapAroundRange` does not permit being left uninitialized
   --> $DIR/invalid_value.rs:139:37
@@ -558,6 +587,11 @@ LL |         let _val: WrapAroundRange = mem::uninitialized();
    |                                     help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
    = note: `WrapAroundRange` must be initialized inside its custom valid range
+note: integers must be initialized (in this struct field)
+  --> $DIR/invalid_value.rs:49:35
+   |
+LL | pub(crate) struct WrapAroundRange(u8);
+   |                                   ^^
 
 error: the type `Result<i32, i32>` does not permit being left uninitialized
   --> $DIR/invalid_value.rs:144:38
@@ -628,6 +662,7 @@ LL |         let _val: NonNull<i32> = MaybeUninit::uninit().assume_init();
    |                                  help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
    = note: `std::ptr::NonNull<i32>` must be non-null
+   = note: raw pointers must be initialized
 
 error: the type `bool` does not permit being left uninitialized
   --> $DIR/invalid_value.rs:159:26