large_enum_variant: Report sizes of variants

This reports the sizes of the largest and second-largest variants.
This commit is contained in:
Philipp Hansch 2020-04-15 09:55:02 +02:00
parent c6cc07a851
commit 69c3e9c90f
No known key found for this signature in database
GPG Key ID: 2B4399C4BF4DCBDE
2 changed files with 43 additions and 10 deletions

View File

@ -21,11 +21,19 @@ declare_clippy_lint! {
/// measure the change this lint suggests. /// measure the change this lint suggests.
/// ///
/// **Example:** /// **Example:**
///
/// ```rust /// ```rust
/// // Bad
/// enum Test { /// enum Test {
/// A(i32), /// A(i32),
/// B([i32; 8000]), /// B([i32; 8000]),
/// } /// }
///
/// // Possibly better
/// enum Test2 {
/// A(i32),
/// B(Box<[i32; 8000]>),
/// }
/// ``` /// ```
pub LARGE_ENUM_VARIANT, pub LARGE_ENUM_VARIANT,
perf, perf,
@ -84,12 +92,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant {
if difference > self.maximum_size_difference_allowed { if difference > self.maximum_size_difference_allowed {
let (i, variant) = largest.1; 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( span_lint_and_then(
cx, cx,
LARGE_ENUM_VARIANT, LARGE_ENUM_VARIANT,
def.variants[i].span, def.variants[i].span,
"large size difference between variants", "large size difference between variants",
|db| { |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 { if variant.fields.len() == 1 {
let span = match def.variants[i].data { let span = match def.variants[i].data {
VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, ..) => { 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) { if let Some(snip) = snippet_opt(cx, span) {
db.span_suggestion( db.span_suggestion(
span, span,
"consider boxing the large fields to reduce the total size of the \ help_text,
enum",
format!("Box<{}>", snip), format!("Box<{}>", snip),
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
return; return;
} }
} }
db.span_help( db.span_help(def.variants[i].span, help_text);
def.variants[i].span,
"consider boxing the large fields to reduce the total size of the enum",
);
}, },
); );
} }

View File

@ -2,9 +2,14 @@ error: large size difference between variants
--> $DIR/large_enum_variant.rs:7:5 --> $DIR/large_enum_variant.rs:7:5
| |
LL | B([i32; 8000]), LL | B([i32; 8000]),
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^ this variant is 32000 bytes
| |
= note: `-D clippy::large-enum-variant` implied by `-D warnings` = 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 help: consider boxing the large fields to reduce the total size of the enum
| |
LL | B(Box<[i32; 8000]>), LL | B(Box<[i32; 8000]>),
@ -14,8 +19,13 @@ error: large size difference between variants
--> $DIR/large_enum_variant.rs:31:5 --> $DIR/large_enum_variant.rs:31:5
| |
LL | ContainingLargeEnum(LargeEnum), 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 help: consider boxing the large fields to reduce the total size of the enum
| |
LL | ContainingLargeEnum(Box<LargeEnum>), LL | ContainingLargeEnum(Box<LargeEnum>),
@ -25,8 +35,13 @@ error: large size difference between variants
--> $DIR/large_enum_variant.rs:41:5 --> $DIR/large_enum_variant.rs:41:5
| |
LL | StructLikeLarge { x: [i32; 8000], y: i32 }, 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 help: consider boxing the large fields to reduce the total size of the enum
--> $DIR/large_enum_variant.rs:41:5 --> $DIR/large_enum_variant.rs:41:5
| |
@ -37,8 +52,13 @@ error: large size difference between variants
--> $DIR/large_enum_variant.rs:46:5 --> $DIR/large_enum_variant.rs:46:5
| |
LL | StructLikeLarge2 { x: [i32; 8000] }, 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 help: consider boxing the large fields to reduce the total size of the enum
| |
LL | StructLikeLarge2 { x: Box<[i32; 8000]> }, LL | StructLikeLarge2 { x: Box<[i32; 8000]> },