@@ -12,10 +12,13 @@ declare_clippy_lint! {
1212 /// `enum`s.
1313 ///
1414 /// **Why is this bad?** Enum size is bounded by the largest variant. Having a
15- /// large variant
16- /// can penalize the memory layout of that enum.
15+ /// large variant can penalize the memory layout of that enum.
1716 ///
18- /// **Known problems:** None.
17+ /// **Known problems:** This lint obviously cannot take the distribution of
18+ /// variants in your running program into account. It is possible that the
19+ /// smaller variants make up less than 1% of all instances, in which case
20+ /// the overhead is negligible and the boxing is counter-productive. Always
21+ /// measure the change this lint suggests.
1922 ///
2023 /// **Example:**
2124 /// ```rust
@@ -52,8 +55,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant {
5255 let ty = cx. tcx . type_of ( did) ;
5356 let adt = ty. ty_adt_def ( ) . expect ( "already checked whether this is an enum" ) ;
5457
55- let mut smallest_variant: Option < ( _ , _ ) > = None ;
5658 let mut largest_variant: Option < ( _ , _ ) > = None ;
59+ let mut second_variant: Option < ( _ , _ ) > = None ;
5760
5861 for ( i, variant) in adt. variants . iter ( ) . enumerate ( ) {
5962 let size: u64 = variant
@@ -69,12 +72,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant {
6972
7073 let grouped = ( size, ( i, variant) ) ;
7174
72- update_if ( & mut smallest_variant, grouped, |a, b| b. 0 <= a. 0 ) ;
73- update_if ( & mut largest_variant, grouped, |a, b| b. 0 >= a. 0 ) ;
75+ if grouped. 0 >= largest_variant. map_or ( 0 , |x| x. 0 ) {
76+ second_variant = largest_variant;
77+ largest_variant = Some ( grouped) ;
78+ }
7479 }
7580
76- if let ( Some ( smallest ) , Some ( largest ) ) = ( smallest_variant , largest_variant ) {
77- let difference = largest. 0 - smallest . 0 ;
81+ if let ( Some ( largest ) , Some ( second ) ) = ( largest_variant , second_variant ) {
82+ let difference = largest. 0 - second . 0 ;
7883
7984 if difference > self . maximum_size_difference_allowed {
8085 let ( i, variant) = largest. 1 ;
@@ -114,16 +119,3 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant {
114119 }
115120 }
116121}
117-
118- fn update_if < T , F > ( old : & mut Option < T > , new : T , f : F )
119- where
120- F : Fn ( & T , & T ) -> bool ,
121- {
122- if let Some ( ref mut val) = * old {
123- if f ( val, & new) {
124- * val = new;
125- }
126- } else {
127- * old = Some ( new) ;
128- }
129- }
0 commit comments