Skip to content

Commit 2c8d5a2

Browse files
committed
Auto merge of rust-lang#8453 - tamaroning:fix_large_enum_variant, r=camsteffen
fix false positives of large_enum_variant fixes: rust-lang#8321 The size of enums containing generic type was calculated to be 0. I changed [large_enum_variant] so that such enums are not linted. changelog: none
2 parents 8bba6b7 + e3b5cac commit 2c8d5a2

File tree

3 files changed

+64
-28
lines changed

3 files changed

+64
-28
lines changed

clippy_lints/src/large_enum_variant.rs

+23-27
Original file line numberDiff line numberDiff line change
@@ -84,34 +84,30 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
8484
if adt.variants.len() <= 1 {
8585
return;
8686
}
87-
let mut variants_size: Vec<VariantInfo> = adt
88-
.variants
89-
.iter()
90-
.enumerate()
91-
.map(|(i, variant)| {
92-
let mut fields_size = Vec::new();
93-
let size: u64 = variant
94-
.fields
95-
.iter()
96-
.enumerate()
97-
.filter_map(|(i, f)| {
98-
let ty = cx.tcx.type_of(f.did);
99-
// don't count generics by filtering out everything
100-
// that does not have a layout
101-
cx.layout_of(ty).ok().map(|l| {
102-
let size = l.size.bytes();
103-
fields_size.push(FieldInfo { ind: i, size });
104-
size
105-
})
106-
})
107-
.sum();
108-
VariantInfo {
109-
ind: i,
110-
size,
111-
fields_size,
87+
let mut variants_size: Vec<VariantInfo> = Vec::new();
88+
for (i, variant) in adt.variants.iter().enumerate() {
89+
let mut fields_size = Vec::new();
90+
for (i, f) in variant.fields.iter().enumerate() {
91+
let ty = cx.tcx.type_of(f.did);
92+
// don't lint variants which have a field of generic type.
93+
match cx.layout_of(ty) {
94+
Ok(l) => {
95+
let fsize = l.size.bytes();
96+
fields_size.push(FieldInfo { ind: i, size: fsize });
97+
},
98+
Err(_) => {
99+
return;
100+
},
112101
}
113-
})
114-
.collect();
102+
}
103+
let size: u64 = fields_size.iter().map(|info| info.size).sum();
104+
105+
variants_size.push(VariantInfo {
106+
ind: i,
107+
size,
108+
fields_size,
109+
});
110+
}
115111

116112
variants_size.sort_by(|a, b| (b.size.cmp(&a.size)));
117113

tests/ui/large_enum_variant.rs

+24
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,30 @@ enum LargeEnum8 {
7474
ContainingMoreThanOneField([i32; 8000], [i32; 2], [i32; 9500], [i32; 30]),
7575
}
7676

77+
enum LargeEnum9 {
78+
A(Struct<()>),
79+
B(Struct2),
80+
}
81+
82+
enum LargeEnumOk2<T> {
83+
A(T),
84+
B(Struct2),
85+
}
86+
87+
enum LargeEnumOk3<T> {
88+
A(Struct<T>),
89+
B(Struct2),
90+
}
91+
92+
struct Struct<T> {
93+
a: i32,
94+
t: T,
95+
}
96+
97+
struct Struct2 {
98+
a: [i32; 8000],
99+
}
100+
77101
fn main() {
78102
large_enum_variant!();
79103
}

tests/ui/large_enum_variant.stderr

+17-1
Original file line numberDiff line numberDiff line change
@@ -111,5 +111,21 @@ help: consider boxing the large fields to reduce the total size of the enum
111111
LL | ContainingMoreThanOneField(Box<[i32; 8000]>, [i32; 2], Box<[i32; 9500]>, [i32; 30]),
112112
| ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
113113

114-
error: aborting due to 7 previous errors
114+
error: large size difference between variants
115+
--> $DIR/large_enum_variant.rs:79:5
116+
|
117+
LL | B(Struct2),
118+
| ^^^^^^^^^^ this variant is 32000 bytes
119+
|
120+
note: and the second-largest variant is 4 bytes:
121+
--> $DIR/large_enum_variant.rs:78:5
122+
|
123+
LL | A(Struct<()>),
124+
| ^^^^^^^^^^^^^
125+
help: consider boxing the large fields to reduce the total size of the enum
126+
|
127+
LL | B(Box<Struct2>),
128+
| ~~~~~~~~~~~~
129+
130+
error: aborting due to 8 previous errors
115131

0 commit comments

Comments
 (0)