From 08cd140ea6a1557951e2b9c4a4e8f037f37c7760 Mon Sep 17 00:00:00 2001 From: Tom Kuson Date: Wed, 14 Jun 2023 23:00:30 +0100 Subject: [PATCH] Ignore `reimplemented-builtin` if in `async` context (#5101) ## Summary Checks if `checker` is in an `async` context. If yes, return early. Fixes #5098. ## Test Plan `cargo test` --- .../test/fixtures/flake8_simplify/SIM110.py | 14 +++++++++++ .../rules/reimplemented_builtin.rs | 13 +++++++++++ ...ke8_simplify__tests__SIM110_SIM110.py.snap | 23 +++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/crates/ruff/resources/test/fixtures/flake8_simplify/SIM110.py b/crates/ruff/resources/test/fixtures/flake8_simplify/SIM110.py index b02ac7c28c..cc2527e092 100644 --- a/crates/ruff/resources/test/fixtures/flake8_simplify/SIM110.py +++ b/crates/ruff/resources/test/fixtures/flake8_simplify/SIM110.py @@ -171,3 +171,17 @@ def f(): if x.isdigit(): return True return False + +async def f(): + # OK + for x in iterable: + if await check(x): + return True + return False + +async def f(): + # SIM110 + for x in iterable: + if check(x): + return True + return False diff --git a/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs b/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs index 0641da8aef..c306b589a8 100644 --- a/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs +++ b/crates/ruff/src/rules/flake8_simplify/rules/reimplemented_builtin.rs @@ -5,6 +5,7 @@ use rustpython_parser::ast::{ use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; +use ruff_python_ast::helpers::any_over_expr; use ruff_python_ast::source_code::Generator; use crate::checkers::ast::Checker; @@ -224,6 +225,11 @@ fn return_stmt(id: &str, test: &Expr, target: &Expr, iter: &Expr, generator: Gen generator.stmt(&node3.into()) } +/// Return `true` if the `Expr` contains an `await` expression. +fn contains_await(expr: &Expr) -> bool { + any_over_expr(expr, &|expr| matches!(expr, Expr::Await(_))) +} + /// SIM110, SIM111 pub(crate) fn convert_for_loop_to_any_all( checker: &mut Checker, @@ -236,6 +242,13 @@ pub(crate) fn convert_for_loop_to_any_all( if let Some(loop_info) = return_values_for_else(stmt) .or_else(|| sibling.and_then(|sibling| return_values_for_siblings(stmt, sibling))) { + // Check if loop_info.target, loop_info.iter, or loop_info.test contains `await`. + if contains_await(loop_info.target) + || contains_await(loop_info.iter) + || contains_await(loop_info.test) + { + return; + } if loop_info.return_value && !loop_info.next_return_value { if checker.enabled(Rule::ReimplementedBuiltin) { let contents = return_stmt( diff --git a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM110_SIM110.py.snap b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM110_SIM110.py.snap index 7c56013102..1a815035bd 100644 --- a/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM110_SIM110.py.snap +++ b/crates/ruff/src/rules/flake8_simplify/snapshots/ruff__rules__flake8_simplify__tests__SIM110_SIM110.py.snap @@ -294,4 +294,27 @@ SIM110.py:162:5: SIM110 [*] Use `return any(x.isdigit() for x in "012ß9💣2ℝ 167 164 | 168 165 | def f(): +SIM110.py:184:5: SIM110 [*] Use `return any(check(x) for x in iterable)` instead of `for` loop + | +182 | async def f(): +183 | # SIM110 +184 | for x in iterable: + | _____^ +185 | | if check(x): +186 | | return True +187 | | return False + | |________________^ SIM110 + | + = help: Replace with `return any(check(x) for x in iterable)` + +ℹ Suggested fix +181 181 | +182 182 | async def f(): +183 183 | # SIM110 +184 |- for x in iterable: +185 |- if check(x): +186 |- return True +187 |- return False + 184 |+ return any(check(x) for x in iterable) +