[syntax-errors] Detect yield from inside async function (#20051)

<!--
Thank you for contributing to Ruff/ty! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary

This PR implements
https://docs.astral.sh/ruff/rules/yield-from-in-async-function/ as a
syntax semantic error

## Test Plan

<!-- How was it tested? -->
I have written a simple inline test as directed in
[https://github.com/astral-sh/ruff/issues/17412](https://github.com/astral-sh/ruff/issues/17412)

---------

Signed-off-by: 11happy <soni5happy@gmail.com>
Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
Co-authored-by: Brent Westbrook <36778786+ntBre@users.noreply.github.com>
This commit is contained in:
Bhuminjay Soni 2025-09-03 19:43:05 +05:30 committed by GitHub
parent 5d7c17c20a
commit 4c3e1930f6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 140 additions and 33 deletions

View file

@ -709,6 +709,16 @@ impl SemanticSyntaxChecker {
}
Expr::YieldFrom(_) => {
Self::yield_outside_function(ctx, expr, YieldOutsideFunctionKind::YieldFrom);
if ctx.in_function_scope() && ctx.in_async_context() {
// test_err yield_from_in_async_function
// async def f(): yield from x
Self::add_error(
ctx,
SemanticSyntaxErrorKind::YieldFromInAsyncFunction,
expr.range(),
);
}
}
Expr::Await(_) => {
Self::yield_outside_function(ctx, expr, YieldOutsideFunctionKind::Await);
@ -989,6 +999,9 @@ impl Display for SemanticSyntaxError {
SemanticSyntaxErrorKind::AnnotatedNonlocal(name) => {
write!(f, "annotated name `{name}` can't be nonlocal")
}
SemanticSyntaxErrorKind::YieldFromInAsyncFunction => {
f.write_str("`yield from` statement in async function; use `async for` instead")
}
}
}
}
@ -1346,6 +1359,9 @@ pub enum SemanticSyntaxErrorKind {
/// Represents a type annotation on a variable that's been declared nonlocal
AnnotatedNonlocal(String),
/// Represents the use of `yield from` inside an asynchronous function.
YieldFromInAsyncFunction,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, get_size2::GetSize)]