@@ -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;
@@ -206,20 +207,33 @@ fn pat_has_no_bindings(pat: &'_ Pat<'_>) -> bool {
206
207
207
208
/// Checks if the passed block is a simple identity referring to bindings created by the pattern
208
209
fn expr_is_simple_identity ( pat : & ' _ Pat < ' _ > , expr : & ' _ Expr < ' _ > ) -> bool {
209
- // TODO support patterns with multiple bindings and tuples, like:
210
+ // We support patterns with multiple bindings and tuples, like:
210
211
// let ... = if let (Some(foo), bar) = g() { (foo, bar) } else { ... }
211
- if_chain ! {
212
- if let ExprKind :: Path ( QPath :: Resolved ( _ty, path) ) = & peel_blocks( expr) . kind;
213
- if let [ path_seg] = path. segments;
214
- then {
215
- let mut pat_bindings = Vec :: new( ) ;
216
- pat. each_binding_or_first( & mut |_ann, _hir_id, _sp, ident| {
217
- pat_bindings. push( ident) ;
218
- } ) ;
219
- if let [ binding] = & pat_bindings[ ..] {
220
- return path_seg. ident == * binding;
212
+ let peeled = peel_blocks ( expr) ;
213
+ let paths = match peeled. kind {
214
+ ExprKind :: Tup ( exprs) | ExprKind :: Array ( exprs) => exprs,
215
+ ExprKind :: Path ( _) => std:: slice:: from_ref ( peeled) ,
216
+ _ => return false ,
217
+ } ;
218
+ let mut pat_bindings = FxHashSet :: default ( ) ;
219
+ pat. each_binding_or_first ( & mut |_ann, _hir_id, _sp, ident| {
220
+ pat_bindings. insert ( ident) ;
221
+ } ) ;
222
+ if pat_bindings. len ( ) < paths. len ( ) {
223
+ return false ;
224
+ }
225
+ for path in paths {
226
+ if_chain ! {
227
+ if let ExprKind :: Path ( QPath :: Resolved ( _ty, path) ) = path. kind;
228
+ if let [ path_seg] = path. segments;
229
+ then {
230
+ if !pat_bindings. remove( & path_seg. ident) {
231
+ return false ;
232
+ }
233
+ } else {
234
+ return false ;
221
235
}
222
236
}
223
237
}
224
- false
238
+ true
225
239
}
0 commit comments