lint: extern non-exhaustive types are improper
This commit makes the `improper_ctype` lint trigger for non-exhaustive types when those types aren't defined in the current crate. Signed-off-by: David Wood <david@davidtw.co>
This commit is contained in:
parent
7870050796
commit
080aa86635
@ -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(),
|
||||
|
@ -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 }
|
||||
}
|
@ -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() { }
|
@ -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
|
||||
|
@ -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() { }
|
Loading…
x
Reference in New Issue
Block a user