Skip to content

Conversation

@ibraheemdev
Copy link
Member

@ibraheemdev ibraheemdev commented Dec 3, 2025

Summary

We currently perform a subtyping check, similar to what we were doing for @final instances before #21167, which is incorrect, e.g. we currently consider type[X[Any]] and type[X[T]]] disjoint (where X is @final).

Stacked on #21769.

@ibraheemdev ibraheemdev added the ty Multi-file analysis & type inference label Dec 3, 2025
@ibraheemdev ibraheemdev force-pushed the ibraheem/final-class-disjointness branch from 964fc95 to 38334c8 Compare December 3, 2025 06:21
@astral-sh-bot
Copy link

astral-sh-bot bot commented Dec 3, 2025

Diagnostic diff on typing conformance tests

No changes detected when running ty on typing conformance tests ✅

@astral-sh-bot
Copy link

astral-sh-bot bot commented Dec 3, 2025

mypy_primer results

Changes were detected when running on open source projects
beartype (https://github.com/beartype/beartype)
- beartype/claw/_package/clawpkgtrie.py:66:29: warning[unsupported-base] Unsupported class base with type `<class 'dict[str, PackagesTrieBlacklist]'> | <class 'dict[str, Divergent]'>`
- beartype/claw/_package/clawpkgtrie.py:247:29: warning[unsupported-base] Unsupported class base with type `<class 'dict[str, PackagesTrieWhitelist]'> | <class 'dict[str, Divergent]'>`
- Found 498 diagnostics
+ Found 496 diagnostics

mongo-python-driver (https://github.com/mongodb/mongo-python-driver)
- bson/son.py:43:31: error[invalid-assignment] Object of type `<class 'Pattern[str]'>` is not assignable to `<class 'Pattern[Any]'>`
- Found 458 diagnostics
+ Found 457 diagnostics

scikit-build-core (https://github.com/scikit-build/scikit-build-core)
- src/scikit_build_core/_logging.py:153:13: warning[unsupported-base] Unsupported class base with type `<class 'Mapping[str, Style]'> | <class 'Mapping[str, Divergent]'>`
- Found 42 diagnostics
+ Found 41 diagnostics

static-frame (https://github.com/static-frame/static-frame)
- static_frame/core/display.py:483:66: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/display.py:486:57: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/display.py:517:85: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/frame.py:7157:74: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/index.py:251:49: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/index.py:689:66: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/index_hierarchy.py:556:41: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/index_hierarchy.py:557:37: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/index_hierarchy.py:558:30: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/pivot.py:248:76: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/pivot.py:249:48: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/pivot.py:250:55: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/pivot.py:252:47: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/pivot.py:253:44: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/pivot.py:260:44: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/reduce.py:462:48: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/reduce.py:463:39: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/reduce.py:486:48: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/reduce.py:487:39: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/series.py:2106:64: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/type_blocks.py:1881:72: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/type_blocks.py:1883:70: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/util.py:444:48: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/util.py:445:34: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/util.py:446:40: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/util.py:448:52: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/util.py:449:28: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/util.py:452:34: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/util.py:453:89: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/util.py:2094:34: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/util.py:2095:32: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/util.py:2096:32: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- Found 1845 diagnostics
+ Found 1813 diagnostics

pandas (https://github.com/pandas-dev/pandas)
+ pandas/plotting/_matplotlib/converter.py:602:5: error[invalid-argument-type] Method `__getitem__` of type `Overload[(key: ndarray[tuple[Any, ...], dtype[integer[Any] | bool[bool]]] | tuple[ndarray[tuple[Any, ...], dtype[integer[Any] | bool[bool]]], ...], /) -> ndarray[tuple[Any, ...], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]], (key: SupportsIndex | tuple[SupportsIndex, ...], /) -> Any, (key: SupportsIndex | slice[Any, Any, Any] | EllipsisType | ... omitted 5 union elements, /) -> ndarray[tuple[Any, ...], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]], (key: str, /) -> ndarray[tuple[int], dtype[Any]], (key: list[str], /) -> ndarray[tuple[int], dtype[void]]]` cannot be called with key of type `Literal["val"]` on object of type `ndarray[tuple[int], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]]`
+ pandas/plotting/_matplotlib/converter.py:603:5: error[invalid-argument-type] Method `__getitem__` of type `Overload[(key: ndarray[tuple[Any, ...], dtype[integer[Any] | bool[bool]]] | tuple[ndarray[tuple[Any, ...], dtype[integer[Any] | bool[bool]]], ...], /) -> ndarray[tuple[Any, ...], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]], (key: SupportsIndex | tuple[SupportsIndex, ...], /) -> Any, (key: SupportsIndex | slice[Any, Any, Any] | EllipsisType | ... omitted 5 union elements, /) -> ndarray[tuple[Any, ...], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]], (key: str, /) -> ndarray[tuple[int], dtype[Any]], (key: list[str], /) -> ndarray[tuple[int], dtype[void]]]` cannot be called with key of type `Literal["fmt"]` on object of type `ndarray[tuple[int], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]]`
+ pandas/plotting/_matplotlib/converter.py:604:5: error[invalid-argument-type] Method `__getitem__` of type `Overload[(key: ndarray[tuple[Any, ...], dtype[integer[Any] | bool[bool]]] | tuple[ndarray[tuple[Any, ...], dtype[integer[Any] | bool[bool]]], ...], /) -> ndarray[tuple[Any, ...], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]], (key: SupportsIndex | tuple[SupportsIndex, ...], /) -> Any, (key: SupportsIndex | slice[Any, Any, Any] | EllipsisType | ... omitted 5 union elements, /) -> ndarray[tuple[Any, ...], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]], (key: str, /) -> ndarray[tuple[int], dtype[Any]], (key: list[str], /) -> ndarray[tuple[int], dtype[void]]]` cannot be called with key of type `Literal["maj"]` on object of type `ndarray[tuple[int], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]]`
+ pandas/plotting/_matplotlib/converter.py:606:16: error[invalid-argument-type] Method `__getitem__` of type `Overload[(key: ndarray[tuple[Any, ...], dtype[integer[Any] | bool[bool]]] | tuple[ndarray[tuple[Any, ...], dtype[integer[Any] | bool[bool]]], ...], /) -> ndarray[tuple[Any, ...], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]], (key: SupportsIndex | tuple[SupportsIndex, ...], /) -> Any, (key: SupportsIndex | slice[Any, Any, Any] | EllipsisType | ... omitted 5 union elements, /) -> ndarray[tuple[Any, ...], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]], (key: str, /) -> ndarray[tuple[int], dtype[Any]], (key: list[str], /) -> ndarray[tuple[int], dtype[void]]]` cannot be called with key of type `Literal["maj"]` on object of type `ndarray[tuple[int], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]]`
+ pandas/plotting/_matplotlib/converter.py:607:16: error[invalid-argument-type] Method `__getitem__` of type `Overload[(key: ndarray[tuple[Any, ...], dtype[integer[Any] | bool[bool]]] | tuple[ndarray[tuple[Any, ...], dtype[integer[Any] | bool[bool]]], ...], /) -> ndarray[tuple[Any, ...], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]], (key: SupportsIndex | tuple[SupportsIndex, ...], /) -> Any, (key: SupportsIndex | slice[Any, Any, Any] | EllipsisType | ... omitted 5 union elements, /) -> ndarray[tuple[Any, ...], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]], (key: str, /) -> ndarray[tuple[int], dtype[Any]], (key: list[str], /) -> ndarray[tuple[int], dtype[void]]]` cannot be called with key of type `Literal["min"]` on object of type `ndarray[tuple[int], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]]`
+ pandas/plotting/_matplotlib/converter.py:608:16: error[invalid-argument-type] Method `__getitem__` of type `Overload[(key: ndarray[tuple[Any, ...], dtype[integer[Any] | bool[bool]]] | tuple[ndarray[tuple[Any, ...], dtype[integer[Any] | bool[bool]]], ...], /) -> ndarray[tuple[Any, ...], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]], (key: SupportsIndex | tuple[SupportsIndex, ...], /) -> Any, (key: SupportsIndex | slice[Any, Any, Any] | EllipsisType | ... omitted 5 union elements, /) -> ndarray[tuple[Any, ...], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]], (key: str, /) -> ndarray[tuple[int], dtype[Any]], (key: list[str], /) -> ndarray[tuple[int], dtype[void]]]` cannot be called with key of type `Literal["fmt"]` on object of type `ndarray[tuple[int], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]]`
+ pandas/plotting/_matplotlib/converter.py:702:13: error[invalid-assignment] Invalid subscript assignment with key of type `Literal["min"]` and value of type `Literal[True]` on object of type `ndarray[tuple[int], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]]`
+ pandas/plotting/_matplotlib/converter.py:705:13: error[invalid-argument-type] Method `__getitem__` of type `Overload[(key: ndarray[tuple[Any, ...], dtype[integer[Any] | bool[bool]]] | tuple[ndarray[tuple[Any, ...], dtype[integer[Any] | bool[bool]]], ...], /) -> ndarray[tuple[Any, ...], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]], (key: SupportsIndex | tuple[SupportsIndex, ...], /) -> Any, (key: SupportsIndex | slice[Any, Any, Any] | EllipsisType | ... omitted 5 union elements, /) -> ndarray[tuple[Any, ...], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]], (key: str, /) -> ndarray[tuple[int], dtype[Any]], (key: list[str], /) -> ndarray[tuple[int], dtype[void]]]` cannot be called with key of type `Literal["min"]` on object of type `ndarray[tuple[int], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]]`
+ pandas/plotting/_matplotlib/converter.py:770:12: error[invalid-return-type] Return type does not match returned value: expected `ndarray[tuple[Any, ...], dtype[Any]]`, found `ndarray[tuple[int], list[Unknown | tuple[str, <class 'signedinteger[_64Bit]'>] | tuple[str, <class 'bool'>] | tuple[str, str]]]`
- Found 3791 diagnostics
+ Found 3800 diagnostics

pydantic (https://github.com/pydantic/pydantic)
- pydantic/fields.py:943:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:943:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:983:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:983:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1026:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1026:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1066:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1066:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1109:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1109:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1148:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1148:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1188:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`
+ pydantic/fields.py:1188:5: error[invalid-parameter-default] Default value of type `PydanticUndefinedType` is not assignable to annotated parameter type `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`
- pydantic/fields.py:1567:13: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, Divergent] | ((dict[str, Divergent], /) -> None) | None`, found `Top[dict[Unknown, Unknown]] | (((dict[str, Divergent], /) -> None) & ~Top[dict[Unknown, Unknown]]) | None`
+ pydantic/fields.py:1567:13: error[invalid-argument-type] Argument is incorrect: Expected `dict[str, int | float | str | ... omitted 3 union elements] | ((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) | None`, found `Top[dict[Unknown, Unknown]] | (((dict[str, int | float | str | ... omitted 3 union elements], /) -> None) & ~Top[dict[Unknown, Unknown]]) | None`

No memory usage changes detected ✅

@codspeed-hq
Copy link

codspeed-hq bot commented Dec 3, 2025

CodSpeed Performance Report

Merging #21770 will improve performances by 5.7%

Comparing ibraheem/type-of-final-class-disjointness (a7521b1) with ibraheem/final-class-disjointness (8ad0e50)

Summary

⚡ 1 improvement
✅ 21 untouched
⏩ 30 skipped1

Benchmarks breakdown

Mode Benchmark BASE HEAD Change
WallTime medium[colour-science] 94.6 s 89.5 s +5.7%

Footnotes

  1. 30 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@ibraheemdev ibraheemdev force-pushed the ibraheem/type-of-final-class-disjointness branch 3 times, most recently from b7a9f44 to 05560fb Compare December 3, 2025 10:08
static_assert(not is_subtype_of(type[InvSub[bool]], type[InvSub[int]]))
static_assert(not is_subtype_of(type[InvSub[int]], type[InvSub[bool]]))
static_assert(is_disjoint_from(type[InvSub[int]], type[InvSub[str]]))
static_assert(not is_disjoint_from(type[InvSub[bool]], type[InvSub[int]]))
Copy link
Member Author

@ibraheemdev ibraheemdev Dec 3, 2025

Choose a reason for hiding this comment

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

There are a couple false negatives here, including this one (see #21769 (comment)).

@ibraheemdev ibraheemdev marked this pull request as ready for review December 3, 2025 11:28
@ibraheemdev ibraheemdev force-pushed the ibraheem/final-class-disjointness branch from 38334c8 to 8ad0e50 Compare December 3, 2025 20:42
@ibraheemdev ibraheemdev force-pushed the ibraheem/type-of-final-class-disjointness branch from 05560fb to a7521b1 Compare December 3, 2025 20:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants