Skip to content

Commit b2daa39

Browse files
adityasingh2400ntBre
authored andcommitted
[flake8-comprehensions] Document RecursionError edge case in __len__ (C416) (astral-sh#25286)
C416's autofix rewrites a list comprehension like `[item for item in self]` into `list(self)`, but when the original is reached from inside `__len__`, the rewrite recurses: CPython's `list()` constructor probes `__length_hint__` (which dispatches to `__len__`) as a sizing optimization while iterating, so `list(self)` from inside `__len__` calls `__len__` again. The same applies to `dict()` and `set()` calls on `self`. In astral-sh#13752, MichaReiser noted that extending the docs would be reasonable and that detecting this control flow isn't the goal. I added a paragraph to the C416 docstring with a runnable example of the failure mode, plus the `# noqa: C416` workaround for when the comprehension is reached (directly or transitively) from `__len__`. The change is docstring-only. `cargo dev generate-all` and `uvx prek run --from-ref main` both pass. fixes astral-sh#13752 --------- Co-authored-by: Brent Westbrook <brentrwestbrook@gmail.com>
1 parent 42ebf36 commit b2daa39

1 file changed

Lines changed: 5 additions & 3 deletions

File tree

crates/ruff_linter/src/rules/flake8_comprehensions/rules/unnecessary_comprehension.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,12 @@ use crate::rules::flake8_comprehensions::fixes;
5252
/// cannot consistently infer if the iterable type is a sequence or a mapping and cannot suggest
5353
/// the correct fix for mappings.
5454
///
55-
/// ## Fix safety
56-
/// Due to the known problem with dictionary comprehensions, this fix is marked as unsafe.
55+
/// Additionally, rewriting comprehensions inside an object's `__len__` method may cause a
56+
/// `RecursionError`, as collection constructors can call back into `__len__`.
5757
///
58-
/// Additionally, this fix may drop comments when rewriting the comprehension.
58+
/// ## Fix safety
59+
/// This rule's fix is always marked as unsafe because of the known problems described above and
60+
/// because comments may be dropped when rewriting the comprehension.
5961
#[derive(ViolationMetadata)]
6062
#[violation_metadata(stable_since = "v0.0.73")]
6163
pub(crate) struct UnnecessaryComprehension {

0 commit comments

Comments
 (0)