about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/ui/auxiliary/unsafe-fields-crate-dep.rs7
-rw-r--r--tests/ui/feature-gates/feature-gate-unsafe_fields.rs25
-rw-r--r--tests/ui/feature-gates/feature-gate-unsafe_fields.with_gate.stderr11
-rw-r--r--tests/ui/feature-gates/feature-gate-unsafe_fields.without_gate.stderr33
-rw-r--r--tests/ui/stats/input-stats.stderr30
-rw-r--r--tests/ui/thir-print/thir-tree-match.stdout6
-rw-r--r--tests/ui/unsafe-fields-crate.rs62
-rw-r--r--tests/ui/unsafe-fields-crate.stderr47
-rw-r--r--tests/ui/unsafe-fields-parse.rs10
-rw-r--r--tests/ui/unsafe-fields-parse.stderr18
-rw-r--r--tests/ui/unsafe-fields.rs109
-rw-r--r--tests/ui/unsafe-fields.stderr75
12 files changed, 415 insertions, 18 deletions
diff --git a/tests/ui/auxiliary/unsafe-fields-crate-dep.rs b/tests/ui/auxiliary/unsafe-fields-crate-dep.rs
new file mode 100644
index 00000000000..95b928402a9
--- /dev/null
+++ b/tests/ui/auxiliary/unsafe-fields-crate-dep.rs
@@ -0,0 +1,7 @@
+#![allow(incomplete_features)]
+#![feature(unsafe_fields)]
+
+pub struct WithUnsafeField {
+    pub unsafe unsafe_field: u32,
+    pub safe_field: u32,
+}
diff --git a/tests/ui/feature-gates/feature-gate-unsafe_fields.rs b/tests/ui/feature-gates/feature-gate-unsafe_fields.rs
new file mode 100644
index 00000000000..8f9b411df46
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-unsafe_fields.rs
@@ -0,0 +1,25 @@
+//@ compile-flags: --crate-type=lib
+//@ revisions: with_gate without_gate
+//@ [with_gate] check-pass
+
+#![cfg_attr(with_gate, feature(unsafe_fields))] //[with_gate]~ WARNING
+
+#[cfg(any())]
+struct Foo {
+    unsafe field: (), //[without_gate]~ ERROR
+}
+
+// This should not parse as an unsafe field definition.
+struct FooTuple(unsafe fn());
+
+#[cfg(any())]
+enum Bar {
+    Variant { unsafe field: () }, //[without_gate]~ ERROR
+    // This should not parse as an unsafe field definition.
+    VariantTuple(unsafe fn()),
+}
+
+#[cfg(any())]
+union Baz {
+    unsafe field: (), //[without_gate]~ ERROR
+}
diff --git a/tests/ui/feature-gates/feature-gate-unsafe_fields.with_gate.stderr b/tests/ui/feature-gates/feature-gate-unsafe_fields.with_gate.stderr
new file mode 100644
index 00000000000..a7deeb057d8
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-unsafe_fields.with_gate.stderr
@@ -0,0 +1,11 @@
+warning: the feature `unsafe_fields` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/feature-gate-unsafe_fields.rs:5:32
+   |
+LL | #![cfg_attr(with_gate, feature(unsafe_fields))]
+   |                                ^^^^^^^^^^^^^
+   |
+   = note: see issue #132922 <https://github.com/rust-lang/rust/issues/132922> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/feature-gates/feature-gate-unsafe_fields.without_gate.stderr b/tests/ui/feature-gates/feature-gate-unsafe_fields.without_gate.stderr
new file mode 100644
index 00000000000..ad0f5fd59ac
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-unsafe_fields.without_gate.stderr
@@ -0,0 +1,33 @@
+error[E0658]: `unsafe` fields are experimental
+  --> $DIR/feature-gate-unsafe_fields.rs:9:5
+   |
+LL |     unsafe field: (),
+   |     ^^^^^^
+   |
+   = note: see issue #132922 <https://github.com/rust-lang/rust/issues/132922> for more information
+   = help: add `#![feature(unsafe_fields)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `unsafe` fields are experimental
+  --> $DIR/feature-gate-unsafe_fields.rs:17:15
+   |
+LL |     Variant { unsafe field: () },
+   |               ^^^^^^
+   |
+   = note: see issue #132922 <https://github.com/rust-lang/rust/issues/132922> for more information
+   = help: add `#![feature(unsafe_fields)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: `unsafe` fields are experimental
+  --> $DIR/feature-gate-unsafe_fields.rs:24:5
+   |
+LL |     unsafe field: (),
+   |     ^^^^^^
+   |
+   = note: see issue #132922 <https://github.com/rust-lang/rust/issues/132922> for more information
+   = help: add `#![feature(unsafe_fields)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr
index 2cc2c8019fa..f2dd9043759 100644
--- a/tests/ui/stats/input-stats.stderr
+++ b/tests/ui/stats/input-stats.stderr
@@ -15,17 +15,17 @@ ast-stats-1 ForeignItem               88 ( 1.3%)             1            88
 ast-stats-1 - Fn                        88 ( 1.3%)             1
 ast-stats-1 Arm                       96 ( 1.4%)             2            48
 ast-stats-1 FnDecl                   120 ( 1.8%)             5            24
-ast-stats-1 FieldDef                 160 ( 2.4%)             2            80
 ast-stats-1 Param                    160 ( 2.4%)             4            40
 ast-stats-1 Stmt                     160 ( 2.4%)             5            32
 ast-stats-1 - Let                       32 ( 0.5%)             1
 ast-stats-1 - MacCall                   32 ( 0.5%)             1
 ast-stats-1 - Expr                      96 ( 1.4%)             3
+ast-stats-1 FieldDef                 176 ( 2.6%)             2            88
 ast-stats-1 Block                    192 ( 2.9%)             6            32
 ast-stats-1 Variant                  208 ( 3.1%)             2           104
 ast-stats-1 AssocItem                352 ( 5.3%)             4            88
-ast-stats-1 - Type                     176 ( 2.7%)             2
-ast-stats-1 - Fn                       176 ( 2.7%)             2
+ast-stats-1 - Type                     176 ( 2.6%)             2
+ast-stats-1 - Fn                       176 ( 2.6%)             2
 ast-stats-1 GenericBound             352 ( 5.3%)             4            88
 ast-stats-1 - Trait                    352 ( 5.3%)             4
 ast-stats-1 GenericParam             480 ( 7.2%)             5            96
@@ -38,7 +38,7 @@ ast-stats-1 - Path                      72 ( 1.1%)             1
 ast-stats-1 - Match                     72 ( 1.1%)             1
 ast-stats-1 - Struct                    72 ( 1.1%)             1
 ast-stats-1 - Lit                      144 ( 2.2%)             2
-ast-stats-1 - Block                    216 ( 3.3%)             3
+ast-stats-1 - Block                    216 ( 3.2%)             3
 ast-stats-1 PathSegment              744 (11.2%)            31            24
 ast-stats-1 Ty                       896 (13.5%)            14            64
 ast-stats-1 - Ref                       64 ( 1.0%)             1
@@ -53,7 +53,7 @@ ast-stats-1 - Enum                     136 ( 2.0%)             1
 ast-stats-1 - Fn                       272 ( 4.1%)             2
 ast-stats-1 - Use                      408 ( 6.1%)             3
 ast-stats-1 ----------------------------------------------------------------
-ast-stats-1 Total                  6_640                   116
+ast-stats-1 Total                  6_656                   116
 ast-stats-1
 ast-stats-2 POST EXPANSION AST STATS
 ast-stats-2 Name                Accumulated Size         Count     Item Size
@@ -73,14 +73,14 @@ ast-stats-2 InlineAsm                120 ( 1.6%)             1           120
 ast-stats-2 Attribute                128 ( 1.8%)             4            32
 ast-stats-2 - DocComment                32 ( 0.4%)             1
 ast-stats-2 - Normal                    96 ( 1.3%)             3
-ast-stats-2 FieldDef                 160 ( 2.2%)             2            80
 ast-stats-2 Param                    160 ( 2.2%)             4            40
 ast-stats-2 Stmt                     160 ( 2.2%)             5            32
 ast-stats-2 - Let                       32 ( 0.4%)             1
 ast-stats-2 - Semi                      32 ( 0.4%)             1
 ast-stats-2 - Expr                      96 ( 1.3%)             3
+ast-stats-2 FieldDef                 176 ( 2.4%)             2            88
 ast-stats-2 Block                    192 ( 2.6%)             6            32
-ast-stats-2 Variant                  208 ( 2.9%)             2           104
+ast-stats-2 Variant                  208 ( 2.8%)             2           104
 ast-stats-2 AssocItem                352 ( 4.8%)             4            88
 ast-stats-2 - Type                     176 ( 2.4%)             2
 ast-stats-2 - Fn                       176 ( 2.4%)             2
@@ -98,7 +98,7 @@ ast-stats-2 - Struct                    72 ( 1.0%)             1
 ast-stats-2 - InlineAsm                 72 ( 1.0%)             1
 ast-stats-2 - Lit                      144 ( 2.0%)             2
 ast-stats-2 - Block                    216 ( 3.0%)             3
-ast-stats-2 PathSegment              864 (11.9%)            36            24
+ast-stats-2 PathSegment              864 (11.8%)            36            24
 ast-stats-2 Ty                       896 (12.3%)            14            64
 ast-stats-2 - Ref                       64 ( 0.9%)             1
 ast-stats-2 - Ptr                       64 ( 0.9%)             1
@@ -111,9 +111,9 @@ ast-stats-2 - Impl                     136 ( 1.9%)             1
 ast-stats-2 - ExternCrate              136 ( 1.9%)             1
 ast-stats-2 - ForeignMod               136 ( 1.9%)             1
 ast-stats-2 - Fn                       272 ( 3.7%)             2
-ast-stats-2 - Use                      544 ( 7.5%)             4
+ast-stats-2 - Use                      544 ( 7.4%)             4
 ast-stats-2 ----------------------------------------------------------------
-ast-stats-2 Total                  7_288                   127
+ast-stats-2 Total                  7_304                   127
 ast-stats-2
 hir-stats HIR STATS
 hir-stats Name                Accumulated Size         Count     Item Size
@@ -132,11 +132,11 @@ hir-stats Body                      72 ( 0.8%)             3            24
 hir-stats ImplItemRef               72 ( 0.8%)             2            36
 hir-stats InlineAsm                 72 ( 0.8%)             1            72
 hir-stats Arm                       80 ( 0.9%)             2            40
-hir-stats FieldDef                  96 ( 1.1%)             2            48
 hir-stats Stmt                      96 ( 1.1%)             3            32
 hir-stats - Let                       32 ( 0.4%)             1
 hir-stats - Semi                      32 ( 0.4%)             1
 hir-stats - Expr                      32 ( 0.4%)             1
+hir-stats FieldDef                 112 ( 1.2%)             2            56
 hir-stats FnDecl                   120 ( 1.3%)             3            40
 hir-stats Attribute                128 ( 1.4%)             4            32
 hir-stats GenericArgs              144 ( 1.6%)             3            48
@@ -162,17 +162,17 @@ hir-stats - Match                     64 ( 0.7%)             1
 hir-stats - Struct                    64 ( 0.7%)             1
 hir-stats - InlineAsm                 64 ( 0.7%)             1
 hir-stats - Lit                      128 ( 1.4%)             2
-hir-stats - Block                    384 ( 4.3%)             6
+hir-stats - Block                    384 ( 4.2%)             6
 hir-stats Item                     968 (10.7%)            11            88
 hir-stats - Enum                      88 ( 1.0%)             1
 hir-stats - Trait                     88 ( 1.0%)             1
 hir-stats - Impl                      88 ( 1.0%)             1
 hir-stats - ExternCrate               88 ( 1.0%)             1
 hir-stats - ForeignMod                88 ( 1.0%)             1
-hir-stats - Fn                       176 ( 2.0%)             2
+hir-stats - Fn                       176 ( 1.9%)             2
 hir-stats - Use                      352 ( 3.9%)             4
 hir-stats Path                   1_240 (13.7%)            31            40
-hir-stats PathSegment            1_920 (21.3%)            40            48
+hir-stats PathSegment            1_920 (21.2%)            40            48
 hir-stats ----------------------------------------------------------------
-hir-stats Total                  9_024                   180
+hir-stats Total                  9_040                   180
 hir-stats
diff --git a/tests/ui/thir-print/thir-tree-match.stdout b/tests/ui/thir-print/thir-tree-match.stdout
index a9d6985928a..d56f15fb221 100644
--- a/tests/ui/thir-print/thir-tree-match.stdout
+++ b/tests/ui/thir-print/thir-tree-match.stdout
@@ -92,7 +92,7 @@ body:
                                                                                         adt_def: 
                                                                                             AdtDef {
                                                                                                 did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo)
-                                                                                                variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])) }], tainted: None, flags:  }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], tainted: None, flags:  }]
+                                                                                                variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])), safety: Safe }], tainted: None, flags:  }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], tainted: None, flags:  }]
                                                                                                 flags: IS_ENUM
                                                                                                 repr: ReprOptions { int: None, align: None, pack: None, flags: , field_shuffle_seed: 3477539199540094892 }
                                                                                         args: []
@@ -154,7 +154,7 @@ body:
                                                                                         adt_def: 
                                                                                             AdtDef {
                                                                                                 did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo)
-                                                                                                variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])) }], tainted: None, flags:  }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], tainted: None, flags:  }]
+                                                                                                variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])), safety: Safe }], tainted: None, flags:  }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], tainted: None, flags:  }]
                                                                                                 flags: IS_ENUM
                                                                                                 repr: ReprOptions { int: None, align: None, pack: None, flags: , field_shuffle_seed: 3477539199540094892 }
                                                                                         args: []
@@ -206,7 +206,7 @@ body:
                                                                                         adt_def: 
                                                                                             AdtDef {
                                                                                                 did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo)
-                                                                                                variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])) }], tainted: None, flags:  }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], tainted: None, flags:  }]
+                                                                                                variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])), safety: Safe }], tainted: None, flags:  }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], tainted: None, flags:  }]
                                                                                                 flags: IS_ENUM
                                                                                                 repr: ReprOptions { int: None, align: None, pack: None, flags: , field_shuffle_seed: 3477539199540094892 }
                                                                                         args: []
diff --git a/tests/ui/unsafe-fields-crate.rs b/tests/ui/unsafe-fields-crate.rs
new file mode 100644
index 00000000000..cfb9ad6b544
--- /dev/null
+++ b/tests/ui/unsafe-fields-crate.rs
@@ -0,0 +1,62 @@
+//@ compile-flags: --crate-type=lib
+//@ aux-build: unsafe-fields-crate-dep.rs
+
+extern crate unsafe_fields_crate_dep;
+
+use unsafe_fields_crate_dep::WithUnsafeField;
+
+fn new_without_unsafe() -> WithUnsafeField {
+    WithUnsafeField {
+        //~^ ERROR
+        unsafe_field: 0,
+        safe_field: 0,
+    }
+}
+
+fn operate_on_safe_field(s: &mut WithUnsafeField) {
+    s.safe_field = 2;
+    &s.safe_field;
+    s.safe_field;
+}
+
+fn set_unsafe_field(s: &mut WithUnsafeField) {
+    unsafe {
+        s.unsafe_field = 2;
+    }
+}
+
+fn read_unsafe_field(s: &WithUnsafeField) -> u32 {
+    unsafe { s.unsafe_field }
+}
+
+fn ref_unsafe_field(s: &WithUnsafeField) -> &u32 {
+    unsafe { &s.unsafe_field }
+}
+
+fn destructure(s: &WithUnsafeField) {
+    unsafe {
+        let WithUnsafeField { safe_field, unsafe_field } = s;
+    }
+}
+
+fn set_unsafe_field_without_unsafe(s: &mut WithUnsafeField) {
+    s.unsafe_field = 2;
+    //~^ ERROR
+}
+
+fn read_unsafe_field_without_unsafe(s: &WithUnsafeField) -> u32 {
+    s.unsafe_field
+    //~^ ERROR
+}
+
+fn ref_unsafe_field_without_unsafe(s: &WithUnsafeField) -> &u32 {
+    &s.unsafe_field
+    //~^ ERROR
+}
+
+fn destructure_without_unsafe(s: &WithUnsafeField) {
+    let WithUnsafeField { safe_field, unsafe_field } = s;
+    //~^ ERROR
+
+    let WithUnsafeField { safe_field, .. } = s;
+}
diff --git a/tests/ui/unsafe-fields-crate.stderr b/tests/ui/unsafe-fields-crate.stderr
new file mode 100644
index 00000000000..778c26e0a43
--- /dev/null
+++ b/tests/ui/unsafe-fields-crate.stderr
@@ -0,0 +1,47 @@
+error[E0133]: initializing type with an unsafe field is unsafe and requires unsafe block
+  --> $DIR/unsafe-fields-crate.rs:9:5
+   |
+LL | /     WithUnsafeField {
+LL | |
+LL | |         unsafe_field: 0,
+LL | |         safe_field: 0,
+LL | |     }
+   | |_____^ initialization of struct with unsafe field
+   |
+   = note: unsafe fields may carry library invariants
+
+error[E0133]: use of unsafe field is unsafe and requires unsafe block
+  --> $DIR/unsafe-fields-crate.rs:43:5
+   |
+LL |     s.unsafe_field = 2;
+   |     ^^^^^^^^^^^^^^ use of unsafe field
+   |
+   = note: unsafe fields may carry library invariants
+
+error[E0133]: use of unsafe field is unsafe and requires unsafe block
+  --> $DIR/unsafe-fields-crate.rs:48:5
+   |
+LL |     s.unsafe_field
+   |     ^^^^^^^^^^^^^^ use of unsafe field
+   |
+   = note: unsafe fields may carry library invariants
+
+error[E0133]: use of unsafe field is unsafe and requires unsafe block
+  --> $DIR/unsafe-fields-crate.rs:53:6
+   |
+LL |     &s.unsafe_field
+   |      ^^^^^^^^^^^^^^ use of unsafe field
+   |
+   = note: unsafe fields may carry library invariants
+
+error[E0133]: use of unsafe field is unsafe and requires unsafe block
+  --> $DIR/unsafe-fields-crate.rs:58:39
+   |
+LL |     let WithUnsafeField { safe_field, unsafe_field } = s;
+   |                                       ^^^^^^^^^^^^ use of unsafe field
+   |
+   = note: unsafe fields may carry library invariants
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/unsafe-fields-parse.rs b/tests/ui/unsafe-fields-parse.rs
new file mode 100644
index 00000000000..67277731293
--- /dev/null
+++ b/tests/ui/unsafe-fields-parse.rs
@@ -0,0 +1,10 @@
+//@ compile-flags: --crate-type=lib
+#![allow(incomplete_features)]
+#![feature(unsafe_fields)]
+
+// Parse errors even *with* unsafe_fields, which would make the compiler early-exit otherwise.
+enum A {
+    TupleLike(unsafe u32), //~ ERROR
+}
+
+struct B(unsafe u32); //~ ERROR
diff --git a/tests/ui/unsafe-fields-parse.stderr b/tests/ui/unsafe-fields-parse.stderr
new file mode 100644
index 00000000000..5a45ab03ffe
--- /dev/null
+++ b/tests/ui/unsafe-fields-parse.stderr
@@ -0,0 +1,18 @@
+error: expected type, found keyword `unsafe`
+  --> $DIR/unsafe-fields-parse.rs:7:15
+   |
+LL | enum A {
+   |      - while parsing this enum
+LL |     TupleLike(unsafe u32),
+   |               ^^^^^^ expected type
+   |
+   = help: enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`
+
+error: expected type, found keyword `unsafe`
+  --> $DIR/unsafe-fields-parse.rs:10:10
+   |
+LL | struct B(unsafe u32);
+   |          ^^^^^^ expected type
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/unsafe-fields.rs b/tests/ui/unsafe-fields.rs
new file mode 100644
index 00000000000..637471582d7
--- /dev/null
+++ b/tests/ui/unsafe-fields.rs
@@ -0,0 +1,109 @@
+//@ compile-flags: --crate-type=lib
+#![allow(incomplete_features)]
+#![feature(unsafe_fields)]
+
+struct WithUnsafeField {
+    unsafe unsafe_field: u32,
+    safe_field: u32,
+}
+
+enum A {
+    WithUnsafeField { unsafe unsafe_field: u32, safe_field: u32 },
+}
+
+fn f(a: A) {
+    let A::WithUnsafeField { unsafe_field, safe_field } = a;
+    //~^ ERROR
+}
+
+struct WithInvalidUnsafeField {
+    unsafe unsafe_noncopy_field: Vec<u32>, //~ ERROR
+}
+
+struct WithManuallyDropUnsafeField {
+    unsafe unsafe_noncopy_field: std::mem::ManuallyDrop<Vec<u32>>,
+}
+
+union WithUnsafeFieldUnion {
+    unsafe unsafe_field: u32,
+    safe_field: u32,
+}
+
+impl WithUnsafeField {
+    fn new() -> WithUnsafeField {
+        unsafe {
+            WithUnsafeField {
+                unsafe_field: 0,
+                safe_field: 0,
+            }
+        }
+    }
+
+    fn new_without_unsafe() -> WithUnsafeField {
+        WithUnsafeField { //~ ERROR
+            unsafe_field: 0,
+            safe_field: 0,
+        }
+    }
+
+    fn operate_on_safe_field(&mut self) {
+        self.safe_field = 2;
+        &self.safe_field;
+        self.safe_field;
+    }
+
+    fn set_unsafe_field(&mut self) {
+        unsafe {
+            self.unsafe_field = 2;
+        }
+    }
+
+    fn read_unsafe_field(&self) -> u32 {
+        unsafe {
+            self.unsafe_field
+        }
+    }
+
+    fn ref_unsafe_field(&self) -> &u32 {
+        unsafe {
+            &self.unsafe_field
+        }
+    }
+
+    fn destructure(&self) {
+        unsafe {
+            let Self { safe_field, unsafe_field } = self;
+        }
+    }
+
+    fn set_unsafe_field_without_unsafe(&mut self) {
+        self.unsafe_field = 2;
+        //~^ ERROR
+    }
+
+    fn read_unsafe_field_without_unsafe(&self) -> u32 {
+        self.unsafe_field
+        //~^ ERROR
+    }
+
+    fn ref_unsafe_field_without_unsafe(&self) -> &u32 {
+        &self.unsafe_field
+        //~^ ERROR
+    }
+
+    fn destructure_without_unsafe(&self) {
+        let Self { safe_field, unsafe_field } = self;
+        //~^ ERROR
+
+        let WithUnsafeField { safe_field, .. } = self;
+    }
+
+    fn offset_of(&self) -> usize {
+        std::mem::offset_of!(WithUnsafeField, unsafe_field)
+    }
+
+    fn raw_const(&self) -> *const u32 {
+        &raw const self.unsafe_field
+        //~^ ERROR
+    }
+}
diff --git a/tests/ui/unsafe-fields.stderr b/tests/ui/unsafe-fields.stderr
new file mode 100644
index 00000000000..a1c5d2b44cd
--- /dev/null
+++ b/tests/ui/unsafe-fields.stderr
@@ -0,0 +1,75 @@
+error[E0740]: field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be unsafe
+  --> $DIR/unsafe-fields.rs:20:5
+   |
+LL |     unsafe unsafe_noncopy_field: Vec<u32>,
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: unsafe fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`
+help: wrap the field type in `ManuallyDrop<...>`
+   |
+LL |     unsafe unsafe_noncopy_field: std::mem::ManuallyDrop<Vec<u32>>,
+   |                                  +++++++++++++++++++++++        +
+
+error[E0133]: use of unsafe field is unsafe and requires unsafe block
+  --> $DIR/unsafe-fields.rs:15:30
+   |
+LL |     let A::WithUnsafeField { unsafe_field, safe_field } = a;
+   |                              ^^^^^^^^^^^^ use of unsafe field
+   |
+   = note: unsafe fields may carry library invariants
+
+error[E0133]: initializing type with an unsafe field is unsafe and requires unsafe block
+  --> $DIR/unsafe-fields.rs:43:9
+   |
+LL | /         WithUnsafeField {
+LL | |             unsafe_field: 0,
+LL | |             safe_field: 0,
+LL | |         }
+   | |_________^ initialization of struct with unsafe field
+   |
+   = note: unsafe fields may carry library invariants
+
+error[E0133]: use of unsafe field is unsafe and requires unsafe block
+  --> $DIR/unsafe-fields.rs:80:9
+   |
+LL |         self.unsafe_field = 2;
+   |         ^^^^^^^^^^^^^^^^^ use of unsafe field
+   |
+   = note: unsafe fields may carry library invariants
+
+error[E0133]: use of unsafe field is unsafe and requires unsafe block
+  --> $DIR/unsafe-fields.rs:85:9
+   |
+LL |         self.unsafe_field
+   |         ^^^^^^^^^^^^^^^^^ use of unsafe field
+   |
+   = note: unsafe fields may carry library invariants
+
+error[E0133]: use of unsafe field is unsafe and requires unsafe block
+  --> $DIR/unsafe-fields.rs:90:10
+   |
+LL |         &self.unsafe_field
+   |          ^^^^^^^^^^^^^^^^^ use of unsafe field
+   |
+   = note: unsafe fields may carry library invariants
+
+error[E0133]: use of unsafe field is unsafe and requires unsafe block
+  --> $DIR/unsafe-fields.rs:95:32
+   |
+LL |         let Self { safe_field, unsafe_field } = self;
+   |                                ^^^^^^^^^^^^ use of unsafe field
+   |
+   = note: unsafe fields may carry library invariants
+
+error[E0133]: use of unsafe field is unsafe and requires unsafe block
+  --> $DIR/unsafe-fields.rs:106:20
+   |
+LL |         &raw const self.unsafe_field
+   |                    ^^^^^^^^^^^^^^^^^ use of unsafe field
+   |
+   = note: unsafe fields may carry library invariants
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0133, E0740.
+For more information about an error, try `rustc --explain E0133`.