Skip to content

Commit 26c1428

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 f794b6d commit 26c1428

File tree

123 files changed

+2353
-883
lines changed

Some content is hidden

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

123 files changed

+2353
-883
lines changed

compiler/rustc_codegen_cranelift/example/std_example.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ fn rust_call_abi() {
209209
struct I64X2([i64; 2]);
210210

211211
#[cfg_attr(target_arch = "s390x", allow(dead_code))]
212-
#[allow(improper_ctypes_definitions)]
212+
#[allow(improper_c_fn_definitions)]
213213
extern "C" fn foo(_a: I64X2) {}
214214

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

compiler/rustc_lint/messages.ftl

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ lint_implicit_unsafe_autorefs = implicit autoref creates a reference to the dere
370370
.method_def = method calls to `{$method_name}` require a reference
371371
.suggestion = try using a raw pointer method instead; or if this reference is intentional, make it explicit
372372
373-
lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe
373+
lint_improper_ctypes = {$desc} uses type `{$ty}`, which is not FFI-safe
374374
.label = not FFI-safe
375375
.note = the type is defined here
376376
@@ -420,35 +420,34 @@ lint_improper_ctypes_pat_intrange_reason = integers constrained to a given range
420420
421421
lint_improper_ctypes_ptr_validity_help = consider using a raw pointer, or wrapping `{$ty}` in an `Option<_>`
422422
lint_improper_ctypes_ptr_validity_reason =
423-
boxes and references are assumed to be valid (non-null, non-dangling, aligned) pointers,
423+
boxes, references, and function pointers are assumed to be valid (non-null, non-dangling, aligned) pointers,
424424
which cannot be garanteed if their values are produced by non-rust code
425425
426-
lint_improper_ctypes_sized_ptr_to_unsafe_type =
427-
this reference (`{$ty}`) is ABI-compatible with a C pointer, but `{$inner_ty}` itself does not have a C layout
428-
429426
lint_improper_ctypes_slice_help = consider using a raw pointer to the slice's first element (and a length) instead
430427
lint_improper_ctypes_slice_reason = slices have no C equivalent
431428
432429
lint_improper_ctypes_str_help = consider using `*const u8` and a length instead
433430
lint_improper_ctypes_str_reason = string slices have no C equivalent
434431
432+
lint_improper_ctypes_struct_consider_transparent = `{$ty}` has exactly one non-zero-sized field, consider making it `#[repr(transparent)]` instead
435433
lint_improper_ctypes_struct_dueto = this struct/enum/union (`{$ty}`) is FFI-unsafe due to a `{$inner_ty}` field
436-
lint_improper_ctypes_struct_fieldless_help = consider adding a member to this struct
437434
438-
lint_improper_ctypes_struct_fieldless_reason = this struct has no fields
439-
lint_improper_ctypes_struct_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
435+
lint_improper_ctypes_struct_fieldless_help = consider adding a member to this struct
436+
lint_improper_ctypes_struct_fieldless_reason = `{$ty}` has no fields
440437
441-
lint_improper_ctypes_struct_layout_reason = this struct has unspecified layout
442-
lint_improper_ctypes_struct_non_exhaustive = this struct is non-exhaustive
443-
lint_improper_ctypes_struct_zst = this struct contains only zero-sized fields
438+
lint_improper_ctypes_struct_layout_help = consider adding a `#[repr(C)]` (not `#[repr(C,packed)]`) or `#[repr(transparent)]` attribute to `{$ty}`
439+
lint_improper_ctypes_struct_layout_reason = `{$ty}` has unspecified layout
440+
lint_improper_ctypes_struct_non_exhaustive = `{$ty}` is non-exhaustive
441+
lint_improper_ctypes_struct_zst = `{$ty}` contains only zero-sized fields
444442
445443
lint_improper_ctypes_tuple_help = consider using a struct instead
446-
447444
lint_improper_ctypes_tuple_reason = tuples have unspecified layout
448-
lint_improper_ctypes_union_fieldless_help = consider adding a member to this union
449445
446+
447+
lint_improper_ctypes_union_consider_transparent = `{$ty}` has exactly one non-zero-sized field, consider making it `#[repr(transparent)]` instead
448+
lint_improper_ctypes_union_fieldless_help = consider adding a member to this union
450449
lint_improper_ctypes_union_fieldless_reason = this union has no fields
451-
lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union
450+
lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` attribute to this union
452451
453452
lint_improper_ctypes_union_layout_reason = this union has unspecified layout
454453
lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive

compiler/rustc_lint/src/lib.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,7 @@ late_lint_methods!(
197197
DefaultCouldBeDerived: DefaultCouldBeDerived::default(),
198198
DerefIntoDynSupertrait: DerefIntoDynSupertrait,
199199
DropForgetUseless: DropForgetUseless,
200-
ImproperCTypesDeclarations: ImproperCTypesDeclarations,
201-
ImproperCTypesDefinitions: ImproperCTypesDefinitions,
200+
ImproperCTypesLint: ImproperCTypesLint,
202201
InvalidFromUtf8: InvalidFromUtf8,
203202
VariantSizeDifferences: VariantSizeDifferences,
204203
PathStatements: PathStatements,
@@ -338,6 +337,14 @@ fn register_builtins(store: &mut LintStore) {
338337
REFINING_IMPL_TRAIT_INTERNAL
339338
);
340339

340+
add_lint_group!(
341+
"improper_c_boundaries",
342+
IMPROPER_C_CALLBACKS,
343+
IMPROPER_C_FN_DEFINITIONS,
344+
IMPROPER_CTYPE_DEFINITIONS,
345+
IMPROPER_CTYPES
346+
);
347+
341348
add_lint_group!("deprecated_safe", DEPRECATED_SAFE_2024);
342349

343350
// Register renamed and removed lints.
@@ -356,6 +363,7 @@ fn register_builtins(store: &mut LintStore) {
356363
store.register_renamed("unused_tuple_struct_fields", "dead_code");
357364
store.register_renamed("static_mut_ref", "static_mut_refs");
358365
store.register_renamed("temporary_cstring_as_ptr", "dangling_pointers_from_temporaries");
366+
store.register_renamed("improper_ctypes_definitions", "improper_c_fn_definitions");
359367

360368
// These were moved to tool lints, but rustc still sees them when compiling normally, before
361369
// 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,
@@ -711,6 +714,26 @@ pub(crate) fn transparent_newtype_field<'a, 'tcx>(
711714
})
712715
}
713716

717+
/// for a given ADT variant, list which fields are non-1ZST
718+
/// (`repr(transparent)` guarantees that there is at most one)
719+
pub(crate) fn map_non_1zst_fields<'a, 'tcx>(
720+
tcx: TyCtxt<'tcx>,
721+
variant: &'a ty::VariantDef,
722+
) -> Vec<bool> {
723+
let typing_env = ty::TypingEnv::non_body_analysis(tcx, variant.def_id);
724+
variant
725+
.fields
726+
.iter()
727+
.map(|field| {
728+
let field_ty = tcx.type_of(field.did).instantiate_identity();
729+
let is_1zst = tcx
730+
.layout_of(typing_env.as_query_input(field_ty))
731+
.is_ok_and(|layout| layout.is_1zst());
732+
!is_1zst
733+
})
734+
.collect()
735+
}
736+
714737
/// Is type known to be non-null?
715738
fn ty_is_known_nonnull<'tcx>(
716739
tcx: TyCtxt<'tcx>,

0 commit comments

Comments
 (0)