mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-24 21:53:23 +00:00
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:
commit
2c8d5a2500
3 changed files with 64 additions and 28 deletions
|
@ -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)));
|
||||
|
||||
|
|
|
@ -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!();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue