Skip to content

Commit f043685

Browse files
committed
ImproperCTypes: change what type is blamed, use nested help messages
A major change to the content of linting messages, but not where they occur. Now, the "uses type `_`" part of the message mentions the type directly visible where the error occurs, and the nested note/help messages trace the link to the actual source of the FFI-unsafety
1 parent 04f6cc5 commit f043685

16 files changed

+123
-30
lines changed

compiler/rustc_lint/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,8 @@ lint_improper_ctypes_str_reason = string slices have no C equivalent
380380
lint_improper_ctypes_struct_fieldless_help = consider adding a member to this struct
381381
382382
lint_improper_ctypes_struct_fieldless_reason = this struct has no fields
383+
lint_improper_ctypes_struct_dueto = this struct/enum/union (`{$ty}`) is FFI-unsafe due to a `{$inner_ty}` field
384+
383385
lint_improper_ctypes_struct_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
384386
385387
lint_improper_ctypes_struct_layout_reason = this struct has unspecified layout

compiler/rustc_lint/src/types/improper_ctypes.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,6 @@ impl<'tcx> FfiResult<'tcx> {
436436
/// For instance, if we have a repr(C) struct in a function's argument, FFI unsafeties inside the struct
437437
/// are to be blamed on the struct and not the members.
438438
/// This is where we use this wrapper, to tell "all FFI-unsafeties in there are caused by this `ty`"
439-
#[expect(unused)]
440439
fn with_overrides(mut self, override_cause_ty: Option<Ty<'tcx>>) -> FfiResult<'tcx> {
441440
use FfiResult::*;
442441

@@ -982,7 +981,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
982981
all_phantom &= match self.visit_type(state.get_next(ty), field_ty) {
983982
FfiSafe => false,
984983
FfiPhantom(..) => true,
985-
r @ FfiUnsafe { .. } => return r,
984+
r @ FfiUnsafe { .. } => {
985+
return r.wrap_all(ty, fluent::lint_improper_ctypes_struct_dueto, None);
986+
}
986987
}
987988
}
988989

@@ -1033,7 +1034,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
10331034
);
10341035
}
10351036

1036-
if def.non_enum_variant().fields.is_empty() {
1037+
let ffires = if def.non_enum_variant().fields.is_empty() {
10371038
FfiResult::new_with_reason(
10381039
ty,
10391040
if def.is_struct() {
@@ -1049,7 +1050,15 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
10491050
)
10501051
} else {
10511052
self.visit_variant_fields(state, ty, def, def.non_enum_variant(), args)
1052-
}
1053+
};
1054+
1055+
// Here, if there is something wrong, then the "fault" comes from inside the struct itself.
1056+
// Even if we add more details to the lint, the initial line must specify that
1057+
// the FFI-unsafety is because of the struct
1058+
// Plus, if the struct is from another crate, then there's not much that can be done anyways
1059+
//
1060+
// So, we override the "cause type" of the lint.
1061+
ffires.with_overrides(Some(ty))
10531062
}
10541063

10551064
fn visit_enum(
@@ -1096,10 +1105,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
10961105
}
10971106
});
10981107
if let ControlFlow::Break(result) = ret {
1099-
return result;
1108+
// this enum is visited in the middle of another lint,
1109+
// so we override the "cause type" of the lint
1110+
// (for more detail, see comment in ``visit_struct_union`` before its call to ``result.with_overrides``)
1111+
result.with_overrides(Some(ty))
1112+
} else {
1113+
FfiSafe
11001114
}
1101-
1102-
FfiSafe
11031115
}
11041116

11051117
/// Checks if the given type is "ffi-safe" (has a stable, well-defined

tests/ui/extern/extern-C-non-FFI-safe-arg-ice-52334.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ type Foo = extern "C" fn(::std::ffi::CStr);
88
//~^ WARN `extern` callback uses type
99
extern "C" {
1010
fn meh(blah: Foo);
11+
// ^ FIXME: the error isn't seen here but at least it's reported elsewhere
1112
}
1213

1314
fn main() {

tests/ui/extern/extern-C-str-arg-ice-80125.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ pub struct Struct(ExternCallback);
77

88
#[no_mangle]
99
pub extern "C" fn register_something(bind: ExternCallback) -> Struct {
10-
//~^ WARN `extern` fn uses type `Struct`, which is not FFI-safe
10+
// ^ FIXME: the error isn't seen here, but at least it's reported elsewhere
11+
//~^^ WARN `extern` fn uses type `Struct`, which is not FFI-safe
1112
Struct(bind)
1213
}
1314

tests/ui/lint/improper-ctypes/lint-113436-1.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ pub struct Bar {
2020
}
2121

2222
extern "C" fn bar(x: Bar) -> Bar {
23-
//~^ ERROR `extern` fn uses type `NotSafe`, which is not FFI-safe
24-
//~^^ ERROR `extern` fn uses type `NotSafe`, which is not FFI-safe
23+
//~^ ERROR `extern` fn uses type `Bar`, which is not FFI-safe
24+
//~^^ ERROR `extern` fn uses type `Bar`, which is not FFI-safe
2525
todo!()
2626
}
2727

tests/ui/lint/improper-ctypes/lint-113436-1.stderr

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1-
error: `extern` fn uses type `NotSafe`, which is not FFI-safe
1+
error: `extern` fn uses type `Bar`, which is not FFI-safe
22
--> $DIR/lint-113436-1.rs:22:22
33
|
44
LL | extern "C" fn bar(x: Bar) -> Bar {
55
| ^^^ not FFI-safe
66
|
7+
= note: this struct/enum/union (`Bar`) is FFI-unsafe due to a `NotSafe` field
8+
note: the type is defined here
9+
--> $DIR/lint-113436-1.rs:16:1
10+
|
11+
LL | pub struct Bar {
12+
| ^^^^^^^^^^^^^^
713
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
814
= note: this struct has unspecified layout
915
note: the type is defined here
@@ -17,12 +23,18 @@ note: the lint level is defined here
1723
LL | #![deny(improper_ctypes_definitions)]
1824
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
1925

20-
error: `extern` fn uses type `NotSafe`, which is not FFI-safe
26+
error: `extern` fn uses type `Bar`, which is not FFI-safe
2127
--> $DIR/lint-113436-1.rs:22:30
2228
|
2329
LL | extern "C" fn bar(x: Bar) -> Bar {
2430
| ^^^ not FFI-safe
2531
|
32+
= note: this struct/enum/union (`Bar`) is FFI-unsafe due to a `NotSafe` field
33+
note: the type is defined here
34+
--> $DIR/lint-113436-1.rs:16:1
35+
|
36+
LL | pub struct Bar {
37+
| ^^^^^^^^^^^^^^
2638
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
2739
= note: this struct has unspecified layout
2840
note: the type is defined here

tests/ui/lint/improper-ctypes/lint-73249-3.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub struct A {
1818
}
1919

2020
extern "C" {
21-
pub fn lint_me() -> A; //~ ERROR: uses type `Qux`
21+
pub fn lint_me() -> A; //~ ERROR: `extern` block uses type `A`
2222
}
2323

2424
fn main() {}

tests/ui/lint/improper-ctypes/lint-73249-3.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1-
error: `extern` block uses type `Qux`, which is not FFI-safe
1+
error: `extern` block uses type `A`, which is not FFI-safe
22
--> $DIR/lint-73249-3.rs:21:25
33
|
44
LL | pub fn lint_me() -> A;
55
| ^ not FFI-safe
66
|
7+
= note: this struct/enum/union (`A`) is FFI-unsafe due to a `Qux` field
8+
note: the type is defined here
9+
--> $DIR/lint-73249-3.rs:16:1
10+
|
11+
LL | pub struct A {
12+
| ^^^^^^^^^^^^
713
= note: opaque types have no C equivalent
814
note: the lint level is defined here
915
--> $DIR/lint-73249-3.rs:2:9

tests/ui/lint/improper-ctypes/lint-73249-5.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub struct A {
1818
}
1919

2020
extern "C" {
21-
pub fn lint_me() -> A; //~ ERROR: uses type `Qux`
21+
pub fn lint_me() -> A; //~ ERROR: uses type `A`
2222
}
2323

2424
fn main() {}

tests/ui/lint/improper-ctypes/lint-73249-5.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: `extern` block uses type `Qux`, which is not FFI-safe
1+
error: `extern` block uses type `A`, which is not FFI-safe
22
--> $DIR/lint-73249-5.rs:21:25
33
|
44
LL | pub fn lint_me() -> A;

0 commit comments

Comments
 (0)