From 69af980b28225a21b1ab30270069bd673ebc0372 Mon Sep 17 00:00:00 2001 From: Elazar Gershuni Date: Tue, 15 Aug 2017 19:21:21 +0300 Subject: [PATCH] Add arguments to callee context in a call expression (#3116) Fix #3097. --- mypy/checkexpr.py | 15 ++++++++++++++- test-data/unit/check-inference-context.test | 16 ++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index a26637dfd544..4ac17c373c3f 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -212,7 +212,20 @@ def visit_call_expr(self, e: CallExpr, allow_none_return: bool = False) -> Type: elif typ.node.is_newtype: self.msg.fail(messages.CANNOT_ISINSTANCE_NEWTYPE, e) self.try_infer_partial_type(e) - callee_type = self.accept(e.callee, always_allow_any=True) + if isinstance(e.callee, LambdaExpr): + formal_to_actual = map_actuals_to_formals( + e.arg_kinds, e.arg_names, + e.callee.arg_kinds, e.callee.arg_names, + lambda i: self.accept(e.args[i])) + + arg_types = [join.join_type_list([self.accept(e.args[j]) for j in formal_to_actual[i]]) + for i in range(len(e.callee.arg_kinds))] + type_context = CallableType(arg_types, e.callee.arg_kinds, e.callee.arg_names, + ret_type=self.object_type(), + fallback=self.named_type('builtins.function')) + else: + type_context = None + callee_type = self.accept(e.callee, type_context, always_allow_any=True) if (self.chk.options.disallow_untyped_calls and self.chk.in_checked_function() and isinstance(callee_type, CallableType) diff --git a/test-data/unit/check-inference-context.test b/test-data/unit/check-inference-context.test index 13ad0efff083..f7b58fff0ff4 100644 --- a/test-data/unit/check-inference-context.test +++ b/test-data/unit/check-inference-context.test @@ -569,6 +569,22 @@ class A: pass class B: pass [builtins fixtures/list.pyi] +[case testInferLambdaTypeUsingContext] +x : str = (lambda x: x + 1)(1) # E: Incompatible types in assignment (expression has type "int", variable has type "str") +reveal_type((lambda x, y: x + y)(1, 2)) # E: Revealed type is 'builtins.int' +(lambda x, y: x + y)(1, "") # E: Unsupported operand types for + ("int" and "str") +(lambda *, x, y: x + y)(x=1, y="") # E: Unsupported operand types for + ("int" and "str") +reveal_type((lambda s, i: s)(i=0, s='x')) # E: Revealed type is 'builtins.str' +reveal_type((lambda s, i: i)(i=0, s='x')) # E: Revealed type is 'builtins.int' +reveal_type((lambda x, s, i: x)(1.0, i=0, s='x')) # E: Revealed type is 'builtins.float' +(lambda x, s, i: x)() # E: Too few arguments +(lambda: 0)(1) # E: Too many arguments +-- varargs are not handled, but it should not crash +reveal_type((lambda *k, s, i: i)(type, i=0, s='x')) # E: Revealed type is 'Any' +reveal_type((lambda s, *k, i: i)(i=0, s='x')) # E: Revealed type is 'Any' +reveal_type((lambda s, i, **k: i)(i=0, s='x')) # E: Revealed type is 'Any' +[builtins fixtures/dict.pyi] + [case testInferLambdaAsGenericFunctionArgument] from typing import TypeVar, List, Any, Callable t = TypeVar('t')