Skip to content

[ty] Fix disjointness checks with type-of @final classes#21770

Merged
ibraheemdev merged 2 commits intomainfrom
ibraheem/type-of-final-class-disjointness
Dec 10, 2025
Merged

[ty] Fix disjointness checks with type-of @final classes#21770
ibraheemdev merged 2 commits intomainfrom
ibraheem/type-of-final-class-disjointness

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 ✅

@ibraheemdev ibraheemdev force-pushed the ibraheem/type-of-final-class-disjointness branch from 1a0174d to 394be60 Compare December 3, 2025 06:21
@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 491 diagnostics
+ Found 489 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:5335:57: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/frame.py:5346:64: 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.py:1117:80: 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:455:69: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/util.py:457:67: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- static_frame/core/util.py:459:49: 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 1833 diagnostics
+ Found 1795 diagnostics

pandas-stubs (https://github.com/pandas-dev/pandas-stubs)
- pandas-stubs/_typing.pyi:1217:16: warning[unused-ignore-comment] Unused blanket `type: ignore` directive
- Found 5259 diagnostics
+ Found 5258 diagnostics

No memory usage changes detected ✅

@codspeed-hq
Copy link

codspeed-hq bot commented Dec 3, 2025

CodSpeed Performance Report

Merging #21770 will not alter performance

Comparing ibraheem/type-of-final-class-disjointness (e4e1ff2) with main (5dc0079)

Summary

✅ 22 untouched
⏩ 30 skipped1

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
Base automatically changed from ibraheem/final-class-disjointness to main December 10, 2025 19:17
@ibraheemdev ibraheemdev force-pushed the ibraheem/type-of-final-class-disjointness branch from a7521b1 to 2b923ed Compare December 10, 2025 19:18
@ibraheemdev ibraheemdev force-pushed the ibraheem/type-of-final-class-disjointness branch from 2b923ed to 7dfe6e0 Compare December 10, 2025 19:21
@sharkdp
Copy link
Contributor

sharkdp commented Dec 10, 2025

Oh, it looks like you're solving some some tests with TODOs that I added earlier today (astral-sh/ty#1842)

@ibraheemdev ibraheemdev force-pushed the ibraheem/type-of-final-class-disjointness branch from 6e8ce19 to e4e1ff2 Compare December 10, 2025 19:51
@ibraheemdev
Copy link
Member Author

@sharkdp I think I've fixed those by delegating to the default specialization, now that we have an implementation for disjointness between generic aliases.

@ibraheemdev ibraheemdev merged commit a2fb2ee into main Dec 10, 2025
42 checks passed
@ibraheemdev ibraheemdev deleted the ibraheem/type-of-final-class-disjointness branch December 10, 2025 20:15
dcreager added a commit that referenced this pull request Dec 10, 2025
…-cycle

* origin/main:
  [ty] Support implicit type of `cls` in signatures (#21771)
  [ty] add `SyntheticTypedDictType` and implement `normalized` and `is_equivalent_to` (#21784)
  [ty] Fix disjointness checks with type-of `@final` classes (#21770)
  [ty] Fix negation upper bounds in constraint sets (#21897)
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.

3 participants

Comments