From 69c3e9c90f9a7731dcfe129b10e55e440ee6f484 Mon Sep 17 00:00:00 2001
From: Philipp Hansch <dev@phansch.net>
Date: Wed, 15 Apr 2020 09:55:02 +0200
Subject: [PATCH] large_enum_variant: Report sizes of variants

This reports the sizes of the largest and second-largest variants.
---
 clippy_lints/src/large_enum_variant.rs | 25 +++++++++++++++++------
 tests/ui/large_enum_variant.stderr     | 28 ++++++++++++++++++++++----
 2 files changed, 43 insertions(+), 10 deletions(-)

diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs
index 00bbba64841..7ac83739be6 100644
--- a/clippy_lints/src/large_enum_variant.rs
+++ b/clippy_lints/src/large_enum_variant.rs
@@ -21,11 +21,19 @@ declare_clippy_lint! {
     /// measure the change this lint suggests.
     ///
     /// **Example:**
+    ///
     /// ```rust
+    /// // Bad
     /// enum Test {
     ///     A(i32),
     ///     B([i32; 8000]),
     /// }
+    ///
+    /// // Possibly better
+    /// enum Test2 {
+    ///     A(i32),
+    ///     B(Box<[i32; 8000]>),
+    /// }
     /// ```
     pub LARGE_ENUM_VARIANT,
     perf,
@@ -84,12 +92,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant {
                 if difference > self.maximum_size_difference_allowed {
                     let (i, variant) = largest.1;
 
+                    let help_text = "consider boxing the large fields to reduce the total size of the enum";
                     span_lint_and_then(
                         cx,
                         LARGE_ENUM_VARIANT,
                         def.variants[i].span,
                         "large size difference between variants",
                         |db| {
+                            db.span_label(
+                                def.variants[(largest.1).0].span,
+                                &format!("this variant is {} bytes", largest.0),
+                            );
+                            db.span_note(
+                                def.variants[(second.1).0].span,
+                                &format!("and the second-largest variant is {} bytes:", second.0),
+                            );
                             if variant.fields.len() == 1 {
                                 let span = match def.variants[i].data {
                                     VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, ..) => {
@@ -100,18 +117,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant {
                                 if let Some(snip) = snippet_opt(cx, span) {
                                     db.span_suggestion(
                                         span,
-                                        "consider boxing the large fields to reduce the total size of the \
-                                         enum",
+                                        help_text,
                                         format!("Box<{}>", snip),
                                         Applicability::MaybeIncorrect,
                                     );
                                     return;
                                 }
                             }
-                            db.span_help(
-                                def.variants[i].span,
-                                "consider boxing the large fields to reduce the total size of the enum",
-                            );
+                            db.span_help(def.variants[i].span, help_text);
                         },
                     );
                 }
diff --git a/tests/ui/large_enum_variant.stderr b/tests/ui/large_enum_variant.stderr
index 5d659611533..8ce641a81f2 100644
--- a/tests/ui/large_enum_variant.stderr
+++ b/tests/ui/large_enum_variant.stderr
@@ -2,9 +2,14 @@ error: large size difference between variants
   --> $DIR/large_enum_variant.rs:7:5
    |
 LL |     B([i32; 8000]),
-   |     ^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^ this variant is 32000 bytes
    |
    = note: `-D clippy::large-enum-variant` implied by `-D warnings`
+note: and the second-largest variant is 4 bytes:
+  --> $DIR/large_enum_variant.rs:6:5
+   |
+LL |     A(i32),
+   |     ^^^^^^
 help: consider boxing the large fields to reduce the total size of the enum
    |
 LL |     B(Box<[i32; 8000]>),
@@ -14,8 +19,13 @@ error: large size difference between variants
   --> $DIR/large_enum_variant.rs:31:5
    |
 LL |     ContainingLargeEnum(LargeEnum),
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this variant is 32004 bytes
    |
+note: and the second-largest variant is 8 bytes:
+  --> $DIR/large_enum_variant.rs:30:5
+   |
+LL |     VariantOk(i32, u32),
+   |     ^^^^^^^^^^^^^^^^^^^
 help: consider boxing the large fields to reduce the total size of the enum
    |
 LL |     ContainingLargeEnum(Box<LargeEnum>),
@@ -25,8 +35,13 @@ error: large size difference between variants
   --> $DIR/large_enum_variant.rs:41:5
    |
 LL |     StructLikeLarge { x: [i32; 8000], y: i32 },
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this variant is 32004 bytes
    |
+note: and the second-largest variant is 8 bytes:
+  --> $DIR/large_enum_variant.rs:40:5
+   |
+LL |     VariantOk(i32, u32),
+   |     ^^^^^^^^^^^^^^^^^^^
 help: consider boxing the large fields to reduce the total size of the enum
   --> $DIR/large_enum_variant.rs:41:5
    |
@@ -37,8 +52,13 @@ error: large size difference between variants
   --> $DIR/large_enum_variant.rs:46:5
    |
 LL |     StructLikeLarge2 { x: [i32; 8000] },
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this variant is 32000 bytes
    |
+note: and the second-largest variant is 8 bytes:
+  --> $DIR/large_enum_variant.rs:45:5
+   |
+LL |     VariantOk(i32, u32),
+   |     ^^^^^^^^^^^^^^^^^^^
 help: consider boxing the large fields to reduce the total size of the enum
    |
 LL |     StructLikeLarge2 { x: Box<[i32; 8000]> },