Use approx_ty_size for large_enum_variant

This commit is contained in:
Lukas Lueg 2022-08-30 22:27:21 +02:00
parent 30e4532153
commit 584000a792
6 changed files with 269 additions and 141 deletions

View file

@ -1,13 +1,12 @@
//! lint when there is a large size difference between variants on an enum //! lint when there is a large size difference between variants on an enum
use clippy_utils::source::snippet_with_applicability; use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{diagnostics::span_lint_and_then, ty::is_copy}; use clippy_utils::{diagnostics::span_lint_and_then, ty::approx_ty_size, ty::is_copy};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::{Item, ItemKind}; use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{Adt, AdtDef, GenericArg, List, Ty};
use rustc_middle::ty::{Adt, Ty};
use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Span; use rustc_span::source_map::Span;
@ -17,7 +16,7 @@ declare_clippy_lint! {
/// `enum`s. /// `enum`s.
/// ///
/// ### Why is this bad? /// ### Why is this bad?
/// Enum size is bounded by the largest variant. Having a /// Enum size is bounded by the largest variant. Having one
/// large variant can penalize the memory layout of that enum. /// large variant can penalize the memory layout of that enum.
/// ///
/// ### Known problems /// ### Known problems
@ -33,8 +32,9 @@ declare_clippy_lint! {
/// use case it may be possible to store the large data in an auxiliary /// use case it may be possible to store the large data in an auxiliary
/// structure (e.g. Arena or ECS). /// structure (e.g. Arena or ECS).
/// ///
/// The lint will ignore generic types if the layout depends on the /// The lint will ignore the impact of generic types to the type layout by
/// generics, even if the size difference will be large anyway. /// assuming every type parameter is zero-sized. Depending on your use case,
/// this may lead to a false positive.
/// ///
/// ### Example /// ### Example
/// ```rust /// ```rust
@ -83,6 +83,38 @@ struct VariantInfo {
fields_size: Vec<FieldInfo>, fields_size: Vec<FieldInfo>,
} }
fn variants_size<'tcx>(
cx: &LateContext<'tcx>,
adt: AdtDef<'tcx>,
subst: &'tcx List<GenericArg<'tcx>>,
) -> Vec<VariantInfo> {
let mut variants_size = adt
.variants()
.iter()
.enumerate()
.map(|(i, variant)| {
let mut fields_size = variant
.fields
.iter()
.enumerate()
.map(|(i, f)| FieldInfo {
ind: i,
size: approx_ty_size(cx, f.ty(cx.tcx, subst)),
})
.collect::<Vec<_>>();
fields_size.sort_by(|a, b| (a.size.cmp(&b.size)));
VariantInfo {
ind: i,
size: fields_size.iter().map(|info| info.size).sum(),
fields_size,
}
})
.collect::<Vec<_>>();
variants_size.sort_by(|a, b| (b.size.cmp(&a.size)));
variants_size
}
impl_lint_pass!(LargeEnumVariant => [LARGE_ENUM_VARIANT]); impl_lint_pass!(LargeEnumVariant => [LARGE_ENUM_VARIANT]);
impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant { impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
@ -92,36 +124,14 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
} }
if let ItemKind::Enum(ref def, _) = item.kind { if let ItemKind::Enum(ref def, _) = item.kind {
let ty = cx.tcx.type_of(item.def_id); let ty = cx.tcx.type_of(item.def_id);
let adt = ty.ty_adt_def().expect("already checked whether this is an enum"); let (adt, subst) = match ty.kind() {
Adt(adt, subst) => (adt, subst),
_ => panic!("already checked whether this is an enum"),
};
if adt.variants().len() <= 1 { if adt.variants().len() <= 1 {
return; return;
} }
let mut variants_size: Vec<VariantInfo> = Vec::new(); let variants_size = variants_size(cx, *adt, subst);
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;
},
}
}
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)));
let mut difference = variants_size[0].size - variants_size[1].size; let mut difference = variants_size[0].size - variants_size[1].size;
if difference > self.maximum_size_difference_allowed { if difference > self.maximum_size_difference_allowed {
@ -129,20 +139,30 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
span_lint_and_then( span_lint_and_then(
cx, cx,
LARGE_ENUM_VARIANT, LARGE_ENUM_VARIANT,
def.variants[variants_size[0].ind].span, item.span,
"large size difference between variants", "large size difference between variants",
|diag| { |diag| {
diag.span_label( diag.span_label(
def.variants[variants_size[0].ind].span, item.span,
&format!("this variant is {} bytes", variants_size[0].size), format!("the entire enum is at least {} bytes", approx_ty_size(cx, ty)),
); );
diag.span_note( diag.span_label(
def.variants[variants_size[0].ind].span,
format!("the largest variant contains at least {} bytes", variants_size[0].size),
);
diag.span_label(
def.variants[variants_size[1].ind].span, def.variants[variants_size[1].ind].span,
&format!("and the second-largest variant is {} bytes:", variants_size[1].size), &if variants_size[1].fields_size.is_empty() {
"the second-largest variant carries no data at all".to_owned()
} else {
format!(
"the second-largest variant contains at least {} bytes",
variants_size[1].size
)
},
); );
let fields = def.variants[variants_size[0].ind].data.fields(); 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 mut applicability = Applicability::MaybeIncorrect;
if is_copy(cx, ty) || maybe_copy(cx, ty) { if is_copy(cx, ty) || maybe_copy(cx, ty) {
diag.span_note( diag.span_note(

View file

@ -3,7 +3,7 @@ Checks for large size differences between variants on
`enum`s. `enum`s.
### Why is this bad? ### Why is this bad?
Enum size is bounded by the largest variant. Having a Enum size is bounded by the largest variant. Having one
large variant can penalize the memory layout of that enum. large variant can penalize the memory layout of that enum.
### Known problems ### Known problems
@ -19,8 +19,9 @@ still be `Clone`, but that is worse ergonomically. Depending on the
use case it may be possible to store the large data in an auxiliary use case it may be possible to store the large data in an auxiliary
structure (e.g. Arena or ECS). structure (e.g. Arena or ECS).
The lint will ignore generic types if the layout depends on the The lint will ignore the impact of generic types to the type layout by
generics, even if the size difference will be large anyway. assuming every type parameter is zero-sized. Depending on your use case,
this may lead to a false positive.
### Example ### Example
``` ```

View file

@ -130,6 +130,30 @@ impl<T: Copy> Clone for SomeGenericPossiblyCopyEnum<T> {
impl<T: Copy> Copy for SomeGenericPossiblyCopyEnum<T> {} impl<T: Copy> Copy for SomeGenericPossiblyCopyEnum<T> {}
enum LargeEnumWithGenerics<T> {
Small,
Large((T, [u8; 512])),
}
struct Foo<T> {
foo: T,
}
enum WithGenerics {
Large([Foo<u64>; 64]),
Small(u8),
}
enum PossiblyLargeEnumWithConst<const U: usize> {
SmallBuffer([u8; 4]),
MightyBuffer([u16; U]),
}
enum LargeEnumOfConst {
Ok,
Error(PossiblyLargeEnumWithConst<256>),
}
fn main() { fn main() {
large_enum_variant!(); large_enum_variant!();
} }

View file

@ -1,143 +1,177 @@
error: large size difference between variants error: large size difference between variants
--> $DIR/large_enum_variant.rs:12:5 --> $DIR/large_enum_variant.rs:10:1
| |
LL | B([i32; 8000]), LL | / enum LargeEnum {
| ^^^^^^^^^^^^^^ this variant is 32000 bytes LL | | A(i32),
| | ------ the second-largest variant contains at least 4 bytes
LL | | B([i32; 8000]),
| | -------------- the largest variant contains at least 32000 bytes
LL | | }
| |_^ the entire enum is at least 32004 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:11: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]>),
| ~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~
error: large size difference between variants error: large size difference between variants
--> $DIR/large_enum_variant.rs:36:5 --> $DIR/large_enum_variant.rs:34:1
| |
LL | ContainingLargeEnum(LargeEnum), LL | / enum LargeEnum2 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this variant is 32004 bytes LL | | VariantOk(i32, u32),
| | ------------------- the second-largest variant contains at least 8 bytes
LL | | ContainingLargeEnum(LargeEnum),
| | ------------------------------ the largest variant contains at least 32004 bytes
LL | | }
| |_^ the entire enum is at least 32008 bytes
| |
note: and the second-largest variant is 8 bytes:
--> $DIR/large_enum_variant.rs:35: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>),
| ~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~
error: large size difference between variants error: large size difference between variants
--> $DIR/large_enum_variant.rs:40:5 --> $DIR/large_enum_variant.rs:39:1
| |
LL | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), LL | / enum LargeEnum3 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this variant is 70004 bytes LL | | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]),
| | --------------------------------------------------------- the largest variant contains at least 70004 bytes
LL | | VoidVariant,
LL | | StructLikeLittle { x: i32, y: i32 },
| | ----------------------------------- the second-largest variant contains at least 8 bytes
LL | | }
| |_^ the entire enum is at least 70008 bytes
| |
note: and the second-largest variant is 8 bytes:
--> $DIR/large_enum_variant.rs:42:5
|
LL | StructLikeLittle { x: i32, y: 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 | ContainingMoreThanOneField(i32, Box<[i32; 8000]>, Box<[i32; 9500]>), LL | ContainingMoreThanOneField(i32, Box<[i32; 8000]>, Box<[i32; 9500]>),
| ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
error: large size difference between variants error: large size difference between variants
--> $DIR/large_enum_variant.rs:47:5 --> $DIR/large_enum_variant.rs:45:1
| |
LL | StructLikeLarge { x: [i32; 8000], y: i32 }, LL | / enum LargeEnum4 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this variant is 32004 bytes LL | | VariantOk(i32, u32),
| | ------------------- the second-largest variant contains at least 8 bytes
LL | | StructLikeLarge { x: [i32; 8000], y: i32 },
| | ------------------------------------------ the largest variant contains at least 32004 bytes
LL | | }
| |_^ the entire enum is at least 32008 bytes
| |
note: and the second-largest variant is 8 bytes:
--> $DIR/large_enum_variant.rs:46: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 | StructLikeLarge { x: Box<[i32; 8000]>, y: i32 }, LL | StructLikeLarge { x: Box<[i32; 8000]>, y: i32 },
| ~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~
error: large size difference between variants error: large size difference between variants
--> $DIR/large_enum_variant.rs:52:5 --> $DIR/large_enum_variant.rs:50:1
| |
LL | StructLikeLarge2 { x: [i32; 8000] }, LL | / enum LargeEnum5 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this variant is 32000 bytes LL | | VariantOk(i32, u32),
| | ------------------- the second-largest variant contains at least 8 bytes
LL | | StructLikeLarge2 { x: [i32; 8000] },
| | ----------------------------------- the largest variant contains at least 32000 bytes
LL | | }
| |_^ the entire enum is at least 32004 bytes
| |
note: and the second-largest variant is 8 bytes:
--> $DIR/large_enum_variant.rs:51: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]> },
| ~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~
error: large size difference between variants error: large size difference between variants
--> $DIR/large_enum_variant.rs:68:5 --> $DIR/large_enum_variant.rs:66:1
| |
LL | B([u8; 1255]), LL | / enum LargeEnum7 {
| ^^^^^^^^^^^^^ this variant is 1255 bytes LL | | A,
LL | | B([u8; 1255]),
| | ------------- the largest variant contains at least 1255 bytes
LL | | C([u8; 200]),
| | ------------ the second-largest variant contains at least 200 bytes
LL | | }
| |_^ the entire enum is at least 1256 bytes
| |
note: and the second-largest variant is 200 bytes:
--> $DIR/large_enum_variant.rs:69:5
|
LL | C([u8; 200]),
| ^^^^^^^^^^^^
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<[u8; 1255]>), LL | B(Box<[u8; 1255]>),
| ~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~
error: large size difference between variants error: large size difference between variants
--> $DIR/large_enum_variant.rs:74:5 --> $DIR/large_enum_variant.rs:72:1
| |
LL | ContainingMoreThanOneField([i32; 8000], [i32; 2], [i32; 9500], [i32; 30]), LL | / enum LargeEnum8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this variant is 70128 bytes LL | | VariantOk(i32, u32),
| | ------------------- the second-largest variant contains at least 8 bytes
LL | | ContainingMoreThanOneField([i32; 8000], [i32; 2], [i32; 9500], [i32; 30]),
| | ------------------------------------------------------------------------- the largest variant contains at least 70128 bytes
LL | | }
| |_^ the entire enum is at least 70132 bytes
| |
note: and the second-largest variant is 8 bytes:
--> $DIR/large_enum_variant.rs:73: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 | ContainingMoreThanOneField(Box<[i32; 8000]>, [i32; 2], Box<[i32; 9500]>, [i32; 30]), LL | ContainingMoreThanOneField(Box<[i32; 8000]>, [i32; 2], Box<[i32; 9500]>, [i32; 30]),
| ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
error: large size difference between variants error: large size difference between variants
--> $DIR/large_enum_variant.rs:79:5 --> $DIR/large_enum_variant.rs:77:1
| |
LL | B(Struct2), LL | / enum LargeEnum9 {
| ^^^^^^^^^^ this variant is 32000 bytes LL | | A(Struct<()>),
| | ------------- the second-largest variant contains at least 4 bytes
LL | | B(Struct2),
| | ---------- the largest variant contains at least 32000 bytes
LL | | }
| |_^ the entire enum is at least 32004 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 help: consider boxing the large fields to reduce the total size of the enum
| |
LL | B(Box<Struct2>), LL | B(Box<Struct2>),
| ~~~~~~~~~~~~ | ~~~~~~~~~~~~
error: large size difference between variants error: large size difference between variants
--> $DIR/large_enum_variant.rs:104:5 --> $DIR/large_enum_variant.rs:82:1
| |
LL | B([u128; 4000]), LL | / enum LargeEnumOk2<T> {
| ^^^^^^^^^^^^^^^ this variant is 64000 bytes LL | | A(T),
| | ---- the second-largest variant contains at least 0 bytes
LL | | B(Struct2),
| | ---------- the largest variant contains at least 32000 bytes
LL | | }
| |_^ the entire enum is at least 32000 bytes
| |
note: and the second-largest variant is 1 bytes: help: consider boxing the large fields to reduce the total size of the enum
--> $DIR/large_enum_variant.rs:103:5 |
LL | B(Box<Struct2>),
| ~~~~~~~~~~~~
error: large size difference between variants
--> $DIR/large_enum_variant.rs:87:1
|
LL | / enum LargeEnumOk3<T> {
LL | | A(Struct<T>),
| | ------------ the second-largest variant contains at least 4 bytes
LL | | B(Struct2),
| | ---------- the largest variant contains at least 32000 bytes
LL | | }
| |_^ the entire enum is at least 32000 bytes
|
help: consider boxing the large fields to reduce the total size of the enum
|
LL | B(Box<Struct2>),
| ~~~~~~~~~~~~
error: large size difference between variants
--> $DIR/large_enum_variant.rs:102:1
|
LL | / enum CopyableLargeEnum {
LL | | A(bool),
| | ------- the second-largest variant contains at least 1 bytes
LL | | B([u128; 4000]),
| | --------------- the largest variant contains at least 64000 bytes
LL | | }
| |_^ the entire enum is at least 64008 bytes
| |
LL | A(bool),
| ^^^^^^^
note: boxing a variant would require the type no longer be `Copy` note: boxing a variant would require the type no longer be `Copy`
--> $DIR/large_enum_variant.rs:102:6 --> $DIR/large_enum_variant.rs:102:6
| |
@ -150,16 +184,16 @@ LL | B([u128; 4000]),
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
error: large size difference between variants error: large size difference between variants
--> $DIR/large_enum_variant.rs:109:5 --> $DIR/large_enum_variant.rs:107:1
| |
LL | B([u128; 4000]), LL | / enum ManuallyCopyLargeEnum {
| ^^^^^^^^^^^^^^^ this variant is 64000 bytes LL | | A(bool),
| | ------- the second-largest variant contains at least 1 bytes
LL | | B([u128; 4000]),
| | --------------- the largest variant contains at least 64000 bytes
LL | | }
| |_^ the entire enum is at least 64008 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` note: boxing a variant would require the type no longer be `Copy`
--> $DIR/large_enum_variant.rs:107:6 --> $DIR/large_enum_variant.rs:107:6
| |
@ -172,16 +206,16 @@ LL | B([u128; 4000]),
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^
error: large size difference between variants error: large size difference between variants
--> $DIR/large_enum_variant.rs:122:5 --> $DIR/large_enum_variant.rs:120:1
| |
LL | B([u64; 4000]), LL | / enum SomeGenericPossiblyCopyEnum<T> {
| ^^^^^^^^^^^^^^ this variant is 32000 bytes LL | | A(bool, std::marker::PhantomData<T>),
| | ------------------------------------ the second-largest variant contains at least 1 bytes
LL | | B([u64; 4000]),
| | -------------- the largest variant contains at least 32000 bytes
LL | | }
| |_^ the entire enum is at least 32008 bytes
| |
note: and the second-largest variant is 1 bytes:
--> $DIR/large_enum_variant.rs:121:5
|
LL | A(bool, std::marker::PhantomData<T>),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: boxing a variant would require the type no longer be `Copy` note: boxing a variant would require the type no longer be `Copy`
--> $DIR/large_enum_variant.rs:120:6 --> $DIR/large_enum_variant.rs:120:6
| |
@ -193,5 +227,53 @@ help: consider boxing the large fields to reduce the total size of the enum
LL | B([u64; 4000]), LL | B([u64; 4000]),
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
error: aborting due to 11 previous errors error: large size difference between variants
--> $DIR/large_enum_variant.rs:133:1
|
LL | / enum LargeEnumWithGenerics<T> {
LL | | Small,
| | ----- the second-largest variant carries no data at all
LL | | Large((T, [u8; 512])),
| | --------------------- the largest variant contains at least 512 bytes
LL | | }
| |_^ the entire enum is at least 512 bytes
|
help: consider boxing the large fields to reduce the total size of the enum
|
LL | Large(Box<(T, [u8; 512])>),
| ~~~~~~~~~~~~~~~~~~~
error: large size difference between variants
--> $DIR/large_enum_variant.rs:142:1
|
LL | / enum WithGenerics {
LL | | Large([Foo<u64>; 64]),
| | --------------------- the largest variant contains at least 512 bytes
LL | | Small(u8),
| | --------- the second-largest variant contains at least 1 bytes
LL | | }
| |_^ the entire enum is at least 520 bytes
|
help: consider boxing the large fields to reduce the total size of the enum
|
LL | Large(Box<[Foo<u64>; 64]>),
| ~~~~~~~~~~~~~~~~~~~
error: large size difference between variants
--> $DIR/large_enum_variant.rs:152:1
|
LL | / enum LargeEnumOfConst {
LL | | Ok,
| | -- the second-largest variant carries no data at all
LL | | Error(PossiblyLargeEnumWithConst<256>),
| | -------------------------------------- the largest variant contains at least 514 bytes
LL | | }
| |_^ the entire enum is at least 514 bytes
|
help: consider boxing the large fields to reduce the total size of the enum
|
LL | Error(Box<PossiblyLargeEnumWithConst<256>>),
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 16 previous errors

View file

@ -1,4 +1,5 @@
#![warn(clippy::result_large_err)] #![warn(clippy::result_large_err)]
#![allow(clippy::large_enum_variant)]
pub fn small_err() -> Result<(), u128> { pub fn small_err() -> Result<(), u128> {
Ok(()) Ok(())

View file

@ -1,5 +1,5 @@
error: the `Err`-variant returned from this function is very large error: the `Err`-variant returned from this function is very large
--> $DIR/result_large_err.rs:7:23 --> $DIR/result_large_err.rs:8:23
| |
LL | pub fn large_err() -> Result<(), [u8; 512]> { LL | pub fn large_err() -> Result<(), [u8; 512]> {
| ^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes | ^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes
@ -8,7 +8,7 @@ LL | pub fn large_err() -> Result<(), [u8; 512]> {
= help: try reducing the size of `[u8; 512]`, for example by boxing large elements or replacing it with `Box<[u8; 512]>` = help: try reducing the size of `[u8; 512]`, for example by boxing large elements or replacing it with `Box<[u8; 512]>`
error: the `Err`-variant returned from this function is very large error: the `Err`-variant returned from this function is very large
--> $DIR/result_large_err.rs:18:21 --> $DIR/result_large_err.rs:19:21
| |
LL | pub fn ret() -> Result<(), Self> { LL | pub fn ret() -> Result<(), Self> {
| ^^^^^^^^^^^^^^^^ the `Err`-variant is at least 240 bytes | ^^^^^^^^^^^^^^^^ the `Err`-variant is at least 240 bytes
@ -16,7 +16,7 @@ LL | pub fn ret() -> Result<(), Self> {
= help: try reducing the size of `FullyDefinedLargeError`, for example by boxing large elements or replacing it with `Box<FullyDefinedLargeError>` = help: try reducing the size of `FullyDefinedLargeError`, for example by boxing large elements or replacing it with `Box<FullyDefinedLargeError>`
error: the `Err`-variant returned from this function is very large error: the `Err`-variant returned from this function is very large
--> $DIR/result_large_err.rs:23:26 --> $DIR/result_large_err.rs:24:26
| |
LL | pub fn struct_error() -> Result<(), FullyDefinedLargeError> { LL | pub fn struct_error() -> Result<(), FullyDefinedLargeError> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 240 bytes | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 240 bytes
@ -24,7 +24,7 @@ LL | pub fn struct_error() -> Result<(), FullyDefinedLargeError> {
= help: try reducing the size of `FullyDefinedLargeError`, for example by boxing large elements or replacing it with `Box<FullyDefinedLargeError>` = help: try reducing the size of `FullyDefinedLargeError`, for example by boxing large elements or replacing it with `Box<FullyDefinedLargeError>`
error: the `Err`-variant returned from this function is very large error: the `Err`-variant returned from this function is very large
--> $DIR/result_large_err.rs:28:45 --> $DIR/result_large_err.rs:29:45
| |
LL | pub fn large_err_via_type_alias<T>(x: T) -> Fdlr<T> { LL | pub fn large_err_via_type_alias<T>(x: T) -> Fdlr<T> {
| ^^^^^^^ the `Err`-variant is at least 240 bytes | ^^^^^^^ the `Err`-variant is at least 240 bytes
@ -32,7 +32,7 @@ LL | pub fn large_err_via_type_alias<T>(x: T) -> Fdlr<T> {
= help: try reducing the size of `FullyDefinedLargeError`, for example by boxing large elements or replacing it with `Box<FullyDefinedLargeError>` = help: try reducing the size of `FullyDefinedLargeError`, for example by boxing large elements or replacing it with `Box<FullyDefinedLargeError>`
error: the `Err`-variant returned from this function is very large error: the `Err`-variant returned from this function is very large
--> $DIR/result_large_err.rs:36:34 --> $DIR/result_large_err.rs:37:34
| |
LL | pub fn param_large_error<R>() -> Result<(), (u128, R, FullyDefinedLargeError)> { LL | pub fn param_large_error<R>() -> Result<(), (u128, R, FullyDefinedLargeError)> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 256 bytes | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 256 bytes
@ -40,7 +40,7 @@ LL | pub fn param_large_error<R>() -> Result<(), (u128, R, FullyDefinedLargeErro
= help: try reducing the size of `(u128, R, FullyDefinedLargeError)`, for example by boxing large elements or replacing it with `Box<(u128, R, FullyDefinedLargeError)>` = help: try reducing the size of `(u128, R, FullyDefinedLargeError)`, for example by boxing large elements or replacing it with `Box<(u128, R, FullyDefinedLargeError)>`
error: the `Err`-variant returned from this function is very large error: the `Err`-variant returned from this function is very large
--> $DIR/result_large_err.rs:47:34 --> $DIR/result_large_err.rs:48:34
| |
LL | pub fn large_enum_error() -> Result<(), Self> { LL | pub fn large_enum_error() -> Result<(), Self> {
| ^^^^^^^^^^^^^^^^ the `Err`-variant is at least 513 bytes | ^^^^^^^^^^^^^^^^ the `Err`-variant is at least 513 bytes
@ -48,7 +48,7 @@ LL | pub fn large_enum_error() -> Result<(), Self> {
= help: try reducing the size of `LargeErrorVariants<()>`, for example by boxing large elements or replacing it with `Box<LargeErrorVariants<()>>` = help: try reducing the size of `LargeErrorVariants<()>`, for example by boxing large elements or replacing it with `Box<LargeErrorVariants<()>>`
error: the `Err`-variant returned from this function is very large error: the `Err`-variant returned from this function is very large
--> $DIR/result_large_err.rs:53:25 --> $DIR/result_large_err.rs:54:25
| |
LL | fn large_error() -> Result<(), [u8; 512]> { LL | fn large_error() -> Result<(), [u8; 512]> {
| ^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes | ^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes
@ -56,7 +56,7 @@ LL | fn large_error() -> Result<(), [u8; 512]> {
= help: try reducing the size of `[u8; 512]`, for example by boxing large elements or replacing it with `Box<[u8; 512]>` = help: try reducing the size of `[u8; 512]`, for example by boxing large elements or replacing it with `Box<[u8; 512]>`
error: the `Err`-variant returned from this function is very large error: the `Err`-variant returned from this function is very large
--> $DIR/result_large_err.rs:72:29 --> $DIR/result_large_err.rs:73:29
| |
LL | pub fn large_union_err() -> Result<(), FullyDefinedUnionError> { LL | pub fn large_union_err() -> Result<(), FullyDefinedUnionError> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes
@ -64,7 +64,7 @@ LL | pub fn large_union_err() -> Result<(), FullyDefinedUnionError> {
= help: try reducing the size of `FullyDefinedUnionError`, for example by boxing large elements or replacing it with `Box<FullyDefinedUnionError>` = help: try reducing the size of `FullyDefinedUnionError`, for example by boxing large elements or replacing it with `Box<FullyDefinedUnionError>`
error: the `Err`-variant returned from this function is very large error: the `Err`-variant returned from this function is very large
--> $DIR/result_large_err.rs:81:40 --> $DIR/result_large_err.rs:82:40
| |
LL | pub fn param_large_union<T: Copy>() -> Result<(), UnionError<T>> { LL | pub fn param_large_union<T: Copy>() -> Result<(), UnionError<T>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes | ^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes
@ -72,7 +72,7 @@ LL | pub fn param_large_union<T: Copy>() -> Result<(), UnionError<T>> {
= help: try reducing the size of `UnionError<T>`, for example by boxing large elements or replacing it with `Box<UnionError<T>>` = help: try reducing the size of `UnionError<T>`, for example by boxing large elements or replacing it with `Box<UnionError<T>>`
error: the `Err`-variant returned from this function is very large error: the `Err`-variant returned from this function is very large
--> $DIR/result_large_err.rs:90:34 --> $DIR/result_large_err.rs:91:34
| |
LL | pub fn array_error_subst<U>() -> Result<(), ArrayError<i32, U>> { LL | pub fn array_error_subst<U>() -> Result<(), ArrayError<i32, U>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 128 bytes | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 128 bytes
@ -80,7 +80,7 @@ LL | pub fn array_error_subst<U>() -> Result<(), ArrayError<i32, U>> {
= help: try reducing the size of `ArrayError<i32, U>`, for example by boxing large elements or replacing it with `Box<ArrayError<i32, U>>` = help: try reducing the size of `ArrayError<i32, U>`, for example by boxing large elements or replacing it with `Box<ArrayError<i32, U>>`
error: the `Err`-variant returned from this function is very large error: the `Err`-variant returned from this function is very large
--> $DIR/result_large_err.rs:94:31 --> $DIR/result_large_err.rs:95:31
| |
LL | pub fn array_error<T, U>() -> Result<(), ArrayError<(i32, T), U>> { LL | pub fn array_error<T, U>() -> Result<(), ArrayError<(i32, T), U>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 128 bytes | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 128 bytes