'Why basic interface in type parameters causes resulting monomorphic function to use runtime.assertI2I()?

Polymorphic function (full code see here):

type Intf interface{ 
    Do() 
}
type Intf2 interface {
    Intf
    Do2()
}

func CallIntf[T Intf](intf T) {
    intf.Do()
}

Manual monomorph:

func CallIntf_mono(intf Intf) {
    intf.Do()
}

Instantiation:

    var intf2 Intf2
    intf2 = &impl{}
    CallIntf[Intf](intf2)

Instantiation asm (contains a call to runtime.assertI2I()):

    LEAQ    type."".impl(SB), AX
    CALL    runtime.newobject(SB)
    MOVQ    AX, ""..autotmp_13+24(SP)
    LEAQ    go.itab.*"".impl,"".Intf2(SB), BX
    LEAQ    type."".Intf(SB), AX
    CALL    runtime.convI2I(SB)
    MOVQ    AX, BX
    MOVQ    ""..autotmp_13+24(SP), CX
    LEAQ    ""..dict.CallIntf["".Intf](SB), AX
    CALL    "".CallIntf[go.shape.interface { Do() }_0](SB)

Generated monomorphic function asm (contains a call to runtime.assertI2I()):

    TEXT    "".CallIntf[go.shape.interface { Do() }_0](SB), DUPOK|ABIInternal, $32-24
    MOVQ    CX, "".intf+56(SP)
    LEAQ    type."".Intf(SB), AX
    CALL    runtime.assertI2I(SB)
    MOVQ    24(AX), CX
    MOVQ    "".intf+56(SP), AX
    CALL    CX
    MOVQ    24(SP), BP
    ADDQ    $32, SP
    RET

Manual monomorph asm (does not call runtime.assertI2I()):

    TEXT    "".CallIntf_mono(SB), ABIInternal, $16-16
    MOVQ    AX, "".intf+24(FP)
    MOVQ    BX, "".intf+32(FP)
    MOVQ    24(AX), CX
    MOVQ    BX, AX
    CALL    CX
    MOVQ    8(SP), BP
    ADDQ    $16, SP
    RET

Question: Why does the generated monomorphic function use runtime.assertI2I(), while the manual monomorphic function does not? In which case caller would use a type which is needed to be converted?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source