55from collections .abc import Mapping
66from typing import Callable
77
8+ from mypy .nodes import ARG_STAR , ARG_STAR2
89from mypyc .codegen .cstring import c_string_initializer
910from mypyc .codegen .emit import Emitter , HeaderDeclaration , ReturnHandler
1011from mypyc .codegen .emitfunc import native_function_doc_initializer , native_function_header
@@ -224,7 +225,7 @@ def generate_class(cl: ClassIR, module: str, emitter: Emitter) -> None:
224225 name = cl .name
225226 name_prefix = cl .name_prefix (emitter .names )
226227
227- setup_name = f" { name_prefix } _setup"
228+ setup_name = emitter . native_function_name ( cl . setup )
228229 new_name = f"{ name_prefix } _new"
229230 finalize_name = f"{ name_prefix } _finalize"
230231 members_name = f"{ name_prefix } _members"
@@ -317,10 +318,8 @@ def emit_line() -> None:
317318 fields ["tp_basicsize" ] = base_size
318319
319320 if generate_full :
320- # Declare setup method that allocates and initializes an object. type is the
321- # type of the class being initialized, which could be another class if there
322- # is an interpreted subclass.
323- emitter .emit_line (f"static PyObject *{ setup_name } (PyTypeObject *type);" )
321+ assert cl .setup is not None
322+ emitter .emit_line (native_function_header (cl .setup , emitter ) + ";" )
324323 assert cl .ctor is not None
325324 emitter .emit_line (native_function_header (cl .ctor , emitter ) + ";" )
326325
@@ -390,9 +389,7 @@ def emit_line() -> None:
390389
391390 emitter .emit_line ()
392391 if generate_full :
393- generate_setup_for_class (
394- cl , setup_name , defaults_fn , vtable_name , shadow_vtable_name , emitter
395- )
392+ generate_setup_for_class (cl , defaults_fn , vtable_name , shadow_vtable_name , emitter )
396393 emitter .emit_line ()
397394 generate_constructor_for_class (cl , cl .ctor , init_fn , setup_name , vtable_name , emitter )
398395 emitter .emit_line ()
@@ -579,16 +576,16 @@ def generate_vtable(
579576
580577def generate_setup_for_class (
581578 cl : ClassIR ,
582- func_name : str ,
583579 defaults_fn : FuncIR | None ,
584580 vtable_name : str ,
585581 shadow_vtable_name : str | None ,
586582 emitter : Emitter ,
587583) -> None :
588584 """Generate a native function that allocates an instance of a class."""
589- emitter .emit_line ("static PyObject *" )
590- emitter .emit_line (f"{ func_name } (PyTypeObject *type)" )
585+ emitter .emit_line (native_function_header (cl .setup , emitter ))
591586 emitter .emit_line ("{" )
587+ type_arg_name = REG_PREFIX + cl .setup .sig .args [0 ].name
588+ emitter .emit_line (f"PyTypeObject *type = (PyTypeObject*){ type_arg_name } ;" )
592589 struct_name = cl .struct_name (emitter .names )
593590 emitter .emit_line (f"{ struct_name } *self;" )
594591
@@ -663,6 +660,33 @@ def emit_attr_defaults_func_call(defaults_fn: FuncIR, self_name: str, emitter: E
663660 )
664661
665662
663+ def emit_setup_or_dunder_new_call (
664+ cl : ClassIR ,
665+ setup_name : str ,
666+ type_arg : str ,
667+ native_prefix : bool ,
668+ new_args : str ,
669+ emitter : Emitter ,
670+ ) -> None :
671+ def emit_null_check () -> None :
672+ emitter .emit_line ("if (self == NULL)" )
673+ emitter .emit_line (" return NULL;" )
674+
675+ new_fn = cl .get_method ("__new__" )
676+ if not new_fn :
677+ emitter .emit_line (f"PyObject *self = { setup_name } ({ type_arg } );" )
678+ emit_null_check ()
679+ return
680+ prefix = emitter .get_group_prefix (new_fn .decl ) + NATIVE_PREFIX if native_prefix else PREFIX
681+ new_args = ", " .join ([type_arg , new_args ])
682+ emitter .emit_line (f"PyObject *self = { prefix } { new_fn .cname (emitter .names )} ({ new_args } );" )
683+ emit_null_check ()
684+
685+ # skip __init__ if __new__ returns some other type
686+ emitter .emit_line (f"if (Py_TYPE(self) != { emitter .type_struct_name (cl )} )" )
687+ emitter .emit_line (" return self;" )
688+
689+
666690def generate_constructor_for_class (
667691 cl : ClassIR ,
668692 fn : FuncDecl ,
@@ -674,17 +698,30 @@ def generate_constructor_for_class(
674698 """Generate a native function that allocates and initializes an instance of a class."""
675699 emitter .emit_line (f"{ native_function_header (fn , emitter )} " )
676700 emitter .emit_line ("{" )
677- emitter .emit_line (f"PyObject *self = { setup_name } ({ emitter .type_struct_name (cl )} );" )
678- emitter .emit_line ("if (self == NULL)" )
679- emitter .emit_line (" return NULL;" )
680- args = ", " .join (["self" ] + [REG_PREFIX + arg .name for arg in fn .sig .args ])
701+
702+ fn_args = [REG_PREFIX + arg .name for arg in fn .sig .args ]
703+ type_arg = "(PyObject *)" + emitter .type_struct_name (cl )
704+ new_args = ", " .join (fn_args )
705+
706+ use_wrapper = (
707+ cl .has_method ("__new__" )
708+ and len (fn .sig .args ) == 2
709+ and fn .sig .args [0 ].kind == ARG_STAR
710+ and fn .sig .args [1 ].kind == ARG_STAR2
711+ )
712+ emit_setup_or_dunder_new_call (cl , setup_name , type_arg , not use_wrapper , new_args , emitter )
713+
714+ args = ", " .join (["self" ] + fn_args )
681715 if init_fn is not None :
716+ prefix = PREFIX if use_wrapper else NATIVE_PREFIX
717+ cast = "!= NULL ? 0 : -1" if use_wrapper else ""
682718 emitter .emit_line (
683- "char res = {}{}{}({});" .format (
719+ "char res = {}{}{}({}){} ;" .format (
684720 emitter .get_group_prefix (init_fn .decl ),
685- NATIVE_PREFIX ,
721+ prefix ,
686722 init_fn .cname (emitter .names ),
687723 args ,
724+ cast ,
688725 )
689726 )
690727 emitter .emit_line ("if (res == 2) {" )
@@ -717,7 +754,7 @@ def generate_init_for_class(cl: ClassIR, init_fn: FuncIR, emitter: Emitter) -> s
717754 emitter .emit_line ("static int" )
718755 emitter .emit_line (f"{ func_name } (PyObject *self, PyObject *args, PyObject *kwds)" )
719756 emitter .emit_line ("{" )
720- if cl .allow_interpreted_subclasses or cl .builtin_base :
757+ if cl .allow_interpreted_subclasses or cl .builtin_base or cl . has_method ( "__new__" ) :
721758 emitter .emit_line (
722759 "return {}{}(self, args, kwds) != NULL ? 0 : -1;" .format (
723760 PREFIX , init_fn .cname (emitter .names )
@@ -750,15 +787,22 @@ def generate_new_for_class(
750787 emitter .emit_line ("return NULL;" )
751788 emitter .emit_line ("}" )
752789
753- if not init_fn or cl .allow_interpreted_subclasses or cl .builtin_base or cl .is_serializable ():
790+ type_arg = "(PyObject*)type"
791+ new_args = "args, kwds"
792+ emit_setup_or_dunder_new_call (cl , setup_name , type_arg , False , new_args , emitter )
793+ if (
794+ not init_fn
795+ or cl .allow_interpreted_subclasses
796+ or cl .builtin_base
797+ or cl .is_serializable ()
798+ or cl .has_method ("__new__" )
799+ ):
754800 # Match Python semantics -- __new__ doesn't call __init__.
755- emitter .emit_line (f "return { setup_name } (type) ;" )
801+ emitter .emit_line ("return self ;" )
756802 else :
757803 # __new__ of a native class implicitly calls __init__ so that we
758804 # can enforce that instances are always properly initialized. This
759805 # is needed to support always defined attributes.
760- emitter .emit_line (f"PyObject *self = { setup_name } (type);" )
761- emitter .emit_lines ("if (self == NULL)" , " return NULL;" )
762806 emitter .emit_line (
763807 f"PyObject *ret = { PREFIX } { init_fn .cname (emitter .names )} (self, args, kwds);"
764808 )
0 commit comments