Skip to content

Synthesized delegates allow ref safety holes on the boundary of old and updated rules #76087

@jjonescz

Description

@jjonescz
[Fact]
public void RefSafetyRules_SynthesizedDelegate()
{
    var source1 = """
        public static class C
        {
            public static R M(ref int x) => new R { F = ref x };
        }
        public ref struct R
        {
            public ref int F;
        }
        """;
    var ref1 = CreateCompilation(source1, targetFramework: TargetFramework.Net70)
        .VerifyDiagnostics().EmitToImageReference();

    var source2 = """
        R r;
        {
            int x = 1;
            r = C.M(ref x);

            var d = C.M;
            r = d(ref x);
        }
        """;
    CreateCompilation(source2, [ref1], parseOptions: TestOptions.Regular10).VerifyDiagnostics(
        // (4,9): error CS8347: Cannot use a result of 'C.M(ref int)' in this context because it may expose variables referenced by parameter 'x' outside of their declaration scope
        //     r = C.M(ref x);
        Diagnostic(ErrorCode.ERR_EscapeCall, "C.M(ref x)").WithArguments("C.M(ref int)", "x").WithLocation(4, 9),
        // (4,17): error CS8168: Cannot return local 'x' by reference because it is not a ref local
        //     r = C.M(ref x);
        Diagnostic(ErrorCode.ERR_RefReturnLocal, "x").WithArguments("x").WithLocation(4, 17));
}

There is no error reported at r = d(ref x); even though the call is equivalent to r = C.M(ref x); where a ref safety error is reported.

NOTE: Adding tests mentioning this issue in #75930.

Metadata

Metadata

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions