Skip to content

Commit 9d71217

Browse files
committed
Refactor "not FFI-safe" diagnostic
1 parent 79368db commit 9d71217

13 files changed

+202
-132
lines changed

src/librustc_lint/types.rs

+45-27
Original file line numberDiff line numberDiff line change
@@ -859,30 +859,62 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
859859
}
860860
}
861861

862+
fn emit_ffi_unsafe_type_lint(
863+
&mut self,
864+
ty: Ty<'tcx>,
865+
sp: Span,
866+
note: &str,
867+
help: Option<&str>,
868+
) {
869+
let mut diag = self.cx.struct_span_lint(
870+
IMPROPER_CTYPES,
871+
sp,
872+
&format!("`extern` block uses type `{}`, which is not FFI-safe", ty),
873+
);
874+
diag.span_label(sp, "not FFI-safe");
875+
if let Some(help) = help {
876+
diag.help(help);
877+
}
878+
diag.note(note);
879+
if let ty::Adt(def, _) = ty.sty {
880+
if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did) {
881+
diag.span_note(sp, "type defined here");
882+
}
883+
}
884+
diag.emit();
885+
}
886+
862887
fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool {
863888
use crate::rustc::ty::TypeFoldable;
864889

865-
struct ProhibitOpaqueTypes<'a, 'tcx> {
866-
cx: &'a LateContext<'a, 'tcx>,
867-
sp: Span,
890+
struct ProhibitOpaqueTypes<'tcx> {
891+
ty: Option<Ty<'tcx>>,
868892
};
869893

870-
impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> {
894+
impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'tcx> {
871895
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
872896
if let ty::Opaque(..) = ty.sty {
873-
self.cx.span_lint(IMPROPER_CTYPES,
874-
self.sp,
875-
&format!("`extern` block uses type `{}` which is not FFI-safe: \
876-
opaque types have no C equivalent", ty));
897+
self.ty = Some(ty);
877898
true
878899
} else {
879900
ty.super_visit_with(self)
880901
}
881902
}
882903
}
883904

884-
let mut visitor = ProhibitOpaqueTypes { cx: self.cx, sp };
885-
ty.visit_with(&mut visitor)
905+
let mut visitor = ProhibitOpaqueTypes { ty: None };
906+
ty.visit_with(&mut visitor);
907+
if let Some(ty) = visitor.ty {
908+
self.emit_ffi_unsafe_type_lint(
909+
ty,
910+
sp,
911+
"opaque types have no C equivalent",
912+
None,
913+
);
914+
true
915+
} else {
916+
false
917+
}
886918
}
887919

888920
fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>) {
@@ -900,24 +932,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
900932
match self.check_type_for_ffi(&mut FxHashSet::default(), ty) {
901933
FfiResult::FfiSafe => {}
902934
FfiResult::FfiPhantom(ty) => {
903-
self.cx.span_lint(IMPROPER_CTYPES,
904-
sp,
905-
&format!("`extern` block uses type `{}` which is not FFI-safe: \
906-
composed only of `PhantomData`", ty));
935+
self.emit_ffi_unsafe_type_lint(ty, sp, "composed only of `PhantomData`", None);
907936
}
908-
FfiResult::FfiUnsafe { ty: unsafe_ty, reason, help } => {
909-
let msg = format!("`extern` block uses type `{}` which is not FFI-safe: {}",
910-
unsafe_ty, reason);
911-
let mut diag = self.cx.struct_span_lint(IMPROPER_CTYPES, sp, &msg);
912-
if let Some(s) = help {
913-
diag.help(s);
914-
}
915-
if let ty::Adt(def, _) = unsafe_ty.sty {
916-
if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did) {
917-
diag.span_note(sp, "type defined here");
918-
}
919-
}
920-
diag.emit();
937+
FfiResult::FfiUnsafe { ty, reason, help } => {
938+
self.emit_ffi_unsafe_type_lint(ty, sp, reason, help);
921939
}
922940
}
923941
}

src/test/ui/issues/issue-14309.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ struct D {
2727
}
2828

2929
extern "C" {
30-
fn foo(x: A); //~ ERROR type `A` which is not FFI-safe
30+
fn foo(x: A); //~ ERROR type `A`, which is not FFI-safe
3131
fn bar(x: B); //~ ERROR type `A`
3232
fn baz(x: C);
3333
fn qux(x: A2); //~ ERROR type `A`

src/test/ui/issues/issue-14309.stderr

+15-10
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
1+
error: `extern` block uses type `A`, which is not FFI-safe
22
--> $DIR/issue-14309.rs:30:15
33
|
44
LL | fn foo(x: A);
5-
| ^
5+
| ^ not FFI-safe
66
|
77
note: lint level defined here
88
--> $DIR/issue-14309.rs:1:9
99
|
1010
LL | #![deny(improper_ctypes)]
1111
| ^^^^^^^^^^^^^^^
1212
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
13+
= note: this struct has unspecified layout
1314
note: type defined here
1415
--> $DIR/issue-14309.rs:4:1
1516
|
@@ -18,13 +19,14 @@ LL | | x: i32
1819
LL | | }
1920
| |_^
2021

21-
error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
22+
error: `extern` block uses type `A`, which is not FFI-safe
2223
--> $DIR/issue-14309.rs:31:15
2324
|
2425
LL | fn bar(x: B);
25-
| ^
26+
| ^ not FFI-safe
2627
|
2728
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
29+
= note: this struct has unspecified layout
2830
note: type defined here
2931
--> $DIR/issue-14309.rs:4:1
3032
|
@@ -33,13 +35,14 @@ LL | | x: i32
3335
LL | | }
3436
| |_^
3537

36-
error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
38+
error: `extern` block uses type `A`, which is not FFI-safe
3739
--> $DIR/issue-14309.rs:33:15
3840
|
3941
LL | fn qux(x: A2);
40-
| ^^
42+
| ^^ not FFI-safe
4143
|
4244
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
45+
= note: this struct has unspecified layout
4346
note: type defined here
4447
--> $DIR/issue-14309.rs:4:1
4548
|
@@ -48,13 +51,14 @@ LL | | x: i32
4851
LL | | }
4952
| |_^
5053

51-
error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
54+
error: `extern` block uses type `A`, which is not FFI-safe
5255
--> $DIR/issue-14309.rs:34:16
5356
|
5457
LL | fn quux(x: B2);
55-
| ^^
58+
| ^^ not FFI-safe
5659
|
5760
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
61+
= note: this struct has unspecified layout
5862
note: type defined here
5963
--> $DIR/issue-14309.rs:4:1
6064
|
@@ -63,13 +67,14 @@ LL | | x: i32
6367
LL | | }
6468
| |_^
6569

66-
error: `extern` block uses type `A` which is not FFI-safe: this struct has unspecified layout
70+
error: `extern` block uses type `A`, which is not FFI-safe
6771
--> $DIR/issue-14309.rs:36:16
6872
|
6973
LL | fn fred(x: D);
70-
| ^
74+
| ^ not FFI-safe
7175
|
7276
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
77+
= note: this struct has unspecified layout
7378
note: type defined here
7479
--> $DIR/issue-14309.rs:4:1
7580
|

src/test/ui/issues/issue-16250.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
pub struct Foo;
44

55
extern {
6-
pub fn foo(x: (Foo)); //~ ERROR unspecified layout
6+
pub fn foo(x: (Foo)); //~ ERROR `extern` block uses type `Foo`
77
}
88

99
fn main() {

src/test/ui/issues/issue-16250.stderr

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: `extern` block uses type `Foo` which is not FFI-safe: this struct has unspecified layout
1+
error: `extern` block uses type `Foo`, which is not FFI-safe
22
--> $DIR/issue-16250.rs:6:20
33
|
44
LL | pub fn foo(x: (Foo));
5-
| ^^^
5+
| ^^^ not FFI-safe
66
|
77
note: lint level defined here
88
--> $DIR/issue-16250.rs:1:9
@@ -11,6 +11,7 @@ LL | #![deny(warnings)]
1111
| ^^^^^^^^
1212
= note: `#[deny(improper_ctypes)]` implied by `#[deny(warnings)]`
1313
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
14+
= note: this struct has unspecified layout
1415
note: type defined here
1516
--> $DIR/issue-16250.rs:3:1
1617
|

src/test/ui/lint/lint-ctypes-enum.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -36,36 +36,37 @@ struct Rust<T>(T);
3636

3737
extern {
3838
fn zf(x: Z);
39-
fn uf(x: U); //~ ERROR enum has no representation hint
40-
fn bf(x: B); //~ ERROR enum has no representation hint
41-
fn tf(x: T); //~ ERROR enum has no representation hint
39+
fn uf(x: U); //~ ERROR `extern` block uses type `U`
40+
fn bf(x: B); //~ ERROR `extern` block uses type `B`
41+
fn tf(x: T); //~ ERROR `extern` block uses type `T`
4242
fn repr_c(x: ReprC);
4343
fn repr_u8(x: U8);
4444
fn repr_isize(x: Isize);
4545
fn option_ref(x: Option<&'static u8>);
4646
fn option_fn(x: Option<extern "C" fn()>);
4747
fn nonnull(x: Option<std::ptr::NonNull<u8>>);
48-
fn unique(x: Option<std::ptr::Unique<u8>>); //~ ERROR enum has no representation hint
48+
fn unique(x: Option<std::ptr::Unique<u8>>);
49+
//~^ ERROR `extern` block uses type `std::option::Option<std::ptr::Unique<u8>>`
4950
fn nonzero_u8(x: Option<num::NonZeroU8>);
5051
fn nonzero_u16(x: Option<num::NonZeroU16>);
5152
fn nonzero_u32(x: Option<num::NonZeroU32>);
5253
fn nonzero_u64(x: Option<num::NonZeroU64>);
5354
fn nonzero_u128(x: Option<num::NonZeroU128>);
54-
//~^ ERROR 128-bit integers don't currently have a known stable ABI
55+
//~^ ERROR `extern` block uses type `u128`
5556
fn nonzero_usize(x: Option<num::NonZeroUsize>);
5657
fn nonzero_i8(x: Option<num::NonZeroI8>);
5758
fn nonzero_i16(x: Option<num::NonZeroI16>);
5859
fn nonzero_i32(x: Option<num::NonZeroI32>);
5960
fn nonzero_i64(x: Option<num::NonZeroI64>);
6061
fn nonzero_i128(x: Option<num::NonZeroI128>);
61-
//~^ ERROR 128-bit integers don't currently have a known stable ABI
62+
//~^ ERROR `extern` block uses type `i128`
6263
fn nonzero_isize(x: Option<num::NonZeroIsize>);
6364
fn transparent_struct(x: Option<TransparentStruct<num::NonZeroU8>>);
6465
fn transparent_enum(x: Option<TransparentEnum<num::NonZeroU8>>);
6566
fn transparent_union(x: Option<TransparentUnion<num::NonZeroU8>>);
66-
//~^ ERROR enum has no representation hint
67-
fn repr_rust(x: Option<Rust<num::NonZeroU8>>); //~ ERROR enum has no representation hint
68-
fn no_result(x: Result<(), num::NonZeroI32>); //~ ERROR enum has no representation hint
67+
//~^ ERROR `extern` block uses type
68+
fn repr_rust(x: Option<Rust<num::NonZeroU8>>); //~ ERROR `extern` block uses type
69+
fn no_result(x: Result<(), num::NonZeroI32>); //~ ERROR `extern` block uses type
6970
}
7071

71-
pub fn main() { }
72+
pub fn main() {}
+34-23
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,101 @@
1-
error: `extern` block uses type `U` which is not FFI-safe: enum has no representation hint
1+
error: `extern` block uses type `U`, which is not FFI-safe
22
--> $DIR/lint-ctypes-enum.rs:39:13
33
|
44
LL | fn uf(x: U);
5-
| ^
5+
| ^ not FFI-safe
66
|
77
note: lint level defined here
88
--> $DIR/lint-ctypes-enum.rs:3:9
99
|
1010
LL | #![deny(improper_ctypes)]
1111
| ^^^^^^^^^^^^^^^
1212
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
13+
= note: enum has no representation hint
1314
note: type defined here
1415
--> $DIR/lint-ctypes-enum.rs:9:1
1516
|
1617
LL | enum U { A }
1718
| ^^^^^^^^^^^^
1819

19-
error: `extern` block uses type `B` which is not FFI-safe: enum has no representation hint
20+
error: `extern` block uses type `B`, which is not FFI-safe
2021
--> $DIR/lint-ctypes-enum.rs:40:13
2122
|
2223
LL | fn bf(x: B);
23-
| ^
24+
| ^ not FFI-safe
2425
|
2526
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
27+
= note: enum has no representation hint
2628
note: type defined here
2729
--> $DIR/lint-ctypes-enum.rs:10:1
2830
|
2931
LL | enum B { C, D }
3032
| ^^^^^^^^^^^^^^^
3133

32-
error: `extern` block uses type `T` which is not FFI-safe: enum has no representation hint
34+
error: `extern` block uses type `T`, which is not FFI-safe
3335
--> $DIR/lint-ctypes-enum.rs:41:13
3436
|
3537
LL | fn tf(x: T);
36-
| ^
38+
| ^ not FFI-safe
3739
|
3840
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
41+
= note: enum has no representation hint
3942
note: type defined here
4043
--> $DIR/lint-ctypes-enum.rs:11:1
4144
|
4245
LL | enum T { E, F, G }
4346
| ^^^^^^^^^^^^^^^^^^
4447

45-
error: `extern` block uses type `std::option::Option<std::ptr::Unique<u8>>` which is not FFI-safe: enum has no representation hint
48+
error: `extern` block uses type `std::option::Option<std::ptr::Unique<u8>>`, which is not FFI-safe
4649
--> $DIR/lint-ctypes-enum.rs:48:17
4750
|
4851
LL | fn unique(x: Option<std::ptr::Unique<u8>>);
49-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
52+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
5053
|
5154
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
55+
= note: enum has no representation hint
5256

53-
error: `extern` block uses type `u128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
54-
--> $DIR/lint-ctypes-enum.rs:53:23
57+
error: `extern` block uses type `u128`, which is not FFI-safe
58+
--> $DIR/lint-ctypes-enum.rs:54:23
5559
|
5660
LL | fn nonzero_u128(x: Option<num::NonZeroU128>);
57-
| ^^^^^^^^^^^^^^^^^^^^^^^^
61+
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
62+
|
63+
= note: 128-bit integers don't currently have a known stable ABI
5864

59-
error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
60-
--> $DIR/lint-ctypes-enum.rs:60:23
65+
error: `extern` block uses type `i128`, which is not FFI-safe
66+
--> $DIR/lint-ctypes-enum.rs:61:23
6167
|
6268
LL | fn nonzero_i128(x: Option<num::NonZeroI128>);
63-
| ^^^^^^^^^^^^^^^^^^^^^^^^
69+
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
70+
|
71+
= note: 128-bit integers don't currently have a known stable ABI
6472

65-
error: `extern` block uses type `std::option::Option<TransparentUnion<std::num::NonZeroU8>>` which is not FFI-safe: enum has no representation hint
66-
--> $DIR/lint-ctypes-enum.rs:65:28
73+
error: `extern` block uses type `std::option::Option<TransparentUnion<std::num::NonZeroU8>>`, which is not FFI-safe
74+
--> $DIR/lint-ctypes-enum.rs:66:28
6775
|
6876
LL | fn transparent_union(x: Option<TransparentUnion<num::NonZeroU8>>);
69-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
77+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
7078
|
7179
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
80+
= note: enum has no representation hint
7281

73-
error: `extern` block uses type `std::option::Option<Rust<std::num::NonZeroU8>>` which is not FFI-safe: enum has no representation hint
74-
--> $DIR/lint-ctypes-enum.rs:67:20
82+
error: `extern` block uses type `std::option::Option<Rust<std::num::NonZeroU8>>`, which is not FFI-safe
83+
--> $DIR/lint-ctypes-enum.rs:68:20
7584
|
7685
LL | fn repr_rust(x: Option<Rust<num::NonZeroU8>>);
77-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
86+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
7887
|
7988
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
89+
= note: enum has no representation hint
8090

81-
error: `extern` block uses type `std::result::Result<(), std::num::NonZeroI32>` which is not FFI-safe: enum has no representation hint
82-
--> $DIR/lint-ctypes-enum.rs:68:20
91+
error: `extern` block uses type `std::result::Result<(), std::num::NonZeroI32>`, which is not FFI-safe
92+
--> $DIR/lint-ctypes-enum.rs:69:20
8393
|
8494
LL | fn no_result(x: Result<(), num::NonZeroI32>);
85-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
95+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
8696
|
8797
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
98+
= note: enum has no representation hint
8899

89100
error: aborting due to 9 previous errors
90101

0 commit comments

Comments
 (0)