Skip to content

[syntax-errors] await outside async functions #17363

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 14, 2025

Conversation

ntBre
Copy link
Contributor

@ntBre ntBre commented Apr 11, 2025

Summary

This PR implements detecting the use of await expressions outside of async functions. This is a reimplementation of
await-outside-async (PLE1142) as a semantic syntax error.

Despite the rule name, PLE1142 also applies to async for and async with, so these are covered here too.

Test Plan

Existing PLE1142 tests.

I also deleted more code from the SemanticSyntaxCheckerVisitor to avoid changes in other parser tests.

Summary
--

This PR implements detecting the use of `await` expressions outside of async
functions. This is a reimplementation of
[await-outside-async (PLE1142)](https://docs.astral.sh/ruff/rules/await-outside-async/)
as a semantic syntax error.

Despite the rule name, PLE1142 also applies to `async for` and `async with`, so
these are covered here too.

Test Plan
--

Existing PLE1142 tests, plus new linter tests.

I also deleted more code from the `SemanticSyntaxCheckerVisitor` to avoid
changes in other parser tests.
@ntBre ntBre added the rule Implementing or modifying a lint rule label Apr 11, 2025
@mikeshardmind
Copy link

This one might not belong in syntax-errors and might be better to remain as a disableable rule. Top level await is allowed if the module is compiled with https://docs.python.org/3/library/ast.html#ast.PyCF_ALLOW_TOP_LEVEL_AWAIT. This is useful when working with pyodide, as modules can assume an event loop is running prior to them being imported.

Copy link
Contributor

github-actions bot commented Apr 11, 2025

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

Formatter (stable)

✅ ecosystem check detected no format changes.

Formatter (preview)

✅ ecosystem check detected no format changes.

@ntBre
Copy link
Contributor Author

ntBre commented Apr 11, 2025

This one might not belong in syntax-errors and might be better to remain as a disableable rule. Top level await is allowed if the module is compiled with https://docs.python.org/3/library/ast.html#ast.PyCF_ALLOW_TOP_LEVEL_AWAIT. This is useful when working with pyodide, as modules can assume an event loop is running prior to them being imported.

Oh interesting, thank you! Is there any indication of this option in the file itself, or is this passed externally to the compiler?

This doesn't necessarily need to block this PR because we're still converting the syntax error to a suppressible PLE1142 diagnostic, but we will definitely need to consider this before deprecating the rule or emitting this as a pure syntax error.

@ntBre ntBre marked this pull request as ready for review April 11, 2025 19:43
@mikeshardmind
Copy link

Is there any indication of this option in the file itself, or is this passed externally to the compiler?

Not visible from the file itself. It can be passed as an option to compile, which can be done in a module meta path finder. It's a little advanced use,, so I'm not sure how many projects currently or in the future will do anything with it. The builtin asyncio repl (python -m asyncio) uses it.

@dhruvmanila
Copy link
Member

Despite the rule name, PLE1142 also applies to async for and async with, so these are covered here too.

Interesting. I think we could improve the diagnostic message by replacing "await" with "async with" and "async for" for those cases.

@dhruvmanila
Copy link
Member

dhruvmanila commented Apr 11, 2025

This doesn't necessarily need to block this PR because we're still converting the syntax error to a suppressible PLE1142 diagnostic, but we will definitely need to consider this before deprecating the rule or emitting this as a pure syntax error.

Yeah, maybe we should label this and other PRs as "internal" because there are no user-facing changes except for if we decide to update the error message but that could be done in a follow-up to keep it isolated. What do you think?

@ntBre ntBre added internal An internal refactor or improvement and removed rule Implementing or modifying a lint rule labels Apr 11, 2025
@ntBre
Copy link
Contributor Author

ntBre commented Apr 14, 2025

I added an AwaitOutsideAsyncFunctionKind enum for better error messages in the future, and also noticed that I forgot to wire up the check for dictionary comprehensions. I added some tests for these specifically and copied over the loop from set and list comprehensions.

@ntBre ntBre merged commit 014bb52 into main Apr 14, 2025
22 checks passed
@ntBre ntBre deleted the brent/syn-await-outside-async-function branch April 14, 2025 17:01
dcreager added a commit that referenced this pull request Apr 15, 2025
* main: (31 commits)
  [red-knot] Add some knowledge of `__all__` to `*`-import machinery (#17373)
  Update taiki-e/install-action digest to be7c31b (#17379)
  Update Rust crate mimalloc to v0.1.46 (#17382)
  Update PyO3/maturin-action action to v1.49.1 (#17384)
  Update Rust crate anyhow to v1.0.98 (#17380)
  dependencies: switch from `chrono` to `jiff`
  Update Rust crate bstr to v1.12.0 (#17385)
  [red-knot] Further optimize `*`-import visibility constraints (#17375)
  [red-knot] Minor 'member_lookup_with_policy' fix (#17407)
  [red-knot] Initial support for `dataclass`es (#17353)
  Sync vendored typeshed stubs (#17402)
  [red-knot] improve function/bound method type display (#17294)
  [red-knot] Move relation methods from `CallableType` to `Signature` (#17365)
  [syntax-errors] `await` outside async functions (#17363)
  [red-knot] optimize is_subtype_of for literals (#17394)
  [red-knot] add a large-union-of-string-literals benchmark (#17393)
  Update pre-commit dependencies (#17383)
  [red-knot] mypy_primer: Fail job on panic or internal errors (#17389)
  [red-knot] Document limitations of diagnostics-silencing in unreachable code (#17387)
  [red-knot] detect unreachable attribute assignments (#16852)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
internal An internal refactor or improvement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants