Skip to content

[mypyc] Report error on reserved method name #19407

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions mypyc/irbuild/classdef.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
handle_non_ext_method,
load_type,
)
from mypyc.irbuild.prepare import GENERATOR_HELPER_NAME
from mypyc.irbuild.util import dataclass_type, get_func_def, is_constant, is_dataclass_decorator
from mypyc.primitives.dict_ops import dict_new_op, dict_set_item_op
from mypyc.primitives.generic_ops import (
Expand Down Expand Up @@ -135,6 +136,14 @@ def transform_class_def(builder: IRBuilder, cdef: ClassDef) -> None:
cls_builder = NonExtClassBuilder(builder, cdef)

for stmt in cdef.defs.body:
if (
isinstance(stmt, (FuncDef, Decorator, OverloadedFuncDef))
and stmt.name == GENERATOR_HELPER_NAME
):
builder.error(
f'Method name "{stmt.name}" is reserved for mypyc internal use', stmt.line
)

if isinstance(stmt, OverloadedFuncDef) and stmt.is_property:
if isinstance(cls_builder, NonExtClassBuilder):
# properties with both getters and setters in non_extension
Expand Down
5 changes: 3 additions & 2 deletions mypyc/irbuild/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
setup_func_for_recursive_call,
)
from mypyc.irbuild.nonlocalcontrol import ExceptNonlocalControl
from mypyc.irbuild.prepare import GENERATOR_HELPER_NAME
from mypyc.primitives.exc_ops import (
error_catch_op,
exc_matches_op,
Expand Down Expand Up @@ -231,11 +232,11 @@ def add_helper_to_generator_class(
builder: IRBuilder, arg_regs: list[Register], blocks: list[BasicBlock], fn_info: FuncInfo
) -> FuncDecl:
"""Generates a helper method for a generator class, called by '__next__' and 'throw'."""
helper_fn_decl = fn_info.generator_class.ir.method_decls["__mypyc_generator_helper__"]
helper_fn_decl = fn_info.generator_class.ir.method_decls[GENERATOR_HELPER_NAME]
helper_fn_ir = FuncIR(
helper_fn_decl, arg_regs, blocks, fn_info.fitem.line, traceback_name=fn_info.fitem.name
)
fn_info.generator_class.ir.methods["__mypyc_generator_helper__"] = helper_fn_ir
fn_info.generator_class.ir.methods[GENERATOR_HELPER_NAME] = helper_fn_ir
builder.functions.append(helper_fn_ir)
fn_info.env_class.env_user_function = helper_fn_ir

Expand Down
4 changes: 3 additions & 1 deletion mypyc/irbuild/prepare.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@
from mypyc.options import CompilerOptions
from mypyc.sametype import is_same_type

GENERATOR_HELPER_NAME = "__mypyc_generator_helper__"


def build_type_map(
mapper: Mapper,
Expand Down Expand Up @@ -226,7 +228,7 @@ def create_generator_class_if_needed(

# The implementation of most generator functionality is behind this magic method.
helper_fn_decl = FuncDecl(
"__mypyc_generator_helper__", name, module_name, helper_sig, internal=True
GENERATOR_HELPER_NAME, name, module_name, helper_sig, internal=True
)
cir.method_decls[helper_fn_decl.name] = helper_fn_decl

Expand Down
3 changes: 2 additions & 1 deletion mypyc/irbuild/statement.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
FinallyNonlocalControl,
TryFinallyNonlocalControl,
)
from mypyc.irbuild.prepare import GENERATOR_HELPER_NAME
from mypyc.irbuild.targets import (
AssignmentTarget,
AssignmentTargetAttr,
Expand Down Expand Up @@ -932,7 +933,7 @@ def emit_yield_from_or_await(
to_yield_reg = Register(object_rprimitive)
received_reg = Register(object_rprimitive)

helper_method = "__mypyc_generator_helper__"
helper_method = GENERATOR_HELPER_NAME
if (
isinstance(val, (Call, MethodCall))
and isinstance(val.type, RInstance)
Expand Down
25 changes: 25 additions & 0 deletions mypyc/test-data/irbuild-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -1383,3 +1383,28 @@ class M(type): # E: Inheriting from most builtin types is unimplemented \
@mypyc_attr(native_class=True)
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.
pass

[case testReservedName]
from typing import Any, overload

def decorator(cls):
return cls

class TestMethod:
def __mypyc_generator_helper__(self) -> None: # E: Method name "__mypyc_generator_helper__" is reserved for mypyc internal use
pass

class TestDecorator:
@decorator # E: Method name "__mypyc_generator_helper__" is reserved for mypyc internal use
def __mypyc_generator_helper__(self) -> None:
pass

class TestOverload:
@overload # E: Method name "__mypyc_generator_helper__" is reserved for mypyc internal use
def __mypyc_generator_helper__(self, x: int) -> int: ...

@overload
def __mypyc_generator_helper__(self, x: str) -> str: ...

def __mypyc_generator_helper__(self, x: Any) -> Any:
return x