[flake8-type-checking] Avoid strict behavior when future-annotations are enabled (TC001, TC002, TC003)#25035
Merged
ntBre merged 2 commits intoMay 15, 2026
Conversation
…02/TC003 (fixes astral-sh#23185) Root cause: the skip condition for implicit runtime imports in typing_only_runtime_import required BOTH !future_annotations AND !strict to be true. When a user enabled future_annotations=true without enabling strict mode, the first clause short-circuited the skip, causing TC001/TC002/TC003 to flag imports that have valid runtime siblings -- silently flipping the rules into strict-mode behavior. Fix: gate the skip on the strict setting only. future_annotations is orthogonal -- it controls whether 'from __future__ import annotations' is auto-inserted as part of the fix, not whether runtime-shadowed imports are flagged. Matches the intent stated in the docs and the direction suggested by the maintainer on the issue.
ntBre
reviewed
May 13, 2026
Contributor
ntBre
left a comment
There was a problem hiding this comment.
I had a couple of nits, but this looks right to me, thanks!
…re/test docstrings Per @ntBre's review on astral-sh#25035: - Restore the simpler pre-astral-sh#19100 comment in typing_only_runtime_import.rs - Use assert_diagnostics! for the regression test so future changes produce a snapshot diff instead of a hard assert failure - Drop the duplicated explanation from the test docstring and fixture comments; the test name + fixture header are sufficient context
Contributor
Author
|
Pushed
Full |
future_annotations incorrectly enables strict-mode behavior for TC001/TC002/TC003 (fixes #23185)flake8-type-checking] Avoid strict behavior when future-annotations are enabled (TC001, TC002, TC003)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #23185.
Enabling
lint.future-annotations = truewas silently flippingTC001/TC002/TC003into strict-mode behaviour, even whenlint.flake8-type-checking.strict = false. The two settings are orthogonal — the former controls whetherfrom __future__ import annotationsis 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, the skip condition for implicit runtime imports read:This required both
!future_annotationsand!strictto be true. The moment a user opted intofuture_annotations = true, the first clause became false and the entire skip was bypassed — making the rules behave as ifstrict = true, regardless of the user's explicitstrict = falsesetting.This also matches the direction @ntBre suggested on the issue:
Solution
Drop the
!future_annotationsclause. Only!strictshould gate whether implicit runtime imports are skipped. Thefuture_annotationssetting 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
crates/ruff_linter/src/rules/flake8_type_checking/mod.rs:future_annotations_respects_non_strict_mode, backed by a new fixturecrates/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 zeroTC001/TC002/TC003diagnostics are produced — a result that would have been non-zero prior to this patch.flake8_type_checkinglib tests still pass locally; theadd_future_importsnapshot tests (which exercise thefuture_annotations = truepath) also pass unchanged, confirming the fix does not regress the auto-insert-__future__-import behaviour.cargo test --lib flake8_type_checking→ 92 passed, 0 failedcargo test --lib add_future_import→ 12 passed, 0 failedChecklist