Skip to content

Commit d42b363

Browse files
Merge branch 'master' into patch-11
2 parents c8d6cde + 6aa44da commit d42b363

22 files changed

+268
-152
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ repos:
4141
# actionlint has a shellcheck integration which extracts shell scripts in `run:` steps from GitHub Actions
4242
# and checks these with shellcheck. This is arguably its most useful feature,
4343
# but the integration only works if shellcheck is installed
44-
- "github.com/wasilibs/go-shellcheck/cmd/shellcheck@v0.10.0"
44+
- "github.com/wasilibs/go-shellcheck/cmd/shellcheck@v0.11.0"
4545
- repo: https://github.com/woodruffw/zizmor-pre-commit
4646
rev: v1.5.2
4747
hooks:

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/errors.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -806,8 +806,8 @@ def generate_unused_ignore_errors(self, file: str) -> None:
806806
continue
807807
if codes.UNUSED_IGNORE.code in ignored_codes:
808808
continue
809-
used_ignored_codes = used_ignored_lines[line]
810-
unused_ignored_codes = set(ignored_codes) - set(used_ignored_codes)
809+
used_ignored_codes = set(used_ignored_lines[line])
810+
unused_ignored_codes = [c for c in ignored_codes if c not in used_ignored_codes]
811811
# `ignore` is used
812812
if not ignored_codes and used_ignored_codes:
813813
continue
@@ -817,7 +817,7 @@ def generate_unused_ignore_errors(self, file: str) -> None:
817817
# Display detail only when `ignore[...]` specifies more than one error code
818818
unused_codes_message = ""
819819
if len(ignored_codes) > 1 and unused_ignored_codes:
820-
unused_codes_message = f"[{', '.join(sorted(unused_ignored_codes))}]"
820+
unused_codes_message = f"[{', '.join(unused_ignored_codes)}]"
821821
message = f'Unused "type: ignore{unused_codes_message}" comment'
822822
for unused in unused_ignored_codes:
823823
narrower = set(used_ignored_codes) & codes.sub_code_map[unused]

mypy/fastparse.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,8 @@ def parse(
233233
feature_version = options.python_version[1]
234234
try:
235235
# Disable
236-
# - deprecation warnings about \u
237-
# - syntax warnings for 'invalid escape sequence' (3.12+) and 'return in finally' (3.14+)
236+
# - deprecation warnings for 'invalid escape sequence' (Python 3.11 and below)
237+
# - syntax warnings for 'invalid escape sequence' (3.12+) and 'return in finally' (3.14+)
238238
with warnings.catch_warnings():
239239
warnings.filterwarnings("ignore", category=DeprecationWarning)
240240
warnings.filterwarnings("ignore", category=SyntaxWarning)

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/semanal.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1791,11 +1791,10 @@ def push_type_args(
17911791
return None
17921792
tvs.append((p.name, tv))
17931793

1794-
for name, tv in tvs:
1795-
if self.is_defined_type_param(name):
1796-
self.fail(f'"{name}" already defined as a type parameter', context)
1794+
if self.is_defined_type_param(p.name):
1795+
self.fail(f'"{p.name}" already defined as a type parameter', context)
17971796
else:
1798-
self.add_symbol(name, tv, context, no_progress=True, type_param=True)
1797+
self.add_symbol(p.name, tv, context, no_progress=True, type_param=True)
17991798

18001799
return tvs
18011800

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/irbuild/expression.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -590,8 +590,12 @@ def transform_index_expr(builder: IRBuilder, expr: IndexExpr) -> Value:
590590

591591
base = builder.accept(expr.base, can_borrow=can_borrow_base)
592592

593-
if isinstance(base.type, RTuple) and isinstance(index, IntExpr):
594-
return builder.add(TupleGet(base, index.value, expr.line))
593+
if isinstance(base.type, RTuple):
594+
folded_index = constant_fold_expr(builder, index)
595+
if isinstance(folded_index, int):
596+
length = len(base.type.types)
597+
if -length <= folded_index <= length - 1:
598+
return builder.add(TupleGet(base, folded_index, expr.line))
595599

596600
if isinstance(index, SliceExpr):
597601
value = try_gen_slice_op(builder, base, index)

mypyc/irbuild/main.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ def f(x: int) -> int:
3838
from mypyc.irbuild.mapper import Mapper
3939
from mypyc.irbuild.prebuildvisitor import PreBuildVisitor
4040
from mypyc.irbuild.prepare import (
41+
adjust_generator_classes_of_methods,
4142
build_type_map,
42-
create_generator_class_if_needed,
43+
create_generator_class_for_func,
4344
find_singledispatch_register_impls,
4445
)
4546
from mypyc.irbuild.visitor import IRBuilderVisitor
@@ -68,6 +69,7 @@ def build_ir(
6869
"""
6970

7071
build_type_map(mapper, modules, graph, types, options, errors)
72+
adjust_generator_classes_of_methods(mapper)
7173
singledispatch_info = find_singledispatch_register_impls(modules, errors)
7274

7375
result: ModuleIRs = {}
@@ -87,9 +89,10 @@ def build_ir(
8789
if isinstance(fdef, FuncDef):
8890
# Make generator class name sufficiently unique.
8991
suffix = f"___{fdef.line}"
90-
create_generator_class_if_needed(
91-
module.fullname, None, fdef, mapper, name_suffix=suffix
92-
)
92+
if fdef.is_coroutine or fdef.is_generator:
93+
create_generator_class_for_func(
94+
module.fullname, None, fdef, mapper, name_suffix=suffix
95+
)
9396

9497
# Construct and configure builder objects (cyclic runtime dependency).
9598
visitor = IRBuilderVisitor()

0 commit comments

Comments
 (0)