@@ -3,6 +3,7 @@ use clippy_utils::higher::IfLetOrMatch;
33use clippy_utils:: visitors:: { for_each_expr, Descend } ;
44use clippy_utils:: { meets_msrv, msrvs, peel_blocks} ;
55use if_chain:: if_chain;
6+ use rustc_data_structures:: fx:: FxHashSet ;
67use rustc_hir:: { Expr , ExprKind , MatchSource , Pat , QPath , Stmt , StmtKind } ;
78use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
89use rustc_middle:: lint:: in_external_macro;
@@ -206,20 +207,33 @@ fn pat_has_no_bindings(pat: &'_ Pat<'_>) -> bool {
206207
207208/// Checks if the passed block is a simple identity referring to bindings created by the pattern
208209fn 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:
210211 // 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 ;
221235 }
222236 }
223237 }
224- false
238+ true
225239}
0 commit comments