summaryrefslogtreecommitdiffstats
path: root/src/test/ui/unsafe
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/unsafe
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/test/ui/unsafe')
-rw-r--r--src/test/ui/unsafe/access_union_field.mir.stderr19
-rw-r--r--src/test/ui/unsafe/access_union_field.rs15
-rw-r--r--src/test/ui/unsafe/access_union_field.thir.stderr19
-rw-r--r--src/test/ui/unsafe/inline_asm.mir.stderr11
-rw-r--r--src/test/ui/unsafe/inline_asm.rs9
-rw-r--r--src/test/ui/unsafe/inline_asm.thir.stderr11
-rw-r--r--src/test/ui/unsafe/issue-3080.mir.stderr11
-rw-r--r--src/test/ui/unsafe/issue-3080.rs11
-rw-r--r--src/test/ui/unsafe/issue-3080.thir.stderr11
-rw-r--r--src/test/ui/unsafe/issue-45087-unreachable-unsafe.mir.stderr27
-rw-r--r--src/test/ui/unsafe/issue-45087-unreachable-unsafe.rs31
-rw-r--r--src/test/ui/unsafe/issue-45087-unreachable-unsafe.thir.stderr27
-rw-r--r--src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.mir.stderr35
-rw-r--r--src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.rs28
-rw-r--r--src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.thir.stderr35
-rw-r--r--src/test/ui/unsafe/issue-47412.mir.stderr19
-rw-r--r--src/test/ui/unsafe/issue-47412.rs24
-rw-r--r--src/test/ui/unsafe/issue-47412.thir.stderr19
-rw-r--r--src/test/ui/unsafe/issue-85435-unsafe-op-in-let-under-unsafe-under-closure.rs27
-rw-r--r--src/test/ui/unsafe/issue-87414-query-cycle.rs15
-rw-r--r--src/test/ui/unsafe/ranged_ints.mir.stderr11
-rw-r--r--src/test/ui/unsafe/ranged_ints.rs11
-rw-r--r--src/test/ui/unsafe/ranged_ints.thir.stderr11
-rw-r--r--src/test/ui/unsafe/ranged_ints2.mirunsafeck.stderr11
-rw-r--r--src/test/ui/unsafe/ranged_ints2.rs12
-rw-r--r--src/test/ui/unsafe/ranged_ints2.thirunsafeck.stderr11
-rw-r--r--src/test/ui/unsafe/ranged_ints2_const.mirunsafeck.stderr39
-rw-r--r--src/test/ui/unsafe/ranged_ints2_const.rs29
-rw-r--r--src/test/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr39
-rw-r--r--src/test/ui/unsafe/ranged_ints3.mirunsafeck.stderr11
-rw-r--r--src/test/ui/unsafe/ranged_ints3.rs14
-rw-r--r--src/test/ui/unsafe/ranged_ints3.thirunsafeck.stderr11
-rw-r--r--src/test/ui/unsafe/ranged_ints3_const.mirunsafeck.stderr30
-rw-r--r--src/test/ui/unsafe/ranged_ints3_const.rs24
-rw-r--r--src/test/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr30
-rw-r--r--src/test/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr19
-rw-r--r--src/test/ui/unsafe/ranged_ints3_match.rs22
-rw-r--r--src/test/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr19
-rw-r--r--src/test/ui/unsafe/ranged_ints4.mirunsafeck.stderr11
-rw-r--r--src/test/ui/unsafe/ranged_ints4.rs12
-rw-r--r--src/test/ui/unsafe/ranged_ints4.thirunsafeck.stderr11
-rw-r--r--src/test/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr11
-rw-r--r--src/test/ui/unsafe/ranged_ints4_const.rs22
-rw-r--r--src/test/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr11
-rw-r--r--src/test/ui/unsafe/ranged_ints_const.mir.stderr11
-rw-r--r--src/test/ui/unsafe/ranged_ints_const.rs14
-rw-r--r--src/test/ui/unsafe/ranged_ints_const.thir.stderr11
-rw-r--r--src/test/ui/unsafe/ranged_ints_macro.rs19
-rw-r--r--src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr134
-rw-r--r--src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs87
-rw-r--r--src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr122
-rw-r--r--src/test/ui/unsafe/union-assignop.mirunsafeck.stderr51
-rw-r--r--src/test/ui/unsafe/union-assignop.rs29
-rw-r--r--src/test/ui/unsafe/union-assignop.thirunsafeck.stderr51
-rw-r--r--src/test/ui/unsafe/union-modification.rs37
-rw-r--r--src/test/ui/unsafe/union.mir.stderr19
-rw-r--r--src/test/ui/unsafe/union.rs53
-rw-r--r--src/test/ui/unsafe/union.thir.stderr38
-rw-r--r--src/test/ui/unsafe/union_access_through_block.rs18
-rw-r--r--src/test/ui/unsafe/union_destructure.mir.stderr16
-rw-r--r--src/test/ui/unsafe/union_destructure.rs51
-rw-r--r--src/test/ui/unsafe/union_wild_or_wild.rs12
-rw-r--r--src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.mir.stderr20
-rw-r--r--src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs14
-rw-r--r--src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.thir.stderr20
-rw-r--r--src/test/ui/unsafe/unsafe-assign.mirunsafeck.stderr11
-rw-r--r--src/test/ui/unsafe/unsafe-assign.rs25
-rw-r--r--src/test/ui/unsafe/unsafe-assign.thirunsafeck.stderr11
-rw-r--r--src/test/ui/unsafe/unsafe-block-without-braces.rs6
-rw-r--r--src/test/ui/unsafe/unsafe-block-without-braces.stderr15
-rw-r--r--src/test/ui/unsafe/unsafe-borrow.mirunsafeck.stderr27
-rw-r--r--src/test/ui/unsafe/unsafe-borrow.rs56
-rw-r--r--src/test/ui/unsafe/unsafe-borrow.thirunsafeck.stderr27
-rw-r--r--src/test/ui/unsafe/unsafe-const-fn.mir.stderr11
-rw-r--r--src/test/ui/unsafe/unsafe-const-fn.rs15
-rw-r--r--src/test/ui/unsafe/unsafe-const-fn.thir.stderr11
-rw-r--r--src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.mir.stderr11
-rw-r--r--src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.rs10
-rw-r--r--src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.thir.stderr11
-rw-r--r--src/test/ui/unsafe/unsafe-fn-autoderef.rs23
-rw-r--r--src/test/ui/unsafe/unsafe-fn-autoderef.stderr11
-rw-r--r--src/test/ui/unsafe/unsafe-fn-called-from-safe.mir.stderr11
-rw-r--r--src/test/ui/unsafe/unsafe-fn-called-from-safe.rs10
-rw-r--r--src/test/ui/unsafe/unsafe-fn-called-from-safe.thir.stderr11
-rw-r--r--src/test/ui/unsafe/unsafe-fn-deref-ptr.mir.stderr11
-rw-r--r--src/test/ui/unsafe/unsafe-fn-deref-ptr.rs9
-rw-r--r--src/test/ui/unsafe/unsafe-fn-deref-ptr.thir.stderr11
-rw-r--r--src/test/ui/unsafe/unsafe-fn-used-as-value.mir.stderr11
-rw-r--r--src/test/ui/unsafe/unsafe-fn-used-as-value.rs11
-rw-r--r--src/test/ui/unsafe/unsafe-fn-used-as-value.thir.stderr11
-rw-r--r--src/test/ui/unsafe/unsafe-subtyping.rs11
-rw-r--r--src/test/ui/unsafe/unsafe-subtyping.stderr14
-rw-r--r--src/test/ui/unsafe/unsafe-trait-impl.rs14
-rw-r--r--src/test/ui/unsafe/unsafe-trait-impl.stderr17
-rw-r--r--src/test/ui/unsafe/unsafe-unstable-const-fn.mir.stderr11
-rw-r--r--src/test/ui/unsafe/unsafe-unstable-const-fn.rs14
-rw-r--r--src/test/ui/unsafe/unsafe-unstable-const-fn.thir.stderr11
97 files changed, 2132 insertions, 0 deletions
diff --git a/src/test/ui/unsafe/access_union_field.mir.stderr b/src/test/ui/unsafe/access_union_field.mir.stderr
new file mode 100644
index 000000000..98bc40777
--- /dev/null
+++ b/src/test/ui/unsafe/access_union_field.mir.stderr
@@ -0,0 +1,19 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/access_union_field.rs:13:13
+ |
+LL | let a = foo.bar;
+ | ^^^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/access_union_field.rs:14:13
+ |
+LL | let b = foo.baz;
+ | ^^^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/access_union_field.rs b/src/test/ui/unsafe/access_union_field.rs
new file mode 100644
index 000000000..5c4e695df
--- /dev/null
+++ b/src/test/ui/unsafe/access_union_field.rs
@@ -0,0 +1,15 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![allow(unused_variables)]
+
+union Foo {
+ bar: i8,
+ baz: u8,
+}
+
+fn main() {
+ let foo = Foo { bar: 5 };
+ let a = foo.bar; //~ ERROR access to union field is unsafe and requires unsafe function or block
+ let b = foo.baz; //~ ERROR access to union field is unsafe and requires unsafe function or block
+}
diff --git a/src/test/ui/unsafe/access_union_field.thir.stderr b/src/test/ui/unsafe/access_union_field.thir.stderr
new file mode 100644
index 000000000..98bc40777
--- /dev/null
+++ b/src/test/ui/unsafe/access_union_field.thir.stderr
@@ -0,0 +1,19 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/access_union_field.rs:13:13
+ |
+LL | let a = foo.bar;
+ | ^^^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/access_union_field.rs:14:13
+ |
+LL | let b = foo.baz;
+ | ^^^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/inline_asm.mir.stderr b/src/test/ui/unsafe/inline_asm.mir.stderr
new file mode 100644
index 000000000..633f1edb2
--- /dev/null
+++ b/src/test/ui/unsafe/inline_asm.mir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: use of inline assembly is unsafe and requires unsafe function or block
+ --> $DIR/inline_asm.rs:8:5
+ |
+LL | asm!("nop");
+ | ^^^^^^^^^^^ use of inline assembly
+ |
+ = note: inline assembly is entirely unchecked and can cause undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/inline_asm.rs b/src/test/ui/unsafe/inline_asm.rs
new file mode 100644
index 000000000..12c7efe4f
--- /dev/null
+++ b/src/test/ui/unsafe/inline_asm.rs
@@ -0,0 +1,9 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+// needs-asm-support
+
+use std::arch::asm;
+
+fn main() {
+ asm!("nop"); //~ ERROR use of inline assembly is unsafe and requires unsafe function or block
+}
diff --git a/src/test/ui/unsafe/inline_asm.thir.stderr b/src/test/ui/unsafe/inline_asm.thir.stderr
new file mode 100644
index 000000000..633f1edb2
--- /dev/null
+++ b/src/test/ui/unsafe/inline_asm.thir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: use of inline assembly is unsafe and requires unsafe function or block
+ --> $DIR/inline_asm.rs:8:5
+ |
+LL | asm!("nop");
+ | ^^^^^^^^^^^ use of inline assembly
+ |
+ = note: inline assembly is entirely unchecked and can cause undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/issue-3080.mir.stderr b/src/test/ui/unsafe/issue-3080.mir.stderr
new file mode 100644
index 000000000..f395c30b8
--- /dev/null
+++ b/src/test/ui/unsafe/issue-3080.mir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+ --> $DIR/issue-3080.rs:10:5
+ |
+LL | X(()).with();
+ | ^^^^^^^^^^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/issue-3080.rs b/src/test/ui/unsafe/issue-3080.rs
new file mode 100644
index 000000000..2b5269dda
--- /dev/null
+++ b/src/test/ui/unsafe/issue-3080.rs
@@ -0,0 +1,11 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+struct X(());
+impl X {
+ pub unsafe fn with(&self) { }
+}
+
+fn main() {
+ X(()).with(); //~ ERROR requires unsafe function or block
+}
diff --git a/src/test/ui/unsafe/issue-3080.thir.stderr b/src/test/ui/unsafe/issue-3080.thir.stderr
new file mode 100644
index 000000000..4d8acac61
--- /dev/null
+++ b/src/test/ui/unsafe/issue-3080.thir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function `X::with` is unsafe and requires unsafe function or block
+ --> $DIR/issue-3080.rs:10:5
+ |
+LL | X(()).with();
+ | ^^^^^^^^^^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/issue-45087-unreachable-unsafe.mir.stderr b/src/test/ui/unsafe/issue-45087-unreachable-unsafe.mir.stderr
new file mode 100644
index 000000000..e79609607
--- /dev/null
+++ b/src/test/ui/unsafe/issue-45087-unreachable-unsafe.mir.stderr
@@ -0,0 +1,27 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/issue-45087-unreachable-unsafe.rs:7:5
+ |
+LL | *(1 as *mut u32) = 42;
+ | ^^^^^^^^^^^^^^^^^^^^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/issue-45087-unreachable-unsafe.rs:17:5
+ |
+LL | *a = 1;
+ | ^^^^^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/issue-45087-unreachable-unsafe.rs:29:5
+ |
+LL | *b = 1;
+ | ^^^^^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/issue-45087-unreachable-unsafe.rs b/src/test/ui/unsafe/issue-45087-unreachable-unsafe.rs
new file mode 100644
index 000000000..3e3da667c
--- /dev/null
+++ b/src/test/ui/unsafe/issue-45087-unreachable-unsafe.rs
@@ -0,0 +1,31 @@
+// Verify that unreachable code undergoes unsafety checks.
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+fn main() {
+ return;
+ *(1 as *mut u32) = 42;
+ //~^ ERROR dereference of raw pointer is unsafe
+}
+
+fn panic() -> ! {
+ panic!();
+}
+
+fn f(a: *mut u32) {
+ panic();
+ *a = 1;
+ //~^ ERROR dereference of raw pointer is unsafe
+}
+
+enum Void {}
+
+fn uninhabited() -> Void {
+ panic!();
+}
+
+fn g(b: *mut u32) {
+ uninhabited();
+ *b = 1;
+ //~^ ERROR dereference of raw pointer is unsafe
+}
diff --git a/src/test/ui/unsafe/issue-45087-unreachable-unsafe.thir.stderr b/src/test/ui/unsafe/issue-45087-unreachable-unsafe.thir.stderr
new file mode 100644
index 000000000..e81adad45
--- /dev/null
+++ b/src/test/ui/unsafe/issue-45087-unreachable-unsafe.thir.stderr
@@ -0,0 +1,27 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/issue-45087-unreachable-unsafe.rs:7:5
+ |
+LL | *(1 as *mut u32) = 42;
+ | ^^^^^^^^^^^^^^^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/issue-45087-unreachable-unsafe.rs:17:5
+ |
+LL | *a = 1;
+ | ^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/issue-45087-unreachable-unsafe.rs:29:5
+ |
+LL | *b = 1;
+ | ^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.mir.stderr b/src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.mir.stderr
new file mode 100644
index 000000000..9e9cbcf33
--- /dev/null
+++ b/src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.mir.stderr
@@ -0,0 +1,35 @@
+error: unnecessary `unsafe` block
+ --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:10:13
+ |
+LL | unsafe {
+ | ------ because it's nested under this `unsafe` block
+LL | let f = |v: &mut Vec<_>| {
+LL | unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+ |
+note: the lint level is defined here
+ --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:4:8
+ |
+LL | #[deny(unused_unsafe)]
+ | ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+ --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:12:38
+ |
+LL | unsafe {
+ | ------ because it's nested under this `unsafe` block
+...
+LL | |w: &mut Vec<u32>| { unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+ --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:16:34
+ |
+LL | unsafe {
+ | ------ because it's nested under this `unsafe` block
+...
+LL | |x: &mut Vec<u32>| { unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.rs b/src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.rs
new file mode 100644
index 000000000..ac1cfd62a
--- /dev/null
+++ b/src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.rs
@@ -0,0 +1,28 @@
+// revisions: mir thir
+// [thir]compile-flags: -Zthir-unsafeck
+
+#[deny(unused_unsafe)]
+fn main() {
+ let mut v = Vec::<i32>::with_capacity(24);
+
+ unsafe {
+ let f = |v: &mut Vec<_>| {
+ unsafe { //~ ERROR unnecessary `unsafe`
+ v.set_len(24);
+ |w: &mut Vec<u32>| { unsafe { //~ ERROR unnecessary `unsafe`
+ w.set_len(32);
+ } };
+ }
+ |x: &mut Vec<u32>| { unsafe { //~ ERROR unnecessary `unsafe`
+ x.set_len(40);
+ } };
+ };
+
+ v.set_len(0);
+ f(&mut v);
+ }
+
+ |y: &mut Vec<u32>| { unsafe {
+ y.set_len(48);
+ } };
+}
diff --git a/src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.thir.stderr b/src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.thir.stderr
new file mode 100644
index 000000000..9e9cbcf33
--- /dev/null
+++ b/src/test/ui/unsafe/issue-45107-unnecessary-unsafe-in-closure.thir.stderr
@@ -0,0 +1,35 @@
+error: unnecessary `unsafe` block
+ --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:10:13
+ |
+LL | unsafe {
+ | ------ because it's nested under this `unsafe` block
+LL | let f = |v: &mut Vec<_>| {
+LL | unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+ |
+note: the lint level is defined here
+ --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:4:8
+ |
+LL | #[deny(unused_unsafe)]
+ | ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+ --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:12:38
+ |
+LL | unsafe {
+ | ------ because it's nested under this `unsafe` block
+...
+LL | |w: &mut Vec<u32>| { unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+ --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:16:34
+ |
+LL | unsafe {
+ | ------ because it's nested under this `unsafe` block
+...
+LL | |x: &mut Vec<u32>| { unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/unsafe/issue-47412.mir.stderr b/src/test/ui/unsafe/issue-47412.mir.stderr
new file mode 100644
index 000000000..305f482e8
--- /dev/null
+++ b/src/test/ui/unsafe/issue-47412.mir.stderr
@@ -0,0 +1,19 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/issue-47412.rs:14:11
+ |
+LL | match u.void {}
+ | ^^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/issue-47412.rs:20:11
+ |
+LL | match *ptr {}
+ | ^^^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/issue-47412.rs b/src/test/ui/unsafe/issue-47412.rs
new file mode 100644
index 000000000..df6d6e422
--- /dev/null
+++ b/src/test/ui/unsafe/issue-47412.rs
@@ -0,0 +1,24 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#[derive(Copy, Clone)]
+enum Void {}
+
+// Tests that we detect unsafe places (specifically, union fields and
+// raw pointer dereferences), even when they're matched on while having
+// an uninhabited type (equivalent to `std::intrinsics::unreachable()`).
+
+fn union_field() {
+ union Union { unit: (), void: Void }
+ let u = Union { unit: () };
+ match u.void {}
+ //~^ ERROR access to union field is unsafe
+}
+
+fn raw_ptr_deref() {
+ let ptr = std::ptr::null::<Void>();
+ match *ptr {}
+ //~^ ERROR dereference of raw pointer is unsafe
+}
+
+fn main() {}
diff --git a/src/test/ui/unsafe/issue-47412.thir.stderr b/src/test/ui/unsafe/issue-47412.thir.stderr
new file mode 100644
index 000000000..305f482e8
--- /dev/null
+++ b/src/test/ui/unsafe/issue-47412.thir.stderr
@@ -0,0 +1,19 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/issue-47412.rs:14:11
+ |
+LL | match u.void {}
+ | ^^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/issue-47412.rs:20:11
+ |
+LL | match *ptr {}
+ | ^^^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/issue-85435-unsafe-op-in-let-under-unsafe-under-closure.rs b/src/test/ui/unsafe/issue-85435-unsafe-op-in-let-under-unsafe-under-closure.rs
new file mode 100644
index 000000000..72f7b6747
--- /dev/null
+++ b/src/test/ui/unsafe/issue-85435-unsafe-op-in-let-under-unsafe-under-closure.rs
@@ -0,0 +1,27 @@
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+// This is issue #85435. But the real story is reflected in issue #85561, where
+// a bug in the implementation of feature(capture_disjoint_fields) () was
+// exposed to non-feature-gated code by a diagnostic changing PR that removed
+// the gating in one case.
+
+// This test is double-checking that the case of interest continues to work as
+// expected in the *absence* of that feature gate. At the time of this writing,
+// enabling the feature gate will cause this test to fail. We obviously cannot
+// stabilize that feature until it can correctly handle this test.
+
+fn main() {
+ let val: u8 = 5;
+ let u8_ptr: *const u8 = &val;
+ let _closure = || {
+ unsafe {
+ let tmp = *u8_ptr;
+ tmp
+
+ // Just dereferencing and returning directly compiles fine:
+ // *u8_ptr
+ }
+ };
+}
diff --git a/src/test/ui/unsafe/issue-87414-query-cycle.rs b/src/test/ui/unsafe/issue-87414-query-cycle.rs
new file mode 100644
index 000000000..99e40ba4b
--- /dev/null
+++ b/src/test/ui/unsafe/issue-87414-query-cycle.rs
@@ -0,0 +1,15 @@
+// Regression test for #87414.
+
+// check-pass
+// compile-flags: -Zthir-unsafeck
+
+fn bad<T>() -> Box<dyn Iterator<Item = [(); { |x: u32| { x }; 4 }]>> { todo!() }
+
+fn foo() -> [(); { |x: u32| { x }; 4 }] { todo!() }
+fn bar() { let _: [(); { |x: u32| { x }; 4 }]; }
+
+// This one should not cause any errors either:
+unsafe fn unsf() {}
+fn bad2<T>() -> Box<dyn Iterator<Item = [(); { unsafe { || { unsf() } }; 4 }]>> { todo!() }
+
+fn main() {}
diff --git a/src/test/ui/unsafe/ranged_ints.mir.stderr b/src/test/ui/unsafe/ranged_ints.mir.stderr
new file mode 100644
index 000000000..f9ef7834e
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints.mir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints.rs:10:14
+ |
+LL | let _x = NonZero(0);
+ | ^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr
+ |
+ = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints.rs b/src/test/ui/unsafe/ranged_ints.rs
new file mode 100644
index 000000000..05efe87ba
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints.rs
@@ -0,0 +1,11 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![feature(rustc_attrs)]
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {
+ let _x = NonZero(0); //~ ERROR initializing type with `rustc_layout_scalar_valid_range` attr
+}
diff --git a/src/test/ui/unsafe/ranged_ints.thir.stderr b/src/test/ui/unsafe/ranged_ints.thir.stderr
new file mode 100644
index 000000000..f9ef7834e
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints.thir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints.rs:10:14
+ |
+LL | let _x = NonZero(0);
+ | ^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr
+ |
+ = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints2.mirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints2.mirunsafeck.stderr
new file mode 100644
index 000000000..427843f8d
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints2.mirunsafeck.stderr
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints2.rs:11:13
+ |
+LL | let y = &mut x.0;
+ | ^^^^^^^^ mutation of layout constrained field
+ |
+ = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints2.rs b/src/test/ui/unsafe/ranged_ints2.rs
new file mode 100644
index 000000000..9a6bb18f9
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints2.rs
@@ -0,0 +1,12 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![feature(rustc_attrs)]
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {
+ let mut x = unsafe { NonZero(1) };
+ let y = &mut x.0; //~ ERROR mutation of layout constrained field is unsafe
+}
diff --git a/src/test/ui/unsafe/ranged_ints2.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints2.thirunsafeck.stderr
new file mode 100644
index 000000000..427843f8d
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints2.thirunsafeck.stderr
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints2.rs:11:13
+ |
+LL | let y = &mut x.0;
+ | ^^^^^^^^ mutation of layout constrained field
+ |
+ = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints2_const.mirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints2_const.mirunsafeck.stderr
new file mode 100644
index 000000000..c16550a58
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints2_const.mirunsafeck.stderr
@@ -0,0 +1,39 @@
+error[E0658]: mutable references are not allowed in constant functions
+ --> $DIR/ranged_ints2_const.rs:14:13
+ |
+LL | let y = &mut x.0;
+ | ^^^^^^^^
+ |
+ = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0658]: mutable references are not allowed in constant functions
+ --> $DIR/ranged_ints2_const.rs:21:22
+ |
+LL | let y = unsafe { &mut x.0 };
+ | ^^^^^^^^
+ |
+ = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0658]: mutable references are not allowed in constant functions
+ --> $DIR/ranged_ints2_const.rs:27:22
+ |
+LL | unsafe { let y = &mut x.0; }
+ | ^^^^^^^^
+ |
+ = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints2_const.rs:14:13
+ |
+LL | let y = &mut x.0;
+ | ^^^^^^^^ mutation of layout constrained field
+ |
+ = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0133, E0658.
+For more information about an error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints2_const.rs b/src/test/ui/unsafe/ranged_ints2_const.rs
new file mode 100644
index 000000000..56f5407bb
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints2_const.rs
@@ -0,0 +1,29 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![feature(rustc_attrs)]
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {
+}
+
+const fn foo() -> NonZero<u32> {
+ let mut x = unsafe { NonZero(1) };
+ let y = &mut x.0; //~ ERROR mutable references
+ //~^ ERROR mutation of layout constrained field is unsafe
+ unsafe { NonZero(1) }
+}
+
+const fn bar() -> NonZero<u32> {
+ let mut x = unsafe { NonZero(1) };
+ let y = unsafe { &mut x.0 }; //~ ERROR mutable references
+ unsafe { NonZero(1) }
+}
+
+const fn boo() -> NonZero<u32> {
+ let mut x = unsafe { NonZero(1) };
+ unsafe { let y = &mut x.0; } //~ ERROR mutable references
+ unsafe { NonZero(1) }
+}
diff --git a/src/test/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr
new file mode 100644
index 000000000..b3f139f72
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints2_const.thirunsafeck.stderr
@@ -0,0 +1,39 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints2_const.rs:14:13
+ |
+LL | let y = &mut x.0;
+ | ^^^^^^^^ mutation of layout constrained field
+ |
+ = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error[E0658]: mutable references are not allowed in constant functions
+ --> $DIR/ranged_ints2_const.rs:14:13
+ |
+LL | let y = &mut x.0;
+ | ^^^^^^^^
+ |
+ = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0658]: mutable references are not allowed in constant functions
+ --> $DIR/ranged_ints2_const.rs:21:22
+ |
+LL | let y = unsafe { &mut x.0 };
+ | ^^^^^^^^
+ |
+ = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0658]: mutable references are not allowed in constant functions
+ --> $DIR/ranged_ints2_const.rs:27:22
+ |
+LL | unsafe { let y = &mut x.0; }
+ | ^^^^^^^^
+ |
+ = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0133, E0658.
+For more information about an error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints3.mirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3.mirunsafeck.stderr
new file mode 100644
index 000000000..9eec0b09e
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints3.mirunsafeck.stderr
@@ -0,0 +1,11 @@
+error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints3.rs:13:13
+ |
+LL | let y = &x.0;
+ | ^^^^ borrow of layout constrained field with interior mutability
+ |
+ = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints3.rs b/src/test/ui/unsafe/ranged_ints3.rs
new file mode 100644
index 000000000..76d4bfe95
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints3.rs
@@ -0,0 +1,14 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {
+ let mut x = unsafe { NonZero(Cell::new(1)) };
+ let y = &x.0; //~ ERROR borrow of layout constrained field with interior mutability
+}
diff --git a/src/test/ui/unsafe/ranged_ints3.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3.thirunsafeck.stderr
new file mode 100644
index 000000000..9eec0b09e
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints3.thirunsafeck.stderr
@@ -0,0 +1,11 @@
+error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints3.rs:13:13
+ |
+LL | let y = &x.0;
+ | ^^^^ borrow of layout constrained field with interior mutability
+ |
+ = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints3_const.mirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3_const.mirunsafeck.stderr
new file mode 100644
index 000000000..62df93330
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints3_const.mirunsafeck.stderr
@@ -0,0 +1,30 @@
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
+ --> $DIR/ranged_ints3_const.rs:15:13
+ |
+LL | let y = &x.0;
+ | ^^^^
+ |
+ = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+ = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
+
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
+ --> $DIR/ranged_ints3_const.rs:22:22
+ |
+LL | let y = unsafe { &x.0 };
+ | ^^^^
+ |
+ = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+ = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
+
+error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints3_const.rs:15:13
+ |
+LL | let y = &x.0;
+ | ^^^^ borrow of layout constrained field with interior mutability
+ |
+ = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0133, E0658.
+For more information about an error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints3_const.rs b/src/test/ui/unsafe/ranged_ints3_const.rs
new file mode 100644
index 000000000..637198d36
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints3_const.rs
@@ -0,0 +1,24 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {}
+
+const fn foo() -> NonZero<Cell<u32>> {
+ let mut x = unsafe { NonZero(Cell::new(1)) };
+ let y = &x.0; //~ ERROR the borrowed element may contain interior mutability
+ //~^ ERROR borrow of layout constrained field with interior mutability
+ unsafe { NonZero(Cell::new(1)) }
+}
+
+const fn bar() -> NonZero<Cell<u32>> {
+ let mut x = unsafe { NonZero(Cell::new(1)) };
+ let y = unsafe { &x.0 }; //~ ERROR the borrowed element may contain interior mutability
+ unsafe { NonZero(Cell::new(1)) }
+}
diff --git a/src/test/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr
new file mode 100644
index 000000000..5dbc563aa
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints3_const.thirunsafeck.stderr
@@ -0,0 +1,30 @@
+error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints3_const.rs:15:13
+ |
+LL | let y = &x.0;
+ | ^^^^ borrow of layout constrained field with interior mutability
+ |
+ = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
+ --> $DIR/ranged_ints3_const.rs:15:13
+ |
+LL | let y = &x.0;
+ | ^^^^
+ |
+ = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+ = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
+
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
+ --> $DIR/ranged_ints3_const.rs:22:22
+ |
+LL | let y = unsafe { &x.0 };
+ | ^^^^
+ |
+ = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+ = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0133, E0658.
+For more information about an error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr
new file mode 100644
index 000000000..27c066409
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints3_match.mirunsafeck.stderr
@@ -0,0 +1,19 @@
+error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints3_match.rs:14:17
+ |
+LL | NonZero(ref x) => { x }
+ | ^^^^^ borrow of layout constrained field with interior mutability
+ |
+ = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints3_match.rs:20:23
+ |
+LL | match y { NonZero(ref mut y) => { y } };
+ | ^^^^^^^^^ mutation of layout constrained field
+ |
+ = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints3_match.rs b/src/test/ui/unsafe/ranged_ints3_match.rs
new file mode 100644
index 000000000..d9fcf0bd6
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints3_match.rs
@@ -0,0 +1,22 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {
+ let mut x = unsafe { NonZero(Cell::new(1)) };
+ match x {
+ NonZero(ref x) => { x }
+ //~^ ERROR borrow of layout constrained field with interior mutability
+ };
+
+ let mut y = unsafe { NonZero(42) };
+ match y { NonZero(ref y) => { y } }; // OK, type of `y` is freeze
+ match y { NonZero(ref mut y) => { y } };
+ //~^ ERROR mutation of layout constrained field
+}
diff --git a/src/test/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr
new file mode 100644
index 000000000..27c066409
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints3_match.thirunsafeck.stderr
@@ -0,0 +1,19 @@
+error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints3_match.rs:14:17
+ |
+LL | NonZero(ref x) => { x }
+ | ^^^^^ borrow of layout constrained field with interior mutability
+ |
+ = note: references to fields of layout constrained fields lose the constraints. Coupled with interior mutability, the field can be changed to invalid values
+
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints3_match.rs:20:23
+ |
+LL | match y { NonZero(ref mut y) => { y } };
+ | ^^^^^^^^^ mutation of layout constrained field
+ |
+ = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints4.mirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints4.mirunsafeck.stderr
new file mode 100644
index 000000000..493483d2c
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints4.mirunsafeck.stderr
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints4.rs:11:5
+ |
+LL | x.0 = 0;
+ | ^^^^^^^ mutation of layout constrained field
+ |
+ = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints4.rs b/src/test/ui/unsafe/ranged_ints4.rs
new file mode 100644
index 000000000..fe80af454
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints4.rs
@@ -0,0 +1,12 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![feature(rustc_attrs)]
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {
+ let mut x = unsafe { NonZero(1) };
+ x.0 = 0; //~ ERROR mutation of layout constrained field is unsafe
+}
diff --git a/src/test/ui/unsafe/ranged_ints4.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints4.thirunsafeck.stderr
new file mode 100644
index 000000000..493483d2c
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints4.thirunsafeck.stderr
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints4.rs:11:5
+ |
+LL | x.0 = 0;
+ | ^^^^^^^ mutation of layout constrained field
+ |
+ = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr
new file mode 100644
index 000000000..a06c6f479
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints4_const.mirunsafeck.stderr
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints4_const.rs:13:5
+ |
+LL | x.0 = 0;
+ | ^^^^^^^ mutation of layout constrained field
+ |
+ = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints4_const.rs b/src/test/ui/unsafe/ranged_ints4_const.rs
new file mode 100644
index 000000000..a43c8be71
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints4_const.rs
@@ -0,0 +1,22 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![feature(rustc_attrs)]
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {}
+
+const fn foo() -> NonZero<u32> {
+ let mut x = unsafe { NonZero(1) };
+ x.0 = 0;
+ //~^ ERROR mutation of layout constrained field is unsafe
+ x
+}
+
+const fn bar() -> NonZero<u32> {
+ let mut x = unsafe { NonZero(1) };
+ unsafe { x.0 = 0 }; // this is UB
+ x
+}
diff --git a/src/test/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr b/src/test/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr
new file mode 100644
index 000000000..a06c6f479
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints4_const.thirunsafeck.stderr
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints4_const.rs:13:5
+ |
+LL | x.0 = 0;
+ | ^^^^^^^ mutation of layout constrained field
+ |
+ = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints_const.mir.stderr b/src/test/ui/unsafe/ranged_ints_const.mir.stderr
new file mode 100644
index 000000000..33d134c7c
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints_const.mir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints_const.rs:11:34
+ |
+LL | const fn foo() -> NonZero<u32> { NonZero(0) }
+ | ^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr
+ |
+ = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints_const.rs b/src/test/ui/unsafe/ranged_ints_const.rs
new file mode 100644
index 000000000..472b09681
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints_const.rs
@@ -0,0 +1,14 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![feature(rustc_attrs)]
+
+#[rustc_layout_scalar_valid_range_start(1)]
+#[repr(transparent)]
+pub(crate) struct NonZero<T>(pub(crate) T);
+fn main() {}
+
+const fn foo() -> NonZero<u32> { NonZero(0) }
+//~^ ERROR initializing type with `rustc_layout_scalar_valid_range` attr is unsafe
+
+const fn bar() -> NonZero<u32> { unsafe { NonZero(0) } }
diff --git a/src/test/ui/unsafe/ranged_ints_const.thir.stderr b/src/test/ui/unsafe/ranged_ints_const.thir.stderr
new file mode 100644
index 000000000..33d134c7c
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints_const.thir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: initializing type with `rustc_layout_scalar_valid_range` attr is unsafe and requires unsafe function or block
+ --> $DIR/ranged_ints_const.rs:11:34
+ |
+LL | const fn foo() -> NonZero<u32> { NonZero(0) }
+ | ^^^^^^^^^^ initializing type with `rustc_layout_scalar_valid_range` attr
+ |
+ = note: initializing a layout restricted type's field with a value outside the valid range is undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/ranged_ints_macro.rs b/src/test/ui/unsafe/ranged_ints_macro.rs
new file mode 100644
index 000000000..8293d0299
--- /dev/null
+++ b/src/test/ui/unsafe/ranged_ints_macro.rs
@@ -0,0 +1,19 @@
+// build-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![feature(rustc_attrs)]
+
+macro_rules! apply {
+ ($val:expr) => {
+ #[rustc_layout_scalar_valid_range_start($val)]
+ #[repr(transparent)]
+ pub(crate) struct NonZero<T>(pub(crate) T);
+ }
+}
+
+apply!(1);
+
+fn main() {
+ let _x = unsafe { NonZero(1) };
+}
diff --git a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr
new file mode 100644
index 000000000..fd58e1b1e
--- /dev/null
+++ b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr
@@ -0,0 +1,134 @@
+error: call to unsafe function is unsafe and requires unsafe block (error E0133)
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:12:5
+ |
+LL | unsf();
+ | ^^^^^^ call to unsafe function
+ |
+note: the lint level is defined here
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:4:9
+ |
+LL | #![deny(unsafe_op_in_unsafe_fn)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:15:5
+ |
+LL | *PTR;
+ | ^^^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: use of mutable static is unsafe and requires unsafe block (error E0133)
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:17:5
+ |
+LL | VOID = ();
+ | ^^^^^^^^^ use of mutable static
+ |
+ = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error: unnecessary `unsafe` block
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:20:5
+ |
+LL | unsafe {}
+ | ^^^^^^ unnecessary `unsafe` block
+ |
+note: the lint level is defined here
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:5:9
+ |
+LL | #![deny(unused_unsafe)]
+ | ^^^^^^^^^^^^^
+
+error: call to unsafe function is unsafe and requires unsafe block (error E0133)
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:28:5
+ |
+LL | unsf();
+ | ^^^^^^ call to unsafe function
+ |
+note: the lint level is defined here
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:26:8
+ |
+LL | #[deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(unsafe_op_in_unsafe_fn)]` implied by `#[deny(warnings)]`
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:31:5
+ |
+LL | *PTR;
+ | ^^^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: use of mutable static is unsafe and requires unsafe block (error E0133)
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:33:5
+ |
+LL | VOID = ();
+ | ^^^^^^^^^ use of mutable static
+ |
+ = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error: unnecessary `unsafe` block
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:35:5
+ |
+LL | unsafe {}
+ | ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:49:5
+ |
+LL | unsafe { unsafe { unsf() } }
+ | ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:60:5
+ |
+LL | unsafe fn allow_level() {
+ | ----------------------- because it's nested under this `unsafe` fn
+...
+LL | unsafe { unsf() }
+ | ^^^^^^ unnecessary `unsafe` block
+ |
+ = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
+note: the lint level is defined here
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:53:9
+ |
+LL | #[allow(unsafe_op_in_unsafe_fn)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:72:9
+ |
+LL | unsafe fn nested_allow_level() {
+ | ------------------------------ because it's nested under this `unsafe` fn
+...
+LL | unsafe { unsf() }
+ | ^^^^^^ unnecessary `unsafe` block
+ |
+ = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
+note: the lint level is defined here
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:65:13
+ |
+LL | #[allow(unsafe_op_in_unsafe_fn)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0133]: call to unsafe function is unsafe and requires unsafe block
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:78:5
+ |
+LL | unsf();
+ | ^^^^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:83:9
+ |
+LL | unsf();
+ | ^^^^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs
new file mode 100644
index 000000000..30b072340
--- /dev/null
+++ b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs
@@ -0,0 +1,87 @@
+// revisions: mir thir
+// [thir]compile-flags: -Zthir-unsafeck
+
+#![deny(unsafe_op_in_unsafe_fn)]
+#![deny(unused_unsafe)]
+
+unsafe fn unsf() {}
+const PTR: *const () = std::ptr::null();
+static mut VOID: () = ();
+
+unsafe fn deny_level() {
+ unsf();
+ //[mir]~^ ERROR call to unsafe function is unsafe and requires unsafe block
+ //[thir]~^^ ERROR call to unsafe function `unsf` is unsafe and requires unsafe block
+ *PTR;
+ //~^ ERROR dereference of raw pointer is unsafe and requires unsafe block
+ VOID = ();
+ //~^ ERROR use of mutable static is unsafe and requires unsafe block
+
+ unsafe {}
+ //~^ ERROR unnecessary `unsafe` block
+}
+
+// Check that `unsafe_op_in_unsafe_fn` works starting from the `warn` level.
+#[warn(unsafe_op_in_unsafe_fn)]
+#[deny(warnings)]
+unsafe fn warning_level() {
+ unsf();
+ //[mir]~^ ERROR call to unsafe function is unsafe and requires unsafe block
+ //[thir]~^^ ERROR call to unsafe function `unsf` is unsafe and requires unsafe block
+ *PTR;
+ //~^ ERROR dereference of raw pointer is unsafe and requires unsafe block
+ VOID = ();
+ //~^ ERROR use of mutable static is unsafe and requires unsafe block
+ unsafe {}
+ //~^ ERROR unnecessary `unsafe` block
+}
+
+unsafe fn explicit_block() {
+ // no error
+ unsafe {
+ unsf();
+ *PTR;
+ VOID = ();
+ }
+}
+
+unsafe fn two_explicit_blocks() {
+ unsafe { unsafe { unsf() } }
+ //~^ ERROR unnecessary `unsafe` block
+}
+
+#[allow(unsafe_op_in_unsafe_fn)]
+unsafe fn allow_level() {
+ // lint allowed -> no error
+ unsf();
+ *PTR;
+ VOID = ();
+
+ unsafe { unsf() }
+ //~^ ERROR unnecessary `unsafe` block
+}
+
+unsafe fn nested_allow_level() {
+ #[allow(unsafe_op_in_unsafe_fn)]
+ {
+ // lint allowed -> no error
+ unsf();
+ *PTR;
+ VOID = ();
+
+ unsafe { unsf() }
+ //~^ ERROR unnecessary `unsafe` block
+ }
+}
+
+fn main() {
+ unsf();
+ //[mir]~^ ERROR call to unsafe function is unsafe and requires unsafe block
+ //[thir]~^^ ERROR call to unsafe function `unsf` is unsafe and requires unsafe block
+ #[allow(unsafe_op_in_unsafe_fn)]
+ {
+ unsf();
+ //[mir]~^ ERROR call to unsafe function is unsafe and requires unsafe function or block
+ //[thir]~^^ ERROR call to unsafe function `unsf` is unsafe and requires unsafe function or block
+ }
+}
diff --git a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr
new file mode 100644
index 000000000..2ba6a7293
--- /dev/null
+++ b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr
@@ -0,0 +1,122 @@
+error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:12:5
+ |
+LL | unsf();
+ | ^^^^^^ call to unsafe function
+ |
+note: the lint level is defined here
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:4:9
+ |
+LL | #![deny(unsafe_op_in_unsafe_fn)]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:15:5
+ |
+LL | *PTR;
+ | ^^^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: use of mutable static is unsafe and requires unsafe block (error E0133)
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:17:5
+ |
+LL | VOID = ();
+ | ^^^^ use of mutable static
+ |
+ = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error: unnecessary `unsafe` block
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:20:5
+ |
+LL | unsafe {}
+ | ^^^^^^ unnecessary `unsafe` block
+ |
+note: the lint level is defined here
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:5:9
+ |
+LL | #![deny(unused_unsafe)]
+ | ^^^^^^^^^^^^^
+
+error: call to unsafe function `unsf` is unsafe and requires unsafe block (error E0133)
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:28:5
+ |
+LL | unsf();
+ | ^^^^^^ call to unsafe function
+ |
+note: the lint level is defined here
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:26:8
+ |
+LL | #[deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(unsafe_op_in_unsafe_fn)]` implied by `#[deny(warnings)]`
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:31:5
+ |
+LL | *PTR;
+ | ^^^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: use of mutable static is unsafe and requires unsafe block (error E0133)
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:33:5
+ |
+LL | VOID = ();
+ | ^^^^ use of mutable static
+ |
+ = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error: unnecessary `unsafe` block
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:35:5
+ |
+LL | unsafe {}
+ | ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:49:14
+ |
+LL | unsafe { unsafe { unsf() } }
+ | ------ ^^^^^^ unnecessary `unsafe` block
+ | |
+ | because it's nested under this `unsafe` block
+
+error: unnecessary `unsafe` block
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:60:5
+ |
+LL | unsafe fn allow_level() {
+ | ----------------------- because it's nested under this `unsafe` fn
+...
+LL | unsafe { unsf() }
+ | ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:72:9
+ |
+LL | unsafe fn nested_allow_level() {
+ | ------------------------------ because it's nested under this `unsafe` fn
+...
+LL | unsafe { unsf() }
+ | ^^^^^^ unnecessary `unsafe` block
+
+error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:78:5
+ |
+LL | unsf();
+ | ^^^^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe function or block
+ --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:83:9
+ |
+LL | unsf();
+ | ^^^^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/union-assignop.mirunsafeck.stderr b/src/test/ui/unsafe/union-assignop.mirunsafeck.stderr
new file mode 100644
index 000000000..0ecd5203d
--- /dev/null
+++ b/src/test/ui/unsafe/union-assignop.mirunsafeck.stderr
@@ -0,0 +1,51 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-assignop.rs:19:5
+ |
+LL | foo.a += 5;
+ | ^^^^^^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-assignop.rs:20:6
+ |
+LL | *foo.b += NonCopy;
+ | ^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-assignop.rs:21:6
+ |
+LL | *foo.b = NonCopy;
+ | ^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-assignop.rs:23:5
+ |
+LL | foo.a;
+ | ^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-assignop.rs:25:5
+ |
+LL | foo.b;
+ | ^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-assignop.rs:27:13
+ |
+LL | foo.b = foo.b;
+ | ^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/union-assignop.rs b/src/test/ui/unsafe/union-assignop.rs
new file mode 100644
index 000000000..5e667cd10
--- /dev/null
+++ b/src/test/ui/unsafe/union-assignop.rs
@@ -0,0 +1,29 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+use std::ops::AddAssign;
+use std::mem::ManuallyDrop;
+
+struct NonCopy;
+impl AddAssign for NonCopy {
+ fn add_assign(&mut self, _: Self) {}
+}
+
+union Foo {
+ a: u8, // non-dropping
+ b: ManuallyDrop<NonCopy>,
+}
+
+fn main() {
+ let mut foo = Foo { a: 42 };
+ foo.a += 5; //~ ERROR access to union field is unsafe
+ *foo.b += NonCopy; //~ ERROR access to union field is unsafe
+ *foo.b = NonCopy; //~ ERROR access to union field is unsafe
+ foo.b = ManuallyDrop::new(NonCopy);
+ foo.a; //~ ERROR access to union field is unsafe
+ let foo = Foo { a: 42 };
+ foo.b; //~ ERROR access to union field is unsafe
+ let mut foo = Foo { a: 42 };
+ foo.b = foo.b;
+ //~^ ERROR access to union field is unsafe
+}
diff --git a/src/test/ui/unsafe/union-assignop.thirunsafeck.stderr b/src/test/ui/unsafe/union-assignop.thirunsafeck.stderr
new file mode 100644
index 000000000..24b357e76
--- /dev/null
+++ b/src/test/ui/unsafe/union-assignop.thirunsafeck.stderr
@@ -0,0 +1,51 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-assignop.rs:19:5
+ |
+LL | foo.a += 5;
+ | ^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-assignop.rs:20:6
+ |
+LL | *foo.b += NonCopy;
+ | ^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-assignop.rs:21:6
+ |
+LL | *foo.b = NonCopy;
+ | ^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-assignop.rs:23:5
+ |
+LL | foo.a;
+ | ^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-assignop.rs:25:5
+ |
+LL | foo.b;
+ | ^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union-assignop.rs:27:13
+ |
+LL | foo.b = foo.b;
+ | ^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/union-modification.rs b/src/test/ui/unsafe/union-modification.rs
new file mode 100644
index 000000000..9a53ef908
--- /dev/null
+++ b/src/test/ui/unsafe/union-modification.rs
@@ -0,0 +1,37 @@
+// run-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+union Foo {
+ bar: i8,
+ _blah: isize,
+ _zst: (),
+}
+
+struct FooHolder {
+ inner_foo: Foo
+}
+
+fn do_nothing(_x: &mut Foo) {}
+
+pub fn main() {
+ let mut foo = Foo { bar: 5 };
+ do_nothing(&mut foo);
+ foo.bar = 6;
+ unsafe { foo.bar += 1; }
+ assert_eq!(unsafe { foo.bar }, 7);
+ unsafe {
+ let Foo { bar: inner } = foo;
+ assert_eq!(inner, 7);
+ }
+
+ let foo = Foo { bar: 5 };
+ let foo = if let 3 = if let true = true { 3 } else { 4 } { foo } else { foo };
+
+ let (_foo2, _random) = (foo, 42);
+
+ let mut foo_holder = FooHolder { inner_foo: Foo { bar: 5 } };
+ foo_holder.inner_foo.bar = 4;
+ assert_eq!(unsafe { foo_holder.inner_foo.bar }, 4);
+ drop(foo_holder);
+}
diff --git a/src/test/ui/unsafe/union.mir.stderr b/src/test/ui/unsafe/union.mir.stderr
new file mode 100644
index 000000000..787714cdd
--- /dev/null
+++ b/src/test/ui/unsafe/union.mir.stderr
@@ -0,0 +1,19 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union.rs:30:20
+ |
+LL | Foo { bar: _a } => {},
+ | ^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union.rs:32:11
+ |
+LL | match foo {
+ | ^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/union.rs b/src/test/ui/unsafe/union.rs
new file mode 100644
index 000000000..4338d78ea
--- /dev/null
+++ b/src/test/ui/unsafe/union.rs
@@ -0,0 +1,53 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+union Foo {
+ bar: i8,
+ zst: (),
+ pizza: Pizza,
+}
+
+#[derive(Clone, Copy)]
+struct Pizza {
+ topping: Option<PizzaTopping>
+}
+
+#[allow(dead_code)]
+#[derive(Clone, Copy)]
+enum PizzaTopping {
+ Cheese,
+ Pineapple,
+}
+
+fn do_nothing(_x: &mut Foo) {}
+
+pub fn main() {
+ let mut foo = Foo { bar: 5 };
+ do_nothing(&mut foo);
+
+ // This is UB, so this test isn't run
+ match foo {
+ Foo { bar: _a } => {}, //~ ERROR access to union field is unsafe
+ }
+ match foo { //[mir]~ ERROR access to union field is unsafe
+ Foo {
+ pizza: Pizza { //[thir]~ ERROR access to union field is unsafe
+ topping: Some(PizzaTopping::Cheese) | Some(PizzaTopping::Pineapple) | None
+ }
+ } => {},
+ }
+
+ // MIR unsafeck incorrectly thinks that no unsafe block is needed to do these
+ match foo {
+ Foo { zst: () } => {}, //[thir]~ ERROR access to union field is unsafe
+ }
+ match foo {
+ Foo { pizza: Pizza { .. } } => {}, //[thir]~ ERROR access to union field is unsafe
+ }
+
+ // binding to wildcard is okay
+ match foo {
+ Foo { bar: _ } => {},
+ }
+ let Foo { bar: _ } = foo;
+}
diff --git a/src/test/ui/unsafe/union.thir.stderr b/src/test/ui/unsafe/union.thir.stderr
new file mode 100644
index 000000000..e1a1bd634
--- /dev/null
+++ b/src/test/ui/unsafe/union.thir.stderr
@@ -0,0 +1,38 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union.rs:30:20
+ |
+LL | Foo { bar: _a } => {},
+ | ^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union.rs:34:20
+ |
+LL | pizza: Pizza {
+ | ____________________^
+LL | | topping: Some(PizzaTopping::Cheese) | Some(PizzaTopping::Pineapple) | None
+LL | | }
+ | |_____________^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union.rs:42:20
+ |
+LL | Foo { zst: () } => {},
+ | ^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+ --> $DIR/union.rs:45:22
+ |
+LL | Foo { pizza: Pizza { .. } } => {},
+ | ^^^^^^^^^^^^ access to union field
+ |
+ = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/union_access_through_block.rs b/src/test/ui/unsafe/union_access_through_block.rs
new file mode 100644
index 000000000..e4c0976b8
--- /dev/null
+++ b/src/test/ui/unsafe/union_access_through_block.rs
@@ -0,0 +1,18 @@
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#[derive(Copy, Clone)]
+pub struct Foo { a: bool }
+
+pub union Bar {
+ a: Foo,
+ b: u32,
+}
+pub fn baz(mut bar: Bar) {
+ unsafe {
+ { bar.a }.a = true;
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/unsafe/union_destructure.mir.stderr b/src/test/ui/unsafe/union_destructure.mir.stderr
new file mode 100644
index 000000000..818f5ce03
--- /dev/null
+++ b/src/test/ui/unsafe/union_destructure.mir.stderr
@@ -0,0 +1,16 @@
+warning: unnecessary `unsafe` block
+ --> $DIR/union_destructure.rs:35:5
+ |
+LL | unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+ |
+ = note: `#[warn(unused_unsafe)]` on by default
+
+warning: unnecessary `unsafe` block
+ --> $DIR/union_destructure.rs:41:5
+ |
+LL | unsafe {
+ | ^^^^^^ unnecessary `unsafe` block
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/unsafe/union_destructure.rs b/src/test/ui/unsafe/union_destructure.rs
new file mode 100644
index 000000000..6c88344b5
--- /dev/null
+++ b/src/test/ui/unsafe/union_destructure.rs
@@ -0,0 +1,51 @@
+// run-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#[derive(Copy, Clone)]
+#[allow(dead_code)]
+struct Pie {
+ slices: u8,
+ size: u8,
+}
+
+union Foo {
+ #[allow(dead_code)]
+ bar: i8,
+ baz: Pie
+}
+
+fn main() {
+ let u = Foo { bar: 5 };
+ let (Some(Foo { bar: _ }) | None) = Some(u);
+ let u = Foo { bar: 6 };
+ let (Some(Foo { bar: _ }) | Some(Foo { bar: _ }) | None) = Some(u);
+ unsafe {
+ let u = Foo { bar: 7 };
+ let (Foo { bar } | Foo { bar }) = u;
+ assert_eq!(bar, 7)
+ }
+ let u = Foo { bar: 8 };
+ match Some(u) {
+ Some(Foo { bar: _ }) => 3,
+ None => 4,
+ };
+
+ let u = Foo { bar: 9 };
+ unsafe { //[mir]~ WARNING unnecessary `unsafe` block
+ match u {
+ Foo { baz: Pie { .. } } => {},
+ };
+ }
+ let u = Foo { bar: 10 };
+ unsafe { //[mir]~ WARNING unnecessary `unsafe` block
+ match u {
+ Foo { baz: Pie { slices: _, size: _ } } => {},
+ };
+ }
+
+ let u = Foo { bar: 11 };
+ match u {
+ Foo { baz: _ } => {},
+ };
+}
diff --git a/src/test/ui/unsafe/union_wild_or_wild.rs b/src/test/ui/unsafe/union_wild_or_wild.rs
new file mode 100644
index 000000000..52a0a7abf
--- /dev/null
+++ b/src/test/ui/unsafe/union_wild_or_wild.rs
@@ -0,0 +1,12 @@
+// check-pass
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+union X { a: i8 }
+
+fn main() {
+ let x = X { a: 5 };
+ match x {
+ X { a: _ | _ } => {},
+ }
+}
diff --git a/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.mir.stderr b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.mir.stderr
new file mode 100644
index 000000000..62199e5a2
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.mir.stderr
@@ -0,0 +1,20 @@
+error: unnecessary `unsafe` block
+ --> $DIR/unsafe-around-compiler-generated-unsafe.rs:9:9
+ |
+LL | unsafe { async {}.await; }
+ | ^^^^^^ unnecessary `unsafe` block
+ |
+note: the lint level is defined here
+ --> $DIR/unsafe-around-compiler-generated-unsafe.rs:5:9
+ |
+LL | #![deny(unused_unsafe)]
+ | ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+ --> $DIR/unsafe-around-compiler-generated-unsafe.rs:13:5
+ |
+LL | unsafe { println!("foo"); }
+ | ^^^^^^ unnecessary `unsafe` block
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs
new file mode 100644
index 000000000..c1a327640
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.rs
@@ -0,0 +1,14 @@
+// edition:2018
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![deny(unused_unsafe)]
+
+fn main() {
+ let _ = async {
+ unsafe { async {}.await; } //~ ERROR unnecessary `unsafe`
+ };
+
+ // `format_args!` expands with a compiler-generated unsafe block
+ unsafe { println!("foo"); } //~ ERROR unnecessary `unsafe`
+}
diff --git a/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.thir.stderr b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.thir.stderr
new file mode 100644
index 000000000..62199e5a2
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-around-compiler-generated-unsafe.thir.stderr
@@ -0,0 +1,20 @@
+error: unnecessary `unsafe` block
+ --> $DIR/unsafe-around-compiler-generated-unsafe.rs:9:9
+ |
+LL | unsafe { async {}.await; }
+ | ^^^^^^ unnecessary `unsafe` block
+ |
+note: the lint level is defined here
+ --> $DIR/unsafe-around-compiler-generated-unsafe.rs:5:9
+ |
+LL | #![deny(unused_unsafe)]
+ | ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+ --> $DIR/unsafe-around-compiler-generated-unsafe.rs:13:5
+ |
+LL | unsafe { println!("foo"); }
+ | ^^^^^^ unnecessary `unsafe` block
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/unsafe/unsafe-assign.mirunsafeck.stderr b/src/test/ui/unsafe/unsafe-assign.mirunsafeck.stderr
new file mode 100644
index 000000000..9abc51424
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-assign.mirunsafeck.stderr
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-assign.rs:12:5
+ |
+LL | foo.0.0 = 0;
+ | ^^^^^^^^^^^ mutation of layout constrained field
+ |
+ = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-assign.rs b/src/test/ui/unsafe/unsafe-assign.rs
new file mode 100644
index 000000000..15273165b
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-assign.rs
@@ -0,0 +1,25 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![feature(rustc_attrs)]
+#![allow(unused,dead_code)]
+
+fn nested_field() {
+ #[rustc_layout_scalar_valid_range_start(1)]
+ struct NonZero<T>(T);
+
+ let mut foo = unsafe { NonZero((1,)) };
+ foo.0.0 = 0;
+ //~^ ERROR: mutation of layout constrained field is unsafe
+}
+
+fn block() {
+ #[rustc_layout_scalar_valid_range_start(1)]
+ struct NonZero<T>(T);
+
+ let mut foo = unsafe { NonZero((1,)) };
+ { foo.0 }.0 = 0;
+ // ^ not unsafe because the result of the block expression is a new place
+}
+
+fn main() {}
diff --git a/src/test/ui/unsafe/unsafe-assign.thirunsafeck.stderr b/src/test/ui/unsafe/unsafe-assign.thirunsafeck.stderr
new file mode 100644
index 000000000..9abc51424
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-assign.thirunsafeck.stderr
@@ -0,0 +1,11 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-assign.rs:12:5
+ |
+LL | foo.0.0 = 0;
+ | ^^^^^^^^^^^ mutation of layout constrained field
+ |
+ = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-block-without-braces.rs b/src/test/ui/unsafe/unsafe-block-without-braces.rs
new file mode 100644
index 000000000..4e4611618
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-block-without-braces.rs
@@ -0,0 +1,6 @@
+fn main() {
+ unsafe //{
+ std::mem::transmute::<f32, u32>(1.0);
+ //}
+}
+//~^^^ ERROR expected `{`, found `std`
diff --git a/src/test/ui/unsafe/unsafe-block-without-braces.stderr b/src/test/ui/unsafe/unsafe-block-without-braces.stderr
new file mode 100644
index 000000000..44f77b99c
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-block-without-braces.stderr
@@ -0,0 +1,15 @@
+error: expected `{`, found `std`
+ --> $DIR/unsafe-block-without-braces.rs:3:9
+ |
+LL | unsafe //{
+ | ------ while parsing this `unsafe` expression
+LL | std::mem::transmute::<f32, u32>(1.0);
+ | ^^^ expected `{`
+ |
+help: try placing this code inside a block
+ |
+LL | { std::mem::transmute::<f32, u32>(1.0); }
+ | + +
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/unsafe/unsafe-borrow.mirunsafeck.stderr b/src/test/ui/unsafe/unsafe-borrow.mirunsafeck.stderr
new file mode 100644
index 000000000..a20672249
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-borrow.mirunsafeck.stderr
@@ -0,0 +1,27 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-borrow.rs:12:13
+ |
+LL | let a = &mut foo.0.0;
+ | ^^^^^^^^^^^^ mutation of layout constrained field
+ |
+ = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-borrow.rs:32:13
+ |
+LL | let a = &mut foo.0[2];
+ | ^^^^^^^^^^^^^ mutation of layout constrained field
+ |
+ = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-borrow.rs:51:18
+ |
+LL | NonZero((a,)) => *a = 0,
+ | ^ mutation of layout constrained field
+ |
+ = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-borrow.rs b/src/test/ui/unsafe/unsafe-borrow.rs
new file mode 100644
index 000000000..8dddc70be
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-borrow.rs
@@ -0,0 +1,56 @@
+// revisions: mirunsafeck thirunsafeck
+// [thirunsafeck]compile-flags: -Z thir-unsafeck
+
+#![feature(rustc_attrs)]
+#![allow(unused,dead_code)]
+
+fn tuple_struct() {
+ #[rustc_layout_scalar_valid_range_start(1)]
+ struct NonZero<T>(T);
+
+ let mut foo = unsafe { NonZero((1,)) };
+ let a = &mut foo.0.0;
+ //~^ ERROR: mutation of layout constrained field is unsafe
+}
+
+fn slice() {
+ #[rustc_layout_scalar_valid_range_start(1)]
+ struct NonZero<'a, T>(&'a mut [T]);
+
+ let mut nums = [1, 2, 3, 4];
+ let mut foo = unsafe { NonZero(&mut nums[..]) };
+ let a = &mut foo.0[2];
+ // ^ not unsafe because there is an implicit dereference here
+}
+
+fn array() {
+ #[rustc_layout_scalar_valid_range_start(1)]
+ struct NonZero<T>([T; 4]);
+
+ let nums = [1, 2, 3, 4];
+ let mut foo = unsafe { NonZero(nums) };
+ let a = &mut foo.0[2];
+ //~^ ERROR: mutation of layout constrained field is unsafe
+}
+
+fn block() {
+ #[rustc_layout_scalar_valid_range_start(1)]
+ struct NonZero<T>(T);
+
+ let foo = unsafe { NonZero((1,)) };
+ &mut { foo.0 }.0;
+ // ^ not unsafe because the result of the block expression is a new place
+}
+
+fn mtch() {
+ #[rustc_layout_scalar_valid_range_start(1)]
+ struct NonZero<T>(T);
+
+ let mut foo = unsafe { NonZero((1,)) };
+ match &mut foo {
+ NonZero((a,)) => *a = 0,
+ //~^ ERROR: mutation of layout constrained field is unsafe
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/unsafe/unsafe-borrow.thirunsafeck.stderr b/src/test/ui/unsafe/unsafe-borrow.thirunsafeck.stderr
new file mode 100644
index 000000000..a20672249
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-borrow.thirunsafeck.stderr
@@ -0,0 +1,27 @@
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-borrow.rs:12:13
+ |
+LL | let a = &mut foo.0.0;
+ | ^^^^^^^^^^^^ mutation of layout constrained field
+ |
+ = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-borrow.rs:32:13
+ |
+LL | let a = &mut foo.0[2];
+ | ^^^^^^^^^^^^^ mutation of layout constrained field
+ |
+ = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-borrow.rs:51:18
+ |
+LL | NonZero((a,)) => *a = 0,
+ | ^ mutation of layout constrained field
+ |
+ = note: mutating layout constrained fields cannot statically be checked for valid values
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-const-fn.mir.stderr b/src/test/ui/unsafe/unsafe-const-fn.mir.stderr
new file mode 100644
index 000000000..3031be720
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-const-fn.mir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-const-fn.rs:10:18
+ |
+LL | const VAL: u32 = dummy(0xFFFF);
+ | ^^^^^^^^^^^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-const-fn.rs b/src/test/ui/unsafe/unsafe-const-fn.rs
new file mode 100644
index 000000000..65e3acf30
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-const-fn.rs
@@ -0,0 +1,15 @@
+// A quick test of 'unsafe const fn' functionality
+
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+const unsafe fn dummy(v: u32) -> u32 {
+ !v
+}
+
+const VAL: u32 = dummy(0xFFFF);
+//~^ ERROR E0133
+
+fn main() {
+ assert_eq!(VAL, 0xFFFF0000);
+}
diff --git a/src/test/ui/unsafe/unsafe-const-fn.thir.stderr b/src/test/ui/unsafe/unsafe-const-fn.thir.stderr
new file mode 100644
index 000000000..1a77adf44
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-const-fn.thir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function `dummy` is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-const-fn.rs:10:18
+ |
+LL | const VAL: u32 = dummy(0xFFFF);
+ | ^^^^^^^^^^^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.mir.stderr b/src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.mir.stderr
new file mode 100644
index 000000000..fee645e41
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.mir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-fn-assign-deref-ptr.rs:5:5
+ |
+LL | *p = 0;
+ | ^^^^^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.rs b/src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.rs
new file mode 100644
index 000000000..a94e94375
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.rs
@@ -0,0 +1,10 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+fn f(p: *mut u8) {
+ *p = 0; //~ ERROR dereference of raw pointer is unsafe
+ return;
+}
+
+fn main() {
+}
diff --git a/src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.thir.stderr b/src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.thir.stderr
new file mode 100644
index 000000000..bbe4a415b
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-assign-deref-ptr.thir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-fn-assign-deref-ptr.rs:5:5
+ |
+LL | *p = 0;
+ | ^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-fn-autoderef.rs b/src/test/ui/unsafe/unsafe-fn-autoderef.rs
new file mode 100644
index 000000000..60460fc6e
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-autoderef.rs
@@ -0,0 +1,23 @@
+struct Rec {
+ f: isize
+}
+
+fn f(p: *const Rec) -> isize {
+
+ // Test that * ptrs do not autoderef. There is a deeper reason for
+ // prohibiting this, beyond making unsafe things annoying (which doesn't
+ // actually seem desirable to me). The deeper reason is that if you
+ // have a type like:
+ //
+ // enum foo = *foo;
+ //
+ // you end up with an infinite auto-deref chain, which is
+ // currently impossible (in all other cases, infinite auto-derefs
+ // are prohibited by various checks, such as that the enum is
+ // instantiable and so forth).
+
+ return p.f; //~ ERROR no field `f` on type `*const Rec`
+}
+
+fn main() {
+}
diff --git a/src/test/ui/unsafe/unsafe-fn-autoderef.stderr b/src/test/ui/unsafe/unsafe-fn-autoderef.stderr
new file mode 100644
index 000000000..20a88c356
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-autoderef.stderr
@@ -0,0 +1,11 @@
+error[E0609]: no field `f` on type `*const Rec`
+ --> $DIR/unsafe-fn-autoderef.rs:19:14
+ |
+LL | return p.f;
+ | --^
+ | |
+ | help: `p` is a raw pointer; try dereferencing it: `(*p).f`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/src/test/ui/unsafe/unsafe-fn-called-from-safe.mir.stderr b/src/test/ui/unsafe/unsafe-fn-called-from-safe.mir.stderr
new file mode 100644
index 000000000..1d6fa4cbf
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-called-from-safe.mir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-fn-called-from-safe.rs:7:5
+ |
+LL | f();
+ | ^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-fn-called-from-safe.rs b/src/test/ui/unsafe/unsafe-fn-called-from-safe.rs
new file mode 100644
index 000000000..55072dcc6
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-called-from-safe.rs
@@ -0,0 +1,10 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+unsafe fn f() { return; }
+
+fn main() {
+ f();
+ //[mir]~^ ERROR call to unsafe function is unsafe
+ //[thir]~^^ ERROR call to unsafe function `f` is unsafe
+}
diff --git a/src/test/ui/unsafe/unsafe-fn-called-from-safe.thir.stderr b/src/test/ui/unsafe/unsafe-fn-called-from-safe.thir.stderr
new file mode 100644
index 000000000..206dbd90a
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-called-from-safe.thir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function `f` is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-fn-called-from-safe.rs:7:5
+ |
+LL | f();
+ | ^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-fn-deref-ptr.mir.stderr b/src/test/ui/unsafe/unsafe-fn-deref-ptr.mir.stderr
new file mode 100644
index 000000000..a26149924
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-deref-ptr.mir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-fn-deref-ptr.rs:5:12
+ |
+LL | return *p;
+ | ^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-fn-deref-ptr.rs b/src/test/ui/unsafe/unsafe-fn-deref-ptr.rs
new file mode 100644
index 000000000..dc989535b
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-deref-ptr.rs
@@ -0,0 +1,9 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+fn f(p: *const u8) -> u8 {
+ return *p; //~ ERROR dereference of raw pointer is unsafe
+}
+
+fn main() {
+}
diff --git a/src/test/ui/unsafe/unsafe-fn-deref-ptr.thir.stderr b/src/test/ui/unsafe/unsafe-fn-deref-ptr.thir.stderr
new file mode 100644
index 000000000..a26149924
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-deref-ptr.thir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-fn-deref-ptr.rs:5:12
+ |
+LL | return *p;
+ | ^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-fn-used-as-value.mir.stderr b/src/test/ui/unsafe/unsafe-fn-used-as-value.mir.stderr
new file mode 100644
index 000000000..b08a7109d
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-used-as-value.mir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-fn-used-as-value.rs:8:5
+ |
+LL | x();
+ | ^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-fn-used-as-value.rs b/src/test/ui/unsafe/unsafe-fn-used-as-value.rs
new file mode 100644
index 000000000..9517598c7
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-used-as-value.rs
@@ -0,0 +1,11 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+unsafe fn f() { return; }
+
+fn main() {
+ let x = f;
+ x();
+ //[mir]~^ ERROR call to unsafe function is unsafe
+ //[thir]~^^ ERROR call to unsafe function `f` is unsafe
+}
diff --git a/src/test/ui/unsafe/unsafe-fn-used-as-value.thir.stderr b/src/test/ui/unsafe/unsafe-fn-used-as-value.thir.stderr
new file mode 100644
index 000000000..e81dd3b2b
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-fn-used-as-value.thir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: call to unsafe function `f` is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-fn-used-as-value.rs:8:5
+ |
+LL | x();
+ | ^^^ call to unsafe function
+ |
+ = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-subtyping.rs b/src/test/ui/unsafe/unsafe-subtyping.rs
new file mode 100644
index 000000000..a4b748a50
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-subtyping.rs
@@ -0,0 +1,11 @@
+// Check that safe fns are not a subtype of unsafe fns.
+
+fn foo(x: Option<fn(i32)>) -> Option<unsafe fn(i32)> {
+ x //~ ERROR mismatched types
+}
+
+fn bar(x: fn(i32)) -> unsafe fn(i32) {
+ x // OK, coercion!
+}
+
+fn main() { }
diff --git a/src/test/ui/unsafe/unsafe-subtyping.stderr b/src/test/ui/unsafe/unsafe-subtyping.stderr
new file mode 100644
index 000000000..2db7cc312
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-subtyping.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/unsafe-subtyping.rs:4:5
+ |
+LL | fn foo(x: Option<fn(i32)>) -> Option<unsafe fn(i32)> {
+ | ---------------------- expected `Option<unsafe fn(i32)>` because of return type
+LL | x
+ | ^ expected unsafe fn, found normal fn
+ |
+ = note: expected enum `Option<unsafe fn(_)>`
+ found enum `Option<fn(_)>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/unsafe/unsafe-trait-impl.rs b/src/test/ui/unsafe/unsafe-trait-impl.rs
new file mode 100644
index 000000000..03a251be1
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-trait-impl.rs
@@ -0,0 +1,14 @@
+// Check that safe fns are not a subtype of unsafe fns.
+
+trait Foo {
+ unsafe fn len(&self) -> u32;
+}
+
+impl Foo for u32 {
+ fn len(&self) -> u32 { *self }
+ //~^ ERROR method `len` has an incompatible type for trait
+ //~| expected fn pointer `unsafe fn(&u32) -> _`
+ //~| found fn pointer `fn(&u32) -> _`
+}
+
+fn main() { }
diff --git a/src/test/ui/unsafe/unsafe-trait-impl.stderr b/src/test/ui/unsafe/unsafe-trait-impl.stderr
new file mode 100644
index 000000000..8a0cba1fa
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-trait-impl.stderr
@@ -0,0 +1,17 @@
+error[E0053]: method `len` has an incompatible type for trait
+ --> $DIR/unsafe-trait-impl.rs:8:5
+ |
+LL | fn len(&self) -> u32 { *self }
+ | ^^^^^^^^^^^^^^^^^^^^ expected unsafe fn, found normal fn
+ |
+note: type in trait
+ --> $DIR/unsafe-trait-impl.rs:4:5
+ |
+LL | unsafe fn len(&self) -> u32;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: expected fn pointer `unsafe fn(&u32) -> _`
+ found fn pointer `fn(&u32) -> _`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/unsafe/unsafe-unstable-const-fn.mir.stderr b/src/test/ui/unsafe/unsafe-unstable-const-fn.mir.stderr
new file mode 100644
index 000000000..dcb84a80c
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-unstable-const-fn.mir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-unstable-const-fn.rs:10:5
+ |
+LL | *a == b
+ | ^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsafe/unsafe-unstable-const-fn.rs b/src/test/ui/unsafe/unsafe-unstable-const-fn.rs
new file mode 100644
index 000000000..581b15cdf
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-unstable-const-fn.rs
@@ -0,0 +1,14 @@
+// revisions: mir thir
+// [thir]compile-flags: -Z thir-unsafeck
+
+#![stable(feature = "foo", since = "1.33.0")]
+#![feature(staged_api)]
+
+#[stable(feature = "foo", since = "1.33.0")]
+#[rustc_const_unstable(feature = "const_foo", issue = "none")]
+const fn unstable(a: *const i32, b: i32) -> bool {
+ *a == b
+ //~^ dereference of raw pointer is unsafe
+}
+
+fn main() {}
diff --git a/src/test/ui/unsafe/unsafe-unstable-const-fn.thir.stderr b/src/test/ui/unsafe/unsafe-unstable-const-fn.thir.stderr
new file mode 100644
index 000000000..dcb84a80c
--- /dev/null
+++ b/src/test/ui/unsafe/unsafe-unstable-const-fn.thir.stderr
@@ -0,0 +1,11 @@
+error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
+ --> $DIR/unsafe-unstable-const-fn.rs:10:5
+ |
+LL | *a == b
+ | ^^ dereference of raw pointer
+ |
+ = note: raw pointers may be null, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0133`.