@@ -5,7 +5,7 @@ use clippy_utils::source::snippet_with_applicability;
55use clippy_utils:: { is_in_test, sym} ;
66use rustc_data_structures:: fx:: FxHashSet ;
77use rustc_errors:: Applicability ;
8- use rustc_hir:: { Closure , ClosureKind , CoroutineKind , Expr , ExprKind , LetStmt , LocalSource , Node , Stmt , StmtKind } ;
8+ use rustc_hir:: { Arm , Closure , ClosureKind , CoroutineKind , Expr , ExprKind , LetStmt , LocalSource , Node , Stmt , StmtKind } ;
99use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
1010use rustc_session:: impl_lint_pass;
1111use rustc_span:: { Span , SyntaxContext } ;
@@ -92,15 +92,16 @@ impl LateLintPass<'_> for DbgMacro {
9292 ( macro_call. span , String :: from ( "()" ) )
9393 }
9494 } ,
95- ExprKind :: Match ( args, _, _) => {
96- let suggestion = match args. kind {
95+ ExprKind :: Match ( first, arms, _) => {
96+ let vals = collect_vals ( first, arms) ;
97+ let suggestion = match * vals. as_slice ( ) {
9798 // dbg!(1) => 1
98- ExprKind :: Tup ( [ val] ) => {
99+ [ val] => {
99100 snippet_with_applicability ( cx, val. span . source_callsite ( ) , ".." , & mut applicability)
100101 . to_string ( )
101102 } ,
102103 // dbg!(2, 3) => (2, 3)
103- ExprKind :: Tup ( [ first, .., last] ) => {
104+ [ first, .., last] => {
104105 let snippet = snippet_with_applicability (
105106 cx,
106107 first. span . source_callsite ( ) . to ( last. span . source_callsite ( ) ) ,
@@ -164,3 +165,39 @@ fn is_async_move_desugar<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx
164165fn first_dbg_macro_in_expansion ( cx : & LateContext < ' _ > , span : Span ) -> Option < MacroCall > {
165166 macro_backtrace ( span) . find ( |mc| cx. tcx . is_diagnostic_item ( sym:: dbg_macro, mc. def_id ) )
166167}
168+
169+ /// Extracts all value expressions from the `match`-tree generated by `dbg!`.
170+ ///
171+ /// E.g. from
172+ /// ```rust, ignore
173+ /// match 1 {
174+ /// tmp_1 => match 2 {
175+ /// tmp_2 => {
176+ /// /* printing */
177+ /// (tmp_1, tmp_2)
178+ /// }
179+ /// }
180+ /// }
181+ /// ```
182+ /// this extracts `1` and `2`.
183+ fn collect_vals < ' hir > ( first : & ' hir Expr < ' hir > , mut arms : & ' hir [ Arm < ' hir > ] ) -> Vec < & ' hir Expr < ' hir > > {
184+ let mut vals = vec ! [ first] ;
185+ loop {
186+ let [ arm] = arms else {
187+ unreachable ! ( "dbg! macro expansion only has single-arm matches" )
188+ } ;
189+
190+ match is_async_move_desugar ( arm. body )
191+ . unwrap_or ( arm. body )
192+ . peel_drop_temps ( )
193+ . kind
194+ {
195+ ExprKind :: Block ( ..) => return vals,
196+ ExprKind :: Match ( val, a, _) => {
197+ vals. push ( val) ;
198+ arms = a;
199+ } ,
200+ _ => unreachable ! ( "dbg! macro expansion only results in block or match expressions" ) ,
201+ }
202+ }
203+ }
0 commit comments