Skip to content

Commit a3420f7

Browse files
committed
Tidy comments + tests; revert 'size-is-zero' detection
1 parent 9b3f55e commit a3420f7

File tree

3 files changed

+72
-90
lines changed

3 files changed

+72
-90
lines changed

clippy_lints/src/trailing_zero_sized_array_without_repr_c.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,15 @@ declare_clippy_lint! {
3636
}
3737
declare_lint_pass!(TrailingZeroSizedArrayWithoutReprC => [TRAILING_ZERO_SIZED_ARRAY_WITHOUT_REPR_C]);
3838

39-
// TESTNAME=trailing_zero_sized_array_without_repr_c cargo uitest
40-
4139
impl<'tcx> LateLintPass<'tcx> for TrailingZeroSizedArrayWithoutReprC {
4240
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
4341
if is_struct_with_trailing_zero_sized_array(cx, item) {
42+
// NOTE: This is to include attributes on the definition when we print the lint. If the convention
43+
// is to not do that with struct definitions (I'm not sure), then this isn't necessary.
4444
let attrs = cx.tcx.get_attrs(item.def_id.to_def_id());
45-
let first_attr = attrs.first(); // Actually, I've no idea if this is guaranteed to be the first one in the source code.
46-
45+
let first_attr = attrs.iter().min_by_key(|attr| attr.span.lo());
4746
let lint_span = if let Some(first_attr) = first_attr {
48-
first_attr.span.until(item.span)
47+
first_attr.span.to(item.span)
4948
} else {
5049
item.span
5150
};
@@ -66,18 +65,29 @@ impl<'tcx> LateLintPass<'tcx> for TrailingZeroSizedArrayWithoutReprC {
6665

6766
fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) -> bool {
6867
if_chain! {
69-
// Check if last field is an array
68+
// First check if last field is an array
7069
if let ItemKind::Struct(data, _) = &item.kind;
7170
if let VariantData::Struct(field_defs, _) = data;
7271
if let Some(last_field) = field_defs.last();
7372
if let rustc_hir::TyKind::Array(_, length) = last_field.ty.kind;
7473

75-
// Check if that that array zero-sized.
76-
let length_ldid = cx.tcx.hir().local_def_id(length.hir_id);
77-
let length = Const::from_anon_const(cx.tcx, length_ldid);
78-
if let Some(Constant::Int(length)) = miri_to_const(length);
79-
if length == 0;
74+
// Then check if that that array zero-sized
8075

76+
// This is pretty much copied from `enum_clike.rs` and I don't fully understand it, so let me know
77+
// if there's a better way. I tried `Const::from_anon_const` but it didn't fold in the values
78+
// on the `ZeroSizedWithConst` and `ZeroSizedWithConstFunction` tests.
79+
80+
// This line in particular seems convoluted.
81+
let length_did = cx.tcx.hir().body_owner_def_id(length.body).to_def_id();
82+
let length_ty = cx.tcx.type_of(length_did);
83+
let length = cx
84+
.tcx
85+
.const_eval_poly(length_did)
86+
.ok()
87+
.map(|val| Const::from_value(cx.tcx, val, length_ty))
88+
.and_then(miri_to_const);
89+
if let Some(Constant::Int(length)) = length;
90+
if length == 0;
8191
then {
8292
true
8393
} else {
@@ -88,7 +98,8 @@ fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'tcx>, item: &'tcx
8898

8999
fn has_repr_attr(cx: &LateContext<'tcx>, attrs: &[Attribute]) -> bool {
90100
// NOTE: there's at least four other ways to do this but I liked this one the best. (All five agreed
91-
// on all testcases.) Happy to use another; they're in the commit history.
101+
// on all testcases.) Happy to use another; they're in the commit history if you want to look (or I
102+
// can go find them).
92103
attrs
93104
.iter()
94105
.any(|attr| !rustc_attr::find_repr_attrs(cx.tcx.sess(), attr).is_empty())

tests/ui/trailing_zero_sized_array_without_repr_c.rs

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#![warn(clippy::trailing_zero_sized_array_without_repr_c)]
2-
#![feature(const_generics_defaults)] // see below
32

43
// Do lint:
54

@@ -17,14 +16,16 @@ struct GenericArrayType<T> {
1716
last: [T; 0],
1817
}
1918

20-
#[derive(Debug)]
21-
struct OnlyAnotherAttributeDerive {
19+
#[must_use]
20+
struct OnlyAnotherAttributeMustUse {
2221
field: i32,
2322
last: [usize; 0],
2423
}
2524

26-
#[must_use]
27-
struct OnlyAnotherAttributeMustUse {
25+
// NOTE: Unfortunately the attribute isn't included in the lint output. I'm not sure how to make it
26+
// show up.
27+
#[derive(Debug)]
28+
struct OnlyAnotherAttributeDerive {
2829
field: i32,
2930
last: [usize; 0],
3031
}
@@ -82,6 +83,12 @@ struct NonZeroSizedArray {
8283
last: [usize; 1],
8384
}
8485

86+
struct NotLastField {
87+
f1: u32,
88+
zero_sized: [usize; 0],
89+
last: i32,
90+
}
91+
8592
const ONE: usize = 1;
8693
struct NonZeroSizedWithConst {
8794
field: i32,
@@ -133,21 +140,4 @@ enum DontLintAnonymousStructsFromDesuraging {
133140
C { x: u32, y: [u64; 0] },
134141
}
135142

136-
// NOTE: including these (along with the required feature) triggers an ICE. Not sure why. Should
137-
// make sure the const generics people are aware of that if they weren't already.
138-
139-
// #[repr(C)]
140-
// struct ConstParamOk<const N: usize = 0> {
141-
// field: i32,
142-
// last: [usize; N]
143-
// }
144-
145-
// struct ConstParamLint<const N: usize = 0> {
146-
// field: i32,
147-
// last: [usize; N]
148-
// }
149-
150-
fn main() {
151-
let _ = OnlyAnotherAttributeMustUse { field: 0, last: [] };
152-
let _ = OtherAttributesMustUse { field: 0, last: [] };
153-
}
143+
fn main() {}
Lines changed: 36 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
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
2+
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:5:1
33
|
44
LL | / struct RarelyUseful {
55
LL | | field: i32,
@@ -8,87 +8,76 @@ LL | | }
88
| |_^
99
|
1010
= 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-
|
11+
= help: consider annotating the struct definition with `#[repr(C)]` (or another `repr` attribute)
1912

2013
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
14+
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:10:1
2215
|
23-
LL | / struct OnlyFieldIsZeroSizeArray {
16+
LL | / struct OnlyField {
2417
LL | | first_and_last: [usize; 0],
2518
LL | | }
2619
| |_^
2720
|
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-
|
21+
= help: consider annotating the struct definition with `#[repr(C)]` (or another `repr` attribute)
3522

3623
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
24+
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:14:1
3825
|
3926
LL | / struct GenericArrayType<T> {
4027
LL | | field: i32,
4128
LL | | last: [T; 0],
4229
LL | | }
4330
| |_^
4431
|
45-
help: try annotating the struct definition with `#[repr(C)]` (or another `repr` attribute):
32+
= help: consider annotating the struct definition with `#[repr(C)]` (or another `repr` attribute)
33+
34+
error: trailing zero-sized array in a struct which is not marked `#[repr(C)]`
35+
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:19:1
4636
|
47-
LL + #[repr(C)]
48-
LL + struct GenericArrayType<T> {
49-
LL + field: i32,
50-
LL + last: [T; 0],
51-
LL + }
37+
LL | / #[must_use]
38+
LL | | struct OnlyAnotherAttributeMustUse {
39+
LL | | field: i32,
40+
LL | | last: [usize; 0],
41+
LL | | }
42+
| |_^
5243
|
44+
= help: consider annotating the struct definition with `#[repr(C)]` (or another `repr` attribute)
5345

5446
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
47+
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:28:1
5648
|
57-
LL | / struct ZeroSizedFromExternalConst {
49+
LL | / struct OnlyAnotherAttributeDerive {
5850
LL | | field: i32,
59-
LL | | last: [usize; ZERO],
51+
LL | | last: [usize; 0],
6052
LL | | }
6153
| |_^
6254
|
63-
help: try annotating the struct definition with `#[repr(C)]` (or another `repr` attribute):
55+
= help: consider annotating the struct definition with `#[repr(C)]` (or another `repr` attribute)
56+
57+
error: trailing zero-sized array in a struct which is not marked `#[repr(C)]`
58+
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:34:1
6459
|
65-
LL + #[repr(C)]
66-
LL + struct ZeroSizedFromExternalConst {
67-
LL + field: i32,
68-
LL + last: [usize; ZERO],
69-
LL + }
60+
LL | / struct ZeroSizedWithConst {
61+
LL | | field: i32,
62+
LL | | last: [usize; ZERO],
63+
LL | | }
64+
| |_^
7065
|
66+
= help: consider annotating the struct definition with `#[repr(C)]` (or another `repr` attribute)
7167

7268
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
69+
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:43:1
7470
|
75-
LL | / struct UsingFunction {
71+
LL | / struct ZeroSizedWithConstFunction {
7672
LL | | field: i32,
7773
LL | | last: [usize; compute_zero()],
7874
LL | | }
7975
| |_^
8076
|
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-
|
77+
= help: consider annotating the struct definition with `#[repr(C)]` (or another `repr` attribute)
8978

9079
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
80+
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:48:1
9281
|
9382
LL | / struct LotsOfFields {
9483
LL | | f1: u32,
@@ -99,15 +88,7 @@ LL | | last: [usize; 0],
9988
LL | | }
10089
| |_^
10190
|
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-
...
91+
= help: consider annotating the struct definition with `#[repr(C)]` (or another `repr` attribute)
11192

112-
error: aborting due to 6 previous errors
93+
error: aborting due to 8 previous errors
11394

0 commit comments

Comments
 (0)