remove large_enum_variant
suggestion for Copy
types
This commit is contained in:
parent
1dd55471b4
commit
19f94d52b3
3 changed files with 99 additions and 31 deletions
|
@ -1,7 +1,7 @@
|
|||
//! lint when there is a large size difference between variants on an enum
|
||||
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use clippy_utils::{diagnostics::span_lint_and_then, ty::is_copy};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Item, ItemKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
|
@ -132,37 +132,43 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
|
|||
let fields = def.variants[variants_size[0].ind].data.fields();
|
||||
variants_size[0].fields_size.sort_by(|a, b| (a.size.cmp(&b.size)));
|
||||
let mut applicability = Applicability::MaybeIncorrect;
|
||||
let sugg: Vec<(Span, String)> = variants_size[0]
|
||||
.fields_size
|
||||
.iter()
|
||||
.rev()
|
||||
.map_while(|val| {
|
||||
if difference > self.maximum_size_difference_allowed {
|
||||
difference = difference.saturating_sub(val.size);
|
||||
Some((
|
||||
fields[val.ind].ty.span,
|
||||
format!(
|
||||
"Box<{}>",
|
||||
snippet_with_applicability(
|
||||
cx,
|
||||
fields[val.ind].ty.span,
|
||||
"..",
|
||||
&mut applicability
|
||||
)
|
||||
.into_owned()
|
||||
),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
if is_copy(cx, ty) {
|
||||
diag.span_note(
|
||||
item.ident.span,
|
||||
"boxing a variant would require the type no longer be `Copy`",
|
||||
);
|
||||
} else {
|
||||
let sugg: Vec<(Span, String)> = variants_size[0]
|
||||
.fields_size
|
||||
.iter()
|
||||
.rev()
|
||||
.map_while(|val| {
|
||||
if difference > self.maximum_size_difference_allowed {
|
||||
difference = difference.saturating_sub(val.size);
|
||||
Some((
|
||||
fields[val.ind].ty.span,
|
||||
format!(
|
||||
"Box<{}>",
|
||||
snippet_with_applicability(
|
||||
cx,
|
||||
fields[val.ind].ty.span,
|
||||
"..",
|
||||
&mut applicability
|
||||
)
|
||||
.into_owned()
|
||||
),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
if !sugg.is_empty() {
|
||||
diag.multipart_suggestion(help_text, sugg, Applicability::MaybeIncorrect);
|
||||
return;
|
||||
if !sugg.is_empty() {
|
||||
diag.multipart_suggestion(help_text, sugg, Applicability::MaybeIncorrect);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
diag.span_help(def.variants[variants_size[0].ind].span, help_text);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -98,6 +98,24 @@ struct Struct2 {
|
|||
a: [i32; 8000],
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
enum CopyableLargeEnum {
|
||||
A(bool),
|
||||
B([u128; 4000]),
|
||||
}
|
||||
|
||||
enum ManuallyCopyLargeEnum {
|
||||
A(bool),
|
||||
B([u128; 4000]),
|
||||
}
|
||||
|
||||
impl Clone for ManuallyCopyLargeEnum {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
impl Copy for ManuallyCopyLargeEnum {}
|
||||
|
||||
fn main() {
|
||||
large_enum_variant!();
|
||||
}
|
||||
|
|
|
@ -127,5 +127,49 @@ 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
|
||||
error: large size difference between variants
|
||||
--> $DIR/large_enum_variant.rs:104:5
|
||||
|
|
||||
LL | B([u128; 4000]),
|
||||
| ^^^^^^^^^^^^^^^ this variant is 64000 bytes
|
||||
|
|
||||
note: and the second-largest variant is 1 bytes:
|
||||
--> $DIR/large_enum_variant.rs:103:5
|
||||
|
|
||||
LL | A(bool),
|
||||
| ^^^^^^^
|
||||
note: boxing a variant would require the type no longer be `Copy`
|
||||
--> $DIR/large_enum_variant.rs:102:6
|
||||
|
|
||||
LL | enum CopyableLargeEnum {
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
help: consider boxing the large fields to reduce the total size of the enum
|
||||
--> $DIR/large_enum_variant.rs:104:5
|
||||
|
|
||||
LL | B([u128; 4000]),
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: large size difference between variants
|
||||
--> $DIR/large_enum_variant.rs:109:5
|
||||
|
|
||||
LL | B([u128; 4000]),
|
||||
| ^^^^^^^^^^^^^^^ this variant is 64000 bytes
|
||||
|
|
||||
note: and the second-largest variant is 1 bytes:
|
||||
--> $DIR/large_enum_variant.rs:108:5
|
||||
|
|
||||
LL | A(bool),
|
||||
| ^^^^^^^
|
||||
note: boxing a variant would require the type no longer be `Copy`
|
||||
--> $DIR/large_enum_variant.rs:107:6
|
||||
|
|
||||
LL | enum ManuallyCopyLargeEnum {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
help: consider boxing the large fields to reduce the total size of the enum
|
||||
--> $DIR/large_enum_variant.rs:109:5
|
||||
|
|
||||
LL | B([u128; 4000]),
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue