Skip to content

Commit

Permalink
Rollup merge of rust-lang#48221 - rkruppe:improve-ctypes-lint, r=este…
Browse files Browse the repository at this point in the history
…bank

Overhaul improper_ctypes output

This snowballed into a rather big set of improvements to the diagnostics of the improper_ctypes lint. See commits for details, including effects of each change on the `compile-fail/improper-ctypes.rs` test (now a UI test), which is pretty gnarly and hopefully not representative of real code, but covers a lot of different error cases.

Fixes rust-lang#42050
  • Loading branch information
Manishearth authored Feb 23, 2018
2 parents 5d30cba + 051ea5c commit 9f36a35
Show file tree
Hide file tree
Showing 7 changed files with 316 additions and 166 deletions.
240 changes: 104 additions & 136 deletions src/librustc_lint/types.rs

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions src/test/compile-fail/issue-14309.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ struct D {
}

extern "C" {
fn foo(x: A); //~ ERROR found struct without foreign-function-safe
fn bar(x: B); //~ ERROR foreign-function-safe
fn foo(x: A); //~ ERROR type `A` which is not FFI-safe
fn bar(x: B); //~ ERROR type `A`
fn baz(x: C);
fn qux(x: A2); //~ ERROR foreign-function-safe
fn quux(x: B2); //~ ERROR foreign-function-safe
fn qux(x: A2); //~ ERROR type `A`
fn quux(x: B2); //~ ERROR type `A`
fn corge(x: C2);
fn fred(x: D); //~ ERROR foreign-function-safe
fn fred(x: D); //~ ERROR type `A`
}

fn main() { }
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-16250.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
pub struct Foo;

extern {
pub fn foo(x: (Foo)); //~ ERROR found struct without
pub fn foo(x: (Foo)); //~ ERROR unspecified layout
}

fn main() {
Expand Down
18 changes: 15 additions & 3 deletions src/test/compile-fail/lint-ctypes-enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,23 @@ enum U { A }
enum B { C, D }
enum T { E, F, G }

#[repr(C)]
enum ReprC { A, B, C }

#[repr(u8)]
enum U8 { A, B, C }

#[repr(isize)]
enum Isize { A, B, C }

extern {
fn zf(x: Z);
fn uf(x: U); //~ ERROR found enum without foreign-function-safe
fn bf(x: B); //~ ERROR found enum without foreign-function-safe
fn tf(x: T); //~ ERROR found enum without foreign-function-safe
fn uf(x: U); //~ ERROR enum has no representation hint
fn bf(x: B); //~ ERROR enum has no representation hint
fn tf(x: T); //~ ERROR enum has no representation hint
fn reprc(x: ReprC);
fn u8(x: U8);
fn isize(x: Isize);
}

pub fn main() { }
2 changes: 1 addition & 1 deletion src/test/compile-fail/union/union-repr-c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ union W {

extern "C" {
static FOREIGN1: U; // OK
static FOREIGN2: W; //~ ERROR found union without foreign-function-safe representation
static FOREIGN2: W; //~ ERROR union has unspecified layout
}

fn main() {}
40 changes: 20 additions & 20 deletions src/test/compile-fail/lint-ctypes.rs → src/test/ui/lint-ctypes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,27 +51,27 @@ pub struct TransparentCustomZst(i32, ZeroSize);
pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData<i32>);

extern {
pub fn ptr_type1(size: *const Foo); //~ ERROR: found struct without
pub fn ptr_type2(size: *const Foo); //~ ERROR: found struct without
pub fn slice_type(p: &[u32]); //~ ERROR: found Rust slice type
pub fn str_type(p: &str); //~ ERROR: found Rust type
pub fn box_type(p: Box<u32>); //~ ERROR found struct without
pub fn char_type(p: char); //~ ERROR found Rust type
pub fn i128_type(p: i128); //~ ERROR found Rust type
pub fn u128_type(p: u128); //~ ERROR found Rust type
pub fn trait_type(p: &Clone); //~ ERROR found Rust trait type
pub fn tuple_type(p: (i32, i32)); //~ ERROR found Rust tuple type
pub fn tuple_type2(p: I32Pair); //~ ERROR found Rust tuple type
pub fn zero_size(p: ZeroSize); //~ ERROR found zero-size struct
pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); //~ ERROR found zero-sized type
pub fn ptr_type1(size: *const Foo); //~ ERROR: uses type `Foo`
pub fn ptr_type2(size: *const Foo); //~ ERROR: uses type `Foo`
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 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`
pub fn trait_type(p: &Clone); //~ ERROR uses type `std::clone::Clone`
pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)`
pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)`
pub fn zero_size(p: ZeroSize); //~ ERROR struct has no fields
pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); //~ ERROR composed only of PhantomData
pub fn zero_size_phantom_toplevel()
-> ::std::marker::PhantomData<bool>; //~ ERROR: found zero-sized type
pub fn fn_type(p: RustFn); //~ ERROR found function pointer with Rust
pub fn fn_type2(p: fn()); //~ ERROR found function pointer with Rust
pub fn fn_contained(p: RustBadRet); //~ ERROR: found struct without
pub fn transparent_i128(p: TransparentI128); //~ ERROR: found Rust type `i128`
pub fn transparent_str(p: TransparentStr); //~ ERROR: found Rust type `str`
pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: found struct without
-> ::std::marker::PhantomData<bool>; //~ ERROR: composed only of PhantomData
pub fn fn_type(p: RustFn); //~ ERROR function pointer has Rust-specific
pub fn fn_type2(p: fn()); //~ ERROR function pointer has Rust-specific
pub fn fn_contained(p: RustBadRet); //~ ERROR: uses type `std::boxed::Box<u32>`
pub fn transparent_i128(p: TransparentI128); //~ ERROR: uses type `i128`
pub fn transparent_str(p: TransparentStr); //~ ERROR: uses type `str`
pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: uses type `std::boxed::Box<u32>`

pub fn good3(fptr: Option<extern fn()>);
pub fn good4(aptr: &[u8; 4 as usize]);
Expand Down
170 changes: 170 additions & 0 deletions src/test/ui/lint-ctypes.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout
--> $DIR/lint-ctypes.rs:54:28
|
54 | pub fn ptr_type1(size: *const Foo); //~ ERROR: uses type `Foo`
| ^^^^^^^^^^
|
note: lint level defined here
--> $DIR/lint-ctypes.rs:11:9
|
11 | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
note: type defined here
--> $DIR/lint-ctypes.rs:32:1
|
32 | pub struct Foo;
| ^^^^^^^^^^^^^^^

error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout
--> $DIR/lint-ctypes.rs:55:28
|
55 | pub fn ptr_type2(size: *const Foo); //~ ERROR: uses type `Foo`
| ^^^^^^^^^^
|
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
note: type defined here
--> $DIR/lint-ctypes.rs:32:1
|
32 | pub struct Foo;
| ^^^^^^^^^^^^^^^

error: `extern` block uses type `[u32]` which is not FFI-safe: slices have no C equivalent
--> $DIR/lint-ctypes.rs:56:26
|
56 | pub fn slice_type(p: &[u32]); //~ ERROR: uses type `[u32]`
| ^^^^^^
|
= help: consider using a raw pointer instead

error: `extern` block uses type `str` which is not FFI-safe: string slices have no C equivalent
--> $DIR/lint-ctypes.rs:57:24
|
57 | pub fn str_type(p: &str); //~ ERROR: uses type `str`
| ^^^^
|
= help: consider using `*const u8` and a length instead

error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: this struct has unspecified layout
--> $DIR/lint-ctypes.rs:58:24
|
58 | pub fn box_type(p: Box<u32>); //~ ERROR uses type `std::boxed::Box<u32>`
| ^^^^^^^^
|
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct

error: `extern` block uses type `char` which is not FFI-safe: the `char` type has no C equivalent
--> $DIR/lint-ctypes.rs:59:25
|
59 | pub fn char_type(p: char); //~ ERROR uses type `char`
| ^^^^
|
= help: consider using `u32` or `libc::wchar_t` instead

error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
--> $DIR/lint-ctypes.rs:60:25
|
60 | pub fn i128_type(p: i128); //~ ERROR uses type `i128`
| ^^^^

error: `extern` block uses type `u128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
--> $DIR/lint-ctypes.rs:61:25
|
61 | pub fn u128_type(p: u128); //~ ERROR uses type `u128`
| ^^^^

error: `extern` block uses type `std::clone::Clone` which is not FFI-safe: trait objects have no C equivalent
--> $DIR/lint-ctypes.rs:62:26
|
62 | pub fn trait_type(p: &Clone); //~ ERROR uses type `std::clone::Clone`
| ^^^^^^

error: `extern` block uses type `(i32, i32)` which is not FFI-safe: tuples have unspecified layout
--> $DIR/lint-ctypes.rs:63:26
|
63 | pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)`
| ^^^^^^^^^^
|
= help: consider using a struct instead

error: `extern` block uses type `(i32, i32)` which is not FFI-safe: tuples have unspecified layout
--> $DIR/lint-ctypes.rs:64:27
|
64 | pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)`
| ^^^^^^^
|
= help: consider using a struct instead

error: `extern` block uses type `ZeroSize` which is not FFI-safe: this struct has no fields
--> $DIR/lint-ctypes.rs:65:25
|
65 | pub fn zero_size(p: ZeroSize); //~ ERROR struct has no fields
| ^^^^^^^^
|
= help: consider adding a member to this struct
note: type defined here
--> $DIR/lint-ctypes.rs:28:1
|
28 | pub struct ZeroSize;
| ^^^^^^^^^^^^^^^^^^^^

error: `extern` block uses type `ZeroSizeWithPhantomData` which is not FFI-safe: composed only of PhantomData
--> $DIR/lint-ctypes.rs:66:33
|
66 | pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); //~ ERROR composed only of PhantomData
| ^^^^^^^^^^^^^^^^^^^^^^^

error: `extern` block uses type `std::marker::PhantomData<bool>` which is not FFI-safe: composed only of PhantomData
--> $DIR/lint-ctypes.rs:68:12
|
68 | -> ::std::marker::PhantomData<bool>; //~ ERROR: composed only of PhantomData
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: `extern` block uses type `fn()` which is not FFI-safe: this function pointer has Rust-specific calling convention
--> $DIR/lint-ctypes.rs:69:23
|
69 | pub fn fn_type(p: RustFn); //~ ERROR function pointer has Rust-specific
| ^^^^^^
|
= help: consider using an `fn "extern"(...) -> ...` function pointer instead

error: `extern` block uses type `fn()` which is not FFI-safe: this function pointer has Rust-specific calling convention
--> $DIR/lint-ctypes.rs:70:24
|
70 | pub fn fn_type2(p: fn()); //~ ERROR function pointer has Rust-specific
| ^^^^
|
= help: consider using an `fn "extern"(...) -> ...` function pointer instead

error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: this struct has unspecified layout
--> $DIR/lint-ctypes.rs:71:28
|
71 | pub fn fn_contained(p: RustBadRet); //~ ERROR: uses type `std::boxed::Box<u32>`
| ^^^^^^^^^^
|
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct

error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
--> $DIR/lint-ctypes.rs:72:32
|
72 | pub fn transparent_i128(p: TransparentI128); //~ ERROR: uses type `i128`
| ^^^^^^^^^^^^^^^

error: `extern` block uses type `str` which is not FFI-safe: string slices have no C equivalent
--> $DIR/lint-ctypes.rs:73:31
|
73 | pub fn transparent_str(p: TransparentStr); //~ ERROR: uses type `str`
| ^^^^^^^^^^^^^^
|
= help: consider using `*const u8` and a length instead

error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: this struct has unspecified layout
--> $DIR/lint-ctypes.rs:74:30
|
74 | pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: uses type `std::boxed::Box<u32>`
| ^^^^^^^^^^^^^^^^
|
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct

error: aborting due to 20 previous errors

0 comments on commit 9f36a35

Please sign in to comment.