Skip to content

Commit 82e816c

Browse files
Merge branch 'master' into fix_match_callable
2 parents e80d658 + c6b40df commit 82e816c

13 files changed

+116
-36
lines changed

docs/source/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,9 @@
278278
intersphinx_mapping = {
279279
"python": ("https://docs.python.org/3", None),
280280
"attrs": ("https://www.attrs.org/en/stable/", None),
281-
"cython": ("https://docs.cython.org/en/latest", None),
281+
"cython": ("https://cython.readthedocs.io/en/stable", None),
282282
"monkeytype": ("https://monkeytype.readthedocs.io/en/latest", None),
283-
"setuptools": ("https://setuptools.readthedocs.io/en/latest", None),
283+
"setuptools": ("https://setuptools.pypa.io/en/latest", None),
284284
}
285285

286286

mypy/checker.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5577,6 +5577,8 @@ def infer_variable_types_from_type_maps(
55775577
previous_type, _, _ = self.check_lvalue(expr)
55785578
if previous_type is not None:
55795579
already_exists = True
5580+
if isinstance(expr.node, Var) and expr.node.is_final:
5581+
self.msg.cant_assign_to_final(expr.name, False, expr)
55805582
if self.check_subtype(
55815583
typ,
55825584
previous_type,

mypy/checkexpr.py

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1755,14 +1755,6 @@ def check_callable_call(
17551755
return AnyType(TypeOfAny.from_error), callee
17561756
seen_unpack = True
17571757

1758-
formal_to_actual = map_actuals_to_formals(
1759-
arg_kinds,
1760-
arg_names,
1761-
callee.arg_kinds,
1762-
callee.arg_names,
1763-
lambda i: self.accept(args[i]),
1764-
)
1765-
17661758
# This is tricky: return type may contain its own type variables, like in
17671759
# def [S] (S) -> def [T] (T) -> tuple[S, T], so we need to update their ids
17681760
# to avoid possible id clashes if this call itself appears in a generic
@@ -1773,27 +1765,29 @@ def check_callable_call(
17731765
freeze_all_type_vars(fresh_ret_type)
17741766
callee = callee.copy_modified(ret_type=fresh_ret_type)
17751767

1768+
if callee.is_generic():
1769+
callee = freshen_function_type_vars(callee)
1770+
callee = self.infer_function_type_arguments_using_context(callee, context)
1771+
1772+
formal_to_actual = map_actuals_to_formals(
1773+
arg_kinds,
1774+
arg_names,
1775+
callee.arg_kinds,
1776+
callee.arg_names,
1777+
lambda i: self.accept(args[i]),
1778+
)
1779+
17761780
if callee.is_generic():
17771781
need_refresh = any(
17781782
isinstance(v, (ParamSpecType, TypeVarTupleType)) for v in callee.variables
17791783
)
1780-
callee = freshen_function_type_vars(callee)
1781-
callee = self.infer_function_type_arguments_using_context(callee, context)
1782-
if need_refresh:
1783-
# Argument kinds etc. may have changed due to
1784-
# ParamSpec or TypeVarTuple variables being replaced with an arbitrary
1785-
# number of arguments; recalculate actual-to-formal map
1786-
formal_to_actual = map_actuals_to_formals(
1787-
arg_kinds,
1788-
arg_names,
1789-
callee.arg_kinds,
1790-
callee.arg_names,
1791-
lambda i: self.accept(args[i]),
1792-
)
17931784
callee = self.infer_function_type_arguments(
17941785
callee, args, arg_kinds, arg_names, formal_to_actual, need_refresh, context
17951786
)
17961787
if need_refresh:
1788+
# Argument kinds etc. may have changed due to
1789+
# ParamSpec or TypeVarTuple variables being replaced with an arbitrary
1790+
# number of arguments; recalculate actual-to-formal map
17971791
formal_to_actual = map_actuals_to_formals(
17981792
arg_kinds,
17991793
arg_names,
@@ -2258,6 +2252,11 @@ def infer_function_type_arguments_pass2(
22582252
if isinstance(arg, (NoneType, UninhabitedType)) or has_erased_component(arg):
22592253
inferred_args[i] = None
22602254
callee_type = self.apply_generic_arguments(callee_type, inferred_args, context)
2255+
2256+
if not callee_type.is_generic():
2257+
# Fast path, second pass can't give new information.
2258+
return callee_type, []
2259+
22612260
if need_refresh:
22622261
formal_to_actual = map_actuals_to_formals(
22632262
arg_kinds,
@@ -3469,7 +3468,7 @@ def visit_op_expr(self, e: OpExpr) -> Type:
34693468
# It's actually a type expression X | Y.
34703469
return self.accept(e.analyzed)
34713470
if e.op == "and" or e.op == "or":
3472-
return self.check_boolean_op(e, e)
3471+
return self.check_boolean_op(e)
34733472
if e.op == "*" and isinstance(e.left, ListExpr):
34743473
# Expressions of form [...] * e get special type inference.
34753474
return self.check_list_multiply(e)
@@ -4256,20 +4255,18 @@ def check_op(
42564255
context=context,
42574256
)
42584257

4259-
def check_boolean_op(self, e: OpExpr, context: Context) -> Type:
4258+
def check_boolean_op(self, e: OpExpr) -> Type:
42604259
"""Type check a boolean operation ('and' or 'or')."""
42614260

42624261
# A boolean operation can evaluate to either of the operands.
42634262

4264-
# We use the current type context to guide the type inference of of
4263+
# We use the current type context to guide the type inference of
42654264
# the left operand. We also use the left operand type to guide the type
42664265
# inference of the right operand so that expressions such as
42674266
# '[1] or []' are inferred correctly.
42684267
ctx = self.type_context[-1]
42694268
left_type = self.accept(e.left, ctx)
4270-
expanded_left_type = try_expanding_sum_type_to_union(
4271-
self.accept(e.left, ctx), "builtins.bool"
4272-
)
4269+
expanded_left_type = try_expanding_sum_type_to_union(left_type, "builtins.bool")
42734270

42744271
assert e.op in ("and", "or") # Checked by visit_op_expr
42754272

mypy/checkmember.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,7 @@ def expand_and_bind_callable(
956956
) -> Type:
957957
if not mx.preserve_type_var_ids:
958958
functype = freshen_all_functions_type_vars(functype)
959-
typ = get_proper_type(expand_self_type(var, functype, mx.original_type))
959+
typ = get_proper_type(expand_self_type(var, functype, mx.self_type))
960960
assert isinstance(typ, FunctionLike)
961961
if is_trivial_self:
962962
typ = bind_self_fast(typ, mx.self_type)

mypy/constraints.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1110,7 +1110,10 @@ def visit_callable_type(self, template: CallableType) -> list[Constraint]:
11101110
# like U -> U, should be Callable[..., Any], but if U is a self-type, we can
11111111
# allow it to leak, to be later bound to self. A bunch of existing code
11121112
# depends on this old behaviour.
1113-
and not any(tv.id.is_self() for tv in cactual.variables)
1113+
and not (
1114+
any(tv.id.is_self() for tv in cactual.variables)
1115+
and template.is_ellipsis_args
1116+
)
11141117
):
11151118
# If the actual callable is generic, infer constraints in the opposite
11161119
# direction, and indicate to the solver there are extra type variables

mypy/semanal_shared.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
TypeVarLikeType,
4747
TypeVarTupleType,
4848
UnpackType,
49+
flatten_nested_tuples,
4950
get_proper_type,
5051
)
5152

@@ -290,7 +291,7 @@ def calculate_tuple_fallback(typ: TupleType) -> None:
290291
fallback = typ.partial_fallback
291292
assert fallback.type.fullname == "builtins.tuple"
292293
items = []
293-
for item in typ.items:
294+
for item in flatten_nested_tuples(typ.items):
294295
# TODO: this duplicates some logic in typeops.tuple_fallback().
295296
if isinstance(item, UnpackType):
296297
unpacked_type = get_proper_type(item.type)

mypy/semanal_typeargs.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ def visit_type_alias_type(self, t: TypeAliasType) -> None:
102102
# If there was already an error for the alias itself, there is no point in checking
103103
# the expansion, most likely it will result in the same kind of error.
104104
get_proper_type(t).accept(self)
105+
if t.alias is not None:
106+
t.alias.accept(self)
105107

106108
def visit_tuple_type(self, t: TupleType) -> None:
107109
t.items = flatten_nested_tuples(t.items)
@@ -254,6 +256,10 @@ def visit_unpack_type(self, typ: UnpackType) -> None:
254256
def check_type_var_values(
255257
self, name: str, actuals: list[Type], arg_name: str, valids: list[Type], context: Context
256258
) -> bool:
259+
if self.in_type_alias_expr:
260+
# See testValidTypeAliasValues - we do not enforce typevar compatibility
261+
# at the definition site. We check instantiation validity later.
262+
return False
257263
is_error = False
258264
for actual in get_proper_types(actuals):
259265
# We skip UnboundType here, since they may appear in defn.bases,

mypy/solve.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ def solve_one(lowers: Iterable[Type], uppers: Iterable[Type]) -> Type | None:
270270
uppers = new_uppers
271271

272272
# ...unless this is the only information we have, then we just pass it on.
273+
lowers = list(lowers)
273274
if not uppers and not lowers:
274275
candidate = UninhabitedType()
275276
candidate.ambiguous = True
@@ -281,10 +282,11 @@ def solve_one(lowers: Iterable[Type], uppers: Iterable[Type]) -> Type | None:
281282
# Process each bound separately, and calculate the lower and upper
282283
# bounds based on constraints. Note that we assume that the constraint
283284
# targets do not have constraint references.
284-
if type_state.infer_unions:
285+
if type_state.infer_unions and lowers:
285286
# This deviates from the general mypy semantics because
286287
# recursive types are union-heavy in 95% of cases.
287-
bottom = UnionType.make_union(list(lowers))
288+
# Retain `None` when no bottoms were provided to avoid bogus `Never` inference.
289+
bottom = UnionType.make_union(lowers)
288290
else:
289291
# The order of lowers is non-deterministic.
290292
# We attempt to sort lowers because joins are non-associative. For instance:

test-data/unit/check-protocols.test

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4647,3 +4647,17 @@ reveal_type(t.bar) # N: Revealed type is "def () -> builtins.int"
46474647
tt: Type[P] = C
46484648
reveal_type(tt.foo) # N: Revealed type is "def (builtins.object) -> builtins.int"
46494649
reveal_type(tt.bar) # N: Revealed type is "def (builtins.object) -> builtins.int"
4650+
4651+
[case testProtocolDecoratedSelfBound]
4652+
from abc import abstractmethod
4653+
from typing import Protocol, Self
4654+
4655+
class Proto(Protocol):
4656+
@abstractmethod
4657+
def foo(self, x: Self) -> None: ...
4658+
4659+
class Impl:
4660+
def foo(self, x: Self) -> None:
4661+
pass
4662+
4663+
x: Proto = Impl()

test-data/unit/check-python310.test

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2995,3 +2995,13 @@ match value_type:
29952995
case _:
29962996
assert_never(value_type)
29972997
[builtins fixtures/tuple.pyi]
2998+
2999+
[case testAssignmentToFinalInMatchCaseNotAllowed]
3000+
from typing import Final
3001+
3002+
FOO: Final[int] = 10
3003+
3004+
val: int = 8
3005+
match val:
3006+
case FOO: # E: Cannot assign to final name "FOO"
3007+
pass

0 commit comments

Comments
 (0)