89
89
from mypyc .primitives .generic_ops import py_setattr_op
90
90
from mypyc .primitives .misc_ops import register_function
91
91
from 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
93
93
94
94
# Top-level transform functions
95
95
@@ -548,7 +548,7 @@ def is_decorated(builder: IRBuilder, fdef: FuncDef) -> bool:
548
548
549
549
def gen_glue (
550
550
builder : IRBuilder ,
551
- sig : FuncSignature ,
551
+ base_sig : FuncSignature ,
552
552
target : FuncIR ,
553
553
cls : ClassIR ,
554
554
base : ClassIR ,
@@ -566,9 +566,9 @@ def gen_glue(
566
566
"shadow" glue methods that work with interpreted subclasses.
567
567
"""
568
568
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 )
570
570
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 )
572
572
573
573
574
574
class ArgInfo (NamedTuple ):
@@ -594,7 +594,7 @@ def get_args(builder: IRBuilder, rt_args: Sequence[RuntimeArg], line: int) -> Ar
594
594
595
595
def gen_glue_method (
596
596
builder : IRBuilder ,
597
- sig : FuncSignature ,
597
+ base_sig : FuncSignature ,
598
598
target : FuncIR ,
599
599
cls : ClassIR ,
600
600
base : ClassIR ,
@@ -626,16 +626,25 @@ def f(builder: IRBuilder, x: object) -> int: ...
626
626
If do_pycall is True, then make the call using the C API
627
627
instead of a native call.
628
628
"""
629
+ check_native_override (builder , base_sig , target .decl .sig , line )
630
+
629
631
builder .enter ()
630
- builder .ret_types [- 1 ] = sig .ret_type
632
+ builder .ret_types [- 1 ] = base_sig .ret_type
631
633
632
- rt_args = list (sig .args )
634
+ rt_args = list (base_sig .args )
633
635
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 ))
635
637
636
638
arg_info = get_args (builder , rt_args , line )
637
639
args , arg_kinds , arg_names = arg_info .args , arg_info .arg_kinds , arg_info .arg_names
638
640
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
+
639
648
# We can do a passthrough *args/**kwargs with a native call, but if the
640
649
# args need to get distributed out to arguments, we just let python handle it
641
650
if any (kind .is_star () for kind in arg_kinds ) and any (
@@ -655,11 +664,15 @@ def f(builder: IRBuilder, x: object) -> int: ...
655
664
first , target .name , args [st :], line , arg_kinds [st :], arg_names [st :]
656
665
)
657
666
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 )
660
671
builder .add (Return (retval ))
661
672
662
673
arg_regs , _ , blocks , ret_type , _ = builder .leave ()
674
+ if base_sig .num_bitmap_args :
675
+ rt_args = rt_args [: - base_sig .num_bitmap_args ]
663
676
return FuncIR (
664
677
FuncDecl (
665
678
target .name + "__" + base .name + "_glue" ,
@@ -673,6 +686,35 @@ def f(builder: IRBuilder, x: object) -> int: ...
673
686
)
674
687
675
688
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
+
676
718
def gen_glue_property (
677
719
builder : IRBuilder ,
678
720
sig : FuncSignature ,
0 commit comments