@@ -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;
@@ -201,20 +202,33 @@ fn pat_has_no_bindings(pat: &'_ Pat<'_>) -> bool {
201202
202203/// Checks if the passed block is a simple identity referring to bindings created by the pattern
203204fn 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:
205206 // 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 ;
216230 }
217231 }
218232 }
219- false
233+ true
220234}
0 commit comments