Skip to content

Commit 183fc96

Browse files
authored
[mypyc] Make generated generator helper method internal (#19268)
Add a flag to FuncIR to allow functions to be marked as internal. Don't generate wrapper functions/methods that allow calls from Python for internal methods, since these are internal implementation details. This has these benefits: * Internal functions are private and don't pollute public namespaces. * Signatures of generated functions can use arbitrary C types (e.g. arbitrary pointer types), even those that can't be passed to/from Python. * We generate less C code (fewer wrapper functions).
1 parent fe91422 commit 183fc96

File tree

5 files changed

+19
-4
lines changed

5 files changed

+19
-4
lines changed

mypyc/codegen/emitclass.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,7 @@ def generate_finalize_for_class(
831831
def generate_methods_table(cl: ClassIR, name: str, emitter: Emitter) -> None:
832832
emitter.emit_line(f"static PyMethodDef {name}[] = {{")
833833
for fn in cl.methods.values():
834-
if fn.decl.is_prop_setter or fn.decl.is_prop_getter:
834+
if fn.decl.is_prop_setter or fn.decl.is_prop_getter or fn.internal:
835835
continue
836836
emitter.emit_line(f'{{"{fn.name}",')
837837
emitter.emit_line(f" (PyCFunction){PREFIX}{fn.cname(emitter.names)},")

mypyc/codegen/emitmodule.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ def generate_function_declaration(fn: FuncIR, emitter: Emitter) -> None:
455455
emitter.context.declarations[emitter.native_function_name(fn.decl)] = HeaderDeclaration(
456456
f"{native_function_header(fn.decl, emitter)};", needs_export=True
457457
)
458-
if fn.name != TOP_LEVEL_NAME:
458+
if fn.name != TOP_LEVEL_NAME and not fn.internal:
459459
if is_fastcall_supported(fn, emitter.capi_version):
460460
emitter.context.declarations[PREFIX + fn.cname(emitter.names)] = HeaderDeclaration(
461461
f"{wrapper_function_header(fn, emitter.names)};"
@@ -571,7 +571,7 @@ def generate_c_for_modules(self) -> list[tuple[str, str]]:
571571
for fn in module.functions:
572572
emitter.emit_line()
573573
generate_native_function(fn, emitter, self.source_paths[module_name], module_name)
574-
if fn.name != TOP_LEVEL_NAME:
574+
if fn.name != TOP_LEVEL_NAME and not fn.internal:
575575
emitter.emit_line()
576576
if is_fastcall_supported(fn, emitter.capi_version):
577577
generate_wrapper_function(

mypyc/codegen/emitwrapper.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ def wrapper_function_header(fn: FuncIR, names: NameGenerator) -> str:
6161
6262
See comment above for a summary of the arguments.
6363
"""
64+
assert not fn.internal
6465
return (
6566
"PyObject *{prefix}{name}("
6667
"PyObject *self, PyObject *const *args, size_t nargs, PyObject *kwnames)"

mypyc/ir/func_ir.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ def __init__(
140140
is_prop_setter: bool = False,
141141
is_prop_getter: bool = False,
142142
implicit: bool = False,
143+
internal: bool = False,
143144
) -> None:
144145
self.name = name
145146
self.class_name = class_name
@@ -160,6 +161,9 @@ def __init__(
160161
# Currently only supported for property getters/setters
161162
self.implicit = implicit
162163

164+
# If True, only direct C level calls are supported (no wrapper function)
165+
self.internal = internal
166+
163167
# This is optional because this will be set to the line number when the corresponding
164168
# FuncIR is created
165169
self._line: int | None = None
@@ -204,6 +208,7 @@ def serialize(self) -> JsonDict:
204208
"is_prop_setter": self.is_prop_setter,
205209
"is_prop_getter": self.is_prop_getter,
206210
"implicit": self.implicit,
211+
"internal": self.internal,
207212
}
208213

209214
# TODO: move this to FuncIR?
@@ -226,6 +231,7 @@ def deserialize(cls, data: JsonDict, ctx: DeserMaps) -> FuncDecl:
226231
data["is_prop_setter"],
227232
data["is_prop_getter"],
228233
data["implicit"],
234+
data["internal"],
229235
)
230236

231237

@@ -287,6 +293,10 @@ def fullname(self) -> str:
287293
def id(self) -> str:
288294
return self.decl.id
289295

296+
@property
297+
def internal(self) -> bool:
298+
return self.decl.internal
299+
290300
def cname(self, names: NameGenerator) -> str:
291301
return self.decl.cname(names)
292302

mypyc/irbuild/generator.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,11 @@ def add_helper_to_generator_class(
249249
sig.ret_type,
250250
)
251251
helper_fn_decl = FuncDecl(
252-
"__mypyc_generator_helper__", fn_info.generator_class.ir.name, builder.module_name, sig
252+
"__mypyc_generator_helper__",
253+
fn_info.generator_class.ir.name,
254+
builder.module_name,
255+
sig,
256+
internal=True,
253257
)
254258
helper_fn_ir = FuncIR(
255259
helper_fn_decl, arg_regs, blocks, fn_info.fitem.line, traceback_name=fn_info.fitem.name

0 commit comments

Comments
 (0)