about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc_lint/types.rs27
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs31
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs24
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr47
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs46
5 files changed, 175 insertions, 0 deletions
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 3d14a78c33f..aa6dfa50ddd 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -631,6 +631,16 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                             };
                         }
 
+                        let is_non_exhaustive =
+                            def.non_enum_variant().is_field_list_non_exhaustive();
+                        if is_non_exhaustive && !def.did.is_local() {
+                            return FfiUnsafe {
+                                ty,
+                                reason: "this struct is non-exhaustive",
+                                help: None,
+                            };
+                        }
+
                         if def.non_enum_variant().fields.is_empty() {
                             return FfiUnsafe {
                                 ty,
@@ -730,8 +740,25 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                             }
                         }
 
+                        if def.is_variant_list_non_exhaustive() && !def.did.is_local() {
+                            return FfiUnsafe {
+                                ty,
+                                reason: "this enum is non-exhaustive",
+                                help: None,
+                            };
+                        }
+
                         // Check the contained variants.
                         for variant in &def.variants {
+                            let is_non_exhaustive = variant.is_field_list_non_exhaustive();
+                            if is_non_exhaustive && !variant.def_id.is_local() {
+                                return FfiUnsafe {
+                                    ty,
+                                    reason: "this enum has non-exhaustive variants",
+                                    help: None,
+                                };
+                            }
+
                             for field in &variant.fields {
                                 let field_ty = cx.normalize_erasing_regions(
                                     ParamEnv::reveal_all(),
diff --git a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs
new file mode 100644
index 00000000000..1a187d04251
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs
@@ -0,0 +1,31 @@
+#![feature(non_exhaustive)]
+
+#[non_exhaustive]
+#[repr(C)]
+pub enum NonExhaustiveEnum {
+    Unit,
+    Tuple(u32),
+    Struct { field: u32 }
+}
+
+#[non_exhaustive]
+#[repr(C)]
+pub struct NormalStruct {
+    pub first_field: u16,
+    pub second_field: u16,
+}
+
+#[non_exhaustive]
+#[repr(C)]
+pub struct UnitStruct;
+
+#[non_exhaustive]
+#[repr(C)]
+pub struct TupleStruct (pub u16, pub u16);
+
+#[repr(C)]
+pub enum NonExhaustiveVariants {
+    #[non_exhaustive] Unit,
+    #[non_exhaustive] Tuple(u32),
+    #[non_exhaustive] Struct { field: u32 }
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs
new file mode 100644
index 00000000000..900b9333f76
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs
@@ -0,0 +1,24 @@
+// aux-build:types.rs
+#![deny(improper_ctypes)]
+
+extern crate types;
+
+// This test checks that non-exhaustive types with `#[repr(C)]` from an extern crate are considered
+// improper.
+
+use types::{NonExhaustiveEnum, NormalStruct, UnitStruct, TupleStruct, NonExhaustiveVariants};
+
+extern {
+    pub fn non_exhaustive_enum(_: NonExhaustiveEnum);
+    //~^ ERROR `extern` block uses type `types::NonExhaustiveEnum`, which is not FFI-safe
+    pub fn non_exhaustive_normal_struct(_: NormalStruct);
+    //~^ ERROR `extern` block uses type `types::NormalStruct`, which is not FFI-safe
+    pub fn non_exhaustive_unit_struct(_: UnitStruct);
+    //~^ ERROR `extern` block uses type `types::UnitStruct`, which is not FFI-safe
+    pub fn non_exhaustive_tuple_struct(_: TupleStruct);
+    //~^ ERROR `extern` block uses type `types::TupleStruct`, which is not FFI-safe
+    pub fn non_exhaustive_variant(_: NonExhaustiveVariants);
+    //~^ ERROR `extern` block uses type `types::NonExhaustiveVariants`, which is not FFI-safe
+}
+
+fn main() { }
diff --git a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr
new file mode 100644
index 00000000000..7fbf1157e56
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr
@@ -0,0 +1,47 @@
+error: `extern` block uses type `types::NonExhaustiveEnum`, which is not FFI-safe
+  --> $DIR/extern_crate_improper.rs:12:35
+   |
+LL |     pub fn non_exhaustive_enum(_: NonExhaustiveEnum);
+   |                                   ^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+note: lint level defined here
+  --> $DIR/extern_crate_improper.rs:2:9
+   |
+LL | #![deny(improper_ctypes)]
+   |         ^^^^^^^^^^^^^^^
+   = note: this enum is non-exhaustive
+
+error: `extern` block uses type `types::NormalStruct`, which is not FFI-safe
+  --> $DIR/extern_crate_improper.rs:14:44
+   |
+LL |     pub fn non_exhaustive_normal_struct(_: NormalStruct);
+   |                                            ^^^^^^^^^^^^ not FFI-safe
+   |
+   = note: this struct is non-exhaustive
+
+error: `extern` block uses type `types::UnitStruct`, which is not FFI-safe
+  --> $DIR/extern_crate_improper.rs:16:42
+   |
+LL |     pub fn non_exhaustive_unit_struct(_: UnitStruct);
+   |                                          ^^^^^^^^^^ not FFI-safe
+   |
+   = note: this struct is non-exhaustive
+
+error: `extern` block uses type `types::TupleStruct`, which is not FFI-safe
+  --> $DIR/extern_crate_improper.rs:18:43
+   |
+LL |     pub fn non_exhaustive_tuple_struct(_: TupleStruct);
+   |                                           ^^^^^^^^^^^ not FFI-safe
+   |
+   = note: this struct is non-exhaustive
+
+error: `extern` block uses type `types::NonExhaustiveVariants`, which is not FFI-safe
+  --> $DIR/extern_crate_improper.rs:20:38
+   |
+LL |     pub fn non_exhaustive_variant(_: NonExhaustiveVariants);
+   |                                      ^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = note: this enum has non-exhaustive variants
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs
new file mode 100644
index 00000000000..3f38e3cd8e5
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs
@@ -0,0 +1,46 @@
+// check-pass
+#![feature(non_exhaustive)]
+#![deny(improper_ctypes)]
+
+// This test checks that non-exhaustive types with `#[repr(C)]` are considered proper within
+// the defining crate.
+
+#[non_exhaustive]
+#[repr(C)]
+pub enum NonExhaustiveEnum {
+    Unit,
+    Tuple(u32),
+    Struct { field: u32 }
+}
+
+#[non_exhaustive]
+#[repr(C)]
+pub struct NormalStruct {
+    pub first_field: u16,
+    pub second_field: u16,
+}
+
+#[non_exhaustive]
+#[repr(C)]
+pub struct UnitStruct;
+
+#[non_exhaustive]
+#[repr(C)]
+pub struct TupleStruct (pub u16, pub u16);
+
+#[repr(C)]
+pub enum NonExhaustiveVariants {
+    #[non_exhaustive] Unit,
+    #[non_exhaustive] Tuple(u32),
+    #[non_exhaustive] Struct { field: u32 }
+}
+
+extern {
+    // Unit structs aren't tested here because they will trigger `improper_ctypes` anyway.
+    pub fn non_exhaustive_enum(_: NonExhaustiveEnum);
+    pub fn non_exhaustive_normal_struct(_: NormalStruct);
+    pub fn non_exhaustive_tuple_struct(_: TupleStruct);
+    pub fn non_exhaustive_variant(_: NonExhaustiveVariants);
+}
+
+fn main() { }