Skip to content

[ty] support implicit recursive union type aliases#22238

Open
mtshiba wants to merge 32 commits intoastral-sh:mainfrom
mtshiba:implicit-recursive-union
Open

[ty] support implicit recursive union type aliases#22238
mtshiba wants to merge 32 commits intoastral-sh:mainfrom
mtshiba:implicit-recursive-union

Conversation

@mtshiba
Copy link
Collaborator

@mtshiba mtshiba commented Dec 29, 2025

Summary

Part of astral-sh/ty#1738

This PR allows implicit (or PEP-613) union type aliases to be self-referential.
To achieve this, two new Rust structs are added: LazyUnionTypeInstance and ImplicitTypeAliasType.
As a result, the previous UnionTypeInstance is now called EagerUnionTypeInstance. Also, an Implicit(ImplicitTypeAliasType) variant is added to TypeAliasType.

First, a union type instance is created as EagerUnionTypeInstance. Then, when registering a binding, it is checked whether it can be promoted to LazyUnionTypeInstance. The promotion criteria include whether it is a valid union type and whether it is a non-generic type (this should be relaxed in the future, but is marked as TODO for this PR).

JsonValue = Union[int, float, bool, str, None, dict[str, "JsonValue"], list["JsonValue"]]
# ↑ Lazy      ↑ Eager                                     ↑ Lazy             ↑ Lazy
typing.cast(Union[int, str], x)
#             ↑ Eager

LazyUnionTypeInstance is converted to ImplicitTypeAliasType in a type context. ImplicitTypeAliasType behaves almost identically to PEP-695 type alias (except that it doesn't have a generic context yet).
There are other KnownInstances that can be converted to ImplicitTypeAliasType in a type context, but in this PR we will focus on union type instances.

Also, this change means that implicit type aliases are now shown with their name rather than their expanded type.
This is preferable, assuming there is reasonable intent behind the naming of type aliases.

Fixes astral-sh/ty#1883 (with #22241)
Fixes astral-sh/ty#1998

Performance analysis

#22238 (comment)

Ecosystem analysis

The new false positive errors appears to be due to astral-sh/ty#2015. Type aliases should basically behave the same as value types, but as in astral-sh/ty#2015, inconsistencies in behavior have been observed in implementations, which may also affect performance.

Test Plan

New corpus test
mdtest updated

@mtshiba mtshiba added ty Multi-file analysis & type inference ecosystem-analyzer labels Dec 29, 2025
@astral-sh-bot
Copy link

astral-sh-bot bot commented Dec 29, 2025

Typing conformance results improved 🎉

The percentage of diagnostics emitted that were expected errors increased from 81.39% to 81.52%. The percentage of expected errors that received a diagnostic increased from 71.60% to 72.25%.

Summary

Metric Old New Diff Outcome
True Positives 774 781 +7 ⏫ (✅)
False Positives 177 177 +0
False Negatives 307 300 -7 ⏬ (✅)
Total Diagnostics 951 958 +7
Precision 81.39% 81.52% +0.14% ⏫ (✅)
Recall 71.60% 72.25% +0.65% ⏫ (✅)

True positives added

Details
Location Name Message
aliases_recursive.py:19:12 invalid-assignment Object of type dict[Unknown | str, Unknown | int | float | complex] is not assignable to Json
aliases_recursive.py:20:12 invalid-assignment Object of type list[Unknown | int | float | complex] is not assignable to Json
aliases_recursive.py:38:22 invalid-assignment Object of type tuple[Literal[1], tuple[Literal["1"], Literal[1]], tuple[Literal[1], tuple[Literal[1], list[Unknown | int]]]] is not assignable to RecursiveTuple
aliases_recursive.py:39:22 invalid-assignment Object of type tuple[Literal[1], list[Unknown | int]] is not assignable to RecursiveTuple
aliases_recursive.py:50:24 invalid-assignment Object of type dict[Unknown | str, Unknown | list[Unknown | int]] is not assignable to RecursiveMapping
aliases_recursive.py:51:24 invalid-assignment Object of type dict[Unknown | str, Unknown | str | int | list[Unknown | int]] is not assignable to RecursiveMapping
aliases_recursive.py:52:24 invalid-assignment Object of type dict[Unknown | str, Unknown | str | int | dict[Unknown | str, Unknown | str | int | list[Unknown | int]]] is not assignable to RecursiveMapping

@astral-sh-bot
Copy link

astral-sh-bot bot commented Dec 29, 2025

mypy_primer results

Changes were detected when running on open source projects
more-itertools (https://github.com/more-itertools/more-itertools)
- more_itertools/recipes.py:1098:18: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(int | float | complex | _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], int | float | complex | _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], /) -> int | float | complex | ... omitted 3 union elements`, found `Overload[(base: int, exp: int, mod: int) -> int, (base: int, exp: Literal[0], mod: None = None) -> Literal[1], (base: int, exp: Literal[1, 2, 3, 4, 5, ... omitted 20 literals], mod: None = None) -> int, (base: int, exp: Literal[-1, -2, -3, -4, -5, ... omitted 15 literals], mod: None = None) -> int | float, (base: int, exp: int, mod: None = None) -> Any, (base: Literal[1, 2, 3, 4, 5, ... omitted 20 literals], exp: int | float, mod: None = None) -> int | float, (base: Literal[-1, -2, -3, -4, -5, ... omitted 15 literals], exp: int | float, mod: None = None) -> int | float | complex, (base: int | float, exp: int, mod: None = None) -> int | float, (base: int | float, exp: int | float | complex | _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], mod: None = None) -> Any, (base: int | float | complex, exp: int | float | complex | _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], mod: None = None) -> int | float | complex, [_E_contra, _T_co](base: _SupportsPow2[_E_contra, _T_co], exp: _E_contra, mod: None = None) -> _T_co, [_E_contra, _T_co](base: _SupportsPow3NoneOnly[_E_contra, _T_co], exp: _E_contra, mod: None = None) -> _T_co, [_E_contra, _M_contra, _T_co](base: _SupportsPow3[_E_contra, _M_contra, _T_co], exp: _E_contra, mod: _M_contra) -> _T_co, (base: _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], exp: int | float, mod: None = None) -> Any, (base: _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], exp: int | float | complex, mod: None = None) -> int | float | complex]`
+ more_itertools/recipes.py:1098:18: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `(int | float | complex | _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], int | float | complex | _SupportsPow2[Any, Any] | _SupportsPow3[Any, Any, Any], /) -> int | float | complex | ... omitted 3 union elements`, found `Overload[(base: int, exp: int, mod: int) -> int, (base: int, exp: Literal[0], mod: None = None) -> Literal[1], (base: int, exp: Literal[1, 2, 3, 4, 5, ... omitted 20 literals], mod: None = None) -> int, (base: int, exp: Literal[-1, -2, -3, -4, -5, ... omitted 15 literals], mod: None = None) -> int | float, (base: int, exp: int, mod: None = None) -> Any, (base: Literal[1, 2, 3, 4, 5, ... omitted 20 literals], exp: int | float, mod: None = None) -> int | float, (base: Literal[-1, -2, -3, -4, -5, ... omitted 15 literals], exp: int | float, mod: None = None) -> int | float | complex, (base: int | float, exp: int, mod: None = None) -> int | float, (base: int | float, exp: int | float | complex | _SupportsSomeKindOfPow, mod: None = None) -> Any, (base: int | float | complex, exp: int | float | complex | _SupportsSomeKindOfPow, mod: None = None) -> int | float | complex, [_E_contra, _T_co](base: _SupportsPow2[_E_contra, _T_co], exp: _E_contra, mod: None = None) -> _T_co, [_E_contra, _T_co](base: _SupportsPow3NoneOnly[_E_contra, _T_co], exp: _E_contra, mod: None = None) -> _T_co, [_E_contra, _M_contra, _T_co](base: _SupportsPow3[_E_contra, _M_contra, _T_co], exp: _E_contra, mod: _M_contra) -> _T_co, (base: _SupportsSomeKindOfPow, exp: int | float, mod: None = None) -> Any, (base: _SupportsSomeKindOfPow, exp: int | float | complex, mod: None = None) -> int | float | complex]`

attrs (https://github.com/python-attrs/attrs)
- src/attr/validators.py:175:24: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `(Overload[(pattern: str | Pattern[str], string: str, flags: int = 0) -> Match[str] | None, (pattern: bytes | Pattern[bytes], string: Buffer, flags: int = 0) -> Match[bytes] | None] & ~AlwaysTruthy & ~AlwaysFalsy) | (str & ~AlwaysFalsy)` does not satisfy upper bound `SupportsDunderLT[Any] | SupportsDunderGT[Any]` of type variable `SupportsRichComparisonT`
+ src/attr/validators.py:175:24: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `(Overload[(pattern: str | Pattern[str], string: str, flags: _FlagsType = 0) -> Match[str] | None, (pattern: bytes | Pattern[bytes], string: Buffer, flags: _FlagsType = 0) -> Match[bytes] | None] & ~AlwaysTruthy & ~AlwaysFalsy) | (str & ~AlwaysFalsy)` does not satisfy upper bound `SupportsRichComparison` of type variable `SupportsRichComparisonT`
- tests/test_converters.py:239:16: error[unresolved-attribute] Object of type `((Any, /) -> Any) | Converter[Any, Any]` has no attribute `converter`
+ tests/test_converters.py:239:16: error[unresolved-attribute] Object of type `_ConverterType` has no attribute `converter`
- tests/test_converters.py:240:16: error[unresolved-attribute] Object of type `((Any, /) -> Any) | Converter[Any, Any]` has no attribute `converter`
+ tests/test_converters.py:240:16: error[unresolved-attribute] Object of type `_ConverterType` has no attribute `converter`
- tests/test_converters.py:309:24: error[unresolved-attribute] Object of type `((Any, /) -> Any) | Converter[Any, Any]` has no attribute `converter`
+ tests/test_converters.py:309:24: error[unresolved-attribute] Object of type `_ConverterType` has no attribute `converter`
- tests/test_converters.py:319:16: error[unresolved-attribute] Object of type `((Any, /) -> Any) | Converter[Any, Any]` has no attribute `converter`
+ tests/test_converters.py:319:16: error[unresolved-attribute] Object of type `_ConverterType` has no attribute `converter`
- tests/test_converters.py:320:16: error[unresolved-attribute] Object of type `((Any, /) -> Any) | Converter[Any, Any]` has no attribute `converter`
+ tests/test_converters.py:320:16: error[unresolved-attribute] Object of type `_ConverterType` has no attribute `converter`
- tests/test_validators.py:185:68: error[invalid-argument-type] Argument to function `matches_re` is incorrect: Expected `((str | bytes, str | bytes, int, /) -> Match[str | bytes] | None) | None`, found `Overload[(pattern: str | Pattern[str], string: str, flags: int = 0) -> Match[str] | None, (pattern: bytes | Pattern[bytes], string: Buffer, flags: int = 0) -> Match[bytes] | None]`
+ tests/test_validators.py:185:68: error[invalid-argument-type] Argument to function `matches_re` is incorrect: Expected `((str | bytes, str | bytes, int, /) -> Match[str | bytes] | None) | None`, found `Overload[(pattern: str | Pattern[str], string: str, flags: _FlagsType = 0) -> Match[str] | None, (pattern: bytes | Pattern[bytes], string: Buffer, flags: _FlagsType = 0) -> Match[bytes] | None]`
- tests/test_validators.py:219:56: error[invalid-argument-type] Argument to function `matches_re` is incorrect: Expected `((str | bytes, str | bytes, int, /) -> Match[str | bytes] | None) | None`, found `Overload[(pattern: str | Pattern[str], string: str, flags: int = 0) -> Match[str] | None, (pattern: bytes | Pattern[bytes], string: Buffer, flags: int = 0) -> Match[bytes] | None]`
+ tests/test_validators.py:219:56: error[invalid-argument-type] Argument to function `matches_re` is incorrect: Expected `((str | bytes, str | bytes, int, /) -> Match[str | bytes] | None) | None`, found `Overload[(pattern: str | Pattern[str], string: str, flags: _FlagsType = 0) -> Match[str] | None, (pattern: bytes | Pattern[bytes], string: Buffer, flags: _FlagsType = 0) -> Match[bytes] | None]`
- typing-examples/mypy.py:250:64: error[invalid-argument-type] Argument to function `matches_re` is incorrect: Expected `((str | bytes, str | bytes, int, /) -> Match[str | bytes] | None) | None`, found `Overload[(pattern: str | Pattern[str], string: str, flags: int = 0) -> Match[str] | None, (pattern: bytes | Pattern[bytes], string: Buffer, flags: int = 0) -> Match[bytes] | None]`
+ typing-examples/mypy.py:250:64: error[invalid-argument-type] Argument to function `matches_re` is incorrect: Expected `((str | bytes, str | bytes, int, /) -> Match[str | bytes] | None) | None`, found `Overload[(pattern: str | Pattern[str], string: str, flags: _FlagsType = 0) -> Match[str] | None, (pattern: bytes | Pattern[bytes], string: Buffer, flags: _FlagsType = 0) -> Match[bytes] | None]`

packaging (https://github.com/pypa/packaging)
+ src/packaging/markers.py:144:46: warning[possibly-missing-attribute] Attribute `value` may be missing on object of type `Variable | Value | tuple[MarkerVar, Op, MarkerVar] | Sequence[Any]`
+ src/packaging/markers.py:147:46: warning[possibly-missing-attribute] Attribute `value` may be missing on object of type `Variable | Value | tuple[MarkerVar, Op, MarkerVar] | Sequence[Any]`
+ src/packaging/markers.py:149:12: error[invalid-return-type] Return type does not match returned value: expected `list[Divergent] | MarkerAtom | str`, found `tuple[Variable | Value | tuple[MarkerVar, Op, MarkerVar] | Sequence[Any], Op | tuple[MarkerVar, Op, MarkerVar] | Sequence[Any], Variable | Value | tuple[MarkerVar, Op, MarkerVar] | Sequence[Any]]`
+ src/packaging/markers.py:183:26: warning[possibly-missing-attribute] Attribute `serialize` may be missing on object of type `MarkerVar | Op | tuple[MarkerVar, Op, MarkerVar] | Sequence[Any]`
- Found 24 diagnostics
+ Found 28 diagnostics

aioredis (https://github.com/aio-libs/aioredis)
+ aioredis/client.py:1596:29: error[invalid-argument-type] Argument to function `list_or_args` is incorrect: Argument type `KeysT` does not satisfy upper bound `_StringLikeT` of type variable `_KeyT`
+ aioredis/client.py:1921:37: error[invalid-argument-type] Argument to function `list_or_args` is incorrect: Argument type `KeysT` does not satisfy upper bound `_StringLikeT` of type variable `_KeyT`
+ aioredis/client.py:2160:60: error[invalid-argument-type] Argument to function `list_or_args` is incorrect: Argument type `KeysT` does not satisfy upper bound `_StringLikeT` of type variable `_KeyT`
+ aioredis/client.py:2173:60: error[invalid-argument-type] Argument to function `list_or_args` is incorrect: Argument type `KeysT` does not satisfy upper bound `_StringLikeT` of type variable `_KeyT`
+ aioredis/client.py:2608:36: error[invalid-argument-type] Argument to function `list_or_args` is incorrect: Argument type `KeysT` does not satisfy upper bound `_StringLikeT` of type variable `_KeyT`
+ aioredis/client.py:2616:36: error[invalid-argument-type] Argument to function `list_or_args` is incorrect: Argument type `KeysT` does not satisfy upper bound `_StringLikeT` of type variable `_KeyT`
+ aioredis/client.py:2621:36: error[invalid-argument-type] Argument to function `list_or_args` is incorrect: Argument type `KeysT` does not satisfy upper bound `_StringLikeT` of type variable `_KeyT`
+ aioredis/client.py:2629:36: error[invalid-argument-type] Argument to function `list_or_args` is incorrect: Argument type `KeysT` does not satisfy upper bound `_StringLikeT` of type variable `_KeyT`
+ aioredis/client.py:2666:36: error[invalid-argument-type] Argument to function `list_or_args` is incorrect: Argument type `KeysT` does not satisfy upper bound `_StringLikeT` of type variable `_KeyT`
+ aioredis/client.py:2674:36: error[invalid-argument-type] Argument to function `list_or_args` is incorrect: Argument type `KeysT` does not satisfy upper bound `_StringLikeT` of type variable `_KeyT`
+ aioredis/client.py:3176:36: error[invalid-argument-type] Argument to function `list_or_args` is incorrect: Argument type `KeysT` does not satisfy upper bound `_StringLikeT` of type variable `_KeyT`
+ aioredis/client.py:3190:48: error[invalid-argument-type] Argument to function `list_or_args` is incorrect: Argument type `KeysT` does not satisfy upper bound `_StringLikeT` of type variable `_KeyT`
- aioredis/client.py:3430:34: error[invalid-assignment] Object of type `KeysView[object]` is not assignable to `Sequence[bytes | str | memoryview[int]] | AbstractSet[AnyKeyT@_zaggregate]`
+ aioredis/client.py:3430:34: error[invalid-assignment] Object of type `KeysView[object]` is not assignable to `Sequence[_StringLikeT] | AbstractSet[AnyKeyT@_zaggregate]`
- aioredis/client.py:4114:55: error[invalid-assignment] Object of type `dict[bytes | str | memoryview[int], Any | None]` is not assignable to `dict[bytes | str | memoryview[int], (dict[str, str], /) -> Awaitable[None]]`
+ aioredis/client.py:4114:55: error[invalid-assignment] Object of type `dict[_StringLikeT, Any | None]` is not assignable to `dict[_StringLikeT, (dict[str, str], /) -> Awaitable[None]]`
- aioredis/connection.py:441:16: error[invalid-return-type] Return type does not match returned value: expected `bytes | memoryview[int] | str | ... omitted 4 union elements`, found `int | list[Unknown | bytes | memoryview[int] | ... omitted 5 union elements] | bytes | ... omitted 3 union elements`
+ aioredis/connection.py:441:16: error[invalid-return-type] Return type does not match returned value: expected `EncodableT | ResponseError | None`, found `int | list[Unknown | bytes | memoryview[int] | ... omitted 5 union elements] | bytes | ... omitted 3 union elements`
- Found 29 diagnostics
+ Found 41 diagnostics

janus (https://github.com/aio-libs/janus)
- janus/__init__.py:714:18: error[invalid-argument-type] Argument to function `heappush` is incorrect: Argument type `T@PriorityQueue` does not satisfy upper bound `SupportsDunderLT[Any] | SupportsDunderGT[Any]` of type variable `SupportsRichComparisonT`
+ janus/__init__.py:714:18: error[invalid-argument-type] Argument to function `heappush` is incorrect: Argument type `T@PriorityQueue` does not satisfy upper bound `SupportsRichComparison` of type variable `SupportsRichComparisonT`
- janus/__init__.py:714:36: error[invalid-argument-type] Argument to function `heappush` is incorrect: Argument type `T@PriorityQueue` does not satisfy upper bound `SupportsDunderLT[Any] | SupportsDunderGT[Any]` of type variable `SupportsRichComparisonT`
+ janus/__init__.py:714:36: error[invalid-argument-type] Argument to function `heappush` is incorrect: Argument type `T@PriorityQueue` does not satisfy upper bound `SupportsRichComparison` of type variable `SupportsRichComparisonT`
- janus/__init__.py:717:24: error[invalid-argument-type] Argument to function `heappop` is incorrect: Argument type `T@PriorityQueue` does not satisfy upper bound `SupportsDunderLT[Any] | SupportsDunderGT[Any]` of type variable `SupportsRichComparisonT`
+ janus/__init__.py:717:24: error[invalid-argument-type] Argument to function `heappop` is incorrect: Argument type `T@PriorityQueue` does not satisfy upper bound `SupportsRichComparison` of type variable `SupportsRichComparisonT`

anyio (https://github.com/agronholm/anyio)
- src/anyio/_backends/_asyncio.py:360:34: error[invalid-argument-type] Argument to function `getcoroutinestate` is incorrect: Expected `Coroutine[Any, Any, Any]`, found `Generator[Future[object] | None, None, Unknown] | Coroutine[Any, Any, Unknown]`
+ src/anyio/_backends/_asyncio.py:360:34: error[invalid-argument-type] Argument to function `getcoroutinestate` is incorrect: Expected `Coroutine[Any, Any, Any]`, found `Generator[_TaskYieldType, None, Unknown] | Coroutine[Any, Any, Unknown]`
- src/anyio/_backends/_trio.py:1098:30: error[invalid-argument-type] Argument to function `convert_item` is incorrect: Expected `str | bytes | PathLike[str] | PathLike[bytes]`, found `str | bytes | (Sequence[str | bytes | PathLike[str] | PathLike[bytes]] & PathLike[object]) | PathLike[str] | PathLike[bytes]`
+ src/anyio/_backends/_trio.py:1098:30: error[invalid-argument-type] Argument to function `convert_item` is incorrect: Expected `StrOrBytesPath`, found `str | bytes | PathLike[str] | PathLike[bytes] | (Sequence[StrOrBytesPath] & PathLike[object])`

beartype (https://github.com/beartype/beartype)
- beartype/claw/_importlib/_clawimpload.py:379:9: error[invalid-assignment] Object of type `def cache_from_source_beartype(...) -> str` is not assignable to attribute `cache_from_source` of type `Overload[(path: str | PathLike[str], debug_override: bool, *, optimization: None = None) -> str, (path: str | PathLike[str], debug_override: None = None, *, optimization: Any | None = None) -> str]`
+ beartype/claw/_importlib/_clawimpload.py:379:9: error[invalid-assignment] Object of type `def cache_from_source_beartype(...) -> str` is not assignable to attribute `cache_from_source` of type `Overload[(path: StrPath, debug_override: bool, *, optimization: None = None) -> str, (path: StrPath, debug_override: None = None, *, optimization: Any | None = None) -> str]`

stone (https://github.com/dropbox/stone)
- stone/frontend/ir_generator.py:902:55: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `str | Buffer | SupportsFloat | SupportsIndex`, found `TagRef | (Unknown & ~AstTagRef)`
+ stone/frontend/ir_generator.py:902:55: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `ConvertibleToFloat`, found `TagRef | (Unknown & ~AstTagRef)`

bandersnatch (https://github.com/pypa/bandersnatch)
- src/bandersnatch/mirror.py:264:13: error[invalid-argument-type] Argument to function `max` is incorrect: Argument type `Unknown | int | None` does not satisfy upper bound `SupportsDunderLT[Any] | SupportsDunderGT[Any]` of type variable `SupportsRichComparisonT`
+ src/bandersnatch/mirror.py:264:13: error[invalid-argument-type] Argument to function `max` is incorrect: Argument type `Unknown | int | None` does not satisfy upper bound `SupportsRichComparison` of type variable `SupportsRichComparisonT`

yarl (https://github.com/aio-libs/yarl)
- tests/test_update_query.py:324:24: error[invalid-argument-type] Argument to bound method `with_query` is incorrect: Expected `None | str | Mapping[str, Sequence[str | SupportsInt] | SupportsInt] | Sequence[tuple[str, Sequence[str | SupportsInt] | SupportsInt]]`, found `memoryview[int]`
+ tests/test_update_query.py:324:24: error[invalid-argument-type] Argument to bound method `with_query` is incorrect: Expected `Query`, found `memoryview[int]`
- tests/test_url_query.py:231:26: error[invalid-argument-type] Argument to bound method `update_query` is incorrect: Expected `None | str | Mapping[str, Sequence[str | SupportsInt] | SupportsInt] | Sequence[tuple[str, Sequence[str | SupportsInt] | SupportsInt]]`, found `memoryview[int]`
+ tests/test_url_query.py:231:26: error[invalid-argument-type] Argument to bound method `update_query` is incorrect: Expected `Query`, found `memoryview[int]`
- yarl/_query.py:51:66: error[invalid-argument-type] Argument to function `query_var` is incorrect: Expected `str | SupportsInt`, found `object`
+ yarl/_query.py:51:66: error[invalid-argument-type] Argument to function `query_var` is incorrect: Expected `SimpleQuery`, found `object`

spack (https://github.com/spack/spack)
- lib/spack/spack/binary_distribution.py:2075:38: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `str | PathLike[str]`, found `Sized`
+ lib/spack/spack/binary_distribution.py:2075:38: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `StrPath`, found `Sized`
- lib/spack/spack/cmd/blame.py:158:38: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `str | PathLike[str]`, found `object`
+ lib/spack/spack/cmd/blame.py:158:38: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `StrPath`, found `object`
- lib/spack/spack/cmd/blame.py:168:38: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `str | PathLike[str]`, found `object`
+ lib/spack/spack/cmd/blame.py:168:38: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `StrPath`, found `object`
- lib/spack/spack/cmd/commands.py:563:34: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `object` does not satisfy upper bound `SupportsDunderLT[Any] | SupportsDunderGT[Any]` of type variable `SupportsRichComparisonT`
+ lib/spack/spack/cmd/commands.py:563:34: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `object` does not satisfy upper bound `SupportsRichComparison` of type variable `SupportsRichComparisonT`
- lib/spack/spack/cmd/diff.py:106:24: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `AspFunction` does not satisfy upper bound `SupportsDunderLT[Any] | SupportsDunderGT[Any]` of type variable `SupportsRichComparisonT`
+ lib/spack/spack/cmd/diff.py:106:24: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `AspFunction` does not satisfy upper bound `SupportsRichComparison` of type variable `SupportsRichComparisonT`
- lib/spack/spack/cmd/diff.py:107:30: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `AspFunction` does not satisfy upper bound `SupportsDunderLT[Any] | SupportsDunderGT[Any]` of type variable `SupportsRichComparisonT`
+ lib/spack/spack/cmd/diff.py:107:30: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `AspFunction` does not satisfy upper bound `SupportsRichComparison` of type variable `SupportsRichComparisonT`
- lib/spack/spack/cmd/diff.py:108:30: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `AspFunction` does not satisfy upper bound `SupportsDunderLT[Any] | SupportsDunderGT[Any]` of type variable `SupportsRichComparisonT`
+ lib/spack/spack/cmd/diff.py:108:30: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `AspFunction` does not satisfy upper bound `SupportsRichComparison` of type variable `SupportsRichComparisonT`
- lib/spack/spack/cmd/providers.py:59:40: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `Spec` does not satisfy upper bound `SupportsDunderLT[Any] | SupportsDunderGT[Any]` of type variable `SupportsRichComparisonT`
+ lib/spack/spack/cmd/providers.py:59:40: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `Spec` does not satisfy upper bound `SupportsRichComparison` of type variable `SupportsRichComparisonT`
- lib/spack/spack/config.py:1153:35: error[invalid-argument-type] Argument to function `isfile` is incorrect: Expected `int | str | bytes | PathLike[str] | PathLike[bytes]`, found `object`
+ lib/spack/spack/config.py:1153:35: error[invalid-argument-type] Argument to function `isfile` is incorrect: Expected `FileDescriptorOrPath`, found `object`
- lib/spack/spack/config.py:1155:34: error[invalid-argument-type] Argument to function `isdir` is incorrect: Expected `int | str | bytes | PathLike[str] | PathLike[bytes]`, found `object`
+ lib/spack/spack/config.py:1155:34: error[invalid-argument-type] Argument to function `isdir` is incorrect: Expected `FileDescriptorOrPath`, found `object`
- lib/spack/spack/directives.py:366:15: error[invalid-assignment] Object of type `list[object]` is not assignable to `((type[PackageBase] | Dependency, /) -> None) | str | list[((type[PackageBase] | Dependency, /) -> None) | str] | None`
+ lib/spack/spack/directives.py:366:15: error[invalid-assignment] Object of type `list[object]` is not assignable to `PatchesType | None`
+ lib/spack/spack/directives.py:367:37: error[not-iterable] Object of type `PatchesType | None` is not iterable
- lib/spack/spack/directives.py:367:37: error[not-iterable] Object of type `((type[PackageBase] | Dependency, /) -> None) | str | list[((type[PackageBase] | Dependency, /) -> None) | str] | None` may not be iterable
- lib/spack/spack/directives.py:391:26: error[not-iterable] Object of type `((type[PackageBase] | Dependency, /) -> None) | str | list[((type[PackageBase] | Dependency, /) -> None) | str] | None` may not be iterable
- lib/spack/spack/directives.py:392:9: error[call-non-callable] Object of type `str` is not callable
+ lib/spack/spack/directives.py:391:26: error[not-iterable] Object of type `PatchesType | None` is not iterable
- lib/spack/spack/installer.py:1309:27: error[invalid-argument-type] Argument to bound method `__call__` is incorrect: Expected `str | bytes | PathLike[str] | PathLike[bytes]`, found `Unknown | None | str`
+ lib/spack/spack/installer.py:1309:27: error[invalid-argument-type] Argument to bound method `__call__` is incorrect: Expected `StrOrBytesPath`, found `Unknown | None | str`
- lib/spack/spack/installer.py:1322:23: error[invalid-argument-type] Argument to function `rename` is incorrect: Expected `str | bytes | PathLike[str] | PathLike[bytes]`, found `Unknown | None | str`
+ lib/spack/spack/installer.py:1322:23: error[invalid-argument-type] Argument to function `rename` is incorrect: Expected `StrOrBytesPath`, found `Unknown | None | str`
- lib/spack/spack/llnl/util/filesystem.py:168:5: error[invalid-assignment] Object of type `def copystat(src, dst, follow_symlinks=True) -> Unknown` is not assignable to attribute `copystat` of type `def copystat(src: str | bytes | PathLike[str] | PathLike[bytes], dst: str | bytes | PathLike[str] | PathLike[bytes], *, follow_symlinks: bool = True) -> None`
+ lib/spack/spack/llnl/util/filesystem.py:168:5: error[invalid-assignment] Object of type `def copystat(src, dst, follow_symlinks=True) -> Unknown` is not assignable to attribute `copystat` of type `def copystat(src: StrOrBytesPath, dst: StrOrBytesPath, *, follow_symlinks: bool = True) -> None`
- lib/spack/spack/llnl/util/filesystem.py:1668:35: error[invalid-argument-type] Argument to function `exists` is incorrect: Expected `int | str | bytes | PathLike[str] | PathLike[bytes]`, found `Unknown | Sized`
+ lib/spack/spack/llnl/util/filesystem.py:1668:35: error[invalid-argument-type] Argument to function `exists` is incorrect: Expected `FileDescriptorOrPath`, found `Unknown | Sized`
- lib/spack/spack/llnl/util/filesystem.py:1674:25: error[invalid-argument-type] Argument to function `move` is incorrect: Expected `str | PathLike[str]`, found `Unknown | Sized`
+ lib/spack/spack/llnl/util/filesystem.py:1674:25: error[invalid-argument-type] Argument to function `move` is incorrect: Expected `StrPath`, found `Unknown | Sized`
- lib/spack/spack/package_base.py:1531:33: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `Spec` does not satisfy upper bound `SupportsDunderLT[Any] | SupportsDunderGT[Any]` of type variable `SupportsRichComparisonT`
+ lib/spack/spack/package_base.py:1531:33: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `Spec` does not satisfy upper bound `SupportsRichComparison` of type variable `SupportsRichComparisonT`
- lib/spack/spack/package_base.py:1539:84: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `Spec` does not satisfy upper bound `SupportsDunderLT[Any] | SupportsDunderGT[Any]` of type variable `SupportsRichComparisonT`
+ lib/spack/spack/package_base.py:1539:84: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `Spec` does not satisfy upper bound `SupportsRichComparison` of type variable `SupportsRichComparisonT`
- lib/spack/spack/solver/asp.py:2519:13: error[invalid-argument-type] Method `__getitem__` of type `bound method dict[GitVersion | StandardVersion, list[Provenance]].__getitem__(key: GitVersion | StandardVersion, /) -> list[Provenance]` cannot be called with key of type `ConcreteVersion` on object of type `dict[GitVersion | StandardVersion, list[Provenance]]`
+ lib/spack/spack/solver/asp.py:2519:13: error[invalid-argument-type] Method `__getitem__` of type `bound method dict[GitOrStandardVersion, list[Provenance]].__getitem__(key: GitOrStandardVersion, /) -> list[Provenance]` cannot be called with key of type `ConcreteVersion` on object of type `dict[GitOrStandardVersion, list[Provenance]]`
- lib/spack/spack/solver/asp.py:3270:21: error[invalid-argument-type] Method `__getitem__` of type `bound method dict[GitVersion | StandardVersion, list[Provenance]].__getitem__(key: GitVersion | StandardVersion, /) -> list[Provenance]` cannot be called with key of type `ConcreteVersion` on object of type `dict[GitVersion | StandardVersion, list[Provenance]]`
+ lib/spack/spack/solver/asp.py:3270:21: error[invalid-argument-type] Method `__getitem__` of type `bound method dict[GitOrStandardVersion, list[Provenance]].__getitem__(key: GitOrStandardVersion, /) -> list[Provenance]` cannot be called with key of type `ConcreteVersion` on object of type `dict[GitOrStandardVersion, list[Provenance]]`
- lib/spack/spack/test/cmd/deprecate.py:89:45: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `Spec` does not satisfy upper bound `SupportsDunderLT[Any] | SupportsDunderGT[Any]` of type variable `SupportsRichComparisonT`
+ lib/spack/spack/test/cmd/deprecate.py:89:45: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `Spec` does not satisfy upper bound `SupportsRichComparison` of type variable `SupportsRichComparisonT`
- lib/spack/spack/test/cmd/deprecate.py:90:41: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `Unknown | Spec` does not satisfy upper bound `SupportsDunderLT[Any] | SupportsDunderGT[Any]` of type variable `SupportsRichComparisonT`
+ lib/spack/spack/test/cmd/deprecate.py:90:41: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `Unknown | Spec` does not satisfy upper bound `SupportsRichComparison` of type variable `SupportsRichComparisonT`
- lib/spack/spack/test/directory_layout.py:116:30: error[invalid-argument-type] Argument to bound method `copy` is incorrect: Expected `int | str | list[str] | tuple[str, ...]`, found `SpecHashDescriptor`
+ lib/spack/spack/test/directory_layout.py:116:30: error[invalid-argument-type] Argument to bound method `copy` is incorrect: Expected `int | DepTypes`, found `SpecHashDescriptor`
- lib/spack/spack/test/directory_layout.py:129:37: error[invalid-argument-type] Argument to bound method `copy` is incorrect: Expected `int | str | list[str] | tuple[str, ...]`, found `SpecHashDescriptor`
+ lib/spack/spack/test/directory_layout.py:129:37: error[invalid-argument-type] Argument to bound method `copy` is incorrect: Expected `int | DepTypes`, found `SpecHashDescriptor`
- lib/spack/spack/test/directory_layout.py:134:70: error[invalid-argument-type] Argument to bound method `copy` is incorrect: Expected `int | str | list[str] | tuple[str, ...]`, found `SpecHashDescriptor`
+ lib/spack/spack/test/directory_layout.py:134:70: error[invalid-argument-type] Argument to bound method `copy` is incorrect: Expected `int | DepTypes`, found `SpecHashDescriptor`
- lib/spack/spack/test/llnl/util/lock.py:192:23: error[invalid-argument-type] Argument to bound method `__call__` is incorrect: Expected `str | bytes | PathLike[str] | PathLike[bytes]`, found `None | Unknown`
+ lib/spack/spack/test/llnl/util/lock.py:192:23: error[invalid-argument-type] Argument to bound method `__call__` is incorrect: Expected `StrOrBytesPath`, found `None | Unknown`
- lib/spack/spack/test/llnl/util/lock.py:1091:36: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `(() -> bool) | None | ContextManager[Unknown]`, found `def write(t, v, tb) -> Unknown`
- lib/spack/spack/test/llnl/util/lock.py:1093:40: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `(() -> bool) | None | ContextManager[Unknown]`, found `def write(t, v, tb) -> Unknown`
- lib/spack/spack/test/llnl/util/lock.py:1102:40: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `(() -> bool) | None | ContextManager[Unknown]`, found `def write(t, v, tb) -> Unknown`
- lib/spack/spack/test/llnl/util/lock.py:1108:36: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `(() -> bool) | None | ContextManager[Unknown]`, found `def write(t, v, tb) -> Unknown`
- lib/spack/spack/test/llnl/util/lock.py:1112:44: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `(() -> bool) | None | ContextManager[Unknown]`, found `def write(t, v, tb) -> Unknown`
- lib/spack/spack/test/llnl/util/lock.py:1121:40: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `(() -> bool) | None | ContextManager[Unknown]`, found `def write(t, v, tb) -> Unknown`
- lib/spack/spack/test/llnl/util/lock.py:1125:48: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `(() -> bool) | None | ContextManager[Unknown]`, found `def write(t, v, tb) -> Unknown`
+ lib/spack/spack/test/llnl/util/lock.py:1091:36: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `ReleaseFnType | ContextManager[Unknown]`, found `def write(t, v, tb) -> Unknown`
+ lib/spack/spack/test/llnl/util/lock.py:1093:40: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `ReleaseFnType | ContextManager[Unknown]`, found `def write(t, v, tb) -> Unknown`
+ lib/spack/spack/test/llnl/util/lock.py:1102:40: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `ReleaseFnType | ContextManager[Unknown]`, found `def write(t, v, tb) -> Unknown`
+ lib/spack/spack/test/llnl/util/lock.py:1108:36: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `ReleaseFnType | ContextManager[Unknown]`, found `def write(t, v, tb) -> Unknown`
+ lib/spack/spack/test/llnl/util/lock.py:1112:44: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `ReleaseFnType | ContextManager[Unknown]`, found `def write(t, v, tb) -> Unknown`
+ lib/spack/spack/test/llnl/util/lock.py:1121:40: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `ReleaseFnType | ContextManager[Unknown]`, found `def write(t, v, tb) -> Unknown`
+ lib/spack/spack/test/llnl/util/lock.py:1125:48: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `ReleaseFnType | ContextManager[Unknown]`, found `def write(t, v, tb) -> Unknown`
- lib/spack/spack/test/spec_dag.py:815:32: error[invalid-argument-type] Argument to function `canonicalize` is incorrect: Expected `str | list[str] | tuple[str, ...]`, found `def all(iterable: Iterable[object], /) -> bool`
+ lib/spack/spack/test/spec_dag.py:815:32: error[invalid-argument-type] Argument to function `canonicalize` is incorrect: Expected `DepTypes`, found `def all(iterable: Iterable[object], /) -> bool`
- lib/spack/spack/test/spec_dag.py:819:29: error[invalid-argument-type] Argument to function `canonicalize` is incorrect: Expected `str | list[str] | tuple[str, ...]`, found `None`
+ lib/spack/spack/test/spec_dag.py:819:29: error[invalid-argument-type] Argument to function `canonicalize` is incorrect: Expected `DepTypes`, found `None`
- lib/spack/spack/test/spec_dag.py:821:29: error[invalid-argument-type] Argument to function `canonicalize` is incorrect: Expected `str | list[str] | tuple[str, ...]`, found `list[str | None]`
+ lib/spack/spack/test/spec_dag.py:821:29: error[invalid-argument-type] Argument to function `canonicalize` is incorrect: Expected `DepTypes`, found `list[Unknown | None]`
- lib/spack/spack/test/spec_semantics.py:2121:19: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `Unknown | Spec` does not satisfy upper bound `SupportsDunderLT[Any] | SupportsDunderGT[Any]` of type variable `SupportsRichComparisonT`
+ lib/spack/spack/test/spec_semantics.py:2121:19: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `Unknown | Spec` does not satisfy upper bound `SupportsRichComparison` of type variable `SupportsRichComparisonT`
- lib/spack/spack/vendor/attr/validators.py:186:25: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `(Overload[(pattern: str | Pattern[str], string: str, flags: int = 0) -> Match[str] | None, (pattern: bytes | Pattern[bytes], string: Buffer, flags: int = 0) -> Match[bytes] | None] & ~AlwaysTruthy & ~AlwaysFalsy) | (str & ~AlwaysFalsy)` does not satisfy upper bound `SupportsDunderLT[Any] | SupportsDunderGT[Any]` of type variable `SupportsRichComparisonT`
+ lib/spack/spack/vendor/attr/validators.py:186:25: error[invalid-argument-type] Argument to function `sorted` is incorrect: Argument type `(Overload[(pattern: str | Pattern[str], string: str, flags: _FlagsType = 0) -> Match[str] | None, (pattern: bytes | Pattern[bytes], string: Buffer, flags: _FlagsType = 0) -> Match[bytes] | None] & ~AlwaysTruthy & ~AlwaysFalsy) | (str & ~AlwaysFalsy)` does not satisfy upper bound `SupportsRichComparison` of type variable `SupportsRichComparisonT`
- Found 4338 diagnostics
+ Found 4337 diagnostics

pip (https://github.com/pypa/pip)
- src/pip/_internal/metadata/pkg_resources.py:128:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `IResourceProvider | None`, found `InMemoryMetadata`
+ src/pip/_internal/metadata/pkg_resources.py:128:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `_MetadataType`, found `InMemoryMetadata`
- src/pip/_internal/metadata/pkg_resources.py:149:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `IResourceProvider | None`, found `InMemoryMetadata`
+ src/pip/_internal/metadata/pkg_resources.py:149:13: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Expected `_MetadataType`, found `InMemoryMetadata`
- src/pip/_vendor/distlib/util.py:1473:41: error[invalid-argument-type] Argument to bound method `load_cert_chain` is incorrect: Expected `str | bytes | PathLike[str] | PathLike[bytes]`, found `str | bytes | PathLike[str] | PathLike[bytes] | None`
+ src/pip/_vendor/distlib/util.py:1473:41: error[invalid-argument-type] Argument to bound method `load_cert_chain` is incorrect: Expected `StrOrBytesPath`, found `str | bytes | PathLike[str] | PathLike[bytes] | None`
+ src/pip/_vendor/packaging/markers.py:139:46: warning[possibly-missing-attribute] Attribute `value` may be missing on object of type `Variable | Value | tuple[MarkerVar, Op, MarkerVar] | Sequence[Any]`
+ src/pip/_vendor/packaging/markers.py:142:46: warning[possibly-missing-attribute] Attribute `value` may be missing on object of type `Variable | Value | tuple[MarkerVar, Op, MarkerVar] | Sequence[Any]`
+ src/pip/_vendor/packaging/markers.py:144:12: error[invalid-return-type] Return type does not match returned value: expected `list[Divergent] | MarkerAtom | str`, found `tuple[Variable | Value | tuple[MarkerVar, Op, MarkerVar] | Sequence[Any], Op | tuple[MarkerVar, Op, MarkerVar] | Sequence[Any], Variable | Value | tuple[MarkerVar, Op, MarkerVar] | Sequence[Any]]`
+ src/pip/_vendor/packaging/markers.py:178:26: warning[possibly-missing-attribute] Attribute `serialize` may be missing on object of type `MarkerVar | Op | tuple[MarkerVar, Op, MarkerVar] | Sequence[Any]`
- src/pip/_vendor/pkg_resources/__init__.py:3466:40: error[invalid-argument-type] Argument to bound method `contains` is incorrect: Expected `Version | str`, found `(str & ~Distribution) | (tuple[str, ...] & ~Distribution) | Unknown`
+ src/pip/_vendor/pkg_resources/__init__.py:3466:40: error[invalid-argument-type] Argument to bound method `contains` is incorrect: Expected `UnparsedVersion`, found `(str & ~Distribution) | (tuple[str, ...] & ~Distribution) | Unknown`
- src/pip/_vendor/pyproject_hooks/_in_process/__init__.py:14:31: error[invalid-argument-type] Argument to function `path` is incorrect: Expected `str | ModuleType`, found `str | None`
+ src/pip/_vendor/pyproject_hooks/_in_process/__init__.py:14:31: error[invalid-argument-type] Argument to function `path` is incorrect: Expected `Package`, found `str | None`
- src/pip/_vendor/pyproject_hooks/_in_process/__init__.py:20:29: error[invalid-argument-type] Argument to function `files` is incorrect: Expected `str | ModuleType`, found `str | None`
+ src/pip/_vendor/pyproject_hooks/_in_process/__init__.py:20:29: error[invalid-argument-type] Argument to function `files` is incorrect: Expected `Package`, found `str | None`
+ src/pip/_vendor/rich/control.py:64:13: error[invalid-argument-type] Method `__getitem__` of type `bound method dict[int, (...) -> str].__getitem__(key: int, /) -> (...) -> str` cannot be called with key of type `str` on object of type `dict[int, (...) -> str]`
- src/pip/_vendor/rich/table.py:359:5: error[invalid-argument-type] Argument to bound method `setter` is incorrect: Expected `(Any, Any, /) -> None`, found `def padding(self, padding: int | tuple[int] | tuple[int, int] | tuple[int, int, int, int]) -> Table`
+ src/pip/_vendor/rich/table.py:359:5: error[invalid-argument-type] Argument to bound method `setter` is incorrect: Expected `(Any, Any, /) -> None`, found `def padding(self, padding: PaddingDimensions) -> Table`
- src/pip/_vendor/urllib3/contrib/securetransport.py:671:31: error[invalid-argument-type] Argument to bound method `__call__` is incorrect: Expected `str | bytes | PathLike[str] | PathLike[bytes]`, found `Unknown | None`
+ src/pip/_vendor/urllib3/contrib/securetransport.py:671:31: error[invalid-argument-type] Argument to bound method `__call__` is incorrect: Expected `StrOrBytesPath`, found `Unknown | None`
- src/pip/_vendor/urllib3/util/ssl_.py:182:62: error[invalid-argument-type] Argument to function `wrap_socket` is incorrect: Expected `str | bytes | PathLike[str] | PathLike[bytes] | None`, found `Unknown | None | VerifyMode | bool`
- src/pip/_vendor/urllib3/util/ssl_.py:182:62: error[invalid-argument-type] Argument to function `wrap_socket` is incorrect: Expected `str | bytes | PathLike[str] | PathLike[bytes] | None`, found `Unknown | None | VerifyMode | bool`
+ src/pip/_vendor/urllib3/util/ssl_.py:182:62: error[invalid-argument-type] Argument to function `wrap_socket` is incorrect: Expected `StrOrBytesPath | None`, found `Unknown | None | VerifyMode | bool`
+ src/pip/_vendor/urllib3/util/ssl_.py:182:62: error[invalid-argument-type] Argument to function `wrap_socket` is incorrect: Expected `StrOrBytesPath | None`, found `Unknown | None | VerifyMode | bool`
- Found 625 diagnostics
+ Found 630 diagnostics

black (https://github.com/psf/black)
- src/black/ranges.py:404:28: error[invalid-argument-type] Argument to function `first_leaf` is incorrect: Expected `Leaf | Node`, found `object`
+ src/black/ranges.py:404:28: error[invalid-argument-type] Argument to function `first_leaf` is incorrect: Expected `LN`, found `object`
- src/black/ranges.py:405:26: error[invalid-argument-type] Argument to function `last_leaf` is incorrect: Expected `Leaf | Node`, found `object`
+ src/black/ranges.py:405:26: error[invalid-argument-type] Argument to function `last_leaf` is incorrect: Expected `LN`, found `object`
- src/black/trans.py:470:20: error[invalid-return-type] Return type does not match returned value: expected `Ok[list[int]] | Err[CannotTransform]`, found `Ok[list[Unknown] & ~AlwaysFalsy]`
+ src/black/trans.py:470:20: error[invalid-return-type] Return type does not match returned value: expected `TMatchResult`, found `Ok[list[Unknown] & ~AlwaysFalsy]`
- src/black/trans.py:984:20: error[invalid-return-type] Return type does not match returned value: expected `Ok[list[int]] | Err[CannotTransform]`, found `Ok[list[Unknown] & ~AlwaysFalsy]`
+ src/black/trans.py:984:20: error[invalid-return-type] Return type does not match returned value: expected `TMatchResult`, found `Ok[list[Unknown] & ~AlwaysFalsy]`
- src/black/trans.py:1111:20: error[invalid-return-type] Return type does not match returned value: expected `Ok[list[int]] | Err[CannotTransform]`, found `(Ok[None] & Top[Err[Unknown]]) | Err[CannotTransform]`
+ src/black/trans.py:1111:20: error[invalid-return-type] Return type does not match returned value: expected `TMatchResult`, found `(Ok[None] & Top[Err[Unknown]]) | Err[CannotTransform]`
- src/blib2to3/pytree.py:149:13: error[unresolved-attribute] Unresolved attribute `parent` on type `object`
+ src/blib2to3/pytree.py:149:13: error[invalid-assignment] Object of type `Node` is not assignable to attribute `parent` on type `object | NL`

graphql-core (https://github.com/graphql-python/graphql-core)
- src/graphql/execution/execute.py:1654:42: error[invalid-await] `Awaitable[ReconcilableDeferredGroupedFieldSetResult | NonReconcilableDeferredGroupedFieldSetResult] | ReconcilableDeferredGroupedFieldSetResult | NonReconcilableDeferredGroupedFieldSetResult` is not awaitable
+ src/graphql/execution/execute.py:1654:42: error[invalid-await] `Awaitable[DeferredGroupedFieldSetResult] | DeferredGroupedFieldSetResult` is not awaitable
- src/graphql/execution/execute.py:1657:21: error[invalid-assignment] Object of type `BoxedAwaitableOrValue[CoroutineType[Any, Any, ReconcilableDeferredGroupedFieldSetResult | NonReconcilableDeferredGroupedFieldSetResult] | ReconcilableDeferredGroupedFieldSetResult | NonReconcilableDeferredGroupedFieldSetResult]` is not assignable to attribute `result` of type `BoxedAwaitableOrValue[ReconcilableDeferredGroupedFieldSetResult | NonReconcilableDeferredGroupedFieldSetResult] | (() -> BoxedAwaitableOrValue[ReconcilableDeferredGroupedFieldSetResult | NonReconcilableDeferredGroupedFieldSetResult])`
+ src/graphql/execution/execute.py:1657:21: error[invalid-assignment] Object of type `BoxedAwaitableOrValue[CoroutineType[Any, Any, DeferredGroupedFieldSetResult] | ReconcilableDeferredGroupedFieldSetResult | NonReconcilableDeferredGroupedFieldSetResult]` is not assignable to attribute `result` of type `BoxedAwaitableOrValue[DeferredGroupedFieldSetResult] | (() -> BoxedAwaitableOrValue[DeferredGroupedFieldSetResult])`
- src/graphql/execution/execute.py:1809:32: error[invalid-argument-type] Argument to bound method `append` is incorrect: Expected `BoxedAwaitableOrValue[StreamItemResult] | (() -> BoxedAwaitableOrValue[StreamItemResult])`, found `BoxedAwaitableOrValue[CoroutineType[Any, Any, StreamItemResult] | StreamItemResult]`
+ src/graphql/execution/execute.py:1809:32: error[invalid-argument-type] Argument to bound method `append` is incorrect: Expected `StreamItemRecord`, found `BoxedAwaitableOrValue[CoroutineType[Any, Any, StreamItemResult] | StreamItemResult]`
- src/graphql/execution/incremental_graph.py:349:27: error[invalid-argument-type] Argument to bound method `_enqueue` is incorrect: Expected `ReconcilableDeferredGroupedFieldSetResult | NonReconcilableDeferredGroupedFieldSetResult | StreamItemsResult`, found `object`
+ src/graphql/execution/incremental_graph.py:349:27: error[invalid-argument-type] Argument to bound method `_enqueue` is incorrect: Expected `IncrementalDataRecordResult`, found `object`
- src/graphql/utilities/build_client_schema.py:264:81: error[invalid-assignment] Object of type `dict[str, ((IntrospectionScalarType | IntrospectionObjectType | IntrospectionInterfaceType | ... omitted 3 union elements, /) -> GraphQLNamedType) | ((scalar_introspection: IntrospectionScalarType) -> GraphQLScalarType) | ((object_introspection: IntrospectionObjectType) -> GraphQLObjectType) | ... omitted 4 union elements]` is not assignable to `dict[str, (IntrospectionScalarType | IntrospectionObjectType | IntrospectionInterfaceType | ... omitted 3 union elements, /) -> GraphQLNamedType]`
+ src/graphql/utilities/build_client_schema.py:264:81: error[invalid-assignment] Object of type `dict[str, ((IntrospectionType, /) -> GraphQLNamedType) | ((scalar_introspection: IntrospectionScalarType) -> GraphQLScalarType) | ((object_introspection: IntrospectionObjectType) -> GraphQLObjectType) | ... omitted 4 union elements]` is not assignable to `dict[str, (IntrospectionType, /) -> GraphQLNamedType]`
- src/graphql/utilities/lexicographic_sort_schema.py:55:35: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `GraphQLList[Unknown] | GraphQLNonNull[Unknown] | GraphQLNamedType` does not satisfy upper bound `GraphQLScalarType | GraphQLObjectType | GraphQLInterfaceType | ... omitted 4 union elements` of type variable `GNT_co`
+ src/graphql/utilities/lexicographic_sort_schema.py:55:35: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `GraphQLList[Unknown] | GraphQLNonNull[Unknown] | GraphQLNamedType` does not satisfy upper bound `GraphQLNullableType` of type variable `GNT_co`
+ src/graphql/utilities/type_info.py:194:21: error[no-matching-overload] No overload of function `get_nullable_type` matches arguments
+ src/graphql/validation/rules/values_of_correct_type.py:70:17: error[no-matching-overload] No overload of function `get_nullable_type` matches arguments
- tests/type/test_validation.py:74:24: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `GraphQLNamedType` does not satisfy upper bound `GraphQLScalarType | GraphQLObjectType | GraphQLInterfaceType | ... omitted 4 union elements` of type variable `GNT_co`
+ tests/type/test_validation.py:74:24: error[invalid-argument-type] Argument to bound method `__init__` is incorrect: Argument type `GraphQLNamedType` does not satisfy upper bound `GraphQLNullableType` of type variable `GNT_co`
- Found 638 diagnostics
+ Found 640 diagnostics

aiortc (https://github.com/aiortc/aiortc)
- src/aiortc/rtcpeerconnection.py:132:24: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `str | Buffer | SupportsInt | SupportsIndex | SupportsTrunc`, found `int | str | None`
+ src/aiortc/rtcpeerconnection.py:132:24: error[invalid-argument-type] Argument to function `__new__` is incorrect: Expected `ConvertibleToInt`, found `int | str | None`
- src/aior

... (truncated 5933 lines) ...
Memory usage changes were detected when running on open source projects
trio (https://github.com/python-trio/trio)
-     struct metadata = ~10MB
+     struct metadata = ~11MB
-     memo metadata = ~31MB
+     memo metadata = ~33MB

sphinx (https://github.com/sphinx-doc/sphinx)
- TOTAL MEMORY USAGE: ~287MB
+ TOTAL MEMORY USAGE: ~301MB

@astral-sh-bot
Copy link

astral-sh-bot bot commented Dec 29, 2025

ecosystem-analyzer results

Lint rule Added Removed Changed
invalid-argument-type 92 27 2,152
invalid-key 0 305 0
invalid-assignment 70 5 117
type-assertion-failure 10 0 96
invalid-return-type 26 0 62
possibly-missing-attribute 15 0 62
unresolved-attribute 0 1 49
unused-type-ignore-comment 8 28 0
unsupported-operator 10 0 16
not-iterable 0 3 18
no-matching-overload 19 0 0
invalid-context-manager 1 0 10
invalid-parameter-default 0 0 9
invalid-type-form 0 0 9
not-subscriptable 0 0 9
assert-type-unspellable-subtype 0 0 4
redundant-cast 0 2 2
invalid-await 2 0 1
invalid-type-arguments 0 0 3
missing-typed-dict-key 0 2 0
call-non-callable 0 1 0
Total 253 374 2,619

Full report with detailed diff (timing results)

@codspeed-hq
Copy link

codspeed-hq bot commented Dec 29, 2025

CodSpeed Performance Report

Merging this PR will degrade performance by 11.29%

Comparing mtshiba:implicit-recursive-union (50943c6) with main (1d9c84d)

Summary

⚡ 1 improved benchmark
❌ 5 regressed benchmarks
✅ 48 untouched benchmarks
🆕 1 new benchmark

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
WallTime colour_science 94.6 s 106.7 s -11.29%
WallTime pandas 64.5 s 68.5 s -5.86%
WallTime static_frame 20.9 s 23.3 s -10.05%
WallTime pydantic 7 s 7.4 s -4.78%
WallTime freqtrade 7.9 s 8.7 s -9.4%
🆕 Simulation ty_micro[recursive_union_type_alias_and_protocol] N/A 71.6 ms N/A
Simulation hydra-zen 1.2 s 1.1 s +13.84%

@mtshiba
Copy link
Collaborator Author

mtshiba commented Dec 30, 2025

The codspeed (walltime) results seem to have improved in some cases and worsened in others.
Since instrumented tests showed almost no regressions, it is likely that the changes are due to higher-level compounding effects. For example, whether type alias expansion is eager or lazy may improve the inspection speed of some code while slowing down the inspection speed of other code. Or paths that were previously disabled by Divergent may be executed.
I think it would be difficult to improve everything.

@mtshiba
Copy link
Collaborator Author

mtshiba commented Dec 30, 2025

mypy and pyright seem to expand type aliases as much as possible, regardless of whether they are implicit or PEP-695 style (in the case of recursive type aliases, mypy seems to omit the recursive part and display it such as int | list[...]).
pyrefly does not expand both aliases whenever possible.

@mtshiba mtshiba marked this pull request as ready for review January 5, 2026 15:09
@mtshiba mtshiba requested a review from Gankra as a code owner January 7, 2026 09:08
@mtshiba mtshiba marked this pull request as draft January 7, 2026 09:28
@carljm
Copy link
Contributor

carljm commented Jan 13, 2026

I see this was marked draft -- I'm assuming that means you don't feel it is ready for review/merge yet?

@mtshiba
Copy link
Collaborator Author

mtshiba commented Jan 21, 2026

It appears that the interaction of recent changes with the changes in this PR has caused TypedDict narrowing to stop working. I'm investigating the cause.

@mtshiba
Copy link
Collaborator Author

mtshiba commented Jan 21, 2026

I opened #22786. Please check that out first.

@mtshiba
Copy link
Collaborator Author

mtshiba commented Jan 21, 2026

I see this was marked draft -- I'm assuming that means you don't feel it is ready for review/merge yet?

Everything else seems basically fine, so I'll mark it as ready for review.

@mtshiba mtshiba marked this pull request as ready for review January 21, 2026 11:38
Copy link
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.

Reviewed the test changes here and most of the code changes. Overall this looks really good! Need to look more closely at the union-type changes, and the ecosystem impact. This will likely uncover more cases where we aren't handling Type::TypeAlias correctly, since implicit type aliases are much more used than PEP 695 ones today.

Copy link
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.

Thanks again for working on this, and sorry about the delay to complete my review. Lots of good stuff here, but I think we can do better than all the repeat inference we do in this PR.

Looking at the ecosystem report, the new aioredis diagnostics are false positives and a regression. It looks like we aren't resolving up the new implicit type alias type there in the generics constraint solver, so the constraint solver can't match to the formal parameter and infer typevars. I'm guessing this is a simple change to fix? (It may even be a pre-existing bug that would also show up if the same code used PEP 695 type alias, not sure.)

# error: [invalid-argument-type]
elif isinstance(x, Any | NamedTuple | list[int]):
reveal_type(x) # revealed: int | list[int] | bytes
# TODO: This should be an error
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the limitation that prevents an error in these cases?

Comment on lines +9160 to +9161
/// The type of the full union, which can be used when this `UnionType` instance
/// is used in a type expression context. For `int | str`, this would contain
Copy link
Contributor

Choose a reason for hiding this comment

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

But we don't use this method when the UnionType instance is used in a type expression context, we use custom logic there to create a TypeAliasType for the lazy variant. So this is maybe not the best way to describe the function.

/// `<class 'str'>`. For `Union[int, str]`, this field is `None`, as we infer
/// the elements as type expressions. Use `value_expression_types` to get the
/// corresponding value expression types.
#[returns(ref)]
Copy link
Contributor

Choose a reason for hiding this comment

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

Why did we remove returns-ref here?

Comment on lines +9258 to +9263
UnionTypeInstanceInner::Lazy(_) => Err(InvalidTypeExpressionError {
fallback_type: Type::unknown(),
invalid_expressions: smallvec::smallvec_inline![
InvalidTypeExpression::InvalidType(ty, self.definition.scope(db))
],
}),
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be unreachable, right? Should we mark it as such instead of emitting a confusing error?

Comment on lines +9266 to +9271
other => Err(InvalidTypeExpressionError {
fallback_type: Type::unknown(),
invalid_expressions: smallvec::smallvec_inline![
InvalidTypeExpression::InvalidType(other, self.definition.scope(db))
],
}),
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this also be unreachable?

// Convert eager union instances to lazy for assignments
// This enables lazy evaluation for recursive type aliases like `Foo = int | list["Foo"]`
let value_ty = if let Some(instance) = value_ty.as_union_type_instance()
&& let Some(eager) = instance.as_eager(self.db())
Copy link
Contributor

Choose a reason for hiding this comment

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

So at this point we have already created an eager UnionTypeInstance, which means we've already inferred all its elements as both value and type expressions. Then, if it's convertible to lazy, we throw all of that away and store just the definition.

I wonder a) why we need to be so eager about creating the union_type that we do it before we check if we can convert to lazy, and b) why we throw away the value types rather than storing them in the lazy variant too.

I realize that typing.Union would need to be handled differently since there we never infer elements as value expressions. But in that case it seems like we have more control (we already know it's a union before inferring any element types) -- I think we could have special handling in the assignment inference for a top-level typing.Union subscripting, where we create a lazy union instance and don't infer any of the elements at all until we need them (using the existing infer_deferred_types mechanism that is already used for elements of TypeVar etc.)

DefinitionKind::AnnotatedAssignment(assignment) => assignment.value(&module).unwrap(),
_ => unreachable!(),
};
let value_expression = Expression::new(
Copy link
Contributor

Choose a reason for hiding this comment

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

This means we re-infer the expression type again, potentially twice. Why do we need to do this, when we already inferred its value types in type inference? Why can't the lazy UnionTypeInstance variant, and the implicit TypeAliasType variant, both store the value types we originally inferred?

(I realize this means typing.Union would need a different path; discussed that in a different comment.)

cycle_initial=lazy_union_value_type_cycle_initial,
heap_size=ruff_memory_usage::heap_size
)]
fn lazy_union_value_type<'db>(
Copy link
Contributor

Choose a reason for hiding this comment

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

This method seems basically like a copy of ImplicitTypeAliasType::value_type, including the cycle handling. Could one call the other, or extract a shared helper?

@carljm carljm self-assigned this Feb 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ecosystem-analyzer ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ty hangs on combination of self-ref Union, dataclass and Protocol Do not expand PEP-613 type aliases on hover

2 participants