Skip to content

Commit a4cded5

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 5cb24cc commit a4cded5

File tree

121 files changed

+2366
-906
lines changed

Some content is hidden

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

121 files changed

+2366
-906
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
@@ -368,7 +368,7 @@ lint_implicit_unsafe_autorefs = implicit autoref creates a reference to the dere
368368
.method_def = method calls to `{$method_name}` require a reference
369369
.suggestion = try using a raw pointer method instead; or if this reference is intentional, make it explicit
370370
371-
lint_improper_ctypes = `extern` {$desc} uses type `{$ty}`, which is not FFI-safe
371+
lint_improper_ctypes = {$desc} uses type `{$ty}`, which is not FFI-safe
372372
.label = not FFI-safe
373373
.note = the type is defined here
374374
@@ -418,35 +418,34 @@ lint_improper_ctypes_pat_intrange_reason = integers constrained to a given range
418418
419419
lint_improper_ctypes_ptr_validity_help = consider using a raw pointer, or wrapping `{$ty}` in an `Option<_>`
420420
lint_improper_ctypes_ptr_validity_reason =
421-
boxes and references are assumed to be valid (non-null, non-dangling, aligned) pointers,
421+
boxes, references, and function pointers are assumed to be valid (non-null, non-dangling, aligned) pointers,
422422
which cannot be garanteed if their values are produced by non-rust code
423423
424-
lint_improper_ctypes_sized_ptr_to_unsafe_type =
425-
this reference (`{$ty}`) is ABI-compatible with a C pointer, but `{$inner_ty}` itself does not have a C layout
426-
427424
lint_improper_ctypes_slice_help = consider using a raw pointer to the slice's first element (and a length) instead
428425
lint_improper_ctypes_slice_reason = slices have no C equivalent
429426
430427
lint_improper_ctypes_str_help = consider using `*const u8` and a length instead
431428
lint_improper_ctypes_str_reason = string slices have no C equivalent
432429
430+
lint_improper_ctypes_struct_consider_transparent = `{$ty}` has exactly one non-zero-sized field, consider making it `#[repr(transparent)]` instead
433431
lint_improper_ctypes_struct_dueto = this struct/enum/union (`{$ty}`) is FFI-unsafe due to a `{$inner_ty}` field
434-
lint_improper_ctypes_struct_fieldless_help = consider adding a member to this struct
435432
436-
lint_improper_ctypes_struct_fieldless_reason = this struct has no fields
437-
lint_improper_ctypes_struct_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
433+
lint_improper_ctypes_struct_fieldless_help = consider adding a member to this struct
434+
lint_improper_ctypes_struct_fieldless_reason = `{$ty}` has no fields
438435
439-
lint_improper_ctypes_struct_layout_reason = this struct has unspecified layout
440-
lint_improper_ctypes_struct_non_exhaustive = this struct is non-exhaustive
441-
lint_improper_ctypes_struct_zst = this struct contains only zero-sized fields
436+
lint_improper_ctypes_struct_layout_help = consider adding a `#[repr(C)]` (not `#[repr(C,packed)]`) or `#[repr(transparent)]` attribute to `{$ty}`
437+
lint_improper_ctypes_struct_layout_reason = `{$ty}` has unspecified layout
438+
lint_improper_ctypes_struct_non_exhaustive = `{$ty}` is non-exhaustive
439+
lint_improper_ctypes_struct_zst = `{$ty}` contains only zero-sized fields
442440
443441
lint_improper_ctypes_tuple_help = consider using a struct instead
444-
445442
lint_improper_ctypes_tuple_reason = tuples have unspecified layout
446-
lint_improper_ctypes_union_fieldless_help = consider adding a member to this union
447443
444+
445+
lint_improper_ctypes_union_consider_transparent = `{$ty}` has exactly one non-zero-sized field, consider making it `#[repr(transparent)]` instead
446+
lint_improper_ctypes_union_fieldless_help = consider adding a member to this union
448447
lint_improper_ctypes_union_fieldless_reason = this union has no fields
449-
lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union
448+
lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` attribute to this union
450449
451450
lint_improper_ctypes_union_layout_reason = this union has unspecified layout
452451
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
@@ -194,8 +194,9 @@ late_lint_methods!(
194194
DefaultCouldBeDerived: DefaultCouldBeDerived::default(),
195195
DerefIntoDynSupertrait: DerefIntoDynSupertrait,
196196
DropForgetUseless: DropForgetUseless,
197-
ImproperCTypesDeclarations: ImproperCTypesDeclarations,
198-
ImproperCTypesDefinitions: ImproperCTypesDefinitions,
197+
//ImproperCTypesDeclarations: ImproperCTypesDeclarations,
198+
//ImproperCTypesDefinitions: ImproperCTypesDefinitions,
199+
ImproperCTypesLint: ImproperCTypesLint,
199200
InvalidFromUtf8: InvalidFromUtf8,
200201
VariantSizeDifferences: VariantSizeDifferences,
201202
PathStatements: PathStatements,
@@ -334,6 +335,14 @@ fn register_builtins(store: &mut LintStore) {
334335
REFINING_IMPL_TRAIT_INTERNAL
335336
);
336337

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

339348
// Register renamed and removed lints.
@@ -352,6 +361,7 @@ fn register_builtins(store: &mut LintStore) {
352361
store.register_renamed("unused_tuple_struct_fields", "dead_code");
353362
store.register_renamed("static_mut_ref", "static_mut_refs");
354363
store.register_renamed("temporary_cstring_as_ptr", "dangling_pointers_from_temporaries");
364+
store.register_renamed("improper_ctypes_definitions", "improper_c_fn_definitions");
355365

356366
// These were moved to tool lints, but rustc still sees them when compiling normally, before
357367
// 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)