Skip to content

Commit 35d8c69

Browse files
authored
[mypyc] Report error on reserved method name (#19407)
Changed mypyc to report an error if a method of a compiled class is called `__mypyc_generator_helper__`. The name should be reserved because it might clash with an auto-generated method.
1 parent 930a379 commit 35d8c69

File tree

5 files changed

+42
-4
lines changed

5 files changed

+42
-4
lines changed

mypyc/irbuild/classdef.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
handle_non_ext_method,
6565
load_type,
6666
)
67+
from mypyc.irbuild.prepare import GENERATOR_HELPER_NAME
6768
from mypyc.irbuild.util import dataclass_type, get_func_def, is_constant, is_dataclass_decorator
6869
from mypyc.primitives.dict_ops import dict_new_op, dict_set_item_op
6970
from mypyc.primitives.generic_ops import (
@@ -135,6 +136,14 @@ def transform_class_def(builder: IRBuilder, cdef: ClassDef) -> None:
135136
cls_builder = NonExtClassBuilder(builder, cdef)
136137

137138
for stmt in cdef.defs.body:
139+
if (
140+
isinstance(stmt, (FuncDef, Decorator, OverloadedFuncDef))
141+
and stmt.name == GENERATOR_HELPER_NAME
142+
):
143+
builder.error(
144+
f'Method name "{stmt.name}" is reserved for mypyc internal use', stmt.line
145+
)
146+
138147
if isinstance(stmt, OverloadedFuncDef) and stmt.is_property:
139148
if isinstance(cls_builder, NonExtClassBuilder):
140149
# properties with both getters and setters in non_extension

mypyc/irbuild/generator.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
setup_func_for_recursive_call,
5151
)
5252
from mypyc.irbuild.nonlocalcontrol import ExceptNonlocalControl
53+
from mypyc.irbuild.prepare import GENERATOR_HELPER_NAME
5354
from mypyc.primitives.exc_ops import (
5455
error_catch_op,
5556
exc_matches_op,
@@ -236,11 +237,11 @@ def add_helper_to_generator_class(
236237
builder: IRBuilder, arg_regs: list[Register], blocks: list[BasicBlock], fn_info: FuncInfo
237238
) -> FuncDecl:
238239
"""Generates a helper method for a generator class, called by '__next__' and 'throw'."""
239-
helper_fn_decl = fn_info.generator_class.ir.method_decls["__mypyc_generator_helper__"]
240+
helper_fn_decl = fn_info.generator_class.ir.method_decls[GENERATOR_HELPER_NAME]
240241
helper_fn_ir = FuncIR(
241242
helper_fn_decl, arg_regs, blocks, fn_info.fitem.line, traceback_name=fn_info.fitem.name
242243
)
243-
fn_info.generator_class.ir.methods["__mypyc_generator_helper__"] = helper_fn_ir
244+
fn_info.generator_class.ir.methods[GENERATOR_HELPER_NAME] = helper_fn_ir
244245
builder.functions.append(helper_fn_ir)
245246
fn_info.env_class.env_user_function = helper_fn_ir
246247

mypyc/irbuild/prepare.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171
from mypyc.options import CompilerOptions
7272
from mypyc.sametype import is_same_type
7373

74+
GENERATOR_HELPER_NAME = "__mypyc_generator_helper__"
75+
7476

7577
def build_type_map(
7678
mapper: Mapper,
@@ -229,7 +231,7 @@ def create_generator_class_if_needed(
229231

230232
# The implementation of most generator functionality is behind this magic method.
231233
helper_fn_decl = FuncDecl(
232-
"__mypyc_generator_helper__", name, module_name, helper_sig, internal=True
234+
GENERATOR_HELPER_NAME, name, module_name, helper_sig, internal=True
233235
)
234236
cir.method_decls[helper_fn_decl.name] = helper_fn_decl
235237

mypyc/irbuild/statement.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
FinallyNonlocalControl,
9191
TryFinallyNonlocalControl,
9292
)
93+
from mypyc.irbuild.prepare import GENERATOR_HELPER_NAME
9394
from mypyc.irbuild.targets import (
9495
AssignmentTarget,
9596
AssignmentTargetAttr,
@@ -933,7 +934,7 @@ def emit_yield_from_or_await(
933934
to_yield_reg = Register(object_rprimitive)
934935
received_reg = Register(object_rprimitive)
935936

936-
helper_method = "__mypyc_generator_helper__"
937+
helper_method = GENERATOR_HELPER_NAME
937938
if (
938939
isinstance(val, (Call, MethodCall))
939940
and isinstance(val.type, RInstance)

mypyc/test-data/irbuild-classes.test

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,3 +1383,28 @@ class M(type): # E: Inheriting from most builtin types is unimplemented \
13831383
@mypyc_attr(native_class=True)
13841384
class A(metaclass=M): # E: Class is marked as native_class=True but it can't be a native class. Classes with a metaclass other than ABCMeta, TypingMeta or GenericMeta can't be native classes.
13851385
pass
1386+
1387+
[case testReservedName]
1388+
from typing import Any, overload
1389+
1390+
def decorator(cls):
1391+
return cls
1392+
1393+
class TestMethod:
1394+
def __mypyc_generator_helper__(self) -> None: # E: Method name "__mypyc_generator_helper__" is reserved for mypyc internal use
1395+
pass
1396+
1397+
class TestDecorator:
1398+
@decorator # E: Method name "__mypyc_generator_helper__" is reserved for mypyc internal use
1399+
def __mypyc_generator_helper__(self) -> None:
1400+
pass
1401+
1402+
class TestOverload:
1403+
@overload # E: Method name "__mypyc_generator_helper__" is reserved for mypyc internal use
1404+
def __mypyc_generator_helper__(self, x: int) -> int: ...
1405+
1406+
@overload
1407+
def __mypyc_generator_helper__(self, x: str) -> str: ...
1408+
1409+
def __mypyc_generator_helper__(self, x: Any) -> Any:
1410+
return x

0 commit comments

Comments
 (0)