Skip to content

Commit 44438a5

Browse files
Merge branch 'master' into special_case_typeddict_get
2 parents 46fe2a4 + ac646c0 commit 44438a5

35 files changed

+1380
-181
lines changed

mypy/checker.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5502,7 +5502,7 @@ def visit_with_stmt(self, s: WithStmt) -> None:
55025502
self.accept(s.body)
55035503

55045504
def check_untyped_after_decorator(self, typ: Type, func: FuncDef) -> None:
5505-
if not self.options.disallow_any_decorated or self.is_stub:
5505+
if not self.options.disallow_any_decorated or self.is_stub or self.current_node_deferred:
55065506
return
55075507

55085508
if mypy.checkexpr.has_any_type(typ):

mypy/messages.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2432,13 +2432,13 @@ def format_long_tuple_type(self, typ: TupleType) -> str:
24322432
"""Format very long tuple type using an ellipsis notation"""
24332433
item_cnt = len(typ.items)
24342434
if item_cnt > MAX_TUPLE_ITEMS:
2435-
return "tuple[{}, {}, ... <{} more items>]".format(
2435+
return '"tuple[{}, {}, ... <{} more items>]"'.format(
24362436
format_type_bare(typ.items[0], self.options),
24372437
format_type_bare(typ.items[1], self.options),
24382438
str(item_cnt - 2),
24392439
)
24402440
else:
2441-
return format_type_bare(typ, self.options)
2441+
return format_type(typ, self.options)
24422442

24432443
def generate_incompatible_tuple_error(
24442444
self,
@@ -2517,15 +2517,12 @@ def iteration_dependent_errors(self, iter_errors: IterationDependentErrors) -> N
25172517

25182518
def quote_type_string(type_string: str) -> str:
25192519
"""Quotes a type representation for use in messages."""
2520-
no_quote_regex = r"^<(tuple|union): \d+ items>$"
25212520
if (
25222521
type_string in ["Module", "overloaded function", "<deleted>"]
25232522
or type_string.startswith("Module ")
2524-
or re.match(no_quote_regex, type_string) is not None
25252523
or type_string.endswith("?")
25262524
):
2527-
# Messages are easier to read if these aren't quoted. We use a
2528-
# regex to match strings with variable contents.
2525+
# These messages are easier to read if these aren't quoted.
25292526
return type_string
25302527
return f'"{type_string}"'
25312528

mypy/semanal.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5332,13 +5332,15 @@ def visit_expression_stmt(self, s: ExpressionStmt) -> None:
53325332
s.expr.accept(self)
53335333

53345334
def visit_return_stmt(self, s: ReturnStmt) -> None:
5335+
old = self.statement
53355336
self.statement = s
53365337
if not self.is_func_scope():
53375338
self.fail('"return" outside function', s)
53385339
if self.return_stmt_inside_except_star_block:
53395340
self.fail('"return" not allowed in except* block', s, serious=True)
53405341
if s.expr:
53415342
s.expr.accept(self)
5343+
self.statement = old
53425344

53435345
def visit_raise_stmt(self, s: RaiseStmt) -> None:
53445346
self.statement = s

mypy/test/testsolve.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,14 @@ def test_multiple_variables(self) -> None:
6464
)
6565

6666
def test_no_constraints_for_var(self) -> None:
67-
self.assert_solve([self.fx.t], [], [self.fx.uninhabited])
68-
self.assert_solve([self.fx.t, self.fx.s], [], [self.fx.uninhabited, self.fx.uninhabited])
67+
self.assert_solve([self.fx.t], [], [self.fx.a_uninhabited])
68+
self.assert_solve(
69+
[self.fx.t, self.fx.s], [], [self.fx.a_uninhabited, self.fx.a_uninhabited]
70+
)
6971
self.assert_solve(
7072
[self.fx.t, self.fx.s],
7173
[self.supc(self.fx.s, self.fx.a)],
72-
[self.fx.uninhabited, self.fx.a],
74+
[self.fx.a_uninhabited, self.fx.a],
7375
)
7476

7577
def test_simple_constraints_with_dynamic_type(self) -> None:
@@ -116,7 +118,7 @@ def test_poly_no_constraints(self) -> None:
116118
self.assert_solve(
117119
[self.fx.t, self.fx.u],
118120
[],
119-
[self.fx.uninhabited, self.fx.uninhabited],
121+
[self.fx.a_uninhabited, self.fx.a_uninhabited],
120122
allow_polymorphic=True,
121123
)
122124

@@ -152,7 +154,7 @@ def test_poly_free_pair_with_bounds_uninhabited(self) -> None:
152154
self.assert_solve(
153155
[self.fx.ub, self.fx.uc],
154156
[self.subc(self.fx.ub, self.fx.uc)],
155-
[self.fx.uninhabited, self.fx.uninhabited],
157+
[self.fx.a_uninhabited, self.fx.a_uninhabited],
156158
[],
157159
allow_polymorphic=True,
158160
)

mypy/test/typefixture.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ def make_type_var(
7878
self.anyt = AnyType(TypeOfAny.special_form)
7979
self.nonet = NoneType()
8080
self.uninhabited = UninhabitedType()
81+
self.a_uninhabited = UninhabitedType()
82+
self.a_uninhabited.ambiguous = True
8183

8284
# Abstract class TypeInfos
8385

mypy/types.py

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,7 @@
55
import sys
66
from abc import abstractmethod
77
from collections.abc import Iterable, Sequence
8-
from typing import (
9-
TYPE_CHECKING,
10-
Any,
11-
ClassVar,
12-
Final,
13-
NamedTuple,
14-
NewType,
15-
TypeVar,
16-
Union,
17-
cast,
18-
overload,
19-
)
8+
from typing import TYPE_CHECKING, Any, ClassVar, Final, NewType, TypeVar, Union, cast, overload
209
from typing_extensions import Self, TypeAlias as _TypeAlias, TypeGuard
2110

2211
import mypy.nodes
@@ -1247,10 +1236,10 @@ def accept(self, visitor: TypeVisitor[T]) -> T:
12471236
return visitor.visit_uninhabited_type(self)
12481237

12491238
def __hash__(self) -> int:
1250-
return hash(UninhabitedType)
1239+
return hash((UninhabitedType, self.ambiguous))
12511240

12521241
def __eq__(self, other: object) -> bool:
1253-
return isinstance(other, UninhabitedType)
1242+
return isinstance(other, UninhabitedType) and other.ambiguous == self.ambiguous
12541243

12551244
def serialize(self) -> JsonDict:
12561245
return {".class": "UninhabitedType"}
@@ -1607,11 +1596,25 @@ def bound(self) -> bool:
16071596
return bool(self.items) and self.items[0].is_bound
16081597

16091598

1610-
class FormalArgument(NamedTuple):
1611-
name: str | None
1612-
pos: int | None
1613-
typ: Type
1614-
required: bool
1599+
class FormalArgument:
1600+
def __init__(self, name: str | None, pos: int | None, typ: Type, required: bool) -> None:
1601+
self.name = name
1602+
self.pos = pos
1603+
self.typ = typ
1604+
self.required = required
1605+
1606+
def __eq__(self, other: object) -> bool:
1607+
if not isinstance(other, FormalArgument):
1608+
return NotImplemented
1609+
return (
1610+
self.name == other.name
1611+
and self.pos == other.pos
1612+
and self.typ == other.typ
1613+
and self.required == other.required
1614+
)
1615+
1616+
def __hash__(self) -> int:
1617+
return hash((self.name, self.pos, self.typ, self.required))
16151618

16161619

16171620
class Parameters(ProperType):

mypyc/common.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
MODULE_PREFIX: Final = "CPyModule_" # Cached modules
1616
TYPE_VAR_PREFIX: Final = "CPyTypeVar_" # Type variables when using new-style Python 3.12 syntax
1717
ATTR_PREFIX: Final = "_" # Attributes
18+
FAST_PREFIX: Final = "__mypyc_fast_" # Optimized methods in non-extension classes
1819

1920
ENV_ATTR_NAME: Final = "__mypyc_env__"
2021
NEXT_LABEL_ATTR_NAME: Final = "__mypyc_next_label__"

mypyc/ir/class_ir.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,9 @@ def __init__(
210210
# per-type free "list" of up to length 1.
211211
self.reuse_freed_instance = False
212212

213+
# Is this a class inheriting from enum.Enum? Such classes can be special-cased.
214+
self.is_enum = False
215+
213216
def __repr__(self) -> str:
214217
return (
215218
"ClassIR("
@@ -410,6 +413,7 @@ def serialize(self) -> JsonDict:
410413
"init_self_leak": self.init_self_leak,
411414
"env_user_function": self.env_user_function.id if self.env_user_function else None,
412415
"reuse_freed_instance": self.reuse_freed_instance,
416+
"is_enum": self.is_enum,
413417
}
414418

415419
@classmethod
@@ -466,6 +470,7 @@ def deserialize(cls, data: JsonDict, ctx: DeserMaps) -> ClassIR:
466470
ctx.functions[data["env_user_function"]] if data["env_user_function"] else None
467471
)
468472
ir.reuse_freed_instance = data["reuse_freed_instance"]
473+
ir.is_enum = data["is_enum"]
469474

470475
return ir
471476

0 commit comments

Comments
 (0)