@@ -5,7 +5,7 @@ use clippy_utils::macros::{MacroCall, macro_backtrace};
55use clippy_utils:: source:: snippet_with_applicability;
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 , sym} ;
@@ -90,33 +90,27 @@ impl LateLintPass<'_> for DbgMacro {
9090 ( macro_call. span , String :: from ( "()" ) )
9191 }
9292 } ,
93- // dbg!(1)
94- ExprKind :: Match ( val, ..) => (
95- macro_call. span ,
96- snippet_with_applicability ( cx, val. span . source_callsite ( ) , ".." , & mut applicability)
97- . to_string ( ) ,
98- ) ,
99- // dbg!(2, 3)
100- ExprKind :: Tup (
101- [
102- Expr {
103- kind : ExprKind :: Match ( first, ..) ,
104- ..
105- } ,
106- ..,
107- Expr {
108- kind : ExprKind :: Match ( last, ..) ,
109- ..
110- } ,
111- ] ,
112- ) => {
113- let snippet = snippet_with_applicability (
114- cx,
115- first. span . source_callsite ( ) . to ( last. span . source_callsite ( ) ) ,
116- ".." ,
117- & mut applicability,
118- ) ;
119- ( macro_call. span , format ! ( "({snippet})" ) )
93+ ExprKind :: Match ( first, arms, _) => {
94+ let vals = collect_vals ( first, arms) ;
95+ let suggestion = match vals. as_slice ( ) {
96+ // dbg!(1) => 1
97+ & [ val] => {
98+ snippet_with_applicability ( cx, val. span . source_callsite ( ) , ".." , & mut applicability)
99+ . to_string ( )
100+ }
101+ // dbg!(2, 3) => (2, 3)
102+ & [ first, .., last] => {
103+ let snippet = snippet_with_applicability (
104+ cx,
105+ first. span . source_callsite ( ) . to ( last. span . source_callsite ( ) ) ,
106+ ".." ,
107+ & mut applicability,
108+ ) ;
109+ format ! ( "({snippet})" )
110+ }
111+ _ => unreachable ! ( ) ,
112+ } ;
113+ ( macro_call. span , suggestion)
120114 } ,
121115 _ => unreachable ! ( ) ,
122116 } ;
@@ -169,3 +163,33 @@ fn is_async_move_desugar<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx
169163fn first_dbg_macro_in_expansion ( cx : & LateContext < ' _ > , span : Span ) -> Option < MacroCall > {
170164 macro_backtrace ( span) . find ( |mc| cx. tcx . is_diagnostic_item ( sym:: dbg_macro, mc. def_id ) )
171165}
166+
167+ /// Extracts all value expressions from the `match`-tree generated by `dbg!`.
168+ ///
169+ /// E.g. from
170+ /// ```rust, ignore
171+ /// match 1 {
172+ /// tmp_1 => match 2 {
173+ /// tmp_2 => {
174+ /// /* printing */
175+ /// (tmp_1, tmp_2)
176+ /// }
177+ /// }
178+ /// }
179+ /// ```
180+ /// this extracts `1` and `2`.
181+ fn collect_vals < ' hir > ( first : & ' hir Expr < ' hir > , mut arms : & ' hir [ Arm < ' hir > ] ) -> Vec < & ' hir Expr < ' hir > > {
182+ let mut vals = vec ! [ first] ;
183+ loop {
184+ let [ arm] = arms else { unreachable ! ( "dbg! macro expansion only has single-arm matches" ) } ;
185+
186+ match is_async_move_desugar ( arm. body ) . unwrap_or ( arm. body ) . peel_drop_temps ( ) . kind {
187+ ExprKind :: Block ( ..) => return vals,
188+ ExprKind :: Match ( val, a, _) => {
189+ vals. push ( val) ;
190+ arms = a;
191+ }
192+ _ => unreachable ! ( "dbg! macro expansion only results in block or match expressions" ) ,
193+ }
194+ }
195+ }
0 commit comments