Skip to content

Commit d931eef

Browse files
committed
lint ImproperCTypes: split the two lints into four total [...]
- now the lint scans repr(C) struct/enum/union definitions - it now also scans method declarations in traits - many other changes in the underlying logic - some extra tests
1 parent 4a71f56 commit d931eef

File tree

120 files changed

+2358
-904
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

120 files changed

+2358
-904
lines changed

compiler/rustc_codegen_cranelift/example/std_example.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ fn rust_call_abi() {
206206
#[repr(simd)]
207207
struct I64X2([i64; 2]);
208208

209-
#[allow(improper_ctypes_definitions)]
209+
#[allow(improper_c_fn_definitions)]
210210
extern "C" fn foo(_a: I64X2) {}
211211

212212
#[cfg(target_arch = "x86_64")]

compiler/rustc_lint/messages.ftl

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ lint_implicit_unsafe_autorefs = implicit autoref creates a reference to the dere
364364
.note = creating a reference requires the pointer target to be valid and imposes aliasing requirements
365365
.suggestion = try using a raw pointer method instead; or if this reference is intentional, make it explicit
366366
367-
lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe
367+
lint_improper_ctypes = {$desc} uses type `{$ty}`, which is not FFI-safe
368368
.label = not FFI-safe
369369
.note = the type is defined here
370370
@@ -414,35 +414,34 @@ lint_improper_ctypes_pat_intrange_reason = integers constrained to a given range
414414
415415
lint_improper_ctypes_ptr_validity_help = consider using a raw pointer, or wrapping `{$ty}` in an `Option<_>`
416416
lint_improper_ctypes_ptr_validity_reason =
417-
boxes and references are assumed to be valid (non-null, non-dangling, aligned) pointers,
417+
boxes, references, and function pointers are assumed to be valid (non-null, non-dangling, aligned) pointers,
418418
which cannot be garanteed if their values are produced by non-rust code
419419
420-
lint_improper_ctypes_sized_ptr_to_unsafe_type =
421-
this reference (`{$ty}`) is ABI-compatible with a C pointer, but `{$inner_ty}` itself does not have a C layout
422-
423420
lint_improper_ctypes_slice_help = consider using a raw pointer to the slice's first element (and a length) instead
424421
lint_improper_ctypes_slice_reason = slices have no C equivalent
425422
426423
lint_improper_ctypes_str_help = consider using `*const u8` and a length instead
427424
lint_improper_ctypes_str_reason = string slices have no C equivalent
428425
426+
lint_improper_ctypes_struct_consider_transparent = `{$ty}` has exactly one non-zero-sized field, consider making it `#[repr(transparent)]` instead
429427
lint_improper_ctypes_struct_dueto = this struct/enum/union (`{$ty}`) is FFI-unsafe due to a `{$inner_ty}` field
430-
lint_improper_ctypes_struct_fieldless_help = consider adding a member to this struct
431428
432-
lint_improper_ctypes_struct_fieldless_reason = this struct has no fields
433-
lint_improper_ctypes_struct_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
429+
lint_improper_ctypes_struct_fieldless_help = consider adding a member to this struct
430+
lint_improper_ctypes_struct_fieldless_reason = `{$ty}` has no fields
434431
435-
lint_improper_ctypes_struct_layout_reason = this struct has unspecified layout
436-
lint_improper_ctypes_struct_non_exhaustive = this struct is non-exhaustive
437-
lint_improper_ctypes_struct_zst = this struct contains only zero-sized fields
432+
lint_improper_ctypes_struct_layout_help = consider adding a `#[repr(C)]` (not `#[repr(C,packed)]`) or `#[repr(transparent)]` attribute to `{$ty}`
433+
lint_improper_ctypes_struct_layout_reason = `{$ty}` has unspecified layout
434+
lint_improper_ctypes_struct_non_exhaustive = `{$ty}` is non-exhaustive
435+
lint_improper_ctypes_struct_zst = `{$ty}` contains only zero-sized fields
438436
439437
lint_improper_ctypes_tuple_help = consider using a struct instead
440-
441438
lint_improper_ctypes_tuple_reason = tuples have unspecified layout
442-
lint_improper_ctypes_union_fieldless_help = consider adding a member to this union
443439
440+
441+
lint_improper_ctypes_union_consider_transparent = `{$ty}` has exactly one non-zero-sized field, consider making it `#[repr(transparent)]` instead
442+
lint_improper_ctypes_union_fieldless_help = consider adding a member to this union
444443
lint_improper_ctypes_union_fieldless_reason = this union has no fields
445-
lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union
444+
lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` attribute to this union
446445
447446
lint_improper_ctypes_union_layout_reason = this union has unspecified layout
448447
lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive

compiler/rustc_lint/src/lib.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,9 @@ late_lint_methods!(
195195
DefaultCouldBeDerived: DefaultCouldBeDerived::default(),
196196
DerefIntoDynSupertrait: DerefIntoDynSupertrait,
197197
DropForgetUseless: DropForgetUseless,
198-
ImproperCTypesDeclarations: ImproperCTypesDeclarations,
199-
ImproperCTypesDefinitions: ImproperCTypesDefinitions,
198+
//ImproperCTypesDeclarations: ImproperCTypesDeclarations,
199+
//ImproperCTypesDefinitions: ImproperCTypesDefinitions,
200+
ImproperCTypesLint: ImproperCTypesLint,
200201
InvalidFromUtf8: InvalidFromUtf8,
201202
VariantSizeDifferences: VariantSizeDifferences,
202203
PathStatements: PathStatements,
@@ -335,6 +336,14 @@ fn register_builtins(store: &mut LintStore) {
335336
REFINING_IMPL_TRAIT_INTERNAL
336337
);
337338

339+
add_lint_group!(
340+
"improper_c_boundaries",
341+
IMPROPER_C_CALLBACKS,
342+
IMPROPER_C_FN_DEFINITIONS,
343+
IMPROPER_CTYPE_DEFINITIONS,
344+
IMPROPER_CTYPES
345+
);
346+
338347
add_lint_group!("deprecated_safe", DEPRECATED_SAFE_2024);
339348

340349
// Register renamed and removed lints.
@@ -353,6 +362,7 @@ fn register_builtins(store: &mut LintStore) {
353362
store.register_renamed("unused_tuple_struct_fields", "dead_code");
354363
store.register_renamed("static_mut_ref", "static_mut_refs");
355364
store.register_renamed("temporary_cstring_as_ptr", "dangling_pointers_from_temporaries");
365+
store.register_renamed("improper_ctypes_definitions", "improper_c_fn_definitions");
356366

357367
// These were moved to tool lints, but rustc still sees them when compiling normally, before
358368
// tool lints are registered, so `check_tool_name_for_backwards_compat` doesn't work. Use

compiler/rustc_lint/src/types.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ use tracing::debug;
1111
use {rustc_ast as ast, rustc_hir as hir};
1212

1313
mod improper_ctypes; // these filed do the implementation for ImproperCTypesDefinitions,ImproperCTypesDeclarations
14-
pub(crate) use improper_ctypes::{ImproperCTypesDeclarations, ImproperCTypesDefinitions};
14+
pub(crate) use improper_ctypes::{
15+
IMPROPER_C_CALLBACKS, IMPROPER_C_FN_DEFINITIONS, IMPROPER_CTYPE_DEFINITIONS, IMPROPER_CTYPES,
16+
ImproperCTypesLint,
17+
};
1518

1619
use crate::lints::{
1720
AmbiguousWidePointerComparisons, AmbiguousWidePointerComparisonsAddrMetadataSuggestion,
@@ -701,6 +704,26 @@ pub(crate) fn transparent_newtype_field<'a, 'tcx>(
701704
})
702705
}
703706

707+
/// for a given ADT variant, list which fields are non-1ZST
708+
/// (`repr(transparent)` guarantees that there is at most one)
709+
pub(crate) fn map_non_1zst_fields<'a, 'tcx>(
710+
tcx: TyCtxt<'tcx>,
711+
variant: &'a ty::VariantDef,
712+
) -> Vec<bool> {
713+
let typing_env = ty::TypingEnv::non_body_analysis(tcx, variant.def_id);
714+
variant
715+
.fields
716+
.iter()
717+
.map(|field| {
718+
let field_ty = tcx.type_of(field.did).instantiate_identity();
719+
let is_1zst = tcx
720+
.layout_of(typing_env.as_query_input(field_ty))
721+
.is_ok_and(|layout| layout.is_1zst());
722+
!is_1zst
723+
})
724+
.collect()
725+
}
726+
704727
/// Is type known to be non-null?
705728
fn ty_is_known_nonnull<'tcx>(
706729
tcx: TyCtxt<'tcx>,

0 commit comments

Comments
 (0)