diff options
| author | bors <bors@rust-lang.org> | 2022-02-26 02:42:43 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-02-26 02:42:43 +0000 |
| commit | 2c8d5a2500dccf31bf8800583d4809e27f05a04d (patch) | |
| tree | 74227a93e1131f809ece95df0ad7ae25a65c3176 | |
| parent | 8bba6b7af02f06325fbbf9cb352b177891e06465 (diff) | |
| parent | e3b5cac3c8d4dcbfd767dc8ba99380ab4ac86a91 (diff) | |
| download | rust-2c8d5a2500dccf31bf8800583d4809e27f05a04d.tar.gz rust-2c8d5a2500dccf31bf8800583d4809e27f05a04d.zip | |
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
| -rw-r--r-- | clippy_lints/src/large_enum_variant.rs | 50 | ||||
| -rw-r--r-- | tests/ui/large_enum_variant.rs | 24 | ||||
| -rw-r--r-- | tests/ui/large_enum_variant.stderr | 18 |
3 files changed, 64 insertions, 28 deletions
diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 0191713f60d..d1dc6b775c5 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -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))); diff --git a/tests/ui/large_enum_variant.rs b/tests/ui/large_enum_variant.rs index b45cc849eae..cee9e2372c2 100644 --- a/tests/ui/large_enum_variant.rs +++ b/tests/ui/large_enum_variant.rs @@ -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!(); } diff --git a/tests/ui/large_enum_variant.stderr b/tests/ui/large_enum_variant.stderr index 899f97ce2e1..cbf2ac972e2 100644 --- a/tests/ui/large_enum_variant.stderr +++ b/tests/ui/large_enum_variant.stderr @@ -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 |
