Skip to content

Rule B909 (loop-iterator-mutation) doesn't detect many kinds of list mutation #12164

@Boon-in-Oz

Description

@Boon-in-Oz

Hello and thank you for this excellent tool,

I'm running Ruff as a linter in VS Code with select = ["ALL"], preview = true and only specific rules ignored. I'm still on Python 3.7.7, and using the Ruff 2024.28.0 extension.

I've found that B909 sometimes fires when I extend a list in a loop, but not when I remove or del an item from it. I'm not sure how the original Bugbear behaves in this case but in practice these seem very similar and any of them can cause bugs.

I can't find any report of this in issues, searching for "B909", "mutation", "iterator". The only issue I found was the original task to implement B038: #9511

Repros:

This does not generate any linting errors:
(from https://stackoverflow.com/questions/6260089/strange-result-when-removing-item-from-a-list-while-iterating-over-it-in-python)

numbers = list(range(1, 30))
for i in numbers:
    if i < 20:
        numbers.remove(i)
print(numbers)

[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]

But this triggers both B909 and PERF401:

numbers = list(range(1, 30))
for i in numbers:
    if i < 20:
        numbers.append(i + 20)
print(numbers)

This does not trigger B909 or PERF401 either (though it does correctly trigger FURB148 on the enumerate call)

numbers = list(range(1, 30))
for i, _ in enumerate(numbers):
    if i < 20:
        numbers.append(i)

Same for this:

numbers = list(range(1, 30))
for i, _ in enumerate(numbers):
    if i < 20:
        del numbers[i]
print(numbers)

[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28]

And this (don't try this one, it's an infinite loop)

numbers = list(range(1, 30))
for i, _ in enumerate(numbers):
    if i > 20:
        numbers.append(i)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions