Generate glue methods that mediate between different method types in subclasses. For example, if we have: class A: def f(builder: IRBuilder, x: int) -> object: ... then it is totally permissible to have a subclass class B(A): def f(builder: IRBuilder, x: object) -
(
builder: IRBuilder,
base_sig: FuncSignature,
target: FuncIR,
cls: ClassIR,
base: ClassIR,
line: int,
do_pycall: bool,
)
| 682 | |
| 683 | |
| 684 | def gen_glue_method( |
| 685 | builder: IRBuilder, |
| 686 | base_sig: FuncSignature, |
| 687 | target: FuncIR, |
| 688 | cls: ClassIR, |
| 689 | base: ClassIR, |
| 690 | line: int, |
| 691 | do_pycall: bool, |
| 692 | ) -> FuncIR: |
| 693 | """Generate glue methods that mediate between different method types in subclasses. |
| 694 | |
| 695 | For example, if we have: |
| 696 | |
| 697 | class A: |
| 698 | def f(builder: IRBuilder, x: int) -> object: ... |
| 699 | |
| 700 | then it is totally permissible to have a subclass |
| 701 | |
| 702 | class B(A): |
| 703 | def f(builder: IRBuilder, x: object) -> int: ... |
| 704 | |
| 705 | since '(object) -> int' is a subtype of '(int) -> object' by the usual |
| 706 | contra/co-variant function subtyping rules. |
| 707 | |
| 708 | The trickiness here is that int and object have different |
| 709 | runtime representations in mypyc, so A.f and B.f have |
| 710 | different signatures at the native C level. To deal with this, |
| 711 | we need to generate glue methods that mediate between the |
| 712 | different versions by coercing the arguments and return |
| 713 | values. |
| 714 | |
| 715 | If do_pycall is True, then make the call using the C API |
| 716 | instead of a native call. |
| 717 | """ |
| 718 | check_native_override(builder, base_sig, target.decl.sig, line) |
| 719 | |
| 720 | builder.enter() |
| 721 | builder.ret_types[-1] = base_sig.ret_type |
| 722 | |
| 723 | rt_args = list(base_sig.args) |
| 724 | if target.decl.kind == FUNC_NORMAL: |
| 725 | rt_args[0] = RuntimeArg(base_sig.args[0].name, RInstance(cls)) |
| 726 | |
| 727 | arg_info = get_args(builder, rt_args, line) |
| 728 | args, arg_kinds, arg_names = arg_info.args, arg_info.arg_kinds, arg_info.arg_names |
| 729 | |
| 730 | bitmap_args = None |
| 731 | if base_sig.num_bitmap_args: |
| 732 | args = args[: -base_sig.num_bitmap_args] |
| 733 | arg_kinds = arg_kinds[: -base_sig.num_bitmap_args] |
| 734 | arg_names = arg_names[: -base_sig.num_bitmap_args] |
| 735 | bitmap_args = list(builder.builder.args[-base_sig.num_bitmap_args :]) |
| 736 | |
| 737 | # We can do a passthrough *args/**kwargs with a native call, but if the |
| 738 | # args need to get distributed out to arguments, we just let python handle it |
| 739 | if any(kind.is_star() for kind in arg_kinds) and any( |
| 740 | not arg.kind.is_star() for arg in target.decl.sig.args |
| 741 | ): |
no test coverage detected
searching dependent graphs…