Skip to content

Commit 7808e82

Browse files
authored
Improve type inference special case that involves union with Any (#10887)
When trying to match `list[T]` and `list[str] | Any`, previously we gave up, because the union items caused conflicting inferred values for `T` (`str` and `Any`). Work around the issue by dropping `Any` constraints if there are multiple sets of contraints, since we prefer more precise types. This fixes false positives resulting from python/typeshed#5557, which changed some return types to contain unions with `Any` items. See mypy primer results in #10881 for a real-world example of this in sphinx.
1 parent 10dc451 commit 7808e82

File tree

2 files changed

+18
-0
lines changed

2 files changed

+18
-0
lines changed

mypy/constraints.py

+10
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,16 @@ def any_constraints(options: List[Optional[List[Constraint]]], eager: bool) -> L
216216
# TODO: More generally, if a given (variable, direction) pair appears in
217217
# every option, combine the bounds with meet/join.
218218
return valid_options[0]
219+
elif len(valid_options) > 1:
220+
# Drop constraints that only refer to "Any" and try again. This way Any types
221+
# in unions don't interfere with type inference.
222+
narrowed_options = [option
223+
for option in valid_options
224+
if not (option and
225+
all(isinstance(get_proper_type(c.target), AnyType)
226+
for c in option))]
227+
if len(narrowed_options) < len(valid_options):
228+
return any_constraints([option for option in narrowed_options], eager)
219229

220230
# Otherwise, there are either no valid options or multiple, inconsistent valid
221231
# options. Give up and deduce nothing.

test-data/unit/check-inference-context.test

+8
Original file line numberDiff line numberDiff line change
@@ -1375,3 +1375,11 @@ def f(x: Callable[..., T]) -> T:
13751375

13761376
x: G[str] = f(G)
13771377
[out]
1378+
1379+
[case testConditionalExpressionWithEmptyListAndUnionWithAny]
1380+
from typing import Union, List, Any
1381+
1382+
def f(x: Union[List[str], Any]) -> None:
1383+
a = x if x else []
1384+
reveal_type(a) # N: Revealed type is "Union[builtins.list[builtins.str], Any]"
1385+
[builtins fixtures/list.pyi]

0 commit comments

Comments
 (0)