Skip to content

Control flow: return and raise #17121

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 4 commits into from
Apr 3, 2025
Merged

Control flow: return and raise #17121

merged 4 commits into from
Apr 3, 2025

Conversation

dylwil3
Copy link
Collaborator

@dylwil3 dylwil3 commented Apr 1, 2025

We add support for return and raise statements in the control flow graph: we simply add an edge to the terminal block, push the statements to the current block, and proceed.

This implementation will have to be modified somewhat once we add support for try statements - then we will need to check whether to defer the jump. But for now this will do!

Also in this PR: We fix the unreachable diagnostic range so that it lumps together consecutive unreachable blocks.

@dylwil3 dylwil3 added the internal An internal refactor or improvement label Apr 1, 2025
@dylwil3 dylwil3 mentioned this pull request Apr 1, 2025
9 tasks
Copy link
Contributor

github-actions bot commented Apr 1, 2025

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

ℹ️ ecosystem check detected linter changes. (+18 -0 violations, +0 -0 fixes in 5 projects; 50 projects unchanged)

apache/airflow (+13 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --no-fix --output-format concise --preview --select ALL

+ airflow-core/src/airflow/models/mappedoperator.py:71:9: PLW0101 Unreachable code in `expand_start_from_trigger`
+ airflow-core/src/airflow/triggers/base.py:103:9: PLW0101 Unreachable code in `run`
+ airflow-core/tests/unit/models/test_baseoperator.py:213:21: PLW0101 Unreachable code in `my_work`
+ airflow-core/tests/unit/models/test_mappedoperator.py:1171:17: PLW0101 Unreachable code in `my_work`
+ airflow-core/tests/unit/models/test_mappedoperator.py:1209:25: PLW0101 Unreachable code in `my_work`
+ airflow-core/tests/unit/models/test_mappedoperator.py:1256:25: PLW0101 Unreachable code in `my_work`
+ airflow-core/tests/unit/models/test_mappedoperator.py:565:21: PLW0101 Unreachable code in `my_setup`
+ airflow-core/tests/unit/models/test_mappedoperator.py:636:21: PLW0101 Unreachable code in `other_setup`
+ airflow-core/tests/unit/models/test_mappedoperator.py:652:21: PLW0101 Unreachable code in `my_setup`
+ airflow-core/tests/unit/models/test_mappedoperator.py:678:21: PLW0101 Unreachable code in `other_setup`
+ airflow-core/tests/unit/models/test_mappedoperator.py:851:21: PLW0101 Unreachable code in `my_work`
+ airflow-core/tests/unit/models/test_mappedoperator.py:868:21: PLW0101 Unreachable code in `my_work`
+ airflow-core/tests/unit/models/test_taskinstance.py:3423:13: PLW0101 Unreachable code in `on_finish_callable`

langchain-ai/langchain (+2 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --no-fix --output-format concise --preview

+ libs/core/tests/unit_tests/runnables/test_fallbacks.py:267:5: PLW0101 Unreachable code in `_generate_immediate_error`
+ libs/core/tests/unit_tests/runnables/test_fallbacks.py:295:5: PLW0101 Unreachable code in `_agenerate_immediate_error`

latchbio/latch (+1 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --no-fix --output-format concise --preview

+ src/latch_cli/snakemake/single_task_snakemake.py:236:5: PLW0101 Unreachable code in `empty_generator`

milvus-io/pymilvus (+1 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --no-fix --output-format concise --preview

+ examples/iterator/iterator.py:64:9: PLW0101 Unreachable code in `external_filter_func`

astropy/astropy (+1 -0 violations, +0 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --no-fix --output-format concise --preview

+ astropy/table/tests/test_bst.py:18:5: PLW0101 Unreachable code in `tree`

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
PLW0101 18 18 0 0 0

Copy link
Member

@MichaReiser MichaReiser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing this incrementally makes it convenient to review. Thank you.

|
16 | def after_return():
17 | return 1
18 | / print("unreachable")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need multiline span diagnostics so that we can highlight the "why". (CC: @ntBre might be a good first rule to port)

With our current noqa system. Would a user have to put the noqa on the last line? Would that be confusing if they have

return 1

if a:
	pass
else:
	other # noqa: unreachable

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's the opposite: noqa comments go at the start of the range. So I think it would be

return 1

if a: # noqa: unreachable
	pass
else:
	other 

Playground example with existing rule

Comment on lines +234 to +238
start = end + 1;

if stmts.get(start).is_some() {
let next_block = self.new_block();
self.move_to(next_block);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems a bit repetitive. We may want to abstract this somehow (e.g. store stmts in the current block and have a self.branch(offset) or similar). But I'm fine deferring this a little longer

@dylwil3 dylwil3 merged commit d401a54 into astral-sh:main Apr 3, 2025
22 checks passed
dcreager added a commit that referenced this pull request Apr 3, 2025
* origin/main:
  [red-knot] Fix more [redundant-cast] false positives (#17170)
  [red-knot] Three-argument type-calls take 'str' as the first argument (#17168)
  Control flow: `return` and `raise` (#17121)
  Bump 0.11.3 (#17173)
  [red-knot] Improve `Debug` implementation for `semantic_index::SymbolTable` (#17172)
  [red-knot] Fix `str(…)` calls (#17163)
  [red-knot] visibility_constraint analysis for match cases (#17077)
  [red-knot] Fix playground crashes when diagnostics are stale (#17165)
dcreager added a commit that referenced this pull request Apr 3, 2025
* origin/main: (82 commits)
  [red-knot] Fix more [redundant-cast] false positives (#17170)
  [red-knot] Three-argument type-calls take 'str' as the first argument (#17168)
  Control flow: `return` and `raise` (#17121)
  Bump 0.11.3 (#17173)
  [red-knot] Improve `Debug` implementation for `semantic_index::SymbolTable` (#17172)
  [red-knot] Fix `str(…)` calls (#17163)
  [red-knot] visibility_constraint analysis for match cases (#17077)
  [red-knot] Fix playground crashes when diagnostics are stale (#17165)
  [red-knot] Callable types are disjoint from literals (#17160)
  [red-knot] Fix inference for `pow` between two literal integers (#17161)
  [red-knot] Add GitHub PR annotations when mdtests fail in CI (#17150)
  [red-knot] Fix equivalence of differently ordered unions that contain `Callable` types (#17145)
  [red-knot] Add initial set of tests for unreachable code (#17159)
  [`airflow`] Move `AIR302` to `AIR301` and `AIR303` to `AIR302` (#17151)
  ruff_db: simplify lifetimes on `DiagnosticDisplay`
  [red-knot] Detect division-by-zero in unions and intersections (#17157)
  [`airflow`] Add autofix infrastructure to `AIR302` name checks (#16965)
  [`flake8-bandit`] Mark `str` and `list[str]` literals as trusted input (`S603`) (#17136)
  [`airflow`] Add autofix for `AIR302` attribute checks (#16977)
  [`airflow`] Extend `AIR302` with additional symbols (#17085)
  ...
maxmynter pushed a commit to maxmynter/ruff that referenced this pull request Apr 3, 2025
We add support for `return` and `raise` statements in the control flow
graph: we simply add an edge to the terminal block, push the statements
to the current block, and proceed.

This implementation will have to be modified somewhat once we add
support for `try` statements - then we will need to check whether to
_defer_ the jump. But for now this will do!

Also in this PR: We fix the `unreachable` diagnostic range so that it
lumps together consecutive unreachable blocks.
@ntBre ntBre mentioned this pull request Apr 4, 2025
4 tasks
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.

2 participants