Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[flake8-bugbear] Fix break/continue handling in loop-iterator-mutation (B909) - #24440

#24440
Merged
MichaReiser merged 5 commits into
astral-sh:mainastral-sh/ruff:mainfrom
anishgirianish:fix/b909-break-continue-branch-trackinganishgirianish/ruff:fix/b909-break-continue-branch-trackingCopy head branch name to clipboard
Apr 21, 2026
Merged

[flake8-bugbear] Fix break/continue handling in loop-iterator-mutation (B909)#24440
MichaReiser merged 5 commits into
astral-sh:mainastral-sh/ruff:mainfrom
anishgirianish:fix/b909-break-continue-branch-trackinganishgirianish/ruff:fix/b909-break-continue-branch-trackingCopy head branch name to clipboard

Conversation

@anishgirianish

@anishgirianish anishgirianish commented Apr 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #12402.

B909's branch tracking had a few issues: the branch counter wasn't restored after if blocks, continue wasn't handled as a terminator, nested loop break/continue was incorrectly treated as exiting the outer loop, and there was no branch isolation for for/else, while/else, or try/except/else/finally.

Fixed by tracking loop_depth so nested break only affects the inner loop, giving each arm of forking statements its own branch (merged back into the parent on exit), and pre-scanning loop bodies to determine whether else is unconditional.

Test Plan

Added 8 fixture cases covering nested break/continue, for/else, while/else, and try/except/else/finally.

@astral-sh-bot
astral-sh-bot Bot requested a review from ntBre April 6, 2026 06:18
@astral-sh-bot

astral-sh-bot Bot commented Apr 6, 2026

Copy link
Copy Markdown

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

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

binary-husky/gpt_academic (+0 -1 violations, +0 -0 fixes)

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

- shared_utils/nltk_downloader.py:2141:17: B909 Mutation to loop iterable `self._download_msg_queue` during iteration

pytest-dev/pytest (+0 -1 violations, +0 -0 fixes)

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

- scripts/release.py:65:17: B909 Mutation to loop iterable `lines` during iteration

Changes by rule (1 rules affected)

code total + violation - violation + fix - fix
B909 2 0 2 0 0

@MichaReiser MichaReiser added rule Implementing or modifying a lint rule preview Related to preview mode features labels Apr 8, 2026
Comment thread crates/ruff_linter/src/rules/flake8_bugbear/rules/loop_iterator_mutation.rs Outdated
Comment thread crates/ruff_linter/src/rules/flake8_bugbear/rules/loop_iterator_mutation.rs Outdated
@MichaReiser MichaReiser assigned MichaReiser and unassigned ntBre Apr 9, 2026
@anishgirianish

Copy link
Copy Markdown
Contributor Author

@MichaReiser Thank you so much for the review. Addressed both comments, nested break/continue is now gated by loop depth, and branch tracking covers for/else, while/else, and try/except/else/finally. Ready for re-review whenever you have time!

Thank you

@ntBre
ntBre removed their request for review April 13, 2026 13:37
@MichaReiser MichaReiser changed the title [flake8-bugbear] Fix break/continue handling in loop-iterator-mutation [flake8-bugbear] Fix break/continue handling in loop-iterator-mutation (B909) Apr 14, 2026
Comment thread crates/ruff_linter/src/rules/flake8_bugbear/rules/loop_iterator_mutation.rs Outdated
Comment thread crates/ruff_linter/resources/test/fixtures/flake8_bugbear/B909.py
Comment thread crates/ruff_linter/src/rules/flake8_bugbear/rules/loop_iterator_mutation.rs Outdated

@MichaReiser MichaReiser left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you. I found one more false positive which we should fix if it's easy to do so. If not, that's fine also.

This PR is certainly a big improvement!

Comment thread crates/ruff_linter/resources/test/fixtures/flake8_bugbear/B909.py
@anishgirianish
anishgirianish force-pushed the fix/b909-break-continue-branch-tracking branch from a7d4d02 to e947692 Compare April 18, 2026 19:31
@MichaReiser
MichaReiser merged commit 11db358 into astral-sh:main Apr 21, 2026
44 checks passed
nicopauss pushed a commit to Intersec/lib-common that referenced this pull request Jun 4, 2026
##### [\`v0.15.12\`](https://github.com/astral-sh/ruff/blob/HEAD/CHANGELOG.md#01512)

Released on 2026-04-24.

##### Preview features

- Implement `#ruff:file-ignore` file-level suppressions ([#23599](astral-sh/ruff#23599))
- Implement `#ruff:ignore` logical-line suppressions ([#23404](astral-sh/ruff#23404))
- Revert preview changes to displayed diagnostic severity in LSP ([#24789](astral-sh/ruff#24789))
- \[`airflow`] Implement `task-branch-as-short-circuit` (`AIR004`) ([#23579](astral-sh/ruff#23579))
- \[`flake8-bugbear`] Fix `break`/`continue` handling in `loop-iterator-mutation` (`B909`) ([#24440](astral-sh/ruff#24440))
- \[`pylint`] Fix `PLC2701` for type parameter scopes ([#24576](astral-sh/ruff#24576))

##### Rule changes

- \[`pandas-vet`] Suggest `.array` as well in `PD011` ([#24805](astral-sh/ruff#24805))

##### CLI

- Respect default Unix permissions for cache files ([#24794](astral-sh/ruff#24794))

##### Documentation

- \[`pylint`] Fix `PLR0124` description not to claim self-comparison always returns the same value ([#24749](astral-sh/ruff#24749))
- \[`pyupgrade`] Expand docs on reusable `TypeVar`s and scoping (`UP046`) ([#24153](astral-sh/ruff#24153))
- Improve rules table accessibility ([#24711](astral-sh/ruff#24711))

##### Contributors

- [@dylwil3](https://github.com/dylwil3)
- [@AlexWaygood](https://github.com/AlexWaygood)
- [@woodruffw](https://github.com/woodruffw)
- [@avasis-ai](https://github.com/avasis-ai)
- [@Dev-iL](https://github.com/Dev-iL)
- [@denyszhak](https://github.com/denyszhak)
- [@ShipItAndPray](https://github.com/ShipItAndPray)
- [@anishgirianish](https://github.com/anishgirianish)
- [@augustelalande](https://github.com/augustelalande)
- [@amyreese](https://github.com/amyreese)
- [@majiayu000](https://github.com/majiayu000)
##### [\`v0.15.11\`](https://github.com/astral-sh/ruff/blob/HEAD/CHANGELOG.md#01511)

Released on 2026-04-16.

##### Preview features

- \[`ruff`] Ignore `RUF029` when function is decorated with `asynccontextmanager` ([#24642](astral-sh/ruff#24642))
- \[`airflow`] Implement `airflow-xcom-pull-in-template-string` (`AIR201`) ([#23583](astral-sh/ruff#23583))
- \[`flake8-bandit`] Fix `S103` false positives and negatives in mask analysis ([#24424](astral-sh/ruff#24424))

##### Bug fixes

- \[`flake8-async`] Omit overridden methods for `ASYNC109` ([#24648](astral-sh/ruff#24648))

##### Documentation

- \[`flake8-async`] Add override mention to `ASYNC109` docs ([#24666](astral-sh/ruff#24666))
- Update Neovim config examples to use `vim.lsp.config` ([#24577](astral-sh/ruff#24577))

##### Contributors

- [@augustelalande](https://github.com/augustelalande)
- [@anishgirianish](https://github.com/anishgirianish)
- [@benberryallwood](https://github.com/benberryallwood)
- [@charliermarsh](https://github.com/charliermarsh)
- [@Dev-iL](https://github.com/Dev-iL)

Renovate-Branch: renovate/2024.6-ruff-0.15.x
Change-Id: I2c5de44f14ce3133db71161eae18c7b43f7ba09b
Priv-Id: 9c1a7f10043a2db2338a90de9a62a4d7989df14d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

preview Related to preview mode features rule Implementing or modifying a lint rule

Projects

None yet

Development

Successfully merging this pull request may close these issues.

loop-iterator-mutation (B909) - logic to determine whether the mutation is followed by a break statement is incorrect

3 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.