ruff
5ace2a89 - [`flake8-type-checking`] Avoid `strict` behavior when `future-annotations` are enabled (`TC001`, `TC002`, `TC003`) (#25035)

Commit
151 days ago
[`flake8-type-checking`] Avoid `strict` behavior when `future-annotations` are enabled (`TC001`, `TC002`, `TC003`) (#25035) ## Summary Fixes #23185. Enabling `lint.future-annotations = true` was silently flipping `TC001`/`TC002`/`TC003` into strict-mode behaviour, even when `lint.flake8-type-checking.strict = false`. The two settings are orthogonal — the former controls whether `from __future__ import annotations` is auto-inserted as a fix; the latter controls whether typing-only imports whose module is already imported at runtime should be flagged. ## Root cause In [`crates/ruff_linter/src/rules/flake8_type_checking/rules/typing_only_runtime_import.rs`](https://github.com/astral-sh/ruff/blob/main/crates/ruff_linter/src/rules/flake8_type_checking/rules/typing_only_runtime_import.rs), the skip condition for implicit runtime imports read: ```rust if !checker.settings().future_annotations && !checker.settings().flake8_type_checking.strict && runtime_imports.iter().any(|import| is_implicit_import(binding, import)) { continue; } ``` This required **both** `!future_annotations` **and** `!strict` to be true. The moment a user opted into `future_annotations = true`, the first clause became false and the entire skip was bypassed — making the rules behave as if `strict = true`, regardless of the user's explicit `strict = false` setting. This also matches the direction @ntBre suggested on the issue: > This does sound like a bug to me. I think I may have gotten this logic wrong, and it should be an `or` instead of `and`… ## Solution Drop the `!future_annotations` clause. Only `!strict` should gate whether implicit runtime imports are skipped. The `future_annotations` setting is handled elsewhere (as part of the fix-generation path for adding the `__future__` import); it has no bearing on which imports are flagged. ## Testing - **New regression test** in `crates/ruff_linter/src/rules/flake8_type_checking/mod.rs`: `future_annotations_respects_non_strict_mode`, backed by a new fixture `crates/ruff_linter/resources/test/fixtures/flake8_type_checking/TC001-3_future_strict.py`. The test pins the exact scenario from the issue (`future_annotations=true`, `strict=false`, typing-only import whose module has a runtime-used sibling) and asserts zero `TC001`/`TC002`/`TC003` diagnostics are produced — a result that would have been non-zero prior to this patch. - All 92 pre-existing `flake8_type_checking` lib tests still pass locally; the `add_future_import` snapshot tests (which exercise the `future_annotations = true` path) also pass unchanged, confirming the fix does not regress the auto-insert-`__future__`-import behaviour. - `cargo test --lib flake8_type_checking` → 92 passed, 0 failed - `cargo test --lib add_future_import` → 12 passed, 0 failed ## Checklist - [x] Fixes the root cause (not just the symptom) - [x] New test covers the exact failing scenario from the issue - [x] All existing tests pass - [x] No unrelated changes - [x] Code style matches project conventions - [x] Followed CONTRIBUTING.md
Author
Parents
Loading