Skip to content

Commit

Permalink
improper_ctypes: allow pointers to sized types
Browse files Browse the repository at this point in the history
This commit changes the improper ctypes lint (when operating on
definitions) to consider raw pointers or references to sized types as
FFI-safe.

Signed-off-by: David Wood <[email protected]>
  • Loading branch information
davidtwco committed Jun 24, 2020
1 parent 14ea7a7 commit 5c86348
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 85 deletions.
11 changes: 10 additions & 1 deletion src/librustc_lint/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt, TypeFoldable};
use rustc_span::source_map;
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_span::{Span, DUMMY_SP};
use rustc_target::abi::{Integer, LayoutOf, TagEncoding, VariantIdx, Variants};
use rustc_target::spec::abi::Abi;

Expand Down Expand Up @@ -818,6 +818,15 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
help: Some("consider using a struct instead".into()),
},

ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _)
if {
matches!(self.mode, ImproperCTypesMode::Definitions)
&& ty.is_sized(self.cx.tcx.at(DUMMY_SP), self.cx.param_env)
} =>
{
FfiSafe
}

ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) => {
self.check_type_for_ffi(cache, ty)
}
Expand Down
4 changes: 0 additions & 4 deletions src/test/ui/lint/lint-ctypes-fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,8 @@ pub struct TransparentCustomZst(i32, ZeroSize);
pub struct ZeroSizeWithPhantomData(PhantomData<i32>);

pub extern "C" fn ptr_type1(size: *const Foo) { }
//~^ ERROR: uses type `Foo`

pub extern "C" fn ptr_type2(size: *const Foo) { }
//~^ ERROR: uses type `Foo`

pub extern "C" fn slice_type(p: &[u32]) { }
//~^ ERROR: uses type `[u32]`
Expand Down Expand Up @@ -159,7 +157,6 @@ pub extern "C" fn good1(size: *const libc::c_int) { }
pub extern "C" fn good2(size: *const libc::c_uint) { }

pub extern "C" fn unused_generic1<T>(size: *const Foo) { }
//~^ ERROR: uses type `Foo`

pub extern "C" fn unused_generic2<T>() -> PhantomData<bool> {
//~^ ERROR uses type `std::marker::PhantomData<bool>`
Expand All @@ -169,7 +166,6 @@ pub extern "C" fn unused_generic2<T>() -> PhantomData<bool> {
pub extern "C" fn used_generic1<T>(x: T) { }

pub extern "C" fn used_generic2<T>(x: T, size: *const Foo) { }
//~^ ERROR: uses type `Foo`

pub extern "C" fn used_generic3<T: Default>() -> T {
Default::default()
Expand Down
104 changes: 24 additions & 80 deletions src/test/ui/lint/lint-ctypes-fn.stderr
Original file line number Diff line number Diff line change
@@ -1,47 +1,19 @@
error: `extern` fn uses type `Foo`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:63:35
error: `extern` fn uses type `[u32]`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:67:33
|
LL | pub extern "C" fn ptr_type1(size: *const Foo) { }
| ^^^^^^^^^^ not FFI-safe
LL | pub extern "C" fn slice_type(p: &[u32]) { }
| ^^^^^^ not FFI-safe
|
note: the lint level is defined here
--> $DIR/lint-ctypes-fn.rs:4:9
|
LL | #![deny(improper_ctypes_definitions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: the type is defined here
--> $DIR/lint-ctypes-fn.rs:34:1
|
LL | pub struct Foo;
| ^^^^^^^^^^^^^^^

error: `extern` fn uses type `Foo`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:66:35
|
LL | pub extern "C" fn ptr_type2(size: *const Foo) { }
| ^^^^^^^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: the type is defined here
--> $DIR/lint-ctypes-fn.rs:34:1
|
LL | pub struct Foo;
| ^^^^^^^^^^^^^^^

error: `extern` fn uses type `[u32]`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:69:33
|
LL | pub extern "C" fn slice_type(p: &[u32]) { }
| ^^^^^^ not FFI-safe
|
= help: consider using a raw pointer instead
= note: slices have no C equivalent

error: `extern` fn uses type `str`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:72:31
--> $DIR/lint-ctypes-fn.rs:70:31
|
LL | pub extern "C" fn str_type(p: &str) { }
| ^^^^ not FFI-safe
Expand All @@ -50,7 +22,7 @@ LL | pub extern "C" fn str_type(p: &str) { }
= 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:75:31
--> $DIR/lint-ctypes-fn.rs:73:31
|
LL | pub extern "C" fn box_type(p: Box<u32>) { }
| ^^^^^^^^ not FFI-safe
Expand All @@ -59,7 +31,7 @@ LL | pub extern "C" fn box_type(p: Box<u32>) { }
= note: this struct has unspecified layout

error: `extern` fn uses type `char`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:78:32
--> $DIR/lint-ctypes-fn.rs:76:32
|
LL | pub extern "C" fn char_type(p: char) { }
| ^^^^ not FFI-safe
Expand All @@ -68,23 +40,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:81:32
--> $DIR/lint-ctypes-fn.rs:79: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:84:32
--> $DIR/lint-ctypes-fn.rs:82: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:87:33
--> $DIR/lint-ctypes-fn.rs:85:33
|
LL | pub extern "C" fn tuple_type(p: (i32, i32)) { }
| ^^^^^^^^^^ not FFI-safe
Expand All @@ -93,7 +65,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:90:34
--> $DIR/lint-ctypes-fn.rs:88:34
|
LL | pub extern "C" fn tuple_type2(p: I32Pair) { }
| ^^^^^^^ not FFI-safe
Expand All @@ -102,7 +74,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:93:32
--> $DIR/lint-ctypes-fn.rs:91:32
|
LL | pub extern "C" fn zero_size(p: ZeroSize) { }
| ^^^^^^^^ not FFI-safe
Expand All @@ -116,7 +88,7 @@ LL | pub struct ZeroSize;
| ^^^^^^^^^^^^^^^^^^^^

error: `extern` fn uses type `ZeroSizeWithPhantomData`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:96:40
--> $DIR/lint-ctypes-fn.rs:94:40
|
LL | pub extern "C" fn zero_size_phantom(p: ZeroSizeWithPhantomData) { }
| ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
Expand All @@ -129,15 +101,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:99:51
--> $DIR/lint-ctypes-fn.rs:97: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:104:30
--> $DIR/lint-ctypes-fn.rs:102:30
|
LL | pub extern "C" fn fn_type(p: RustFn) { }
| ^^^^^^ not FFI-safe
Expand All @@ -146,7 +118,7 @@ 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:107:31
--> $DIR/lint-ctypes-fn.rs:105:31
|
LL | pub extern "C" fn fn_type2(p: fn()) { }
| ^^^^ not FFI-safe
Expand All @@ -155,7 +127,7 @@ LL | pub extern "C" fn fn_type2(p: fn()) { }
= 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:110:35
--> $DIR/lint-ctypes-fn.rs:108:35
|
LL | pub extern "C" fn fn_contained(p: RustBadRet) { }
| ^^^^^^^^^^ not FFI-safe
Expand All @@ -164,15 +136,15 @@ LL | pub extern "C" fn fn_contained(p: RustBadRet) { }
= note: this struct has unspecified layout

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

error: `extern` fn uses type `str`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:116:38
--> $DIR/lint-ctypes-fn.rs:114:38
|
LL | pub extern "C" fn transparent_str(p: TransparentStr) { }
| ^^^^^^^^^^^^^^ not FFI-safe
Expand All @@ -181,52 +153,24 @@ LL | pub extern "C" fn transparent_str(p: TransparentStr) { }
= 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:119:37
--> $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 `Foo`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:161:44
|
LL | pub extern "C" fn unused_generic1<T>(size: *const Foo) { }
| ^^^^^^^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: the type is defined here
--> $DIR/lint-ctypes-fn.rs:34:1
|
LL | pub struct Foo;
| ^^^^^^^^^^^^^^^

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

error: `extern` fn uses type `Foo`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:171:48
|
LL | pub extern "C" fn used_generic2<T>(x: T, size: *const Foo) { }
| ^^^^^^^^^^ not FFI-safe
|
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: the type is defined here
--> $DIR/lint-ctypes-fn.rs:34:1
|
LL | pub struct Foo;
| ^^^^^^^^^^^^^^^

error: `extern` fn uses type `std::vec::Vec<T>`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:178:39
--> $DIR/lint-ctypes-fn.rs:174:39
|
LL | pub extern "C" fn used_generic4<T>(x: Vec<T>) { }
| ^^^^^^ not FFI-safe
Expand All @@ -235,13 +179,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:181:41
--> $DIR/lint-ctypes-fn.rs:177: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 24 previous errors
error: aborting due to 20 previous errors

0 comments on commit 5c86348

Please sign in to comment.