Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 22 additions & 21 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -1958,28 +1958,29 @@ def infer_arg_types_in_context(

Returns the inferred types of *actual arguments*.
"""
res: list[Type | None] = [None] * len(args)

for i, actuals in enumerate(formal_to_actual):
# Precompute arg_context so that we type check argument expressions in evaluation order
arg_context: list[Type | None] = [None] * len(args)
for fi, actuals in enumerate(formal_to_actual):
for ai in actuals:
if not arg_kinds[ai].is_star():
arg_type = callee.arg_types[i]
# When the outer context for a function call is known to be recursive,
# we solve type constraints inferred from arguments using unions instead
# of joins. This is a bit arbitrary, but in practice it works for most
# cases. A cleaner alternative would be to switch to single bin type
# inference, but this is a lot of work.
old = self.infer_more_unions_for_recursive_type(arg_type)
res[ai] = self.accept(args[ai], arg_type)
# We need to manually restore union inference state, ugh.
type_state.infer_unions = old

# Fill in the rest of the argument types.
for i, t in enumerate(res):
if not t:
res[i] = self.accept(args[i])
assert all(tp is not None for tp in res)
return cast(list[Type], res)
if arg_kinds[ai].is_star():
continue
arg_context[ai] = callee.arg_types[fi]

res = []
for arg, ctx in zip(args, arg_context):
if ctx is not None:
# When the outer context for a function call is known to be recursive,
# we solve type constraints inferred from arguments using unions instead
# of joins. This is a bit arbitrary, but in practice it works for most
# cases. A cleaner alternative would be to switch to single bin type
# inference, but this is a lot of work.
old = self.infer_more_unions_for_recursive_type(ctx)
res.append(self.accept(arg, ctx))
# We need to manually restore union inference state, ugh.
type_state.infer_unions = old
else:
res.append(self.accept(arg))
return res

def infer_function_type_arguments_using_context(
self, callable: CallableType, error_context: Context
Expand Down
9 changes: 9 additions & 0 deletions test-data/unit/check-python38.test
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,15 @@ if typeguard(x=(n := cast(object, "hi"))):
[out]
main:8: note: Revealed type is "builtins.int"

[case testWalrusAssignmentAcrossCallArguments]
def f(notifications: str, initial_reference: str) -> int:
return 42

f(
initial_reference=(request_reference := "abc"),
notifications=reveal_type(request_reference), # N: Revealed type is "builtins.str"
)

[case testNoCrashOnAssignmentExprClass]
class C:
[(j := i) for i in [1, 2, 3]] # E: Assignment expression within a comprehension cannot be used in a class body
Expand Down