Distribute return type over union #2047
Replies: 1 comment
|
Your intuition is supported by the current overload-call algorithm, but the distribution is specific to overload resolution. An ordinary generic call solves For this finite set of cases, overloads express the correlation: from collections.abc import Sequence
from typing import overload
@overload
def listify(x: Sequence[str], /) -> list[str]: ...
@overload
def listify(x: Sequence[int], /) -> list[int]: ...
def listify[T](x: Sequence[T], /) -> list[T]:
return list(x)With There isn't currently a general annotation that says “map this type constructor distributively over every member of an arbitrary union”. If And yes, the potential combinatorial growth is handled explicitly in the overload algorithm: expandable arguments are considered one at a time, and their successful return types are combined. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Inspired by microsoft/pyright#10673, I looked at this simple example: Code sample in pyright playground
It feels like the revealed type is not actually what we want here. The desirable inference is imo
list[str] | list[int].Is there simple way to annotate
listifyto make the return type distribute over unions, or is this a general type-checker limitation?What seems to happen here is that we assign
Sequence[str] | Sequence[int] <: Sequence[str | int] = Sequence[T], so we pickT = int | str. However, in principle wouldn't it be more precise if the type checker, when seeing aUnionTypeas an argument, passes every member separately and yields theUnionTypeof the individual return types?I guess with multiple arguments this runs into combinatoric explosion...
All reactions