Skip to content

[ty] Enforce Final assignments after conditional bindings#22986

Merged
charliermarsh merged 1 commit intomainfrom
charlie/final
Jan 30, 2026
Merged

[ty] Enforce Final assignments after conditional bindings#22986
charliermarsh merged 1 commit intomainfrom
charlie/final

Conversation

@charliermarsh
Copy link
Member

Summary

When a Final symbol had a conditional prior binding, the iterator could yield Undefined (from the control flow path where the condition was false) as the first element.

Closes astral-sh/ty#2674.

@charliermarsh charliermarsh added ty Multi-file analysis & type inference bug Something isn't working labels Jan 30, 2026
@astral-sh-bot
Copy link

astral-sh-bot bot commented Jan 30, 2026

Typing conformance results

No changes detected ✅

@astral-sh-bot
Copy link

astral-sh-bot bot commented Jan 30, 2026

mypy_primer results

Changes were detected when running on open source projects
pip (https://github.com/pypa/pip)
+ src/pip/_vendor/urllib3/util/ssl_.py:75:27: error[invalid-assignment] Reassignment of `Final` symbol `PROTOCOL_TLS` is not allowed: Reassignment of `Final` symbol
+ src/pip/_vendor/urllib3/util/ssl_.py:80:5: error[invalid-assignment] Reassignment of `Final` symbol `PROTOCOL_TLS_CLIENT` is not allowed: Reassignment of `Final` symbol
+ src/pip/_vendor/urllib3/util/ssl_.py:86:5: error[invalid-assignment] Reassignment of `Final` symbol `OP_NO_SSLv2` is not allowed: Reassignment of `Final` symbol
+ src/pip/_vendor/urllib3/util/ssl_.py:86:18: error[invalid-assignment] Reassignment of `Final` symbol `OP_NO_SSLv3` is not allowed: Reassignment of `Final` symbol
+ src/pip/_vendor/urllib3/util/ssl_.py:87:5: error[invalid-assignment] Reassignment of `Final` symbol `OP_NO_COMPRESSION` is not allowed: Reassignment of `Final` symbol
+ src/pip/_vendor/urllib3/util/ssl_.py:93:5: error[invalid-assignment] Reassignment of `Final` symbol `OP_NO_TICKET` is not allowed: Reassignment of `Final` symbol
- Found 625 diagnostics
+ Found 631 diagnostics

prefect (https://github.com/PrefectHQ/prefect)
+ src/integrations/prefect-dbt/prefect_dbt/core/settings.py:94:28: error[invalid-assignment] Object of type `dict[Any, Any] | int | dict[str, Any] | ... omitted 4 union elements` is not assignable to `dict[str, Any]`
+ src/integrations/prefect-dbt/prefect_dbt/core/settings.py:99:28: error[invalid-assignment] Object of type `int | dict[Any, Any] | float | ... omitted 3 union elements` is not assignable to `dict[str, Any]`
+ src/prefect/cli/deploy/_core.py:86:21: error[invalid-assignment] Object of type `dict[Any, Any] | int | dict[str, Any] | ... omitted 4 union elements` is not assignable to `dict[str, Any]`
+ src/prefect/cli/deploy/_core.py:87:21: error[invalid-assignment] Object of type `int | dict[Any, Any] | float | ... omitted 3 union elements` is not assignable to `dict[str, Any]`
+ src/prefect/deployments/steps/core.py:137:38: error[invalid-argument-type] Argument is incorrect: Argument type `dict[Any, Any] | int | dict[str, Any] | ... omitted 4 union elements` does not satisfy constraints (`str`, `int`, `int | float`, `bool`, `dict[Any, Any]`, `list[Any]`, `None`) of type variable `T`
- src/prefect/utilities/templating.py:320:13: error[invalid-assignment] Invalid subscript assignment with key of type `object` and value of type `Unknown | dict[str, Any]` on object of type `dict[str, Any]`
+ src/prefect/utilities/templating.py:320:13: error[invalid-assignment] Invalid subscript assignment with key of type `object` and value of type `Unknown | int | dict[str, Any] | ... omitted 4 union elements` on object of type `dict[str, Any]`
- src/prefect/utilities/templating.py:323:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_block_document_references | dict[str, Any]`, found `list[Unknown | dict[str, Any]]`
+ src/prefect/utilities/templating.py:323:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_block_document_references | dict[str, Any]`, found `list[Unknown | int | dict[str, Any] | ... omitted 4 union elements]`
- src/prefect/utilities/templating.py:437:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_variables`, found `dict[object, Unknown]`
+ src/prefect/utilities/templating.py:437:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_variables`, found `dict[object, Unknown | int | float | ... omitted 4 union elements]`
- src/prefect/utilities/templating.py:442:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_variables`, found `list[Unknown]`
+ src/prefect/utilities/templating.py:442:16: error[invalid-return-type] Return type does not match returned value: expected `T@resolve_variables`, found `list[Unknown | int | float | ... omitted 4 union elements]`
- src/prefect/workers/base.py:232:13: error[invalid-argument-type] Argument is incorrect: Argument type `str | dict[str, Any]` does not satisfy constraints (`str`, `int`, `int | float`, `bool`, `dict[Any, Any]`, `list[Any]`, `None`) of type variable `T`
+ src/prefect/workers/base.py:232:13: error[invalid-argument-type] Argument is incorrect: Argument type `str | int | dict[str, Any] | ... omitted 3 union elements` does not satisfy constraints (`str`, `int`, `int | float`, `bool`, `dict[Any, Any]`, `list[Any]`, `None`) of type variable `T`
+ src/prefect/workers/base.py:234:22: error[invalid-argument-type] Argument expression after ** must be a mapping type: Found `int | Unknown | float | ... omitted 4 union elements`
- Found 5369 diagnostics
+ Found 5375 diagnostics

scikit-build-core (https://github.com/scikit-build/scikit-build-core)
- src/scikit_build_core/build/wheel.py:99:20: error[no-matching-overload] No overload of bound method `__init__` matches arguments
- Found 47 diagnostics
+ Found 46 diagnostics

dd-trace-py (https://github.com/DataDog/dd-trace-py)
+ ddtrace/vendor/psutil/_common.py:29:5: error[invalid-assignment] Reassignment of `Final` symbol `AF_INET6` is not allowed: Reassignment of `Final` symbol
+ ddtrace/vendor/psutil/_common.py:33:5: error[invalid-assignment] Reassignment of `Final` symbol `AF_UNIX` is not allowed: Reassignment of `Final` symbol
- Found 8567 diagnostics
+ Found 8569 diagnostics

No memory usage changes detected ✅

@charliermarsh
Copy link
Member Author

The new ecosystem diagnostics are false positives, but they may be considered "correct" given our handling of try-except:

try:
    from ssl import PROTOCOL_TLS
    PROTOCOL_SSLv23 = PROTOCOL_TLS
except ImportError:
    try:
        from ssl import PROTOCOL_SSLv23 as PROTOCOL_TLS
        PROTOCOL_SSLv23 = PROTOCOL_TLS
    except ImportError:
        PROTOCOL_SSLv23 = PROTOCOL_TLS = 2

We're flagging the "reassignment" to PROTOCOL_TLS which is declared as Final in ssl.pyi...

@charliermarsh charliermarsh marked this pull request as ready for review January 30, 2026 18:54
@AlexWaygood
Copy link
Member

The new ecosystem diagnostics are false positives, but they may be considered "correct" given our handling of try-except:

I disagree that Final type qualifiers should travel across module boundaries like that, but the consensus was against me in https://discuss.python.org/t/imported-final-variable/82429

@charliermarsh charliermarsh merged commit 0a7bd6f into main Jan 30, 2026
49 checks passed
@charliermarsh charliermarsh deleted the charlie/final branch January 30, 2026 18:58
@charliermarsh
Copy link
Member Author

I was also surprised by this but am significantly less learned in the discourse.

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

Labels

bug Something isn't working ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

no error when reassigning to Final name after conditional assignment

2 participants