Skip to content

[conformance] Error if an imported name marked as Final is re-assigned#2389

Closed
fangyi-zhou wants to merge 5 commits intofacebook:mainfrom
fangyi-zhou:export-final
Closed

[conformance] Error if an imported name marked as Final is re-assigned#2389
fangyi-zhou wants to merge 5 commits intofacebook:mainfrom
fangyi-zhou:export-final

Conversation

@fangyi-zhou
Copy link
Copy Markdown
Contributor

Summary

This diff implements a new feature to error when an imported Final name is re-assigned.
This requirement stems from the spec section:

https://typing.python.org/en/latest/spec/qualifiers.html#importing-final-variables

If a module declares a Final variable and another module imports that variable in an import statement by name or wildcard, the imported symbol inherits the Final type qualifier. Any attempt to assign a different value to this symbol should be flagged as an error by a type checker

Implementation notes:

  • Add a new field is_final for each Export, to indicate whether the name is final
  • Extend export lookup to check for finality, similar to special exports are handled
  • Raise an error if an imported final value is assigned to.

Test Plan

New test case.
Reran conformance test suite and observed 2 fewer errors.

fangyi-zhou and others added 4 commits February 12, 2026 01:11
Add an `is_final` method to the `LookupExport` trait and implement it in
`TransactionHandle`, chasing through re-exports. Use this in a new
`check_for_imported_final_reassignment` check in `bind_name` to emit a
`BadAssignment` error when an imported `Final` name is reassigned.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Final to SpecialExport and extract is_final_annotation helper so
that annotations like typing.Final[int] and typing_extensions.Final are
correctly detected, not just bare Final.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@meta-cla meta-cla bot added the cla signed label Feb 12, 2026
@meta-codesync
Copy link
Copy Markdown
Contributor

meta-codesync bot commented Feb 12, 2026

@migeed-z has imported this pull request. If you are a Meta employee, you can view this in D93045597.

@github-actions
Copy link
Copy Markdown

Diff from mypy_primer, showing the effect of this PR on open source code:

urllib3 (https://github.com/urllib3/urllib3)
+ ERROR src/urllib3/util/ssl_.py:125:9-36: Cannot assign to `HAS_NEVER_CHECK_COMMON_NAME` because it is imported as final [bad-assignment]
+ ::error file=src/urllib3/util/ssl_.py,line=125,col=9,endLine=125,endColumn=36,title=Pyrefly bad-assignment::Cannot assign to `HAS_NEVER_CHECK_COMMON_NAME` because it is imported as final

trio (https://github.com/python-trio/trio)
+ ERROR src/trio/_tests/test_highlevel_socket.py:11:33-34: Cannot assign to `TYPE_CHECKING` because it is imported as final [bad-assignment]
+ ::error file=src/trio/_tests/test_highlevel_socket.py,line=11,col=33,endLine=11,endColumn=34,title=Pyrefly bad-assignment::Cannot assign to `TYPE_CHECKING` because it is imported as final

zulip (https://github.com/zulip/zulip)
+ ERROR zproject/settings.py:41:34-35: Cannot assign to `TYPE_CHECKING` because it is imported as final [bad-assignment]
+ ::error file=zproject/settings.py,line=41,col=34,endLine=41,endColumn=35,title=Pyrefly bad-assignment::Cannot assign to `TYPE_CHECKING` because it is imported as final

ibis (https://github.com/ibis-project/ibis)
+ ERROR ibis/expr/datatypes/__init__.py:4:38-39: Cannot assign to `TYPE_CHECKING` because it is imported as final [bad-assignment]
+ ERROR ibis/expr/types/__init__.py:6:36-37: Cannot assign to `TYPE_CHECKING` because it is imported as final [bad-assignment]
+ ERROR ibis/expr/types/__init__.py:8:34-35: Cannot assign to `TYPE_CHECKING` because it is imported as final [bad-assignment]
+ ERROR ibis/expr/types/__init__.py:9:37-38: Cannot assign to `TYPE_CHECKING` because it is imported as final [bad-assignment]
+ ERROR ibis/expr/types/__init__.py:10:40-41: Cannot assign to `TYPE_CHECKING` because it is imported as final [bad-assignment]
+ ERROR ibis/expr/types/__init__.py:12:34-35: Cannot assign to `TYPE_CHECKING` because it is imported as final [bad-assignment]
+ ERROR ibis/expr/types/__init__.py:13:37-38: Cannot assign to `TYPE_CHECKING` because it is imported as final [bad-assignment]
+ ERROR ibis/expr/types/__init__.py:14:34-35: Cannot assign to `TYPE_CHECKING` because it is imported as final [bad-assignment]
+ ERROR ibis/expr/types/__init__.py:15:37-38: Cannot assign to `TYPE_CHECKING` because it is imported as final [bad-assignment]
+ ERROR ibis/expr/types/__init__.py:16:39-40: Cannot assign to `TYPE_CHECKING` because it is imported as final [bad-assignment]
+ ERROR ibis/expr/types/__init__.py:17:35-36: Cannot assign to `TYPE_CHECKING` because it is imported as final [bad-assignment]
+ ERROR ibis/expr/types/__init__.py:18:37-38: Cannot assign to `TYPE_CHECKING` because it is imported as final [bad-assignment]
+ ERROR ibis/expr/types/__init__.py:19:37-38: Cannot assign to `TYPE_CHECKING` because it is imported as final [bad-assignment]
+ ERROR ibis/expr/types/__init__.py:20:38-39: Cannot assign to `TYPE_CHECKING` because it is imported as final [bad-assignment]
+ ::error file=ibis/expr/datatypes/__init__.py,line=4,col=38,endLine=4,endColumn=39,title=Pyrefly bad-assignment::Cannot assign to `TYPE_CHECKING` because it is imported as final
+ ::error file=ibis/expr/types/__init__.py,line=6,col=36,endLine=6,endColumn=37,title=Pyrefly bad-assignment::Cannot assign to `TYPE_CHECKING` because it is imported as final
+ ::error file=ibis/expr/types/__init__.py,line=8,col=34,endLine=8,endColumn=35,title=Pyrefly bad-assignment::Cannot assign to `TYPE_CHECKING` because it is imported as final
+ ::error file=ibis/expr/types/__init__.py,line=9,col=37,endLine=9,endColumn=38,title=Pyrefly bad-assignment::Cannot assign to `TYPE_CHECKING` because it is imported as final
+ ::error file=ibis/expr/types/__init__.py,line=10,col=40,endLine=10,endColumn=41,title=Pyrefly bad-assignment::Cannot assign to `TYPE_CHECKING` because it is imported as final
+ ::error file=ibis/expr/types/__init__.py,line=12,col=34,endLine=12,endColumn=35,title=Pyrefly bad-assignment::Cannot assign to `TYPE_CHECKING` because it is imported as final
+ ::error file=ibis/expr/types/__init__.py,line=13,col=37,endLine=13,endColumn=38,title=Pyrefly bad-assignment::Cannot assign to `TYPE_CHECKING` because it is imported as final
+ ::error file=ibis/expr/types/__init__.py,line=14,col=34,endLine=14,endColumn=35,title=Pyrefly bad-assignment::Cannot assign to `TYPE_CHECKING` because it is imported as final
+ ::error file=ibis/expr/types/__init__.py,line=15,col=37,endLine=15,endColumn=38,title=Pyrefly bad-assignment::Cannot assign to `TYPE_CHECKING` because it is imported as final
+ ::error file=ibis/expr/types/__init__.py,line=16,col=39,endLine=16,endColumn=40,title=Pyrefly bad-assignment::Cannot assign to `TYPE_CHECKING` because it is imported as final
+ ::error file=ibis/expr/types/__init__.py,line=17,col=35,endLine=17,endColumn=36,title=Pyrefly bad-assignment::Cannot assign to `TYPE_CHECKING` because it is imported as final
+ ::error file=ibis/expr/types/__init__.py,line=18,col=37,endLine=18,endColumn=38,title=Pyrefly bad-assignment::Cannot assign to `TYPE_CHECKING` because it is imported as final
+ ::error file=ibis/expr/types/__init__.py,line=19,col=37,endLine=19,endColumn=38,title=Pyrefly bad-assignment::Cannot assign to `TYPE_CHECKING` because it is imported as final
+ ::error file=ibis/expr/types/__init__.py,line=20,col=38,endLine=20,endColumn=39,title=Pyrefly bad-assignment::Cannot assign to `TYPE_CHECKING` because it is imported as final

@fangyi-zhou
Copy link
Copy Markdown
Contributor Author

fangyi-zhou commented Feb 12, 2026

Checked mypy-primer issues, most of them are of form of re-importing a Final value twice (potentially once via * import, once via direct import)

@migeed-z migeed-z self-assigned this Feb 13, 2026
Copy link
Copy Markdown
Contributor

@stroxler stroxler left a comment

Choose a reason for hiding this comment

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

Review automatically exported from Phabricator review in Meta.

@meta-codesync
Copy link
Copy Markdown
Contributor

meta-codesync bot commented Feb 13, 2026

@migeed-z merged this pull request in a6d9bc1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants