Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit b9948c4

Browse files
committed
Ran dev bless!
1 parent 4b4db59 commit b9948c4

File tree

3 files changed

+147
-41
lines changed

3 files changed

+147
-41
lines changed

clippy_lints/src/trailing_zero_sized_array_without_repr_c.rs

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ declare_clippy_lint! {
2626
/// Use instead:
2727
/// ```rust
2828
/// #[repr(C)]
29-
/// struct MakesSense {
29+
/// struct MoreOftenUseful {
3030
/// some_field: usize,
3131
/// last: [SomeType; 0],
3232
/// }
@@ -45,15 +45,13 @@ declare_lint_pass!(TrailingZeroSizedArrayWithoutReprC => [TRAILING_ZERO_SIZED_AR
4545

4646
impl<'tcx> LateLintPass<'tcx> for TrailingZeroSizedArrayWithoutReprC {
4747
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
48-
dbg!(item.ident);
49-
5048
if is_struct_with_trailing_zero_sized_array(cx, item) && !has_repr_c(cx, item.def_id) {
5149
span_lint_and_sugg(
5250
cx,
5351
TRAILING_ZERO_SIZED_ARRAY_WITHOUT_REPR_C,
5452
item.span,
5553
"trailing zero-sized array in a struct which is not marked `#[repr(C)]`",
56-
"try",
54+
"try annotating the struct definition with `#[repr(C)]` (or another `repr` attribute):",
5755
format!("#[repr(C)]\n{}", snippet(cx, item.span, "..")),
5856
Applicability::MaybeIncorrect,
5957
);
@@ -62,46 +60,40 @@ impl<'tcx> LateLintPass<'tcx> for TrailingZeroSizedArrayWithoutReprC {
6260
}
6361

6462
fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) -> bool {
65-
if let ItemKind::Struct(data, _generics) = &item.kind {
66-
if let VariantData::Struct(field_defs, _) = data {
67-
if let Some(last_field) = field_defs.last() {
68-
if let TyKind::Array(_, aconst) = last_field.ty.kind {
69-
let aconst_def_id = cx.tcx.hir().body_owner_def_id(aconst.body).to_def_id();
70-
let ty = cx.tcx.type_of(aconst_def_id);
71-
let constant = cx
72-
.tcx
73-
// NOTE: maybe const_eval_resolve? seems especially cursed to be using a const expr which
74-
// resolves to 0 to create a zero-sized array, tho
75-
.const_eval_poly(aconst_def_id)
76-
.ok()
77-
.map(|val| rustc_middle::ty::Const::from_value(cx.tcx, val, ty));
78-
if let Some(Constant::Int(val)) = constant.and_then(miri_to_const) {
79-
if val == 0 {
80-
// eprintln!("trailing: true");
81-
return true;
82-
}
83-
}
84-
}
85-
}
63+
if_chain! {
64+
if let ItemKind::Struct(data, _generics) = &item.kind;
65+
if let VariantData::Struct(field_defs, _) = data;
66+
if let Some(last_field) = field_defs.last();
67+
if let TyKind::Array(_, aconst) = last_field.ty.kind;
68+
let aconst_def_id = cx.tcx.hir().body_owner_def_id(aconst.body).to_def_id();
69+
let ty = cx.tcx.type_of(aconst_def_id);
70+
let constant = cx
71+
.tcx
72+
// NOTE: maybe const_eval_resolve?
73+
.const_eval_poly(aconst_def_id)
74+
.ok()
75+
.map(|val| rustc_middle::ty::Const::from_value(cx.tcx, val, ty));
76+
if let Some(Constant::Int(val)) = constant.and_then(miri_to_const);
77+
if val == 0;
78+
then {
79+
true
80+
} else {
81+
false
8682
}
8783
}
88-
// dbg!(aconst);
89-
// eprintln!("trailing: false");
90-
false
9184
}
9285

9386
fn has_repr_c(cx: &LateContext<'tcx>, def_id: LocalDefId) -> bool {
94-
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
95-
let attrs = cx.tcx.hir().attrs(hir_id);
87+
let hir_map = cx.tcx.hir();
88+
let hir_id = hir_map.local_def_id_to_hir_id(def_id);
89+
let attrs = hir_map.attrs(hir_id);
9690

9791
// NOTE: Can there ever be more than one `repr` attribute?
9892
// other `repr` syms: repr, repr128, repr_align, repr_align_enum, repr_no_niche, repr_packed,
9993
// repr_simd, repr_transparent
100-
if let Some(_repr_attr) = attrs.iter().find(|attr| attr.has_name(sym::repr)) {
101-
// eprintln!("repr: true");
94+
if let Some(_attr) = attrs.iter().find(|attr| attr.has_name(sym::repr)) {
10295
true
10396
} else {
104-
// eprintln!("repr: false");
10597
false
10698
}
10799
}

tests/ui/trailing_zero_sized_array_without_repr_c.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#![warn(clippy::trailing_zero_sized_array_without_repr_c)]
2-
3-
// #![feature(const_generics_defaults)]
2+
// #![feature(const_generics_defaults)] // see below
43

54
struct RarelyUseful {
65
field: i32,
@@ -48,6 +47,9 @@ struct UsingFunction {
4847
last: [usize; compute_zero()],
4948
}
5049

50+
// NOTE: including these (along with the required feature) triggers an ICE. Should make sure the
51+
// const generics people are aware of that if they weren't already.
52+
5153
// #[repr(C)]
5254
// struct ConstParamOk<const N: usize = 0> {
5355
// field: i32,
@@ -59,29 +61,29 @@ struct UsingFunction {
5961
// last: [usize; N]
6062
// }
6163

62-
63-
// TODO: actually, uh,,
64+
// TODO: actually, uh,, no idea what behavior here would be
6465
#[repr(packed)]
6566
struct ReprPacked {
6667
small: u8,
6768
medium: i32,
6869
weird: [u64; 0],
6970
}
7071

71-
// same
72+
// TODO: clarify expected behavior
7273
#[repr(align(64))]
7374
struct ReprAlign {
7475
field: i32,
7576
last: [usize; 0],
7677
}
7778

78-
// same
79+
// TODO: clarify expected behavior
7980
#[repr(C, align(64))]
8081
struct ReprCAlign {
8182
field: i32,
8283
last: [usize; 0],
8384
}
8485

86+
// NOTE: because of https://doc.rust-lang.org/stable/reference/type-layout.html#primitive-representation-of-enums-with-fields and I'm not sure when in the compilation pipeline that would happen
8587
#[repr(C)]
8688
enum DontLintAnonymousStructsFromDesuraging {
8789
A(u32),
@@ -109,5 +111,4 @@ struct LotsOfFields {
109111
last: [usize; 0],
110112
}
111113

112-
fn main() {
113-
}
114+
fn main() {}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
error: trailing zero-sized array in a struct which is not marked `#[repr(C)]`
2+
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:4:1
3+
|
4+
LL | / struct RarelyUseful {
5+
LL | | field: i32,
6+
LL | | last: [usize; 0],
7+
LL | | }
8+
| |_^
9+
|
10+
= note: `-D clippy::trailing-zero-sized-array-without-repr-c` implied by `-D warnings`
11+
help: try annotating the struct definition with `#[repr(C)]` (or another `repr` attribute):
12+
|
13+
LL + #[repr(C)]
14+
LL + struct RarelyUseful {
15+
LL + field: i32,
16+
LL + last: [usize; 0],
17+
LL + }
18+
|
19+
20+
error: trailing zero-sized array in a struct which is not marked `#[repr(C)]`
21+
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:15:1
22+
|
23+
LL | / struct OnlyFieldIsZeroSizeArray {
24+
LL | | first_and_last: [usize; 0],
25+
LL | | }
26+
| |_^
27+
|
28+
help: try annotating the struct definition with `#[repr(C)]` (or another `repr` attribute):
29+
|
30+
LL + #[repr(C)]
31+
LL + struct OnlyFieldIsZeroSizeArray {
32+
LL + first_and_last: [usize; 0],
33+
LL + }
34+
|
35+
36+
error: trailing zero-sized array in a struct which is not marked `#[repr(C)]`
37+
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:19:1
38+
|
39+
LL | / struct GenericArrayType<T> {
40+
LL | | field: i32,
41+
LL | | last: [T; 0],
42+
LL | | }
43+
| |_^
44+
|
45+
help: try annotating the struct definition with `#[repr(C)]` (or another `repr` attribute):
46+
|
47+
LL + #[repr(C)]
48+
LL + struct GenericArrayType<T> {
49+
LL + field: i32,
50+
LL + last: [T; 0],
51+
LL + }
52+
|
53+
54+
error: trailing zero-sized array in a struct which is not marked `#[repr(C)]`
55+
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:30:1
56+
|
57+
LL | / struct ZeroSizedFromExternalConst {
58+
LL | | field: i32,
59+
LL | | last: [usize; ZERO],
60+
LL | | }
61+
| |_^
62+
|
63+
help: try annotating the struct definition with `#[repr(C)]` (or another `repr` attribute):
64+
|
65+
LL + #[repr(C)]
66+
LL + struct ZeroSizedFromExternalConst {
67+
LL + field: i32,
68+
LL + last: [usize; ZERO],
69+
LL + }
70+
|
71+
72+
error: trailing zero-sized array in a struct which is not marked `#[repr(C)]`
73+
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:45:1
74+
|
75+
LL | / struct UsingFunction {
76+
LL | | field: i32,
77+
LL | | last: [usize; compute_zero()],
78+
LL | | }
79+
| |_^
80+
|
81+
help: try annotating the struct definition with `#[repr(C)]` (or another `repr` attribute):
82+
|
83+
LL + #[repr(C)]
84+
LL + struct UsingFunction {
85+
LL + field: i32,
86+
LL + last: [usize; compute_zero()],
87+
LL + }
88+
|
89+
90+
error: trailing zero-sized array in a struct which is not marked `#[repr(C)]`
91+
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:94:1
92+
|
93+
LL | / struct LotsOfFields {
94+
LL | | f1: u32,
95+
LL | | f2: u32,
96+
LL | | f3: u32,
97+
... |
98+
LL | | last: [usize; 0],
99+
LL | | }
100+
| |_^
101+
|
102+
help: try annotating the struct definition with `#[repr(C)]` (or another `repr` attribute):
103+
|
104+
LL + #[repr(C)]
105+
LL + struct LotsOfFields {
106+
LL + f1: u32,
107+
LL + f2: u32,
108+
LL + f3: u32,
109+
LL + f4: u32,
110+
...
111+
112+
error: aborting due to 6 previous errors
113+

0 commit comments

Comments
 (0)