@@ -3,6 +3,7 @@ use clippy_utils::higher::IfLetOrMatch;
3
3
use clippy_utils:: visitors:: { for_each_expr, Descend } ;
4
4
use clippy_utils:: { meets_msrv, msrvs, peel_blocks} ;
5
5
use if_chain:: if_chain;
6
+ use rustc_data_structures:: fx:: FxHashSet ;
6
7
use rustc_hir:: { Expr , ExprKind , MatchSource , Pat , QPath , Stmt , StmtKind } ;
7
8
use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
8
9
use rustc_middle:: lint:: in_external_macro;
@@ -201,20 +202,33 @@ fn pat_has_no_bindings(pat: &'_ Pat<'_>) -> bool {
201
202
202
203
/// Checks if the passed block is a simple identity referring to bindings created by the pattern
203
204
fn expr_is_simple_identity ( pat : & ' _ Pat < ' _ > , expr : & ' _ Expr < ' _ > ) -> bool {
204
- // TODO support patterns with multiple bindings and tuples, like:
205
+ // We support patterns with multiple bindings and tuples, like:
205
206
// let ... = if let (Some(foo), bar) = g() { (foo, bar) } else { ... }
206
- if_chain ! {
207
- if let ExprKind :: Path ( QPath :: Resolved ( _ty, path) ) = & peel_blocks( expr) . kind;
208
- if let [ path_seg] = path. segments;
209
- then {
210
- let mut pat_bindings = Vec :: new( ) ;
211
- pat. each_binding_or_first( & mut |_ann, _hir_id, _sp, ident| {
212
- pat_bindings. push( ident) ;
213
- } ) ;
214
- if let [ binding] = & pat_bindings[ ..] {
215
- return path_seg. ident == * binding;
207
+ let peeled = peel_blocks ( expr) ;
208
+ let paths = match peeled. kind {
209
+ ExprKind :: Tup ( exprs) | ExprKind :: Array ( exprs) => exprs,
210
+ ExprKind :: Path ( _) => std:: slice:: from_ref ( peeled) ,
211
+ _ => return false ,
212
+ } ;
213
+ let mut pat_bindings = FxHashSet :: default ( ) ;
214
+ pat. each_binding_or_first ( & mut |_ann, _hir_id, _sp, ident| {
215
+ pat_bindings. insert ( ident) ;
216
+ } ) ;
217
+ if pat_bindings. len ( ) < paths. len ( ) {
218
+ return false ;
219
+ }
220
+ for path in paths {
221
+ if_chain ! {
222
+ if let ExprKind :: Path ( QPath :: Resolved ( _ty, path) ) = path. kind;
223
+ if let [ path_seg] = path. segments;
224
+ then {
225
+ if !pat_bindings. remove( & path_seg. ident) {
226
+ return false ;
227
+ }
228
+ } else {
229
+ return false ;
216
230
}
217
231
}
218
232
}
219
- false
233
+ true
220
234
}
0 commit comments