@@ -87,12 +87,6 @@ pub struct ExcessiveBools {
87
87
max_fn_params_bools : u64 ,
88
88
}
89
89
90
- #[ derive( Eq , PartialEq , Debug , Copy , Clone ) ]
91
- enum Kind {
92
- Struct ,
93
- Fn ,
94
- }
95
-
96
90
impl ExcessiveBools {
97
91
#[ must_use]
98
92
pub fn new ( max_struct_bools : u64 , max_fn_params_bools : u64 ) -> Self {
@@ -101,64 +95,60 @@ impl ExcessiveBools {
101
95
max_fn_params_bools,
102
96
}
103
97
}
98
+ }
104
99
105
- fn too_many_bools < ' tcx > ( & self , tys : impl Iterator < Item = & ' tcx Ty < ' tcx > > , kind : Kind ) -> bool {
106
- if let Ok ( bools) = tys. filter ( |ty| is_bool ( ty) ) . count ( ) . try_into ( ) {
107
- ( if Kind :: Fn == kind {
108
- self . max_fn_params_bools
109
- } else {
110
- self . max_struct_bools
111
- } ) < bools
112
- } else {
113
- false
114
- }
115
- }
100
+ impl_lint_pass ! ( ExcessiveBools => [ STRUCT_EXCESSIVE_BOOLS , FN_PARAMS_EXCESSIVE_BOOLS ] ) ;
116
101
117
- fn check_fn_sig ( & self , cx : & LateContext < ' _ > , fn_decl : & FnDecl < ' _ > , span : Span ) {
118
- if !span. from_expansion ( ) && self . too_many_bools ( fn_decl. inputs . iter ( ) , Kind :: Fn ) {
119
- span_lint_and_help (
120
- cx,
121
- FN_PARAMS_EXCESSIVE_BOOLS ,
122
- span,
123
- format ! ( "more than {} bools in function parameters" , self . max_fn_params_bools) ,
124
- None ,
125
- "consider refactoring bools into two-variant enums" ,
126
- ) ;
127
- }
128
- }
102
+ fn has_n_bools < ' tcx > ( iter : impl Iterator < Item = & ' tcx Ty < ' tcx > > , mut count : u64 ) -> bool {
103
+ iter. filter ( |ty| is_bool ( ty) ) . any ( |_| {
104
+ let ( x, overflow) = count. overflowing_sub ( 1 ) ;
105
+ count = x;
106
+ overflow
107
+ } )
129
108
}
130
109
131
- impl_lint_pass ! ( ExcessiveBools => [ STRUCT_EXCESSIVE_BOOLS , FN_PARAMS_EXCESSIVE_BOOLS ] ) ;
110
+ fn check_fn_decl ( cx : & LateContext < ' _ > , decl : & FnDecl < ' _ > , sp : Span , max : u64 ) {
111
+ if has_n_bools ( decl. inputs . iter ( ) , max) && !sp. from_expansion ( ) {
112
+ span_lint_and_help (
113
+ cx,
114
+ FN_PARAMS_EXCESSIVE_BOOLS ,
115
+ sp,
116
+ format ! ( "more than {max} bools in function parameters" ) ,
117
+ None ,
118
+ "consider refactoring bools into two-variant enums" ,
119
+ ) ;
120
+ }
121
+ }
132
122
133
123
impl < ' tcx > LateLintPass < ' tcx > for ExcessiveBools {
134
124
fn check_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx Item < ' tcx > ) {
135
- if item. span . from_expansion ( ) {
136
- return ;
137
- }
138
- if let ItemKind :: Struct ( variant_data, _) = & item. kind {
139
- if has_repr_attr ( cx, item. hir_id ( ) ) {
140
- return ;
141
- }
142
-
143
- if self . too_many_bools ( variant_data. fields ( ) . iter ( ) . map ( |field| field. ty ) , Kind :: Struct ) {
144
- span_lint_and_help (
145
- cx,
146
- STRUCT_EXCESSIVE_BOOLS ,
147
- item. span ,
148
- format ! ( "more than {} bools in a struct" , self . max_struct_bools) ,
149
- None ,
150
- "consider using a state machine or refactoring bools into two-variant enums" ,
151
- ) ;
152
- }
125
+ if let ItemKind :: Struct ( variant_data, _) = & item. kind
126
+ && variant_data. fields ( ) . len ( ) as u64 > self . max_struct_bools
127
+ && has_n_bools (
128
+ variant_data. fields ( ) . iter ( ) . map ( |field| field. ty ) ,
129
+ self . max_struct_bools ,
130
+ )
131
+ && !has_repr_attr ( cx, item. hir_id ( ) )
132
+ && !item. span . from_expansion ( )
133
+ {
134
+ span_lint_and_help (
135
+ cx,
136
+ STRUCT_EXCESSIVE_BOOLS ,
137
+ item. span ,
138
+ format ! ( "more than {} bools in a struct" , self . max_struct_bools) ,
139
+ None ,
140
+ "consider using a state machine or refactoring bools into two-variant enums" ,
141
+ ) ;
153
142
}
154
143
}
155
144
156
145
fn check_trait_item ( & mut self , cx : & LateContext < ' tcx > , trait_item : & ' tcx TraitItem < ' tcx > ) {
157
146
// functions with a body are already checked by `check_fn`
158
147
if let TraitItemKind :: Fn ( fn_sig, TraitFn :: Required ( _) ) = & trait_item. kind
159
148
&& fn_sig. header . abi == Abi :: Rust
149
+ && fn_sig. decl . inputs . len ( ) as u64 > self . max_fn_params_bools
160
150
{
161
- self . check_fn_sig ( cx, fn_sig. decl , fn_sig. span ) ;
151
+ check_fn_decl ( cx, fn_sig. decl , fn_sig. span , self . max_fn_params_bools ) ;
162
152
}
163
153
}
164
154
@@ -171,12 +161,13 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
171
161
span : Span ,
172
162
def_id : LocalDefId ,
173
163
) {
174
- let hir_id = cx. tcx . local_def_id_to_hir_id ( def_id) ;
175
164
if let Some ( fn_header) = fn_kind. header ( )
176
165
&& fn_header. abi == Abi :: Rust
177
- && get_parent_as_impl ( cx. tcx , hir_id) . map_or ( true , |impl_item| impl_item. of_trait . is_none ( ) )
166
+ && fn_decl. inputs . len ( ) as u64 > self . max_fn_params_bools
167
+ && get_parent_as_impl ( cx. tcx , cx. tcx . local_def_id_to_hir_id ( def_id) )
168
+ . map_or ( true , |impl_item| impl_item. of_trait . is_none ( ) )
178
169
{
179
- self . check_fn_sig ( cx, fn_decl, span) ;
170
+ check_fn_decl ( cx, fn_decl, span, self . max_fn_params_bools ) ;
180
171
}
181
172
}
182
173
}
0 commit comments