diff --git a/mypy/checker.py b/mypy/checker.py index 11499d6b570e..5987033f32d6 100644 --- a/mypy/checker.py +++ b/mypy/checker.py @@ -389,8 +389,8 @@ def defer_node(self, node: DeferredNodeType, enclosing_class: Optional[TypeInfo] self.deferred_nodes.append(DeferredNode(node, enclosing_class)) def handle_cannot_determine_type(self, name: str, context: Context) -> None: - node = self.scope.top_non_lambda_function() - if self.pass_num < self.last_pass and isinstance(node, FuncDef): + node = self.scope.top_function() + if self.pass_num < self.last_pass and isinstance(node, (FuncDef, LambdaExpr)): # Don't report an error yet. Just defer. Note that we don't defer # lambdas because they are coupled to the surrounding function # through the binder and the inferred type of the lambda, so it diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 00e3757a3e7e..280e9a35d537 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -3876,7 +3876,13 @@ def visit_conditional_expr(self, e: ConditionalExpr, allow_none_return: bool = F def analyze_cond_branch(self, map: Optional[Dict[Expression, Type]], node: Expression, context: Optional[Type], allow_none_return: bool = False) -> Type: - with self.chk.binder.frame_context(can_skip=True, fall_through=0): + # We need to be have the correct amount of binder frames. + # Sometimes it can be missing for unreachable parts. + with ( + self.chk.binder.frame_context(can_skip=True, fall_through=0) + if len(self.chk.binder.frames) > 1 + else self.chk.binder.top_frame_context() + ): if map is None: # We still need to type check node, in case we want to # process it for isinstance checks later diff --git a/test-data/unit/check-callable.test b/test-data/unit/check-callable.test index ee1c84edf185..5278d24eb4f4 100644 --- a/test-data/unit/check-callable.test +++ b/test-data/unit/check-callable.test @@ -301,6 +301,28 @@ def f(t: T) -> A: [builtins fixtures/callable.pyi] +[case testCallableTypeVarBoundAndLambdaDefer] +# See https://github.com/python/mypy/issues/11212 +from typing import Callable, TypeVar + +C = TypeVar('C', bound=Callable) + +def dec(val: None) -> Callable[[C], C]: + def wrapper(f): + return f + return wrapper + +lambda: foo() + 2 # error was here + +@dec(None) +def foo() -> int: + return 2 + +lambda: foo() + 2 # double check + +reveal_type(foo() + 2) # N: Revealed type is "builtins.int" +[builtins fixtures/callable.pyi] + [case testCallableTypeUnion] from abc import ABCMeta, abstractmethod from typing import Type, Union diff --git a/test-data/unit/check-optional.test b/test-data/unit/check-optional.test index c6d3d1f48649..814c780d5290 100644 --- a/test-data/unit/check-optional.test +++ b/test-data/unit/check-optional.test @@ -738,8 +738,11 @@ class A: def f(self, x: Optional['A']) -> None: assert x - lambda: (self.y, x.a) # E: Cannot determine type of "y" + lambda: (self.y, x.a) self.y = int() +[out] +main:8: error: Cannot determine type of "y" +main:8: error: Item "None" of "Optional[A]" has no attribute "a" [builtins fixtures/isinstancelist.pyi] [case testDeferredAndOptionalInferenceSpecialCase]