Skip to content

Commit

Permalink
improper_ctypes_definitions: allow Box
Browse files Browse the repository at this point in the history
This commit stops linting against `Box` in `extern "C" fn`s for the
`improper_ctypes_definitions` lint - boxes are documented to be
FFI-safe.

Signed-off-by: David Wood <david@davidtw.co>
  • Loading branch information
davidtwco committed Jul 17, 2020
1 parent e2e29de commit 95df802
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 64 deletions.
13 changes: 12 additions & 1 deletion src/librustc_lint/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,11 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
match ty.kind {
ty::FnPtr(_) => true,
ty::Ref(..) => true,
ty::Adt(def, _)
if def.is_box() && matches!(self.mode, ImproperCTypesMode::Definitions) =>
{
true
}
ty::Adt(def, substs) if def.repr.transparent() && !def.is_union() => {
let guaranteed_nonnull_optimization = self
.cx
Expand Down Expand Up @@ -558,7 +563,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}

/// Check if this enum can be safely exported based on the "nullable pointer optimization".
/// Currently restricted to function pointers, references, `core::num::NonZero*`,
/// Currently restricted to function pointers, boxes, references, `core::num::NonZero*`,
/// `core::ptr::NonNull`, and `#[repr(transparent)]` newtypes.
fn is_repr_nullable_ptr(
&self,
Expand Down Expand Up @@ -692,6 +697,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}

match ty.kind {
ty::Adt(def, _)
if def.is_box() && matches!(self.mode, ImproperCTypesMode::Definitions) =>
{
FfiSafe
}

ty::Adt(def, substs) => {
if def.is_phantom_data() {
return FfiPhantom(ty);
Expand Down
5 changes: 2 additions & 3 deletions src/test/ui/lint/lint-ctypes-fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ pub extern "C" fn str_type(p: &str) { }
//~^ ERROR: uses type `str`

pub extern "C" fn box_type(p: Box<u32>) { }
//~^ ERROR uses type `std::boxed::Box<u32>`

pub extern "C" fn opt_box_type(p: Option<Box<u32>>) { }

pub extern "C" fn char_type(p: char) { }
//~^ ERROR uses type `char`
Expand Down Expand Up @@ -106,7 +107,6 @@ pub extern "C" fn fn_type2(p: fn()) { }
//~^ ERROR uses type `fn()`

pub extern "C" fn fn_contained(p: RustBadRet) { }
//~^ ERROR: uses type `std::boxed::Box<u32>`

pub extern "C" fn transparent_i128(p: TransparentI128) { }
//~^ ERROR: uses type `i128`
Expand All @@ -115,7 +115,6 @@ pub extern "C" fn transparent_str(p: TransparentStr) { }
//~^ ERROR: uses type `str`

pub extern "C" fn transparent_fn(p: TransparentBadFn) { }
//~^ ERROR: uses type `std::boxed::Box<u32>`

pub extern "C" fn good3(fptr: Option<extern fn()>) { }

Expand Down
55 changes: 14 additions & 41 deletions src/test/ui/lint/lint-ctypes-fn.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,8 @@ LL | pub extern "C" fn str_type(p: &str) { }
= help: consider using `*const u8` and a length instead
= note: string slices have no C equivalent

error: `extern` fn uses type `std::boxed::Box<u32>`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:73:31
|
LL | pub extern "C" fn box_type(p: Box<u32>) { }
| ^^^^^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout

error: `extern` fn uses type `char`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:76:32
--> $DIR/lint-ctypes-fn.rs:77:32
|
LL | pub extern "C" fn char_type(p: char) { }
| ^^^^ not FFI-safe
Expand All @@ -40,23 +31,23 @@ LL | pub extern "C" fn char_type(p: char) { }
= note: the `char` type has no C equivalent

error: `extern` fn uses type `i128`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:79:32
--> $DIR/lint-ctypes-fn.rs:80:32
|
LL | pub extern "C" fn i128_type(p: i128) { }
| ^^^^ not FFI-safe
|
= note: 128-bit integers don't currently have a known stable ABI

error: `extern` fn uses type `u128`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:82:32
--> $DIR/lint-ctypes-fn.rs:83:32
|
LL | pub extern "C" fn u128_type(p: u128) { }
| ^^^^ not FFI-safe
|
= note: 128-bit integers don't currently have a known stable ABI

error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:85:33
--> $DIR/lint-ctypes-fn.rs:86:33
|
LL | pub extern "C" fn tuple_type(p: (i32, i32)) { }
| ^^^^^^^^^^ not FFI-safe
Expand All @@ -65,7 +56,7 @@ LL | pub extern "C" fn tuple_type(p: (i32, i32)) { }
= note: tuples have unspecified layout

error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:88:34
--> $DIR/lint-ctypes-fn.rs:89:34
|
LL | pub extern "C" fn tuple_type2(p: I32Pair) { }
| ^^^^^^^ not FFI-safe
Expand All @@ -74,7 +65,7 @@ LL | pub extern "C" fn tuple_type2(p: I32Pair) { }
= note: tuples have unspecified layout

error: `extern` fn uses type `ZeroSize`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:91:32
--> $DIR/lint-ctypes-fn.rs:92:32
|
LL | pub extern "C" fn zero_size(p: ZeroSize) { }
| ^^^^^^^^ not FFI-safe
Expand All @@ -88,7 +79,7 @@ LL | pub struct ZeroSize;
| ^^^^^^^^^^^^^^^^^^^^

error: `extern` fn uses type `ZeroSizeWithPhantomData`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:94:40
--> $DIR/lint-ctypes-fn.rs:95:40
|
LL | pub extern "C" fn zero_size_phantom(p: ZeroSizeWithPhantomData) { }
| ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
Expand All @@ -101,15 +92,15 @@ LL | pub struct ZeroSizeWithPhantomData(PhantomData<i32>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: `extern` fn uses type `std::marker::PhantomData<bool>`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:97:51
--> $DIR/lint-ctypes-fn.rs:98:51
|
LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData<bool> {
| ^^^^^^^^^^^^^^^^^ not FFI-safe
|
= note: composed only of `PhantomData`

error: `extern` fn uses type `fn()`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:102:30
--> $DIR/lint-ctypes-fn.rs:103:30
|
LL | pub extern "C" fn fn_type(p: RustFn) { }
| ^^^^^^ not FFI-safe
Expand All @@ -118,23 +109,14 @@ LL | pub extern "C" fn fn_type(p: RustFn) { }
= note: this function pointer has Rust-specific calling convention

error: `extern` fn uses type `fn()`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:105:31
--> $DIR/lint-ctypes-fn.rs:106:31
|
LL | pub extern "C" fn fn_type2(p: fn()) { }
| ^^^^ not FFI-safe
|
= help: consider using an `extern fn(...) -> ...` function pointer instead
= note: this function pointer has Rust-specific calling convention

error: `extern` fn uses type `std::boxed::Box<u32>`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:108:35
|
LL | pub extern "C" fn fn_contained(p: RustBadRet) { }
| ^^^^^^^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout

error: `extern` fn uses type `i128`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:111:39
|
Expand All @@ -152,25 +134,16 @@ LL | pub extern "C" fn transparent_str(p: TransparentStr) { }
= help: consider using `*const u8` and a length instead
= note: string slices have no C equivalent

error: `extern` fn uses type `std::boxed::Box<u32>`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:117:37
|
LL | pub extern "C" fn transparent_fn(p: TransparentBadFn) { }
| ^^^^^^^^^^^^^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout

error: `extern` fn uses type `std::marker::PhantomData<bool>`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:161:43
--> $DIR/lint-ctypes-fn.rs:160:43
|
LL | pub extern "C" fn unused_generic2<T>() -> PhantomData<bool> {
| ^^^^^^^^^^^^^^^^^ not FFI-safe
|
= note: composed only of `PhantomData`

error: `extern` fn uses type `std::vec::Vec<T>`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:174:39
--> $DIR/lint-ctypes-fn.rs:173:39
|
LL | pub extern "C" fn used_generic4<T>(x: Vec<T>) { }
| ^^^^^^ not FFI-safe
Expand All @@ -179,13 +152,13 @@ LL | pub extern "C" fn used_generic4<T>(x: Vec<T>) { }
= note: this struct has unspecified layout

error: `extern` fn uses type `std::vec::Vec<T>`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:177:41
--> $DIR/lint-ctypes-fn.rs:176:41
|
LL | pub extern "C" fn used_generic5<T>() -> Vec<T> {
| ^^^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout

error: aborting due to 20 previous errors
error: aborting due to 17 previous errors

2 changes: 2 additions & 0 deletions src/test/ui/lint/lint-ctypes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ extern {
pub fn slice_type(p: &[u32]); //~ ERROR: uses type `[u32]`
pub fn str_type(p: &str); //~ ERROR: uses type `str`
pub fn box_type(p: Box<u32>); //~ ERROR uses type `std::boxed::Box<u32>`
pub fn opt_box_type(p: Option<Box<u32>>);
//~^ ERROR uses type `std::option::Option<std::boxed::Box<u32>>`
pub fn char_type(p: char); //~ ERROR uses type `char`
pub fn i128_type(p: i128); //~ ERROR uses type `i128`
pub fn u128_type(p: u128); //~ ERROR uses type `u128`
Expand Down
Loading

0 comments on commit 95df802

Please sign in to comment.