@@ -88,77 +88,67 @@ pub struct ExcessiveBools {
8888 max_fn_params_bools : u64 ,
8989}
9090
91- #[ derive( Eq , PartialEq , Debug , Copy , Clone ) ]
92- enum Kind {
93- Struct ,
94- Fn ,
95- }
96-
9791impl ExcessiveBools {
9892 pub fn new ( conf : & ' static Conf ) -> Self {
9993 Self {
10094 max_struct_bools : conf. max_struct_bools ,
10195 max_fn_params_bools : conf. max_fn_params_bools ,
10296 }
10397 }
98+ }
10499
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 ] ) ;
116101
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+ } )
129108}
130109
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+ }
132122
133123impl < ' tcx > LateLintPass < ' tcx > for ExcessiveBools {
134124 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+ ) ;
153142 }
154143 }
155144
156145 fn check_trait_item ( & mut self , cx : & LateContext < ' tcx > , trait_item : & ' tcx TraitItem < ' tcx > ) {
157146 // functions with a body are already checked by `check_fn`
158147 if let TraitItemKind :: Fn ( fn_sig, TraitFn :: Required ( _) ) = & trait_item. kind
159148 && fn_sig. header . abi == Abi :: Rust
149+ && fn_sig. decl . inputs . len ( ) as u64 > self . max_fn_params_bools
160150 {
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 ) ;
162152 }
163153 }
164154
@@ -171,12 +161,13 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
171161 span : Span ,
172162 def_id : LocalDefId ,
173163 ) {
174- let hir_id = cx. tcx . local_def_id_to_hir_id ( def_id) ;
175164 if let Some ( fn_header) = fn_kind. header ( )
176165 && 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 ( ) )
178169 {
179- self . check_fn_sig ( cx, fn_decl, span) ;
170+ check_fn_decl ( cx, fn_decl, span, self . max_fn_params_bools ) ;
180171 }
181172 }
182173}
0 commit comments