Fix type variable inference for T | Wrapper[T] union patterns#21619
Closed
majidfeiz wants to merge 2 commits into
Closed
Fix type variable inference for T | Wrapper[T] union patterns#21619majidfeiz wants to merge 2 commits into
majidfeiz wants to merge 2 commits into
Conversation
When inferring type arguments for a generic function with a parameter of the form `T | list[T]` (or any `T | Wrapper[T]` pattern), mypy incorrectly inferred `T = Never` instead of the element type. Root cause: `any_constraints()` received two competing options from the union branches — `T >= list[int]` from the bare `T` branch and `T = int` from the `list[T]` branch. Because these are structurally incompatible, `any_constraints()` gave up and returned `[]`, leaving T unconstrained and causing the solver to fall back to `Never`. `handle_recursive_union()` already resolves this correctly by trying parameterized items first (yielding precise bounds like `T = int`) and falling back to bare TypeVar items only when needed. It was gated behind `has_recursive_types()`, which returns `False` for ordinary generic function signatures. The fix extends the fallback condition to also trigger when the union contains a bare TypeVar alongside a parameterized item that itself contains TypeVars (e.g. `list[T]`). The guard deliberately excludes unions like `AnyStr | int` where the non-TypeVar branch carries no TypeVars, preventing regressions with constrained TypeVars. Fixes python#21615
for more information, see https://pre-commit.ci
Contributor
|
Diff from mypy_primer, showing the effect of this PR on open source code: prefect (https://github.com/PrefectHQ/prefect)
- src/prefect/states.py:373: error: Argument 1 to "StateGroup" has incompatible type "Collection[Never]"; expected "list[State[Any]]" [arg-type]
+ src/prefect/states.py:373: error: Argument 1 to "StateGroup" has incompatible type "Collection[Any]"; expected "list[State[Any]]" [arg-type]
- src/prefect/_internal/states.py:243: error: Argument 1 to "StateGroup" has incompatible type "Collection[Never]"; expected "list[State[Any]]" [arg-type]
+ src/prefect/_internal/states.py:243: error: Argument 1 to "StateGroup" has incompatible type "Collection[Any]"; expected "list[State[Any]]" [arg-type]
- src/prefect/task_runners.py:109: error: Overloaded function implementation does not accept all possible parameters of signature 1 [misc]
+ src/prefect/task_runners.py:109: error: Overloaded function implementation cannot satisfy signature 1 due to inconsistencies in how they use type variables [misc]
+ src/prefect/tasks.py:1185: error: Overloaded function implementation cannot satisfy signature 5 due to inconsistencies in how they use type variables [misc]
- src/prefect/task_engine.py:1867: error: Overloaded function implementation does not accept all possible parameters of signature 1 [misc]
+ src/prefect/task_engine.py:1867: error: Overloaded function implementation cannot satisfy signature 1 due to inconsistencies in how they use type variables [misc]
hydra-zen (https://github.com/mit-ll-responsible-ai/hydra-zen)
- src/hydra_zen/typing/_builds_overloads.py:229: error: Overloaded function implementation does not accept all possible parameters of signature 3 [misc]
- src/hydra_zen/typing/_builds_overloads.py:229: error: Overloaded function implementation does not accept all possible parameters of signature 5 [misc]
- src/hydra_zen/typing/_builds_overloads.py:229: error: Overloaded function implementation does not accept all possible parameters of signature 7 [misc]
- src/hydra_zen/typing/_builds_overloads.py:229: error: Overloaded function implementation does not accept all possible parameters of signature 9 [misc]
- src/hydra_zen/typing/_builds_overloads.py:468: error: Overloaded function implementation does not accept all possible parameters of signature 2 [misc]
- src/hydra_zen/typing/_builds_overloads.py:468: error: Overloaded function implementation does not accept all possible parameters of signature 4 [misc]
- src/hydra_zen/typing/_builds_overloads.py:468: error: Overloaded function implementation does not accept all possible parameters of signature 6 [misc]
- src/hydra_zen/typing/_builds_overloads.py:468: error: Overloaded function implementation does not accept all possible parameters of signature 8 [misc]
- src/hydra_zen/typing/_builds_overloads.py:468: error: Overloaded function implementation does not accept all possible parameters of signature 10 [misc]
- src/hydra_zen/typing/_builds_overloads.py:654: error: Overloaded function implementation does not accept all possible parameters of signature 1 [misc]
- src/hydra_zen/typing/_builds_overloads.py:654: error: Overloaded function implementation does not accept all possible parameters of signature 5 [misc]
- src/hydra_zen/structured_configs/_implementations.py:502: error: Need type annotation for "out" [var-annotated]
+ src/hydra_zen/structured_configs/_implementations.py:1604: error: Overloaded function implementation cannot satisfy signature 3 due to inconsistencies in how they use type variables [misc]
+ src/hydra_zen/structured_configs/_implementations.py:1604: error: Overloaded function implementation cannot satisfy signature 4 due to inconsistencies in how they use type variables [misc]
+ src/hydra_zen/structured_configs/_implementations.py:1604: error: Overloaded function implementation cannot satisfy signature 5 due to inconsistencies in how they use type variables [misc]
+ src/hydra_zen/structured_configs/_implementations.py:1604: error: Overloaded function implementation cannot satisfy signature 6 due to inconsistencies in how they use type variables [misc]
+ src/hydra_zen/structured_configs/_implementations.py:1604: error: Overloaded function implementation cannot satisfy signature 7 due to inconsistencies in how they use type variables [misc]
+ src/hydra_zen/structured_configs/_implementations.py:1604: error: Overloaded function implementation cannot satisfy signature 8 due to inconsistencies in how they use type variables [misc]
+ src/hydra_zen/structured_configs/_implementations.py:1604: error: Overloaded function implementation cannot satisfy signature 9 due to inconsistencies in how they use type variables [misc]
- tests/annotations/declarations.py:798: error: Not all union combinations were tried because there are too many unions [misc]
- tests/annotations/declarations.py:800: error: Argument "zen_partial" has incompatible type "bool | None"; expected "Literal[False] | None" [arg-type]
- tests/annotations/declarations.py:817: error: Not all union combinations were tried because there are too many unions [misc]
- tests/annotations/declarations.py:819: error: Argument "zen_partial" to "__call__" of "FullBuilds" has incompatible type "bool | None"; expected "Literal[False] | None" [arg-type]
- tests/annotations/declarations.py:836: error: Not all union combinations were tried because there are too many unions [misc]
- tests/annotations/declarations.py:836: error: Need type annotation for "pout" [var-annotated]
- tests/annotations/declarations.py:837: error: Argument 1 to "__call__" of "PBuilds" has incompatible type "Callable[[int], str]"; expected "def (*Never, **Never) -> Never" [arg-type]
- tests/annotations/declarations.py:876: error: Argument "zen_partial" has incompatible type "bool | None"; expected "Literal[False] | None" [arg-type]
- tests/annotations/declarations.py:878: error: Unused "type: ignore" comment [unused-ignore]
- tests/annotations/declarations.py:895: error: Need type annotation for "maybe_full_sig" [var-annotated]
- tests/annotations/declarations.py:895: error: Argument 1 to "__call__" of "PBuilds" has incompatible type "Callable[[int], Any]"; expected "def (*Never, **Never) -> Never" [arg-type]
- tests/annotations/declarations.py:895: error: Argument "zen_partial" to "__call__" of "StdBuilds" has incompatible type "bool | None"; expected "Literal[False] | None" [arg-type]
- tests/annotations/declarations.py:897: error: Unused "type: ignore" comment [unused-ignore]
- tests/annotations/declarations.py:914: error: Argument "zen_partial" to "__call__" of "FullBuilds" has incompatible type "bool | None"; expected "Literal[False] | None" [arg-type]
- tests/annotations/declarations.py:916: error: Unused "type: ignore" comment [unused-ignore]
- tests/annotations/declarations.py:922: error: Argument "zen_partial" to "__call__" of "FullBuilds" has incompatible type "bool | None"; expected "Literal[False] | None" [arg-type]
antidote (https://github.com/Finistere/antidote)
+ src/antidote/lib/interface_ext/_interface.py:462: error: Value of type variable "Weight" of "__register_implementation" of "ImplementsImpl" cannot be "object" [type-var]
+ src/antidote/lib/interface_ext/_interface.py:464: error: Value of type variable "Weight" of "create_conditions" cannot be "object" [type-var]
+ src/antidote/lib/interface_ext/__init__.py:1266: error: Signature of "when" incompatible with supertype "implements" [override]
+ src/antidote/lib/interface_ext/__init__.py:1266: note: Superclass:
+ src/antidote/lib/interface_ext/__init__.py:1266: note: def [Weight: ImplementationWeight] when(self, *conditions: Predicate[Weight] | Predicate[NeutralWeight] | Weight | NeutralWeight | bool | None, qualified_by: object = ...) -> Callable[[Any], Any]
+ src/antidote/lib/interface_ext/__init__.py:1266: note: Subclass:
+ src/antidote/lib/interface_ext/__init__.py:1266: note: def [Weight: ImplementationWeight] when(self, *conditions: Predicate[Weight] | Predicate[NeutralWeight] | Weight | NeutralWeight | bool | None, qualified_by: object = ...) -> Callable[[C], C]
+ src/antidote/lib/interface_ext/__init__.py:1372: error: Signature of "when" incompatible with supertype "implements" [override]
+ src/antidote/lib/interface_ext/__init__.py:1372: note: Superclass:
+ src/antidote/lib/interface_ext/__init__.py:1372: note: def [Weight: ImplementationWeight] when(self, *conditions: Predicate[Weight] | Predicate[NeutralWeight] | Weight | NeutralWeight | bool | None, qualified_by: object = ...) -> Callable[[Any], Any]
+ src/antidote/lib/interface_ext/__init__.py:1372: note: Subclass:
+ src/antidote/lib/interface_ext/__init__.py:1372: note: def [Weight: ImplementationWeight] when(self, *conditions: Predicate[Weight] | Predicate[NeutralWeight] | Weight | NeutralWeight | bool | None, qualified_by: object = ...) -> Callable[[T], T]
+ tests/lib/interface/test_lazy.py:79: error: Value of type variable "Weight" of "when" of "LazyImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_lazy.py:401: error: Value of type variable "Weight" of "when" of "LazyImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_lazy.py:405: error: Value of type variable "Weight" of "when" of "LazyImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_lazy.py:410: error: Value of type variable "Weight" of "when" of "LazyImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_lazy.py:414: error: Value of type variable "Weight" of "when" of "LazyImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_lazy.py:614: error: Value of type variable "Weight" of "when" of "LazyImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_lazy.py:626: error: Value of type variable "Weight" of "when" of "LazyImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_lazy.py:641: error: Value of type variable "Weight" of "when" of "LazyImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_lazy.py:652: error: Value of type variable "Weight" of "when" of "LazyImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_function.py:72: error: Value of type variable "Weight" of "when" of "FunctionImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_function.py:275: error: Value of type variable "Weight" of "when" of "FunctionImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_function.py:279: error: Value of type variable "Weight" of "when" of "FunctionImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_function.py:284: error: Value of type variable "Weight" of "when" of "FunctionImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_function.py:491: error: Value of type variable "Weight" of "when" of "FunctionImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_function.py:501: error: Value of type variable "Weight" of "when" of "FunctionImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_function.py:515: error: Value of type variable "Weight" of "when" of "FunctionImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_function.py:525: error: Value of type variable "Weight" of "when" of "FunctionImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_custom.py:213: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "Dummy" [type-var]
+ tests/lib/interface/test_conditions.py:54: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "bool" [type-var]
+ tests/lib/interface/test_conditions.py:58: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "bool" [type-var]
+ tests/lib/interface/test_conditions.py:70: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_conditions.py:78: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_conditions.py:116: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "OnlyIf" [type-var]
+ tests/lib/interface/test_conditions.py:120: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "OnlyIf" [type-var]
+ tests/lib/interface/test_conditions.py:132: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "object" [type-var]
+ tests/lib/interface/test_conditions.py:136: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "object" [type-var]
+ tests/lib/interface/test_conditions.py:193: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "Weight | OnlyIf | bool | None" [type-var]
+ tests/lib/interface/test_conditions.py:217: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_conditions.py:278: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_conditions.py:284: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "WeightAlt | None" [type-var]
+ tests/lib/interface/test_conditions.py:294: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_conditions.py:300: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_conditions.py:306: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_conditions.py:312: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_class.py:686: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_class.py:691: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_class.py:697: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_class.py:702: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "Weight | None" [type-var]
+ tests/lib/interface/test_class.py:774: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "bool" [type-var]
+ tests/lib/interface/test_class.py:780: error: Value of type variable "Weight" of "when" of "ClassImplements" cannot be "bool" [type-var]
discord.py (https://github.com/Rapptz/discord.py)
- discord/app_commands/commands.py:1013: error: Argument 1 to "maybe_coroutine" has incompatible type "Callable[[Interaction[ClientT]], Coroutine[Any, Any, bool]]"; expected "Callable[[Interaction[Client]], Never | Awaitable[Never]]" [arg-type]
- discord/ext/commands/cog.py:710: error: Argument 1 to "maybe_coroutine" has incompatible type "Callable[[], Coroutine[Any, Any, None]]"; expected "Callable[[], Never | Awaitable[Never]]" [arg-type]
- discord/ext/commands/cog.py:727: error: Argument 1 to "maybe_coroutine" has incompatible type "Callable[[], Coroutine[Any, Any, None]]"; expected "Callable[[], Never | Awaitable[Never]]" [arg-type]
- discord/ext/commands/cog.py:780: error: Argument 1 to "maybe_coroutine" has incompatible type "Callable[[], Coroutine[Any, Any, None]]"; expected "Callable[[], Never | Awaitable[Never]]" [arg-type]
- discord/ext/commands/hybrid.py:420: error: Argument 1 to "maybe_coroutine" has incompatible type "Callable[[Interaction[ClientT]], Coroutine[Any, Any, bool]]"; expected "Callable[[Interaction[Client]], Never | Awaitable[Never]]" [arg-type]
Tanjun (https://github.com/FasterSpeeding/Tanjun)
- tanjun/hooks.py:389: error: Need type annotation for "results" (hint: "results: list[<type>] = ...") [var-annotated]
- tanjun/dependencies/data.py:220: error: Argument "callback" to "inject" has incompatible type "Callable[..., Coroutine[Any, Any, _T]]"; expected "Callable[..., Coroutine[Any, Any, Never] | Never]" [arg-type]
- tanjun/dependencies/data.py:347: error: Argument "callback" to "inject" has incompatible type "Callable[..., Coroutine[Any, Any, _T]]"; expected "Callable[..., Coroutine[Any, Any, Never] | Never]" [arg-type]
- tanjun/_internal/__init__.py:82: error: Need type annotation for "result" [var-annotated]
- tanjun/_internal/__init__.py:83: error: Statement is unreachable [unreachable]
- tanjun/schedules.py:347: error: Argument 1 to "call_with_async_di" of "Client" has incompatible type "_CallbackSigT"; expected "Callable[..., Coroutine[Any, Any, Never] | Never]" [arg-type]
- tanjun/schedules.py:373: error: Argument 1 to "call_with_async_di" of "Client" has incompatible type "Callable[..., Coroutine[Any, Any, None]]"; expected "Callable[..., Coroutine[Any, Any, Never] | Never]" [arg-type]
- tanjun/schedules.py:396: error: Argument 1 to "call_with_async_di" of "Client" has incompatible type "Callable[..., Coroutine[Any, Any, None]]"; expected "Callable[..., Coroutine[Any, Any, Never] | Never]" [arg-type]
- tanjun/schedules.py:1067: error: Argument 1 to "call_with_async_di" of "Client" has incompatible type "_CallbackSigT"; expected "Callable[..., Coroutine[Any, Any, Never] | Never]" [arg-type]
- tanjun/checks.py:1140: error: Statement is unreachable [unreachable]
- tanjun/commands/slash.py:3191: error: Argument 1 to "call_with_async_di" of "Context" has incompatible type "_SlashCallbackSigT"; expected "Callable[..., Coroutine[Any, Any, Never] | Never]" [arg-type]
- tanjun/commands/slash.py:3235: error: Argument 1 to "call_with_async_di" of "Context" has incompatible type "def (AutocompleteContext, str, /, *Any, **Any) -> Coroutine[Any, Any, None] | def (AutocompleteContext, float, /, *Any, **Any) -> Coroutine[Any, Any, None] | def (AutocompleteContext, int, /, *Any, **Any) -> Coroutine[Any, Any, None]"; expected "Callable[..., Coroutine[Any, Any, Never] | Never]" [arg-type]
- tanjun/commands/message.py:346: error: Argument 1 to "call_with_async_di" of "Context" has incompatible type "_MessageCallbackSigT"; expected "Callable[..., Coroutine[Any, Any, Never] | Never]" [arg-type]
- tanjun/commands/menu.py:689: error: Argument 1 to "call_with_async_di" of "Context" has incompatible type "_AnyMenuCallbackSigT"; expected "Callable[..., Coroutine[Any, Any, Never] | Never]" [arg-type]
- tanjun/clients.py:2294: error: Argument 1 to "call_with_async_di" of "Context" has incompatible type "def (MessageContext, /, *Any, **Any) -> Coroutine[Any, Any, Iterable[str]]"; expected "Callable[..., Coroutine[Any, Any, Never] | Never]" [arg-type]
pandas-stubs (https://github.com/pandas-dev/pandas-stubs)
+ tests/series/complex/test_sub.py:89: error: Expression is of type "Never", not "Series[complex]" [assert-type]
+ tests/series/complex/test_sub.py:90: error: Statement is unreachable [unreachable]
+ tests/indexes/complex/test_sub.py:54: error: Expression is of type "Never", not "Index[complex]" [assert-type]
+ tests/indexes/complex/test_sub.py:55: error: Statement is unreachable [unreachable]
sympy (https://github.com/sympy/sympy)
+ sympy/polys/euclidtools.py:799: error: Overloaded function implementation cannot satisfy signature 2 due to inconsistencies in how they use type variables [misc]
anyio (https://github.com/agronholm/anyio)
+ src/anyio/_core/_tempfile.py:97: error: Value of type variable "AnyStr" of "TemporaryFile" cannot be "str | None" [type-var]
+ src/anyio/_core/_tempfile.py:97: error: Not all union combinations were tried because there are too many unions [misc]
+ src/anyio/_core/_tempfile.py:98: error: Argument 1 to "TemporaryFile" has incompatible type "Literal['r+', '+r', 'rt+', 'r+t', '+rt', 'tr+', 't+r', '+tr', 'w+', '+w', 'wt+', 'w+t', '+wt', 'tw+', 't+w', '+tw', 'a+', '+a', 'at+', 'a+t', '+at', 'ta+', 't+a', '+ta', 'x+', '+x', 'xt+', 'x+t', '+xt', 'tx+', 't+x', '+tx', 'w', 'wt', 'tw', 'a', 'at', 'ta', 'x', 'xt', 'tx', 'r', 'rt', 'tr', 'U', 'rU', 'Ur', 'rtU', 'rUt', 'Urt', 'trU', 'tUr', 'Utr', 'rb+', 'r+b', '+rb', 'br+', 'b+r', '+br', 'wb+', 'w+b', '+wb', 'bw+', 'b+w', '+bw', 'ab+', 'a+b', '+ab', 'ba+', 'b+a', '+ba', 'xb+', 'x+b', '+xb', 'bx+', 'b+x', '+bx', 'rb', 'br', 'rbU', 'rUb', 'Urb', 'brU', 'bUr', 'Ubr', 'wb', 'bw', 'ab', 'ba', 'xb', 'bx']"; expected "Literal['r+', '+r', 'rt+', 'r+t', '+rt', 'tr+', 't+r', '+tr', 'w+', '+w', 'wt+', 'w+t', '+wt', 'tw+', 't+w', '+tw', 'a+', '+a', 'at+', 'a+t', '+at', 'ta+', 't+a', '+ta', 'x+', '+x', 'xt+', 'x+t', '+xt', 'tx+', 't+x', '+tx'] | Literal['w', 'wt', 'tw', 'a', 'at', 'ta', 'x', 'xt', 'tx'] | Literal['r', 'rt', 'tr', 'U', 'rU', 'Ur', 'rtU', 'rUt', 'Urt', 'trU', 'tUr', 'Utr']" [arg-type]
+ src/anyio/_core/_tempfile.py:108: error: Argument 1 to "AsyncFile" has incompatible type "TextIOWrapper[_WrappedBuffer]"; expected "IO[bytes]" [arg-type]
xarray (https://github.com/pydata/xarray)
+ xarray/conventions.py: note: In function "decode_cf_variables":
+ xarray/conventions.py:413: error: Argument "concat_characters" to "decode_cf_variable" has incompatible type "object"; expected "bool" [arg-type]
+ xarray/conventions.py:414: error: Argument "mask_and_scale" to "decode_cf_variable" has incompatible type "object"; expected "bool" [arg-type]
+ xarray/conventions.py:418: error: Argument "stack_char_dim" to "decode_cf_variable" has incompatible type "object | Any"; expected "bool" [arg-type]
+ xarray/conventions.py:419: error: Argument "use_cftime" to "decode_cf_variable" has incompatible type "bool | Mapping[str, bool] | None"; expected "bool | None" [arg-type]
+ xarray/conventions.py:420: error: Argument "decode_timedelta" to "decode_cf_variable" has incompatible type "CFTimedeltaCoder | bool | Mapping[str, bool | CFTimedeltaCoder] | None"; expected "bool | CFTimedeltaCoder | None" [arg-type]
+ xarray/conventions.py:420: error: Argument "decode_timedelta" to "decode_cf_variable" has incompatible type "Mapping[str, bool | CFTimedeltaCoder] | bool | CFTimedeltaCoder | None"; expected "bool | CFTimedeltaCoder | None" [arg-type]
ibis (https://github.com/ibis-project/ibis)
+ ibis/common/egraph.py:733: error: Item "function" of "Callable[..., Any] | Pattern | Variable" has no attribute "substitute" [union-attr]
- ibis/common/egraph.py:731: error: Need type annotation for "rewrite" [var-annotated]
- ibis/common/egraph.py:731: error: Argument 1 to "promote_list" has incompatible type "list[Rewrite]"; expected "Iterable[Never]" [arg-type]
- ibis/expr/types/strings.py:973: error: Need type annotation for "pattern" [var-annotated]
- ibis/expr/types/strings.py:975: error: Argument 1 to "promote_list" has incompatible type "str | StringValue | Deferred | Iterable[str | StringValue | Deferred]"; expected "Iterable[Never]" [arg-type]
+ ibis/expr/types/strings.py:974: error: Argument 2 to "StringSQLLike" has incompatible type "str | StringValue | Deferred"; expected "Value[String, Any]" [arg-type]
- ibis/expr/types/strings.py:1019: error: Need type annotation for "pattern" [var-annotated]
- ibis/expr/types/strings.py:1021: error: Argument 1 to "promote_list" has incompatible type "str | StringValue | Deferred | Iterable[str | StringValue | Deferred]"; expected "Iterable[Never]" [arg-type]
+ ibis/expr/types/strings.py:1020: error: Argument 2 to "StringSQLILike" has incompatible type "str | StringValue | Deferred"; expected "Value[String, Any]" [arg-type]
- ibis/expr/types/relations.py:1141: error: Need type annotation for "arg" [var-annotated]
- ibis/expr/types/relations.py:1143: error: Argument 1 to "promote_list" has incompatible type "Sequence[str | int]"; expected "Iterable[Never]" [arg-type]
- ibis/expr/types/relations.py:4938: error: Argument 1 to "promote_list" has incompatible type "str | Iterable[str] | Selector"; expected "Selector | Iterable[Selector]" [arg-type]
+ ibis/expr/types/relations.py:4940: error: Argument 1 to "_to_selector" has incompatible type "list[object]"; expected "str | Selector | Column | Sequence[str | Selector | Column]" [arg-type]
- ibis/backends/flink/ddl.py:96: error: Argument 1 to "promote_list" has incompatible type "str | Sequence[str] | None"; expected "Iterable[None] | None" [arg-type]
graphql-core (https://github.com/graphql-python/graphql-core)
+ src/graphql/type/definition.py:1263: error: Unused "type: ignore" comment [unused-ignore]
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix type variable inference for
T | Wrapper[T]union patternsSummary
Fixes incorrect
Neverinference when calling a generic function whose parameter typeis a union of a bare TypeVar and a parameterized generic containing that same TypeVar,
such as
T | list[T]orT | dict[str, T].Closes #21615
Problem
Given this function:
Mypy was inferring
T = Neverfor any call where the argument matched theWrapper[T]branch of the union instead of the bareTbranch.Root Cause
In
_infer_constraints(mypy/constraints.py), when the template is aUnionTypeand the direction is
SUPERTYPE_OF, mypy callsany_constraints()with one optionper union item:
TT ≥ list[int](overly broad)list[T]T = int(correct)Because these two options are structurally incompatible,
any_constraints()gives upand returns
[]. With no constraints, the solver falls back toT = Never.The existing helper
handle_recursive_union()already resolves this correctly: ittries the non-TypeVar items first (yielding the precise bound
T = intfromlist[T])and falls back to the bare TypeVar items only when needed. However, it was only invoked
when
has_recursive_types(template)wasTrue, which isFalsefor ordinary genericfunction signatures.
Fix
Extended the fallback condition in
_infer_constraintsto also callhandle_recursive_union()whenany_constraints()returns empty and the uniontemplate contains:
TypeVarTypeitem, andTypeVarTypeitem that itself contains TypeVars (e.g.list[T])The second condition is the key guard. It ensures the fix applies only to genuine
T | Wrapper[T]patterns and not to unrelated unions such asAnyStr | int, whereintcarries no TypeVars and the existing behavior is correct.The docstring of
handle_recursive_union()was also updated to document the broaderuse case.
Test Plan
testUnionInferenceintest-data/unit/check-inference.test: removed thestale expected-error annotation on
g(['a'])that was documenting the bug (includingthe comment that called it an "awkward error message").
testUnionInferenceTypeVarWrappercoveringT | list[T]andT | dict[str, T]with both scalar and container arguments.
Behavior After Fix