Skip to content

Commit

Permalink
Fix crash on partial type inference within a lambda (#14087)
Browse files Browse the repository at this point in the history
Fixes #9654

Seems to be quite straightforward. Erased types should never be stored
on variables, it is just a temporary thing for nested generic calls.
  • Loading branch information
ilevkivskyi authored Nov 14, 2022
1 parent 57ce73d commit cf59b82
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 3 deletions.
15 changes: 12 additions & 3 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@
AnyType,
CallableType,
DeletedType,
ErasedType,
FunctionLike,
Instance,
LiteralType,
Expand Down Expand Up @@ -7040,18 +7041,26 @@ def is_valid_inferred_type(typ: Type, is_lvalue_final: bool = False) -> bool:
return is_lvalue_final
elif isinstance(proper_type, UninhabitedType):
return False
return not typ.accept(NothingSeeker())
return not typ.accept(InvalidInferredTypes())


class NothingSeeker(TypeQuery[bool]):
"""Find any <nothing> types resulting from failed (ambiguous) type inference."""
class InvalidInferredTypes(TypeQuery[bool]):
"""Find type components that are not valid for an inferred type.
These include <Erased> type, and any <nothing> types resulting from failed
(ambiguous) type inference.
"""

def __init__(self) -> None:
super().__init__(any)

def visit_uninhabited_type(self, t: UninhabitedType) -> bool:
return t.ambiguous

def visit_erased_type(self, t: ErasedType) -> bool:
# This can happen inside a lambda.
return True


class SetNothingToAny(TypeTranslator):
"""Replace all ambiguous <nothing> types with Any (to avoid spurious extra errors)."""
Expand Down
26 changes: 26 additions & 0 deletions test-data/unit/check-incremental.test
Original file line number Diff line number Diff line change
Expand Up @@ -6286,3 +6286,29 @@ class C: ...
[out]
[out2]
[out3]

[case testNoCrashOnPartialLambdaInference]
import m
[file m.py]
from typing import TypeVar, Callable

V = TypeVar("V")
def apply(val: V, func: Callable[[V], None]) -> None:
return func(val)

xs = []
apply(0, lambda a: xs.append(a))
[file m.py.2]
from typing import TypeVar, Callable

V = TypeVar("V")
def apply(val: V, func: Callable[[V], None]) -> None:
return func(val)

xs = []
apply(0, lambda a: xs.append(a))
reveal_type(xs)
[builtins fixtures/list.pyi]
[out]
[out2]
tmp/m.py:9: note: Revealed type is "builtins.list[builtins.int]"

0 comments on commit cf59b82

Please sign in to comment.