Skip to content

Unnecessary defensive copy on readonly struct when performing a constrained call #76288

Open
@hamarb123

Description

Version Used: sharplab.io

Steps to Reproduce:

Here we go again with another unnessary defensive copy 😆

struct X
{
    private Y a;
    public readonly string W() => a.ToString(); //defensive copy for call to ToString
}

readonly struct Y
{
}

https://sharplab.io/#v2:EYLgtghglgdgNAFxFANgHwM4IE4FcDGCABABoCwAUAN6VF1EAO2UAbhAgKZECaREA3LXoABAMxFsHCABMA9jBQBPIsICMABiIB1ABQBKIgF4AfHwB0AFVkBlHLADm+wRQC+lSpJnylRLHkI8lDSulEA=

Diagnostic Id:

N/A

Expected Behavior:

No defensive copy is emitted for the call to .ToString(), since Y is readonly, and the default implementation provided by valuetype base classes also does not mutate (since they box & run on that, and also just don't mutate anyway, which is guaranteed by III.2.1) & any future overriding ToString implementation would have to be readonly since Y is readonly.

Actual Behavior:

A defensive copy of a is made (see below).

W marked readonly:

    .method public hidebysig 
        instance string W () cil managed 
    {
        .custom instance void [System.Runtime]System.Runtime.CompilerServices.IsReadOnlyAttribute::.ctor() = (
            01 00 00 00
        )
        .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = (
            01 00 01 00 00
        )
        // Method begins at RVA 0x2050
        // Code size 21 (0x15)
        .maxstack 1
        .locals init (
            [0] valuetype Y
        )

        IL_0000: ldarg.0
        IL_0001: ldfld valuetype Y X::a
        IL_0006: stloc.0
        IL_0007: ldloca.s 0
        IL_0009: constrained. Y
        IL_000f: callvirt instance string [System.Runtime]System.Object::ToString()
        IL_0014: ret
    } // end of method X::W

W not marked readonly:

    .method public hidebysig 
        instance string W () cil managed 
    {
        .custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = (
            01 00 01 00 00
        )
        // Method begins at RVA 0x2050
        // Code size 18 (0x12)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: ldflda valuetype Y X::a
        IL_0006: constrained. Y
        IL_000c: callvirt instance string [System.Runtime]System.Object::ToString()
        IL_0011: ret
    } // end of method X::W

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions