Skip to content

Commit c1d3db3

Browse files
committed
ImproperCTypes: change handling of slices
correctly handle !Sized arrays at the tail-end of structs and a cosmetic change to the array/slice-related lints,
1 parent ec80a09 commit c1d3db3

File tree

6 files changed

+45
-22
lines changed

6 files changed

+45
-22
lines changed

compiler/rustc_lint/messages.ftl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,8 +371,7 @@ lint_improper_ctypes_only_phantomdata = composed only of `PhantomData`
371371
372372
lint_improper_ctypes_opaque = opaque types have no C equivalent
373373
374-
lint_improper_ctypes_slice_help = consider using a raw pointer instead
375-
374+
lint_improper_ctypes_slice_help = consider using a raw pointer to the slice's first element (and a length) instead
376375
lint_improper_ctypes_slice_reason = slices have no C equivalent
377376
378377
lint_improper_ctypes_str_help = consider using `*const u8` and a length instead

compiler/rustc_lint/src/types/improper_ctypes.rs

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -641,8 +641,8 @@ enum OuterTyKind {
641641
},
642642
/// For struct/enum/union fields
643643
AdtField,
644-
/// Placeholder for properties that will be used eventually
645-
UnusedVariant,
644+
/// For arrays/slices but also tuples
645+
OtherItem,
646646
}
647647

648648
impl OuterTyKind {
@@ -660,7 +660,7 @@ impl OuterTyKind {
660660
Self::AdtField
661661
}
662662
}
663-
ty::Tuple(..) | ty::Array(..) | ty::Slice(_) => Self::UnusedVariant,
663+
ty::Tuple(..) | ty::Array(..) | ty::Slice(_) => Self::OtherItem,
664664
k @ _ => bug!("Unexpected outer type {:?} of kind {:?}", ty, k),
665665
}
666666
}
@@ -730,6 +730,15 @@ impl VisitorState {
730730
Self::entry_point(RootUseFlags::STATIC_TY)
731731
}
732732

733+
/// Whether the type is used as the type of a static variable.
734+
fn is_direct_in_static(&self) -> bool {
735+
let ret = self.root_use_flags.contains(RootUseFlags::STATIC);
736+
if ret {
737+
debug_assert!(!self.root_use_flags.contains(RootUseFlags::FUNC));
738+
}
739+
ret && matches!(self.outer_ty_kind, OuterTyKind::None)
740+
}
741+
733742
/// Whether the type is used in a function.
734743
fn is_in_function(&self) -> bool {
735744
let ret = self.root_use_flags.contains(RootUseFlags::FUNC);
@@ -784,6 +793,11 @@ impl VisitorState {
784793
fn is_raw_pointee(&self) -> bool {
785794
matches!(self.outer_ty_kind, OuterTyKind::Pointee { raw: true, .. })
786795
}
796+
797+
/// Whether the current type directly in the memory layout of the parent ty
798+
fn is_memory_inlined(&self) -> bool {
799+
matches!(self.outer_ty_kind, OuterTyKind::AdtField | OuterTyKind::OtherItem)
800+
}
787801
}
788802

789803
/// Visitor used to recursively traverse MIR types and evaluate FFI-safety.
@@ -1254,11 +1268,21 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
12541268
Some(fluent::lint_improper_ctypes_char_help),
12551269
),
12561270

1257-
ty::Slice(_) => FfiResult::new_with_reason(
1258-
ty,
1259-
fluent::lint_improper_ctypes_slice_reason,
1260-
Some(fluent::lint_improper_ctypes_slice_help),
1261-
),
1271+
ty::Slice(inner_ty) => {
1272+
// ty::Slice is used for !Sized arrays, since they are the pointee for actual slices
1273+
let slice_is_actually_array =
1274+
state.is_memory_inlined() || state.is_direct_in_static();
1275+
1276+
if slice_is_actually_array {
1277+
self.visit_type(state.get_next(ty), inner_ty)
1278+
} else {
1279+
FfiResult::new_with_reason(
1280+
ty,
1281+
fluent::lint_improper_ctypes_slice_reason,
1282+
Some(fluent::lint_improper_ctypes_slice_help),
1283+
)
1284+
}
1285+
}
12621286

12631287
ty::Dynamic(..) => {
12641288
FfiResult::new_with_reason(ty, fluent::lint_improper_ctypes_dyn, None)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: `extern` callback uses type `&[u8]`, which is not FFI-safe
44
LL | pub type F = extern "C" fn(&[u8]);
55
| ^^^^^ not FFI-safe
66
|
7-
= help: consider using a raw pointer instead
7+
= help: consider using a raw pointer to the slice's first element (and a length) instead
88
= 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/extern-C-fnptr-lints-slices.rs:1:8

tests/ui/lint/improper-ctypes/lint-94223.stderr

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: `extern` callback uses type `[u8]`, which is not FFI-safe
44
LL | pub fn bad(f: extern "C" fn([u8])) {}
55
| ^^^^ not FFI-safe
66
|
7-
= help: consider using a raw pointer instead
7+
= help: consider using a raw pointer to the slice's first element (and a length) instead
88
= note: slices have no C equivalent
99
note: the lint level is defined here
1010
--> $DIR/lint-94223.rs:2:38
@@ -18,7 +18,7 @@ error: `extern` callback uses type `[u8]`, which is not FFI-safe
1818
LL | pub fn bad_twice(f: Result<extern "C" fn([u8]), extern "C" fn([u8])>) {}
1919
| ^^^^ not FFI-safe
2020
|
21-
= help: consider using a raw pointer instead
21+
= help: consider using a raw pointer to the slice's first element (and a length) instead
2222
= note: slices have no C equivalent
2323

2424
error: `extern` callback uses type `[u8]`, which is not FFI-safe
@@ -27,7 +27,7 @@ error: `extern` callback uses type `[u8]`, which is not FFI-safe
2727
LL | pub fn bad_twice(f: Result<extern "C" fn([u8]), extern "C" fn([u8])>) {}
2828
| ^^^^ not FFI-safe
2929
|
30-
= help: consider using a raw pointer instead
30+
= help: consider using a raw pointer to the slice's first element (and a length) instead
3131
= note: slices have no C equivalent
3232

3333
error: `extern` callback uses type `[u8]`, which is not FFI-safe
@@ -36,7 +36,7 @@ error: `extern` callback uses type `[u8]`, which is not FFI-safe
3636
LL | struct BadStruct(extern "C" fn([u8]));
3737
| ^^^^ not FFI-safe
3838
|
39-
= help: consider using a raw pointer instead
39+
= help: consider using a raw pointer to the slice's first element (and a length) instead
4040
= note: slices have no C equivalent
4141

4242
error: `extern` callback uses type `[u8]`, which is not FFI-safe
@@ -45,7 +45,7 @@ error: `extern` callback uses type `[u8]`, which is not FFI-safe
4545
LL | A(extern "C" fn([u8])),
4646
| ^^^^ not FFI-safe
4747
|
48-
= help: consider using a raw pointer instead
48+
= help: consider using a raw pointer to the slice's first element (and a length) instead
4949
= note: slices have no C equivalent
5050

5151
error: `extern` callback uses type `[u8]`, which is not FFI-safe
@@ -54,7 +54,7 @@ error: `extern` callback uses type `[u8]`, which is not FFI-safe
5454
LL | A(extern "C" fn([u8])),
5555
| ^^^^ not FFI-safe
5656
|
57-
= help: consider using a raw pointer instead
57+
= help: consider using a raw pointer to the slice's first element (and a length) instead
5858
= note: slices have no C equivalent
5959

6060
error: `extern` callback uses type `[u8]`, which is not FFI-safe
@@ -63,7 +63,7 @@ error: `extern` callback uses type `[u8]`, which is not FFI-safe
6363
LL | type Foo = extern "C" fn([u8]);
6464
| ^^^^ not FFI-safe
6565
|
66-
= help: consider using a raw pointer instead
66+
= help: consider using a raw pointer to the slice's first element (and a length) instead
6767
= note: slices have no C equivalent
6868

6969
error: `extern` callback uses type `Option<&<T as FooTrait>::FooType>`, which is not FFI-safe

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: `extern` block uses type `&[u32]`, which is not FFI-safe
44
LL | pub fn slice_type(p: &[u32]);
55
| ^^^^^^ not FFI-safe
66
|
7-
= help: consider using a raw pointer instead
7+
= help: consider using a raw pointer to the slice's first element (and a length) instead
88
= 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.rs:5:9
@@ -177,7 +177,7 @@ note: the type is defined here
177177
|
178178
LL | pub struct TwoBadTypes<'a> {
179179
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
180-
= help: consider using a raw pointer instead
180+
= help: consider using a raw pointer to the slice's first element (and a length) instead
181181
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
182182

183183
error: `extern` block uses type `&UnsizedStructBecauseDyn`, which is not FFI-safe

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ error: `extern` fn uses type `&[u32]`, which is not FFI-safe
1818
LL | pub extern "C" fn slice_type(p: &[u32]) { }
1919
| ^^^^^^ not FFI-safe
2020
|
21-
= help: consider using a raw pointer instead
21+
= help: consider using a raw pointer to the slice's first element (and a length) instead
2222
= note: this reference to an unsized type contains metadata, which makes it incompatible with a C pointer
2323
note: the lint level is defined here
2424
--> $DIR/lint-fn.rs:2:26
@@ -41,7 +41,7 @@ error: `extern` fn uses type `Box<[u8]>`, which is not FFI-safe
4141
LL | pub extern "C" fn boxed_slice(p: Box<[u8]>) { }
4242
| ^^^^^^^^^ not FFI-safe
4343
|
44-
= help: consider using a raw pointer instead
44+
= help: consider using a raw pointer to the slice's first element (and a length) instead
4545
= note: this box for an unsized type contains metadata, which makes it incompatible with a C pointer
4646

4747
error: `extern` fn uses type `Box<str>`, which is not FFI-safe

0 commit comments

Comments
 (0)