8989from mypyc .primitives .generic_ops import py_setattr_op
9090from mypyc .primitives .misc_ops import register_function
9191from mypyc .primitives .registry import builtin_names
92- from mypyc .sametype import is_same_method_signature
92+ from mypyc .sametype import is_same_method_signature , is_same_type
9393
9494# Top-level transform functions
9595
@@ -548,7 +548,7 @@ def is_decorated(builder: IRBuilder, fdef: FuncDef) -> bool:
548548
549549def gen_glue (
550550 builder : IRBuilder ,
551- sig : FuncSignature ,
551+ base_sig : FuncSignature ,
552552 target : FuncIR ,
553553 cls : ClassIR ,
554554 base : ClassIR ,
@@ -566,9 +566,9 @@ def gen_glue(
566566 "shadow" glue methods that work with interpreted subclasses.
567567 """
568568 if fdef .is_property :
569- return gen_glue_property (builder , sig , target , cls , base , fdef .line , do_py_ops )
569+ return gen_glue_property (builder , base_sig , target , cls , base , fdef .line , do_py_ops )
570570 else :
571- return gen_glue_method (builder , sig , target , cls , base , fdef .line , do_py_ops )
571+ return gen_glue_method (builder , base_sig , target , cls , base , fdef .line , do_py_ops )
572572
573573
574574class ArgInfo (NamedTuple ):
@@ -594,7 +594,7 @@ def get_args(builder: IRBuilder, rt_args: Sequence[RuntimeArg], line: int) -> Ar
594594
595595def gen_glue_method (
596596 builder : IRBuilder ,
597- sig : FuncSignature ,
597+ base_sig : FuncSignature ,
598598 target : FuncIR ,
599599 cls : ClassIR ,
600600 base : ClassIR ,
@@ -626,16 +626,25 @@ def f(builder: IRBuilder, x: object) -> int: ...
626626 If do_pycall is True, then make the call using the C API
627627 instead of a native call.
628628 """
629+ check_native_override (builder , base_sig , target .decl .sig , line )
630+
629631 builder .enter ()
630- builder .ret_types [- 1 ] = sig .ret_type
632+ builder .ret_types [- 1 ] = base_sig .ret_type
631633
632- rt_args = list (sig .args )
634+ rt_args = list (base_sig .args )
633635 if target .decl .kind == FUNC_NORMAL :
634- rt_args [0 ] = RuntimeArg (sig .args [0 ].name , RInstance (cls ))
636+ rt_args [0 ] = RuntimeArg (base_sig .args [0 ].name , RInstance (cls ))
635637
636638 arg_info = get_args (builder , rt_args , line )
637639 args , arg_kinds , arg_names = arg_info .args , arg_info .arg_kinds , arg_info .arg_names
638640
641+ bitmap_args = None
642+ if base_sig .num_bitmap_args :
643+ args = args [: - base_sig .num_bitmap_args ]
644+ arg_kinds = arg_kinds [: - base_sig .num_bitmap_args ]
645+ arg_names = arg_names [: - base_sig .num_bitmap_args ]
646+ bitmap_args = builder .builder .args [- base_sig .num_bitmap_args :]
647+
639648 # We can do a passthrough *args/**kwargs with a native call, but if the
640649 # args need to get distributed out to arguments, we just let python handle it
641650 if any (kind .is_star () for kind in arg_kinds ) and any (
@@ -655,11 +664,15 @@ def f(builder: IRBuilder, x: object) -> int: ...
655664 first , target .name , args [st :], line , arg_kinds [st :], arg_names [st :]
656665 )
657666 else :
658- retval = builder .builder .call (target .decl , args , arg_kinds , arg_names , line )
659- retval = builder .coerce (retval , sig .ret_type , line )
667+ retval = builder .builder .call (
668+ target .decl , args , arg_kinds , arg_names , line , bitmap_args = bitmap_args
669+ )
670+ retval = builder .coerce (retval , base_sig .ret_type , line )
660671 builder .add (Return (retval ))
661672
662673 arg_regs , _ , blocks , ret_type , _ = builder .leave ()
674+ if base_sig .num_bitmap_args :
675+ rt_args = rt_args [: - base_sig .num_bitmap_args ]
663676 return FuncIR (
664677 FuncDecl (
665678 target .name + "__" + base .name + "_glue" ,
@@ -673,6 +686,35 @@ def f(builder: IRBuilder, x: object) -> int: ...
673686 )
674687
675688
689+ def check_native_override (
690+ builder : IRBuilder , base_sig : FuncSignature , sub_sig : FuncSignature , line : int
691+ ) -> None :
692+ """Report an error if an override changes signature in unsupported ways.
693+
694+ Glue methods can work around many signature changes but not all of them.
695+ """
696+ for base_arg , sub_arg in zip (base_sig .real_args (), sub_sig .real_args ()):
697+ if base_arg .type .error_overlap :
698+ if not base_arg .optional and sub_arg .optional and base_sig .num_bitmap_args :
699+ # This would change the meanings of bits in the argument defaults
700+ # bitmap, which we don't support. We'd need to do tricky bit
701+ # manipulations to support this generally.
702+ builder .error (
703+ "An argument with type "
704+ + f'"{ base_arg .type } " cannot be given a default value in a method override' ,
705+ line ,
706+ )
707+ if base_arg .type .error_overlap or sub_arg .type .error_overlap :
708+ if not is_same_type (base_arg .type , sub_arg .type ):
709+ # This would change from signaling a default via an error value to
710+ # signaling a default via bitmap, which we don't support.
711+ builder .error (
712+ "Incompatible argument type "
713+ + f'"{ sub_arg .type } " (base class has type "{ base_arg .type } ")' ,
714+ line ,
715+ )
716+
717+
676718def gen_glue_property (
677719 builder : IRBuilder ,
678720 sig : FuncSignature ,
0 commit comments