Skip to content

[ty] Fix assignability of intersections with bounded typevars#24502

Merged
AlexWaygood merged 6 commits intomainfrom
alex/tvinter
Apr 9, 2026
Merged

[ty] Fix assignability of intersections with bounded typevars#24502
AlexWaygood merged 6 commits intomainfrom
alex/tvinter

Conversation

@AlexWaygood
Copy link
Copy Markdown
Member

@AlexWaygood AlexWaygood commented Apr 8, 2026

Summary

This is basically the same PR as #24193, but it applies the optimisation I suggested in #24193 (comment) to get rid of the huge performance regression reported by codspeed.

It also adds some more tests, since several branches added in #24193 could be removed without any tests failing, but in one case the ecosystem report uncovered cases where the added branch did indeed get rid of false positives. I added a test case based on that snippet surfaced by the ecosystem report.

Note that the ecosystem report is still showing large increases in timings for some projects. Curiously, though, one of those projects is freqtrade, and our codspeed benchmark that uses freqtrade doesn't show any change at all as a result of this PR. On the one hand, our codspeed benchmark doesn't use multithreading, whereas the version of ty run by ecosystem-analyzer does, so maybe this is telling us something about how the new code added here scales with multithreading? On the other hand, though, the ecosystem-analyzer timings use a single noisy sample rather than an average across several measurements, like codspeed does.

Fixes astral-sh/ty#3137

Test Plan

mdtests

Co-authored-by: Carl Meyer carl@astral.sh

@AlexWaygood AlexWaygood added the ty Multi-file analysis & type inference label Apr 8, 2026
@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented Apr 8, 2026

Typing conformance results

No changes detected ✅

Current numbers
The percentage of diagnostics emitted that were expected errors held steady at 87.72%. The percentage of expected errors that received a diagnostic held steady at 82.85%. The number of fully passing files held steady at 74/132.

@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented Apr 8, 2026

Memory usage report

Memory usage unchanged ✅

@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented Apr 8, 2026

ecosystem-analyzer results

Lint rule Added Removed Changed
invalid-await 0 40 0
invalid-argument-type 0 13 0
invalid-assignment 1 0 0
invalid-return-type 0 1 0
no-matching-overload 0 1 0
unsupported-operator 0 1 0
Total 1 56 0

Large timing changes:

Project Old Time New Time Change
freqtrade 0.55s 0.91s +65%

Changes in flaky projects detected. Raw diff output excludes flaky projects; see the HTML report for details.

Raw diff (16 changes)
Tanjun (https://github.com/FasterSpeeding/Tanjun)
- tanjun/annotations.py:1949:74 error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `int | float`, found `_NumberT@__getitem__ & ~int`
- tanjun/annotations.py:1996:74 error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `int | float`, found `_NumberT@__getitem__ & ~int`
- tanjun/annotations.py:2110:75 error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `int | float`, found `_NumberT@__getitem__ & ~float`
- tanjun/annotations.py:2110:86 error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `int | float`, found `_NumberT@__getitem__ & ~float`
- tanjun/annotations.py:2724:26 error[invalid-argument-type] Argument to function `parse_annotated_args` is incorrect: Expected `SlashCommand[Any] | MessageCommand[Any]`, found `_CommandUnionT@with_annotated_args & ~AlwaysFalsy`

altair (https://github.com/vega/altair)
- altair/vegalite/v6/api.py:1179:45 error[invalid-argument-type] Argument to function `_reveal_parsed_shorthand` is incorrect: Expected `Mapping[str, Any]`, found `_C@Then & Top[dict[Unknown, Unknown]]`

artigraph (https://github.com/artigraph/artigraph)
- src/arti/internal/type_hints.py:177:37 error[invalid-argument-type] Argument to function `_check_issubclass` is incorrect: Expected `type`, found `T@lenient_issubclass & ~tuple[object, ...]`

beartype (https://github.com/beartype/beartype)
- beartype/_decor/_nontype/decornontype.py:161:43 error[invalid-argument-type] Argument is incorrect: Argument type `BeartypeableT@beartype_nontype & ~type` does not satisfy upper bound `((...) -> Any) | classmethod[Unknown, (...), Unknown] | property` of type variable `BeartypeableT`
- beartype/_decor/_nontype/decornontype.py:220:47 error[invalid-argument-type] Argument is incorrect: Argument type `BeartypeableT@beartype_nontype & ~type` does not satisfy upper bound `((...) -> Any) | classmethod[Unknown, (...), Unknown] | property` of type variable `BeartypeableT`
- beartype/_decor/decorcore.py:133:26 error[invalid-argument-type] Argument to function `beartype_nontype` is incorrect: Argument type `BeartypeableT@_beartype_object_fatal & ~type` does not satisfy upper bound `((...) -> Any) | classmethod[Unknown, (...), Unknown] | property` of type variable `BeartypeableT`

hydpy (https://github.com/hydpy-dev/hydpy)
- hydpy/auxs/iuhtools.py:436:25 error[unsupported-operator] Unary operator `-` is not supported for object of type `VectorFloatFlex@__call__ | Unknown`
- hydpy/auxs/iuhtools.py:431:17 error[no-matching-overload] No overload of function `clip` matches arguments
+ hydpy/auxs/iuhtools.py:431:17 error[invalid-assignment] Object of type `ndarray[tuple[Any, ...], dtype[Any]]` is not assignable to `VectorFloatFlex@__call__`

setuptools (https://github.com/pypa/setuptools)
- setuptools/glob.py:75:42 error[invalid-argument-type] Argument to function `has_magic` is incorrect: Expected `str | bytes`, found `AnyStr@_iglob & ~AlwaysFalsy`

xarray (https://github.com/pydata/xarray)
- xarray/core/dtypes.py:92:36 error[invalid-argument-type] Argument to function `datetime_data` is incorrect: Expected `str | _HasDType[dtype[datetime64[date | int | None] | timedelta64[timedelta | int | None]]] | dtype[datetime64[date | int | None] | timedelta64[timedelta | int | None]] | _HasNumPyDType[dtype[datetime64[date | int | None] | timedelta64[timedelta | int | None]]]`, found `T_dtype@maybe_promote & dtype[object]`
- xarray/core/dtypes.py:105:36 error[invalid-argument-type] Argument to function `datetime_data` is incorrect: Expected `str | _HasDType[dtype[datetime64[date | int | None] | timedelta64[timedelta | int | None]]] | dtype[datetime64[date | int | None] | timedelta64[timedelta | int | None]] | _HasNumPyDType[dtype[datetime64[date | int | None] | timedelta64[timedelta | int | None]]]`, found `T_dtype@maybe_promote & dtype[object]`

Full report with detailed diff (timing results)

@AlexWaygood AlexWaygood marked this pull request as ready for review April 8, 2026 20:53
@AlexWaygood AlexWaygood assigned carljm and unassigned sharkdp Apr 8, 2026
@carljm
Copy link
Copy Markdown
Contributor

carljm commented Apr 8, 2026

Hmm, I wasn't prioritizing reviving that PR because I lost confidence that this ad hoc handling wherever we encounter these intersections was the right way to approach the problem at all, vs synthesizing derived typevars with narrowed bounds. I think it's on @sharkdp's monthly plan to look into that approach? But if this is looking pretty good, doesn't hurt to do this and then see whether we can/should replace it later.

@AlexWaygood
Copy link
Copy Markdown
Member Author

Yeah, I definitely agree that there's probably a more general solution that eliminates this whole class of bugs. This wasn't hard to put together at all, though, and gets rid of real false positives for users in the meantime.

Copy link
Copy Markdown
Contributor

@carljm carljm left a comment

Choose a reason for hiding this comment

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

Looks great, thank you!

Comment thread crates/ty_python_semantic/src/types/relation.rs Outdated
Comment thread crates/ty_python_semantic/src/types/relation.rs Outdated
@AlexWaygood AlexWaygood changed the title [ty] Fix assignability of intersections with bounded typevars (Alex's version) [ty] Fix assignability of intersections with bounded typevars Apr 9, 2026
@AlexWaygood AlexWaygood merged commit 37a1ec8 into main Apr 9, 2026
53 checks passed
@AlexWaygood AlexWaygood deleted the alex/tvinter branch April 9, 2026 13:23
ibraheemdev pushed a commit that referenced this pull request Apr 15, 2026
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.

Generic with bound unassignable to its bound after widening and narrowing

3 participants