about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-02-26 02:42:43 +0000
committerbors <bors@rust-lang.org>2022-02-26 02:42:43 +0000
commit2c8d5a2500dccf31bf8800583d4809e27f05a04d (patch)
tree74227a93e1131f809ece95df0ad7ae25a65c3176
parent8bba6b7af02f06325fbbf9cb352b177891e06465 (diff)
parente3b5cac3c8d4dcbfd767dc8ba99380ab4ac86a91 (diff)
downloadrust-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.rs50
-rw-r--r--tests/ui/large_enum_variant.rs24
-rw-r--r--tests/ui/large_enum_variant.stderr18
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