Auto merge of #8453 - tamaroning:fix_large_enum_variant, r=camsteffen

fix false positives of large_enum_variant

fixes: #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
This commit is contained in:
bors 2022-02-26 02:42:43 +00:00
commit 2c8d5a2500
3 changed files with 64 additions and 28 deletions

View file

@ -84,34 +84,30 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
if adt.variants.len() <= 1 {
return;
}
let mut variants_size: Vec<VariantInfo> = adt
.variants
.iter()
.enumerate()
.map(|(i, variant)| {
let mut fields_size = Vec::new();
let size: u64 = variant
.fields
.iter()
.enumerate()
.filter_map(|(i, f)| {
let ty = cx.tcx.type_of(f.did);
// don't count generics by filtering out everything
// that does not have a layout
cx.layout_of(ty).ok().map(|l| {
let size = l.size.bytes();
fields_size.push(FieldInfo { ind: i, size });
size
})
})
.sum();
VariantInfo {
ind: i,
size,
fields_size,
let mut variants_size: Vec<VariantInfo> = Vec::new();
for (i, variant) in adt.variants.iter().enumerate() {
let mut fields_size = Vec::new();
for (i, f) in variant.fields.iter().enumerate() {
let ty = cx.tcx.type_of(f.did);
// don't lint variants which have a field of generic type.
match cx.layout_of(ty) {
Ok(l) => {
let fsize = l.size.bytes();
fields_size.push(FieldInfo { ind: i, size: fsize });
},
Err(_) => {
return;
},
}
})
.collect();
}
let size: u64 = fields_size.iter().map(|info| info.size).sum();
variants_size.push(VariantInfo {
ind: i,
size,
fields_size,
});
}
variants_size.sort_by(|a, b| (b.size.cmp(&a.size)));

View file

@ -74,6 +74,30 @@ enum LargeEnum8 {
ContainingMoreThanOneField([i32; 8000], [i32; 2], [i32; 9500], [i32; 30]),
}
enum LargeEnum9 {
A(Struct<()>),
B(Struct2),
}
enum LargeEnumOk2<T> {
A(T),
B(Struct2),
}
enum LargeEnumOk3<T> {
A(Struct<T>),
B(Struct2),
}
struct Struct<T> {
a: i32,
t: T,
}
struct Struct2 {
a: [i32; 8000],
}
fn main() {
large_enum_variant!();
}

View file

@ -111,5 +111,21 @@ help: consider boxing the large fields to reduce the total size of the enum
LL | ContainingMoreThanOneField(Box<[i32; 8000]>, [i32; 2], Box<[i32; 9500]>, [i32; 30]),
| ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
error: aborting due to 7 previous errors
error: large size difference between variants
--> $DIR/large_enum_variant.rs:79:5
|
LL | B(Struct2),
| ^^^^^^^^^^ this variant is 32000 bytes
|
note: and the second-largest variant is 4 bytes:
--> $DIR/large_enum_variant.rs:78:5
|
LL | A(Struct<()>),
| ^^^^^^^^^^^^^
help: consider boxing the large fields to reduce the total size of the enum
|
LL | B(Box<Struct2>),
| ~~~~~~~~~~~~
error: aborting due to 8 previous errors