Fix inference with UninhabitedType#16994
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
The primer output looks good! There are a few examples where this change allows for better generic type inference. T = TypeVar("T")
class B(dict[T, T]): ...
def a2(check: bool, a: B[str]) -> None:
reveal_type(a if check else {})-Revealed type is "builtins.object"
+Revealed type is "builtins.dict[builtins.str, builtins.str]"The c = {1: {}, 2: {"key": {}}}
reveal_type(c)-Revealed type is "builtins.dict[builtins.int, builtins.object]"
+Revealed type is "builtins.dict[builtins.int, builtins.dict[builtins.str, builtins.dict[Any, Any]]]-- |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Thanks! Clearly empirically good.
I'm a little unsure about whether this is theoretically good, since it's icky to merge different types in an invariant context.
from typing import Never
def foo(x: list[str], y: list[Never]):
reveal_type([x, y]) # now shows list[list[str]]
o = [x, y]
o[1].append("asdf") # list[Never] now contains a str, this may surprise caller of foo
I think I'm still in favour of merging, but maybe we should have^ as a test
If it's just this edge case with |
|
Diff from mypy_primer, showing the effect of this PR on open source code: steam.py (https://github.com/Gobot1234/steam.py)
- steam/ext/commands/commands.py:589: error: Incompatible types in assignment (expression has type "object", variable has type "dict[str, Command[CogT, [VarArg(Any), KwArg(Any)], Any]]") [assignment]
comtypes (https://github.com/enthought/comtypes)
- comtypes/tools/tlbparser.py:443: error: Incompatible return value type (got "object", expected "list[str]") [return-value]
prefect (https://github.com/PrefectHQ/prefect)
- src/prefect/infrastructure/process.py:243: error: Unpacked dict entry 0 has incompatible type "object"; expected "SupportsKeysAndGetItem[str, str | None]" [dict-item]
jax (https://github.com/google/jax)
+ jax/_src/numpy/lax_numpy.py:1798: error: Unused "type: ignore" comment [unused-ignore]
alectryon (https://github.com/cpitclaudel/alectryon)
+ alectryon/markers.py:100: error: Need type annotation for "QUERY_SHAPE" [var-annotated]
mkdocs (https://github.com/mkdocs/mkdocs)
+ mkdocs/tests/config/config_options_tests.py:1597: error: Need type annotation for "cfg" [var-annotated]
|
Switches the logic from python#16994 to use ambiguous (since is_noreturn was only meant for error messages) See also python#15996
Switches the logic from python#16994 to use ambiguous (since is_noreturn was only meant for error messages) See also python#15996
At the moment, inference fails if an empty dict is used (without annotation) as one of the types. It's because the constraint solver can't resolve
dict[str, int]anddict[Never, Never]. However in this case it's more reasonable to interpret the empty dict asdict[Any, Any]and just use the first type instead. That matches the behavior of pyright.