Skip to content

Unexpected behavior of scoped keyword with interface implementation #78711

@ThousandCuts-0064

Description

@ThousandCuts-0064

Version Used:

.NET 9

Steps to Reproduce:

public static class Demo
{
    public static void Show()
    {
        var stru = new Stru();

        Unsafe(ref stru);

        Console.Out.WriteLine(stru.Span);
    }

    private static void Unsafe<T>(ref T stru) where T : IStru, allows ref struct
    {
        Span<char> span = stackalloc char[10];

        "bug".CopyTo(span);

        stru.UseSpan(span);
    }
}

internal interface IStru
{
    public void UseSpan(scoped Span<char> span);
}

internal ref struct Stru : IStru
{
    public Span<char> Span;

    public void UseSpan(Span<char> span) => Span = span;
}

Look at IStru.UseSpan(scoped Span<char> span).
Parameter span has the scoped keyword.
Now look inside Demo.Unsafe<T>(ref T stru).
It is valid to pass a Span<char> that references stack allocated memory to stru.UseSpan because of the scoped keyword.
The issue is that ref struct Stru implements IStru and omits the scoped keyword.
This allows it to capture the span parameter.
Now after I call Demo.Unsafe<T>(ref T stru) I get reference to undefined memory.
It seems wrong given this is not in unsafe context and should be prevented by the ref safe context rules.

Expected Behavior:

The code should not compile.

Actual Behavior:

The code compiles and you can read / write to undefined memory.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions