From 92537a0e5b73629b7c25061ccff6dc255e53c6b6 Mon Sep 17 00:00:00 2001 From: J-ZhengLi Date: Fri, 29 Dec 2023 10:15:45 +0800 Subject: [PATCH 1/2] add test case with a proc macro `fake_desugar_await` --- tests/ui/auxiliary/proc_macro_attr.rs | 20 ++++++++++++++++++++ tests/ui/blocks_in_conditions.fixed | 13 +++++++++++++ tests/ui/blocks_in_conditions.rs | 13 +++++++++++++ tests/ui/blocks_in_conditions.stderr | 16 +++++++++++----- 4 files changed, 57 insertions(+), 5 deletions(-) diff --git a/tests/ui/auxiliary/proc_macro_attr.rs b/tests/ui/auxiliary/proc_macro_attr.rs index ac544737099c..75f7a20f961b 100644 --- a/tests/ui/auxiliary/proc_macro_attr.rs +++ b/tests/ui/auxiliary/proc_macro_attr.rs @@ -125,3 +125,23 @@ pub fn fake_main(_attr: TokenStream, item: TokenStream) -> TokenStream { } .into() } + +#[proc_macro_attribute] +pub fn fake_desugar_await(_args: TokenStream, input: TokenStream) -> TokenStream { + let mut async_fn = syn::parse_macro_input!(input as syn::ItemFn); + + for stmt in &mut async_fn.block.stmts { + if let syn::Stmt::Expr(syn::Expr::Match(syn::ExprMatch { expr: scrutinee, .. }), _) = stmt { + if let syn::Expr::Await(syn::ExprAwait { base, await_token, .. }) = scrutinee.as_mut() { + let blc = quote_spanned!( await_token.span => { + #[allow(clippy::let_and_return)] + let __pinned = #base; + __pinned + }); + *scrutinee = parse_quote!(#blc); + } + } + } + + quote!(#async_fn).into() +} diff --git a/tests/ui/blocks_in_conditions.fixed b/tests/ui/blocks_in_conditions.fixed index efef60567a97..ac1ad68ffc23 100644 --- a/tests/ui/blocks_in_conditions.fixed +++ b/tests/ui/blocks_in_conditions.fixed @@ -1,3 +1,5 @@ +//@aux-build:proc_macro_attr.rs + #![warn(clippy::blocks_in_conditions)] #![allow(unused, clippy::let_and_return, clippy::needless_if)] #![warn(clippy::nonminimal_bool)] @@ -99,4 +101,15 @@ fn issue_12162() { } } +mod issue_12016 { + #[proc_macro_attr::fake_desugar_await] + pub async fn await_becomes_block() -> i32 { + let res = await; match res { + Some(1) => 2, + Some(2) => 3, + _ => 0, + } + } +} + fn main() {} diff --git a/tests/ui/blocks_in_conditions.rs b/tests/ui/blocks_in_conditions.rs index 8bd8a939eb16..e72daaa910d4 100644 --- a/tests/ui/blocks_in_conditions.rs +++ b/tests/ui/blocks_in_conditions.rs @@ -1,3 +1,5 @@ +//@aux-build:proc_macro_attr.rs + #![warn(clippy::blocks_in_conditions)] #![allow(unused, clippy::let_and_return, clippy::needless_if)] #![warn(clippy::nonminimal_bool)] @@ -99,4 +101,15 @@ fn issue_12162() { } } +mod issue_12016 { + #[proc_macro_attr::fake_desugar_await] + pub async fn await_becomes_block() -> i32 { + match Some(1).await { + Some(1) => 2, + Some(2) => 3, + _ => 0, + } + } +} + fn main() {} diff --git a/tests/ui/blocks_in_conditions.stderr b/tests/ui/blocks_in_conditions.stderr index b00fe2f632c7..cb2f6da3516c 100644 --- a/tests/ui/blocks_in_conditions.stderr +++ b/tests/ui/blocks_in_conditions.stderr @@ -1,5 +1,5 @@ error: in an `if` condition, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` - --> $DIR/blocks_in_conditions.rs:23:5 + --> $DIR/blocks_in_conditions.rs:25:5 | LL | / if { LL | | @@ -20,13 +20,13 @@ LL ~ }; if res { | error: omit braces around single expression condition - --> $DIR/blocks_in_conditions.rs:35:8 + --> $DIR/blocks_in_conditions.rs:37:8 | LL | if { true } { 6 } else { 10 } | ^^^^^^^^ help: try: `true` error: this boolean expression can be simplified - --> $DIR/blocks_in_conditions.rs:41:8 + --> $DIR/blocks_in_conditions.rs:43:8 | LL | if true && x == 3 { 6 } else { 10 } | ^^^^^^^^^^^^^^ help: try: `x == 3` @@ -35,7 +35,7 @@ LL | if true && x == 3 { 6 } else { 10 } = help: to override `-D warnings` add `#[allow(clippy::nonminimal_bool)]` error: in a `match` scrutinee, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` - --> $DIR/blocks_in_conditions.rs:68:5 + --> $DIR/blocks_in_conditions.rs:70:5 | LL | / match { LL | | @@ -53,5 +53,11 @@ LL + opt LL ~ }; match res { | -error: aborting due to 4 previous errors +error: in a `match` scrutinee, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` + --> $DIR/blocks_in_conditions.rs:107:9 + | +LL | match Some(1).await { + | ^^^^^^^^^^^^^^^^^^^ help: try: `let res = await; match res` + +error: aborting due to 5 previous errors From 4cc7b7e09287c1a4908d73c1104b222858193e85 Mon Sep 17 00:00:00 2001 From: J-ZhengLi Date: Mon, 12 Feb 2024 04:16:11 +0800 Subject: [PATCH 2/2] stop linting [`blocks_in_conditions`] on `match` on proc macros --- clippy_lints/src/blocks_in_conditions.rs | 4 ++-- tests/ui/blocks_in_conditions.fixed | 2 +- tests/ui/blocks_in_conditions.stderr | 8 +------- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/blocks_in_conditions.rs b/clippy_lints/src/blocks_in_conditions.rs index ff4dffd06079..eae87db26c6f 100644 --- a/clippy_lints/src/blocks_in_conditions.rs +++ b/clippy_lints/src/blocks_in_conditions.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; use clippy_utils::source::snippet_block_with_applicability; use clippy_utils::ty::implements_trait; use clippy_utils::visitors::{for_each_expr, Descend}; -use clippy_utils::{get_parent_expr, higher}; +use clippy_utils::{get_parent_expr, higher, is_from_proc_macro}; use core::ops::ControlFlow; use rustc_errors::Applicability; use rustc_hir::{BlockCheckMode, Expr, ExprKind, MatchSource}; @@ -94,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInConditions { } } else { let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span); - if span.from_expansion() || expr.span.from_expansion() { + if span.from_expansion() || expr.span.from_expansion() || is_from_proc_macro(cx, cond) { return; } // move block higher diff --git a/tests/ui/blocks_in_conditions.fixed b/tests/ui/blocks_in_conditions.fixed index ac1ad68ffc23..caf29e23d545 100644 --- a/tests/ui/blocks_in_conditions.fixed +++ b/tests/ui/blocks_in_conditions.fixed @@ -104,7 +104,7 @@ fn issue_12162() { mod issue_12016 { #[proc_macro_attr::fake_desugar_await] pub async fn await_becomes_block() -> i32 { - let res = await; match res { + match Some(1).await { Some(1) => 2, Some(2) => 3, _ => 0, diff --git a/tests/ui/blocks_in_conditions.stderr b/tests/ui/blocks_in_conditions.stderr index cb2f6da3516c..4d3efb4ffd1f 100644 --- a/tests/ui/blocks_in_conditions.stderr +++ b/tests/ui/blocks_in_conditions.stderr @@ -53,11 +53,5 @@ LL + opt LL ~ }; match res { | -error: in a `match` scrutinee, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let` - --> $DIR/blocks_in_conditions.rs:107:9 - | -LL | match Some(1).await { - | ^^^^^^^^^^^^^^^^^^^ help: try: `let res = await; match res` - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors