Skip to content

Commit 4ea974e

Browse files
Merge branch 'master' into patch-10
2 parents 78aa363 + d69419c commit 4ea974e

26 files changed

+532
-184
lines changed

mypy/checkpattern.py

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from mypy.maptype import map_instance_to_supertype
1515
from mypy.meet import narrow_declared_type
1616
from mypy.messages import MessageBuilder
17-
from mypy.nodes import ARG_POS, Context, Expression, NameExpr, TypeAlias, TypeInfo, Var
17+
from mypy.nodes import ARG_POS, Context, Expression, NameExpr, TypeAlias, Var
1818
from mypy.options import Options
1919
from mypy.patterns import (
2020
AsPattern,
@@ -37,6 +37,7 @@
3737
)
3838
from mypy.types import (
3939
AnyType,
40+
FunctionLike,
4041
Instance,
4142
LiteralType,
4243
NoneType,
@@ -538,27 +539,20 @@ def visit_class_pattern(self, o: ClassPattern) -> PatternType:
538539
# Check class type
539540
#
540541
type_info = o.class_ref.node
541-
if type_info is None:
542-
typ: Type = AnyType(TypeOfAny.from_error)
543-
elif isinstance(type_info, TypeAlias) and not type_info.no_args:
542+
typ = self.chk.expr_checker.accept(o.class_ref)
543+
p_typ = get_proper_type(typ)
544+
if isinstance(type_info, TypeAlias) and not type_info.no_args:
544545
self.msg.fail(message_registry.CLASS_PATTERN_GENERIC_TYPE_ALIAS, o)
545546
return self.early_non_match()
546-
elif isinstance(type_info, TypeInfo):
547-
typ = fill_typevars_with_any(type_info)
548-
elif isinstance(type_info, TypeAlias):
549-
typ = type_info.target
550-
elif (
551-
isinstance(type_info, Var)
552-
and type_info.type is not None
553-
and isinstance(get_proper_type(type_info.type), AnyType)
554-
):
555-
typ = type_info.type
556-
else:
557-
if isinstance(type_info, Var) and type_info.type is not None:
558-
name = type_info.type.str_with_options(self.options)
559-
else:
560-
name = type_info.name
561-
self.msg.fail(message_registry.CLASS_PATTERN_TYPE_REQUIRED.format(name), o)
547+
elif isinstance(p_typ, FunctionLike) and p_typ.is_type_obj():
548+
typ = fill_typevars_with_any(p_typ.type_object())
549+
elif not isinstance(p_typ, AnyType):
550+
self.msg.fail(
551+
message_registry.CLASS_PATTERN_TYPE_REQUIRED.format(
552+
typ.str_with_options(self.options)
553+
),
554+
o,
555+
)
562556
return self.early_non_match()
563557

564558
new_type, rest_type = self.chk.conditional_types_with_intersection(
@@ -697,6 +691,8 @@ def should_self_match(self, typ: Type) -> bool:
697691
typ = get_proper_type(typ)
698692
if isinstance(typ, TupleType):
699693
typ = typ.partial_fallback
694+
if isinstance(typ, AnyType):
695+
return False
700696
if isinstance(typ, Instance) and typ.type.get("__match_args__") is not None:
701697
# Named tuples and other subtypes of builtins that define __match_args__
702698
# should not self match.

mypy/meet.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,9 @@ def narrow_declared_type(declared: Type, narrowed: Type) -> Type:
170170
):
171171
# We put this branch early to get T(bound=Union[A, B]) instead of
172172
# Union[T(bound=A), T(bound=B)] that will be confusing for users.
173-
return declared.copy_modified(upper_bound=original_narrowed)
173+
return declared.copy_modified(
174+
upper_bound=narrow_declared_type(declared.upper_bound, original_narrowed)
175+
)
174176
elif not is_overlapping_types(declared, narrowed, prohibit_none_typevar_overlap=True):
175177
if state.strict_optional:
176178
return UninhabitedType()

mypy/stubgenc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ def add_args(
322322
default_value = get_default_value(i, arg)
323323
if default_value is not _Missing.VALUE:
324324
if arg in annotations:
325-
argtype = annotations[arg]
325+
argtype = get_annotation(arg)
326326
else:
327327
argtype = self.get_type_annotation(default_value)
328328
if argtype == "None":

mypy/typeops.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -789,9 +789,9 @@ def false_only(t: Type) -> ProperType:
789789
if not ret_type.can_be_false:
790790
return UninhabitedType(line=t.line)
791791
elif isinstance(t, Instance):
792-
if t.type.is_final or t.type.is_enum:
792+
if (t.type.is_final or t.type.is_enum) and state.strict_optional:
793793
return UninhabitedType(line=t.line)
794-
elif isinstance(t, LiteralType) and t.is_enum_literal():
794+
elif isinstance(t, LiteralType) and t.is_enum_literal() and state.strict_optional:
795795
return UninhabitedType(line=t.line)
796796

797797
new_t = copy_type(t)

mypyc/codegen/emitclass.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ def setter_name(cl: ClassIR, attribute: str, names: NameGenerator) -> str:
410410

411411

412412
def generate_object_struct(cl: ClassIR, emitter: Emitter) -> None:
413-
seen_attrs: set[tuple[str, RType]] = set()
413+
seen_attrs: set[str] = set()
414414
lines: list[str] = []
415415
lines += ["typedef struct {", "PyObject_HEAD", "CPyVTableItem *vtable;"]
416416
if cl.has_method("__call__"):
@@ -427,9 +427,11 @@ def generate_object_struct(cl: ClassIR, emitter: Emitter) -> None:
427427
lines.append(f"{BITMAP_TYPE} {attr};")
428428
bitmap_attrs.append(attr)
429429
for attr, rtype in base.attributes.items():
430-
if (attr, rtype) not in seen_attrs:
430+
# Generated class may redefine certain attributes with different
431+
# types in subclasses (this would be unsafe for user-defined classes).
432+
if attr not in seen_attrs:
431433
lines.append(f"{emitter.ctype_spaced(rtype)}{emitter.attr(attr)};")
432-
seen_attrs.add((attr, rtype))
434+
seen_attrs.add(attr)
433435

434436
if isinstance(rtype, RTuple):
435437
emitter.declare_tuple_struct(rtype)

mypyc/codegen/emitmodule.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,8 @@ def emit_module_exec_func(
10641064
"(PyObject *){t}_template, NULL, modname);".format(t=type_struct)
10651065
)
10661066
emitter.emit_lines(f"if (unlikely(!{type_struct}))", " goto fail;")
1067+
name_prefix = cl.name_prefix(emitter.names)
1068+
emitter.emit_line(f"CPyDef_{name_prefix}_trait_vtable_setup();")
10671069

10681070
emitter.emit_lines("if (CPyGlobalsInit() < 0)", " goto fail;")
10691071

mypyc/ir/func_ir.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,11 @@ def __init__(
149149
module_name: str,
150150
sig: FuncSignature,
151151
kind: int = FUNC_NORMAL,
152+
*,
152153
is_prop_setter: bool = False,
153154
is_prop_getter: bool = False,
155+
is_generator: bool = False,
156+
is_coroutine: bool = False,
154157
implicit: bool = False,
155158
internal: bool = False,
156159
) -> None:
@@ -161,6 +164,8 @@ def __init__(
161164
self.kind = kind
162165
self.is_prop_setter = is_prop_setter
163166
self.is_prop_getter = is_prop_getter
167+
self.is_generator = is_generator
168+
self.is_coroutine = is_coroutine
164169
if class_name is None:
165170
self.bound_sig: FuncSignature | None = None
166171
else:
@@ -219,6 +224,8 @@ def serialize(self) -> JsonDict:
219224
"kind": self.kind,
220225
"is_prop_setter": self.is_prop_setter,
221226
"is_prop_getter": self.is_prop_getter,
227+
"is_generator": self.is_generator,
228+
"is_coroutine": self.is_coroutine,
222229
"implicit": self.implicit,
223230
"internal": self.internal,
224231
}
@@ -240,10 +247,12 @@ def deserialize(cls, data: JsonDict, ctx: DeserMaps) -> FuncDecl:
240247
data["module_name"],
241248
FuncSignature.deserialize(data["sig"], ctx),
242249
data["kind"],
243-
data["is_prop_setter"],
244-
data["is_prop_getter"],
245-
data["implicit"],
246-
data["internal"],
250+
is_prop_setter=data["is_prop_setter"],
251+
is_prop_getter=data["is_prop_getter"],
252+
is_generator=data["is_generator"],
253+
is_coroutine=data["is_coroutine"],
254+
implicit=data["implicit"],
255+
internal=data["internal"],
247256
)
248257

249258

mypyc/irbuild/context.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,11 @@ def curr_env_reg(self) -> Value:
9898
def can_merge_generator_and_env_classes(self) -> bool:
9999
# In simple cases we can place the environment into the generator class,
100100
# instead of having two separate classes.
101-
return self.is_generator and not self.is_nested and not self.contains_nested
101+
if self._generator_class and not self._generator_class.ir.is_final_class:
102+
result = False
103+
else:
104+
result = self.is_generator and not self.is_nested and not self.contains_nested
105+
return result
102106

103107

104108
class ImplicitClass:

mypyc/irbuild/for_helpers.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,18 +1204,18 @@ def gen_cleanup(self) -> None:
12041204
gen.gen_cleanup()
12051205

12061206

1207-
def get_expr_length(expr: Expression) -> int | None:
1207+
def get_expr_length(builder: IRBuilder, expr: Expression) -> int | None:
12081208
if isinstance(expr, (StrExpr, BytesExpr)):
12091209
return len(expr.value)
12101210
elif isinstance(expr, (ListExpr, TupleExpr)):
12111211
# if there are no star expressions, or we know the length of them,
12121212
# we know the length of the expression
1213-
stars = [get_expr_length(i) for i in expr.items if isinstance(i, StarExpr)]
1213+
stars = [get_expr_length(builder, i) for i in expr.items if isinstance(i, StarExpr)]
12141214
if None not in stars:
12151215
other = sum(not isinstance(i, StarExpr) for i in expr.items)
12161216
return other + sum(stars) # type: ignore [arg-type]
12171217
elif isinstance(expr, StarExpr):
1218-
return get_expr_length(expr.expr)
1218+
return get_expr_length(builder, expr.expr)
12191219
elif (
12201220
isinstance(expr, RefExpr)
12211221
and isinstance(expr.node, Var)
@@ -1237,6 +1237,11 @@ def get_expr_length(expr: Expression) -> int | None:
12371237
# TODO: extend this, set and dict comps can be done as well but will
12381238
# need special logic to consider the possibility of key conflicts.
12391239
# Range, enumerate, zip are all simple logic.
1240+
1241+
# we might still be able to get the length directly from the type
1242+
rtype = builder.node_type(expr)
1243+
if isinstance(rtype, RTuple):
1244+
return len(rtype.types)
12401245
return None
12411246

12421247

@@ -1245,7 +1250,7 @@ def get_expr_length_value(
12451250
) -> Value:
12461251
rtype = builder.node_type(expr)
12471252
assert is_sequence_rprimitive(rtype) or isinstance(rtype, RTuple), rtype
1248-
length = get_expr_length(expr)
1253+
length = get_expr_length(builder, expr)
12491254
if length is None:
12501255
# We cannot compute the length at compile time, so we will fetch it.
12511256
return builder.builder.builtin_len(expr_reg, line, use_pyssize_t=use_pyssize_t)

mypyc/irbuild/function.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
instantiate_callable_class,
7070
setup_callable_class,
7171
)
72-
from mypyc.irbuild.context import FuncInfo
72+
from mypyc.irbuild.context import FuncInfo, GeneratorClass
7373
from mypyc.irbuild.env_class import (
7474
add_vars_to_env,
7575
finalize_env_class,
@@ -246,6 +246,12 @@ def c() -> None:
246246
is_generator = fn_info.is_generator
247247
builder.enter(fn_info, ret_type=sig.ret_type)
248248

249+
if is_generator:
250+
fitem = builder.fn_info.fitem
251+
assert isinstance(fitem, FuncDef), fitem
252+
generator_class_ir = builder.mapper.fdef_to_generator[fitem]
253+
builder.fn_info.generator_class = GeneratorClass(generator_class_ir)
254+
249255
# Functions that contain nested functions need an environment class to store variables that
250256
# are free in their nested functions. Generator functions need an environment class to
251257
# store a variable denoting the next instruction to be executed when the __next__ function
@@ -357,8 +363,8 @@ def gen_func_ir(
357363
builder.module_name,
358364
sig,
359365
func_decl.kind,
360-
func_decl.is_prop_getter,
361-
func_decl.is_prop_setter,
366+
is_prop_getter=func_decl.is_prop_getter,
367+
is_prop_setter=func_decl.is_prop_setter,
362368
)
363369
func_ir = FuncIR(func_decl, args, blocks, fitem.line, traceback_name=fitem.name)
364370
else:

0 commit comments

Comments
 (0)