Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler fails to report a possible boxing of a ref struct #76682

Open
AlekseyTs opened this issue Jan 8, 2025 · 2 comments
Open

Compiler fails to report a possible boxing of a ref struct #76682

AlekseyTs opened this issue Jan 8, 2025 · 2 comments
Labels
Area-Compilers Feature - Ref Fields untriaged Issues and PRs which have not yet been triaged by a lead

Comments

@AlekseyTs
Copy link
Contributor

Consider the following code:

class Program
{
    void Test1(S1 x)
    {
        x.ToString(); // No error
    }

    void Test2(S2 x)
    {
        x.ToString(); // CS0029: Cannot implicitly convert type 'S2' to 'System.ValueType'
    }
    
    void Test3<T>(T x) where T : allows ref struct
    {
        x.ToString(); // error CS0029: Cannot implicitly convert type 'T' to 'object'
    }
}

ref struct S1
{
    public override string ToString()
    {
        return "";
    }
}

ref struct S2
{
}

Observed:

  • No error is reported for ToString call in Test1
  • An error is reported for ToString call in Test2 and Test3

At the same time IL for Test1 looks like this:

    .method private hidebysig instance void Test1 (valuetype S1 x) cil managed 
    {
        .maxstack 8

        IL_0000: ldarga.s x
        IL_0002: constrained. S1
        IL_0008: callvirt instance string [System.Runtime]System.Object::ToString()
        IL_000d: pop
        IL_000e: ret
    }

It utilizes a constrained call of Object::ToString on a ref struct. A constrained call boxes the struct receiver when the struct doesn't override/implement the target method.

In a general case, it is quite possible that S1 won't override ToString at runtime. For example, when it is defined in a different assembly, etc. That is one of the reasons why compiler doesn't call the override directly even when it is present at compile time. In that case, the call will be boxing a ref struct. Presumably that will cause an exception.

We should consider reporting a compilation error for a situation like this.
See dotnet/runtime#111166 as well.

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged Issues and PRs which have not yet been triaged by a lead label Jan 8, 2025
@AlekseyTs
Copy link
Contributor Author

CC @jaredpar

@huoyaoyuan
Copy link
Member

What about Span<T>.ToString? It should follow into this case, but it has legitimate use cases, especially for Span<char>.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers Feature - Ref Fields untriaged Issues and PRs which have not yet been triaged by a lead
Projects
None yet
Development

No branches or pull requests

2 participants