Skip to content

Commit bce6664

Browse files
authored
Rollup merge of rust-lang#48221 - rkruppe:improve-ctypes-lint, r=estebank
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
2 parents 23cf624 + 051ea5c commit bce6664

File tree

7 files changed

+316
-166
lines changed

7 files changed

+316
-166
lines changed

src/librustc_lint/types.rs

+104-136
Large diffs are not rendered by default.

src/test/compile-fail/issue-14309.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ struct D {
3737
}
3838

3939
extern "C" {
40-
fn foo(x: A); //~ ERROR found struct without foreign-function-safe
41-
fn bar(x: B); //~ ERROR foreign-function-safe
40+
fn foo(x: A); //~ ERROR type `A` which is not FFI-safe
41+
fn bar(x: B); //~ ERROR type `A`
4242
fn baz(x: C);
43-
fn qux(x: A2); //~ ERROR foreign-function-safe
44-
fn quux(x: B2); //~ ERROR foreign-function-safe
43+
fn qux(x: A2); //~ ERROR type `A`
44+
fn quux(x: B2); //~ ERROR type `A`
4545
fn corge(x: C2);
46-
fn fred(x: D); //~ ERROR foreign-function-safe
46+
fn fred(x: D); //~ ERROR type `A`
4747
}
4848

4949
fn main() { }

src/test/compile-fail/issue-16250.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
pub struct Foo;
1414

1515
extern {
16-
pub fn foo(x: (Foo)); //~ ERROR found struct without
16+
pub fn foo(x: (Foo)); //~ ERROR unspecified layout
1717
}
1818

1919
fn main() {

src/test/compile-fail/lint-ctypes-enum.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,23 @@ enum U { A }
1616
enum B { C, D }
1717
enum T { E, F, G }
1818

19+
#[repr(C)]
20+
enum ReprC { A, B, C }
21+
22+
#[repr(u8)]
23+
enum U8 { A, B, C }
24+
25+
#[repr(isize)]
26+
enum Isize { A, B, C }
27+
1928
extern {
2029
fn zf(x: Z);
21-
fn uf(x: U); //~ ERROR found enum without foreign-function-safe
22-
fn bf(x: B); //~ ERROR found enum without foreign-function-safe
23-
fn tf(x: T); //~ ERROR found enum without foreign-function-safe
30+
fn uf(x: U); //~ ERROR enum has no representation hint
31+
fn bf(x: B); //~ ERROR enum has no representation hint
32+
fn tf(x: T); //~ ERROR enum has no representation hint
33+
fn reprc(x: ReprC);
34+
fn u8(x: U8);
35+
fn isize(x: Isize);
2436
}
2537

2638
pub fn main() { }

src/test/compile-fail/union/union-repr-c.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ union W {
2222

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

2828
fn main() {}

src/test/compile-fail/lint-ctypes.rs src/test/ui/lint-ctypes.rs

+20-20
Original file line numberDiff line numberDiff line change
@@ -51,27 +51,27 @@ pub struct TransparentCustomZst(i32, ZeroSize);
5151
pub struct ZeroSizeWithPhantomData(::std::marker::PhantomData<i32>);
5252

5353
extern {
54-
pub fn ptr_type1(size: *const Foo); //~ ERROR: found struct without
55-
pub fn ptr_type2(size: *const Foo); //~ ERROR: found struct without
56-
pub fn slice_type(p: &[u32]); //~ ERROR: found Rust slice type
57-
pub fn str_type(p: &str); //~ ERROR: found Rust type
58-
pub fn box_type(p: Box<u32>); //~ ERROR found struct without
59-
pub fn char_type(p: char); //~ ERROR found Rust type
60-
pub fn i128_type(p: i128); //~ ERROR found Rust type
61-
pub fn u128_type(p: u128); //~ ERROR found Rust type
62-
pub fn trait_type(p: &Clone); //~ ERROR found Rust trait type
63-
pub fn tuple_type(p: (i32, i32)); //~ ERROR found Rust tuple type
64-
pub fn tuple_type2(p: I32Pair); //~ ERROR found Rust tuple type
65-
pub fn zero_size(p: ZeroSize); //~ ERROR found zero-size struct
66-
pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); //~ ERROR found zero-sized type
54+
pub fn ptr_type1(size: *const Foo); //~ ERROR: uses type `Foo`
55+
pub fn ptr_type2(size: *const Foo); //~ ERROR: uses type `Foo`
56+
pub fn slice_type(p: &[u32]); //~ ERROR: uses type `[u32]`
57+
pub fn str_type(p: &str); //~ ERROR: uses type `str`
58+
pub fn box_type(p: Box<u32>); //~ ERROR uses type `std::boxed::Box<u32>`
59+
pub fn char_type(p: char); //~ ERROR uses type `char`
60+
pub fn i128_type(p: i128); //~ ERROR uses type `i128`
61+
pub fn u128_type(p: u128); //~ ERROR uses type `u128`
62+
pub fn trait_type(p: &Clone); //~ ERROR uses type `std::clone::Clone`
63+
pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)`
64+
pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)`
65+
pub fn zero_size(p: ZeroSize); //~ ERROR struct has no fields
66+
pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); //~ ERROR composed only of PhantomData
6767
pub fn zero_size_phantom_toplevel()
68-
-> ::std::marker::PhantomData<bool>; //~ ERROR: found zero-sized type
69-
pub fn fn_type(p: RustFn); //~ ERROR found function pointer with Rust
70-
pub fn fn_type2(p: fn()); //~ ERROR found function pointer with Rust
71-
pub fn fn_contained(p: RustBadRet); //~ ERROR: found struct without
72-
pub fn transparent_i128(p: TransparentI128); //~ ERROR: found Rust type `i128`
73-
pub fn transparent_str(p: TransparentStr); //~ ERROR: found Rust type `str`
74-
pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: found struct without
68+
-> ::std::marker::PhantomData<bool>; //~ ERROR: composed only of PhantomData
69+
pub fn fn_type(p: RustFn); //~ ERROR function pointer has Rust-specific
70+
pub fn fn_type2(p: fn()); //~ ERROR function pointer has Rust-specific
71+
pub fn fn_contained(p: RustBadRet); //~ ERROR: uses type `std::boxed::Box<u32>`
72+
pub fn transparent_i128(p: TransparentI128); //~ ERROR: uses type `i128`
73+
pub fn transparent_str(p: TransparentStr); //~ ERROR: uses type `str`
74+
pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: uses type `std::boxed::Box<u32>`
7575

7676
pub fn good3(fptr: Option<extern fn()>);
7777
pub fn good4(aptr: &[u8; 4 as usize]);

src/test/ui/lint-ctypes.stderr

+170
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout
2+
--> $DIR/lint-ctypes.rs:54:28
3+
|
4+
54 | pub fn ptr_type1(size: *const Foo); //~ ERROR: uses type `Foo`
5+
| ^^^^^^^^^^
6+
|
7+
note: lint level defined here
8+
--> $DIR/lint-ctypes.rs:11:9
9+
|
10+
11 | #![deny(improper_ctypes)]
11+
| ^^^^^^^^^^^^^^^
12+
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
13+
note: type defined here
14+
--> $DIR/lint-ctypes.rs:32:1
15+
|
16+
32 | pub struct Foo;
17+
| ^^^^^^^^^^^^^^^
18+
19+
error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout
20+
--> $DIR/lint-ctypes.rs:55:28
21+
|
22+
55 | pub fn ptr_type2(size: *const Foo); //~ ERROR: uses type `Foo`
23+
| ^^^^^^^^^^
24+
|
25+
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
26+
note: type defined here
27+
--> $DIR/lint-ctypes.rs:32:1
28+
|
29+
32 | pub struct Foo;
30+
| ^^^^^^^^^^^^^^^
31+
32+
error: `extern` block uses type `[u32]` which is not FFI-safe: slices have no C equivalent
33+
--> $DIR/lint-ctypes.rs:56:26
34+
|
35+
56 | pub fn slice_type(p: &[u32]); //~ ERROR: uses type `[u32]`
36+
| ^^^^^^
37+
|
38+
= help: consider using a raw pointer instead
39+
40+
error: `extern` block uses type `str` which is not FFI-safe: string slices have no C equivalent
41+
--> $DIR/lint-ctypes.rs:57:24
42+
|
43+
57 | pub fn str_type(p: &str); //~ ERROR: uses type `str`
44+
| ^^^^
45+
|
46+
= help: consider using `*const u8` and a length instead
47+
48+
error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: this struct has unspecified layout
49+
--> $DIR/lint-ctypes.rs:58:24
50+
|
51+
58 | pub fn box_type(p: Box<u32>); //~ ERROR uses type `std::boxed::Box<u32>`
52+
| ^^^^^^^^
53+
|
54+
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
55+
56+
error: `extern` block uses type `char` which is not FFI-safe: the `char` type has no C equivalent
57+
--> $DIR/lint-ctypes.rs:59:25
58+
|
59+
59 | pub fn char_type(p: char); //~ ERROR uses type `char`
60+
| ^^^^
61+
|
62+
= help: consider using `u32` or `libc::wchar_t` instead
63+
64+
error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
65+
--> $DIR/lint-ctypes.rs:60:25
66+
|
67+
60 | pub fn i128_type(p: i128); //~ ERROR uses type `i128`
68+
| ^^^^
69+
70+
error: `extern` block uses type `u128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
71+
--> $DIR/lint-ctypes.rs:61:25
72+
|
73+
61 | pub fn u128_type(p: u128); //~ ERROR uses type `u128`
74+
| ^^^^
75+
76+
error: `extern` block uses type `std::clone::Clone` which is not FFI-safe: trait objects have no C equivalent
77+
--> $DIR/lint-ctypes.rs:62:26
78+
|
79+
62 | pub fn trait_type(p: &Clone); //~ ERROR uses type `std::clone::Clone`
80+
| ^^^^^^
81+
82+
error: `extern` block uses type `(i32, i32)` which is not FFI-safe: tuples have unspecified layout
83+
--> $DIR/lint-ctypes.rs:63:26
84+
|
85+
63 | pub fn tuple_type(p: (i32, i32)); //~ ERROR uses type `(i32, i32)`
86+
| ^^^^^^^^^^
87+
|
88+
= help: consider using a struct instead
89+
90+
error: `extern` block uses type `(i32, i32)` which is not FFI-safe: tuples have unspecified layout
91+
--> $DIR/lint-ctypes.rs:64:27
92+
|
93+
64 | pub fn tuple_type2(p: I32Pair); //~ ERROR uses type `(i32, i32)`
94+
| ^^^^^^^
95+
|
96+
= help: consider using a struct instead
97+
98+
error: `extern` block uses type `ZeroSize` which is not FFI-safe: this struct has no fields
99+
--> $DIR/lint-ctypes.rs:65:25
100+
|
101+
65 | pub fn zero_size(p: ZeroSize); //~ ERROR struct has no fields
102+
| ^^^^^^^^
103+
|
104+
= help: consider adding a member to this struct
105+
note: type defined here
106+
--> $DIR/lint-ctypes.rs:28:1
107+
|
108+
28 | pub struct ZeroSize;
109+
| ^^^^^^^^^^^^^^^^^^^^
110+
111+
error: `extern` block uses type `ZeroSizeWithPhantomData` which is not FFI-safe: composed only of PhantomData
112+
--> $DIR/lint-ctypes.rs:66:33
113+
|
114+
66 | pub fn zero_size_phantom(p: ZeroSizeWithPhantomData); //~ ERROR composed only of PhantomData
115+
| ^^^^^^^^^^^^^^^^^^^^^^^
116+
117+
error: `extern` block uses type `std::marker::PhantomData<bool>` which is not FFI-safe: composed only of PhantomData
118+
--> $DIR/lint-ctypes.rs:68:12
119+
|
120+
68 | -> ::std::marker::PhantomData<bool>; //~ ERROR: composed only of PhantomData
121+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
122+
123+
error: `extern` block uses type `fn()` which is not FFI-safe: this function pointer has Rust-specific calling convention
124+
--> $DIR/lint-ctypes.rs:69:23
125+
|
126+
69 | pub fn fn_type(p: RustFn); //~ ERROR function pointer has Rust-specific
127+
| ^^^^^^
128+
|
129+
= help: consider using an `fn "extern"(...) -> ...` function pointer instead
130+
131+
error: `extern` block uses type `fn()` which is not FFI-safe: this function pointer has Rust-specific calling convention
132+
--> $DIR/lint-ctypes.rs:70:24
133+
|
134+
70 | pub fn fn_type2(p: fn()); //~ ERROR function pointer has Rust-specific
135+
| ^^^^
136+
|
137+
= help: consider using an `fn "extern"(...) -> ...` function pointer instead
138+
139+
error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: this struct has unspecified layout
140+
--> $DIR/lint-ctypes.rs:71:28
141+
|
142+
71 | pub fn fn_contained(p: RustBadRet); //~ ERROR: uses type `std::boxed::Box<u32>`
143+
| ^^^^^^^^^^
144+
|
145+
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
146+
147+
error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
148+
--> $DIR/lint-ctypes.rs:72:32
149+
|
150+
72 | pub fn transparent_i128(p: TransparentI128); //~ ERROR: uses type `i128`
151+
| ^^^^^^^^^^^^^^^
152+
153+
error: `extern` block uses type `str` which is not FFI-safe: string slices have no C equivalent
154+
--> $DIR/lint-ctypes.rs:73:31
155+
|
156+
73 | pub fn transparent_str(p: TransparentStr); //~ ERROR: uses type `str`
157+
| ^^^^^^^^^^^^^^
158+
|
159+
= help: consider using `*const u8` and a length instead
160+
161+
error: `extern` block uses type `std::boxed::Box<u32>` which is not FFI-safe: this struct has unspecified layout
162+
--> $DIR/lint-ctypes.rs:74:30
163+
|
164+
74 | pub fn transparent_fn(p: TransparentBadFn); //~ ERROR: uses type `std::boxed::Box<u32>`
165+
| ^^^^^^^^^^^^^^^^
166+
|
167+
= help: consider adding a #[repr(C)] or #[repr(transparent)] attribute to this struct
168+
169+
error: aborting due to 20 previous errors
170+

0 commit comments

Comments
 (0)