Skip to content

Commit 8b6289f

Browse files
committed
lint ImproperCTypes: message tweaks and refactoring from code review
1 parent 9b59dd8 commit 8b6289f

7 files changed

+52
-49
lines changed

compiler/rustc_lint/messages.ftl

+4-4
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ lint_improper_ctypes_pat_help = consider using the base type instead
391391
lint_improper_ctypes_pat_reason = pattern types have no C equivalent
392392
393393
lint_improper_ctypes_sized_ptr_to_unsafe_type =
394-
this reference (`{$ty}`) is can safely be translated into a C pointer, but `{$inner_ty}` itself is not FFI-safe
394+
this reference (`{$ty}`) is ABI-compatible with a C pointer, but `{$inner_ty}` itself does not have a C layout
395395
396396
lint_improper_ctypes_slice_help = consider using a raw pointer to the slice's first element (and a length) instead
397397
@@ -419,9 +419,9 @@ lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[re
419419
lint_improper_ctypes_union_layout_reason = this union has unspecified layout
420420
lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive
421421
422-
lint_improper_ctypes_unsized_box = this box for an unsized rust type contains metadata, which makes it incompatible with a C pointer
423-
lint_improper_ctypes_unsized_ptr = this pointer to an unsized rust type contains metadata, which makes it incompatible with a C pointer
424-
lint_improper_ctypes_unsized_ref = this reference to an unsized rust type contains metadata, which makes it incompatible with a C pointer
422+
lint_improper_ctypes_unsized_box = this box for an unsized type contains metadata, which makes it incompatible with a C pointer
423+
lint_improper_ctypes_unsized_ptr = this pointer to an unsized type contains metadata, which makes it incompatible with a C pointer
424+
lint_improper_ctypes_unsized_ref = this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
425425
426426
lint_incomplete_include =
427427
include macro expected single expression in source

compiler/rustc_lint/src/types.rs

+27-24
Original file line numberDiff line numberDiff line change
@@ -743,10 +743,10 @@ enum FfiResult<'tcx> {
743743
/// Determine if a type is sized or not, and wether it affects references/pointers/boxes to it
744744
#[derive(Clone, Copy)]
745745
enum TypeSizedness {
746-
/// sized type (pointers are C-compatible)
747-
Sized,
746+
/// type of definite size (pointers are C-compatible)
747+
Definite,
748748
/// unsized type because it includes an opaque/foreign type (pointers are C-compatible)
749-
UnsizedBecauseForeign,
749+
UnsizedWithExternType,
750750
/// unsized type for other reasons (slice, string, dyn Trait, closure, ...) (pointers are not C-compatible)
751751
UnsizedWithMetadata,
752752
}
@@ -757,13 +757,13 @@ fn get_type_sizedness<'tcx, 'a>(cx: &'a LateContext<'tcx>, ty: Ty<'tcx>) -> Type
757757
let tcx = cx.tcx;
758758

759759
if ty.is_sized(tcx, cx.typing_env()) {
760-
TypeSizedness::Sized
760+
TypeSizedness::Definite
761761
} else {
762762
match ty.kind() {
763763
ty::Slice(_) => TypeSizedness::UnsizedWithMetadata,
764764
ty::Str => TypeSizedness::UnsizedWithMetadata,
765765
ty::Dynamic(..) => TypeSizedness::UnsizedWithMetadata,
766-
ty::Foreign(..) => TypeSizedness::UnsizedBecauseForeign,
766+
ty::Foreign(..) => TypeSizedness::UnsizedWithExternType,
767767
// While opaque types are checked for earlier, if a projection in a struct field
768768
// normalizes to an opaque type, then it will reach this branch.
769769
ty::Alias(ty::Opaque, ..) => todo!("We... don't know enough about this type yet?"),
@@ -797,8 +797,8 @@ fn get_type_sizedness<'tcx, 'a>(cx: &'a LateContext<'tcx>, ty: Ty<'tcx>) -> Type
797797
.unwrap_or(field_ty);
798798
match get_type_sizedness(cx, field_ty) {
799799
s @ (TypeSizedness::UnsizedWithMetadata
800-
| TypeSizedness::UnsizedBecauseForeign) => s,
801-
TypeSizedness::Sized => {
800+
| TypeSizedness::UnsizedWithExternType) => s,
801+
TypeSizedness::Definite => {
802802
bug!("failed to find the reason why struct `{:?}` is unsized", ty)
803803
}
804804
}
@@ -816,16 +816,16 @@ fn get_type_sizedness<'tcx, 'a>(cx: &'a LateContext<'tcx>, ty: Ty<'tcx>) -> Type
816816
.unwrap_or(field_ty);
817817
match get_type_sizedness(cx, field_ty) {
818818
s @ (TypeSizedness::UnsizedWithMetadata
819-
| TypeSizedness::UnsizedBecauseForeign) => s,
820-
TypeSizedness::Sized => {
819+
| TypeSizedness::UnsizedWithExternType) => s,
820+
TypeSizedness::Definite => {
821821
bug!("failed to find the reason why tuple `{:?}` is unsized", ty)
822822
}
823823
}
824824
}
825-
t => {
825+
ty => {
826826
bug!(
827827
"we shouldn't be trying to determine if this is unsized for a reason or another: `{:?}`",
828-
t
828+
ty
829829
)
830830
}
831831
}
@@ -1135,7 +1135,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
11351135
match *ty.kind() {
11361136
ty::Adt(def, args) => {
11371137
if let Some(inner_ty) = ty.boxed_ty() {
1138-
if let TypeSizedness::UnsizedBecauseForeign | TypeSizedness::Sized =
1138+
if let TypeSizedness::UnsizedWithExternType | TypeSizedness::Definite =
11391139
get_type_sizedness(self.cx, inner_ty)
11401140
{
11411141
// discussion on declaration vs definition:
@@ -1340,24 +1340,27 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
13401340
}
13411341

13421342
ty::RawPtr(inner_ty, _) | ty::Ref(_, inner_ty, _) => {
1343-
if let TypeSizedness::UnsizedBecauseForeign | TypeSizedness::Sized =
1343+
if let TypeSizedness::UnsizedWithExternType | TypeSizedness::Definite =
13441344
get_type_sizedness(self.cx, inner_ty)
13451345
{
1346-
// there's a nuance on what this lint should do for function definitions
1347-
// (`extern "C" fn fn_name(...) {...}`) versus declarations (`extern "C" {fn fn_name(...);}`).
1348-
// (this is touched upon in https://github.com/rust-lang/rust/issues/66220
1349-
// and https://github.com/rust-lang/rust/pull/72700)
1346+
// there's a nuance on what this lint should do for
1347+
// function definitions (`extern "C" fn fn_name(...) {...}`)
1348+
// versus declarations (`unsafe extern "C" {fn fn_name(...);}`).
1349+
// This is touched upon in https://github.com/rust-lang/rust/issues/66220
1350+
// and https://github.com/rust-lang/rust/pull/72700
13501351
//
13511352
// The big question is: what does "ABI safety" mean? if you have something translated to a C pointer
13521353
// (which has a stable layout) but points to FFI-unsafe type, is it safe?
1353-
// on one hand, the function's ABI will match that of a similar C-declared function API,
1354-
// on the other, dereferencing the pointer in not-rust will be painful.
1355-
// In this code, the opinion is split between function declarations and function definitions.
1354+
// On one hand, the function's ABI will match that of a similar C-declared function API,
1355+
// on the other, dereferencing the pointer on the other side of the FFI boundary will be painful.
1356+
// In this code, the opinion on is split between function declarations and function definitions,
1357+
// with the idea that at least one side of the FFI boundary needs to treat the pointee as an opaque type.
13561358
// For declarations, we see this as unsafe, but for definitions, we see this as safe.
1357-
// This is mostly because, for extern function declarations, the actual definition of the function is written somewhere else,
1358-
// so the fact that a pointer's pointee should be treated as opaque to one side or the other can be explicitely written out.
1359-
// For extern function definitions, however, both callee and some callers can be written in rust,
1360-
// so developers need to keep as much typing information as possible.
1359+
//
1360+
// For extern function declarations, the actual definition of the function is written somewhere else,
1361+
// meaning the declaration is free to express this opaqueness with an extern type (opaque caller-side) or a std::ffi::c_void (opaque callee-side)
1362+
// For extern function definitions, however, in the case where the type is opaque caller-side, it is not opaque callee-side,
1363+
// and having the full type information is necessary to compile the function.
13611364
if matches!(self.mode, CItemKind::Definition) {
13621365
return FfiSafe;
13631366
} else if matches!(ty.kind(), ty::RawPtr(..))

tests/ui/lint/extern-C-fnptr-lints-slices.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ LL | pub type F = extern "C" fn(&[u8]);
66
|
77
= note: the function pointer to `for<'a> extern "C" fn(&'a [u8])` is FFI-unsafe due to `&[u8]`
88
= help: consider using a raw pointer to the slice's first element (and a length) instead
9-
= note: this reference to an unsized rust type contains metadata, which makes it incompatible with a C pointer
9+
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
1010
note: the lint level is defined here
1111
--> $DIR/extern-C-fnptr-lints-slices.rs:1:8
1212
|

tests/ui/lint/lint-ctypes-73249-2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: `extern` block uses type `Qux`, which is not FFI-safe
44
LL | fn lint_me() -> A<()>;
55
| ^^^^^ not FFI-safe
66
|
7-
= note: this reference (`&Qux`) is can safely be translated into a C pointer, but `Qux` itself is not FFI-safe
7+
= note: this reference (`&Qux`) is ABI-compatible with a C pointer, but `Qux` itself does not have a C layout
88
= note: opaque types have no C equivalent
99
note: the lint level is defined here
1010
--> $DIR/lint-ctypes-73249-2.rs:2:9

tests/ui/lint/lint-ctypes-cstr.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ LL | fn take_cstr_ref(s: &CStr);
1919
| ^^^^^ not FFI-safe
2020
|
2121
= help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()`
22-
= note: this reference to an unsized rust type contains metadata, which makes it incompatible with a C pointer
22+
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
2323

2424
error: `extern` block uses type `CString`, which is not FFI-safe
2525
--> $DIR/lint-ctypes-cstr.rs:13:24
@@ -36,7 +36,7 @@ error: `extern` block uses type `CString`, which is not FFI-safe
3636
LL | fn take_cstring_ref(s: &CString);
3737
| ^^^^^^^^ not FFI-safe
3838
|
39-
= note: this reference (`&CString`) is can safely be translated into a C pointer, but `CString` itself is not FFI-safe
39+
= note: this reference (`&CString`) is ABI-compatible with a C pointer, but `CString` itself does not have a C layout
4040
= help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()`
4141
= note: `CStr`/`CString` do not have a guaranteed layout
4242

@@ -46,7 +46,7 @@ error: `extern` block uses type `CString`, which is not FFI-safe
4646
LL | fn no_special_help_for_mut_cstring(s: *mut CString);
4747
| ^^^^^^^^^^^^ not FFI-safe
4848
|
49-
= note: this reference (`*mut CString`) is can safely be translated into a C pointer, but `CString` itself is not FFI-safe
49+
= note: this reference (`*mut CString`) is ABI-compatible with a C pointer, but `CString` itself does not have a C layout
5050
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
5151
= note: this struct has unspecified layout
5252

@@ -56,7 +56,7 @@ error: `extern` block uses type `CString`, which is not FFI-safe
5656
LL | fn no_special_help_for_mut_cstring_ref(s: &mut CString);
5757
| ^^^^^^^^^^^^ not FFI-safe
5858
|
59-
= note: this reference (`&mut CString`) is can safely be translated into a C pointer, but `CString` itself is not FFI-safe
59+
= note: this reference (`&mut CString`) is ABI-compatible with a C pointer, but `CString` itself does not have a C layout
6060
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
6161
= note: this struct has unspecified layout
6262

@@ -67,7 +67,7 @@ LL | extern "C" fn rust_take_cstr_ref(s: &CStr) {}
6767
| ^^^^^ not FFI-safe
6868
|
6969
= help: consider passing a `*const std::ffi::c_char` instead, and use `CStr::as_ptr()`
70-
= note: this reference to an unsized rust type contains metadata, which makes it incompatible with a C pointer
70+
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
7171
note: the lint level is defined here
7272
--> $DIR/lint-ctypes-cstr.rs:2:26
7373
|

tests/ui/lint/lint-ctypes-fn.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | pub extern "C" fn slice_type(p: &[u32]) { }
55
| ^^^^^^ not FFI-safe
66
|
77
= help: consider using a raw pointer to the slice's first element (and a length) instead
8-
= note: this reference to an unsized rust type contains metadata, which makes it incompatible with a C pointer
8+
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
99
note: the lint level is defined here
1010
--> $DIR/lint-ctypes-fn.rs:2:9
1111
|
@@ -19,7 +19,7 @@ LL | pub extern "C" fn str_type(p: &str) { }
1919
| ^^^^ not FFI-safe
2020
|
2121
= help: consider using `*const u8` and a length instead
22-
= note: this reference to an unsized rust type contains metadata, which makes it incompatible with a C pointer
22+
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
2323

2424
error: `extern` fn uses type `Box<[u8]>`, which is not FFI-safe
2525
--> $DIR/lint-ctypes-fn.rs:80:34
@@ -28,7 +28,7 @@ LL | pub extern "C" fn boxed_slice(p: Box<[u8]>) { }
2828
| ^^^^^^^^^ not FFI-safe
2929
|
3030
= help: consider using a raw pointer to the slice's first element (and a length) instead
31-
= note: this box for an unsized rust type contains metadata, which makes it incompatible with a C pointer
31+
= note: this box for an unsized type contains metadata, which makes it incompatible with a C pointer
3232

3333
error: `extern` fn uses type `Box<str>`, which is not FFI-safe
3434
--> $DIR/lint-ctypes-fn.rs:83:35
@@ -37,15 +37,15 @@ LL | pub extern "C" fn boxed_string(p: Box<str>) { }
3737
| ^^^^^^^^ not FFI-safe
3838
|
3939
= help: consider using `*const u8` and a length instead
40-
= note: this box for an unsized rust type contains metadata, which makes it incompatible with a C pointer
40+
= note: this box for an unsized type contains metadata, which makes it incompatible with a C pointer
4141

4242
error: `extern` fn uses type `Box<dyn Trait>`, which is not FFI-safe
4343
--> $DIR/lint-ctypes-fn.rs:86:34
4444
|
4545
LL | pub extern "C" fn boxed_trait(p: Box<dyn Trait>) { }
4646
| ^^^^^^^^^^^^^^ not FFI-safe
4747
|
48-
= note: this box for an unsized rust type contains metadata, which makes it incompatible with a C pointer
48+
= note: this box for an unsized type contains metadata, which makes it incompatible with a C pointer
4949

5050
error: `extern` fn uses type `char`, which is not FFI-safe
5151
--> $DIR/lint-ctypes-fn.rs:89:32
@@ -158,7 +158,7 @@ LL | pub extern "C" fn transparent_str(p: TransparentStr) { }
158158
| ^^^^^^^^^^^^^^ not FFI-safe
159159
|
160160
= help: consider using `*const u8` and a length instead
161-
= note: this reference to an unsized rust type contains metadata, which makes it incompatible with a C pointer
161+
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
162162

163163
error: `extern` fn uses type `PhantomData<bool>`, which is not FFI-safe
164164
--> $DIR/lint-ctypes-fn.rs:172:43

tests/ui/lint/lint-ctypes.stderr

+8-8
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: `extern` block uses type `Foo`, which is not FFI-safe
44
LL | pub fn ptr_type1(size: *const Foo);
55
| ^^^^^^^^^^ not FFI-safe
66
|
7-
= note: this reference (`*const Foo`) is can safely be translated into a C pointer, but `Foo` itself is not FFI-safe
7+
= note: this reference (`*const Foo`) is ABI-compatible with a C pointer, but `Foo` itself does not have a C layout
88
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
99
= note: this struct has unspecified layout
1010
note: the type is defined here
@@ -24,7 +24,7 @@ error: `extern` block uses type `Foo`, which is not FFI-safe
2424
LL | pub fn ptr_type2(size: *const Foo);
2525
| ^^^^^^^^^^ not FFI-safe
2626
|
27-
= note: this reference (`*const Foo`) is can safely be translated into a C pointer, but `Foo` itself is not FFI-safe
27+
= note: this reference (`*const Foo`) is ABI-compatible with a C pointer, but `Foo` itself does not have a C layout
2828
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
2929
= note: this struct has unspecified layout
3030
note: the type is defined here
@@ -39,7 +39,7 @@ error: `extern` block uses type `((),)`, which is not FFI-safe
3939
LL | pub fn ptr_tuple(p: *const ((),));
4040
| ^^^^^^^^^^^^ not FFI-safe
4141
|
42-
= note: this reference (`*const ((),)`) is can safely be translated into a C pointer, but `((),)` itself is not FFI-safe
42+
= note: this reference (`*const ((),)`) is ABI-compatible with a C pointer, but `((),)` itself does not have a C layout
4343
= help: consider using a struct instead
4444
= note: tuples have unspecified layout
4545

@@ -50,7 +50,7 @@ LL | pub fn slice_type(p: &[u32]);
5050
| ^^^^^^ not FFI-safe
5151
|
5252
= help: consider using a raw pointer to the slice's first element (and a length) instead
53-
= note: this reference to an unsized rust type contains metadata, which makes it incompatible with a C pointer
53+
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
5454

5555
error: `extern` block uses type `&str`, which is not FFI-safe
5656
--> $DIR/lint-ctypes.rs:65:24
@@ -59,7 +59,7 @@ LL | pub fn str_type(p: &str);
5959
| ^^^^ not FFI-safe
6060
|
6161
= help: consider using `*const u8` and a length instead
62-
= note: this reference to an unsized rust type contains metadata, which makes it incompatible with a C pointer
62+
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
6363

6464
error: `extern` block uses type `char`, which is not FFI-safe
6565
--> $DIR/lint-ctypes.rs:68:25
@@ -92,7 +92,7 @@ error: `extern` block uses type `&dyn Bar`, which is not FFI-safe
9292
LL | pub fn trait_type(p: &dyn Bar);
9393
| ^^^^^^^^ not FFI-safe
9494
|
95-
= note: this reference to an unsized rust type contains metadata, which makes it incompatible with a C pointer
95+
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
9696

9797
error: `extern` block uses type `(i32, i32)`, which is not FFI-safe
9898
--> $DIR/lint-ctypes.rs:72:26
@@ -180,7 +180,7 @@ LL | pub fn transparent_str(p: TransparentStr);
180180
| ^^^^^^^^^^^^^^ not FFI-safe
181181
|
182182
= help: consider using `*const u8` and a length instead
183-
= note: this reference to an unsized rust type contains metadata, which makes it incompatible with a C pointer
183+
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
184184

185185
error: `extern` block uses type `[u8; 8]`, which is not FFI-safe
186186
--> $DIR/lint-ctypes.rs:85:27
@@ -197,7 +197,7 @@ error: `extern` block uses type `&UnsizedStructBecauseDyn`, which is not FFI-saf
197197
LL | pub fn struct_unsized_ptr_has_metadata(p: &UnsizedStructBecauseDyn);
198198
| ^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
199199
|
200-
= note: this reference to an unsized rust type contains metadata, which makes it incompatible with a C pointer
200+
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
201201

202202
error: `extern` block uses type `Option<UnsafeCell<extern "C" fn()>>`, which is not FFI-safe
203203
--> $DIR/lint-ctypes.rs:90:26

0 commit comments

Comments
 (0)