Skip to content

Commit ba25420

Browse files
jaredparjjonescz
andauthored
Tests to verify ref safety bug fix (#74341)
* Tests to verify ref safety bug fix These tests verify that issue #63852 is fixed. It was very likely fixed as part of #73081 closes #63852 * formatting issue * Apply suggestions from code review Co-authored-by: Jan Jones <[email protected]> --------- Co-authored-by: Jan Jones <[email protected]>
1 parent 433f79a commit ba25420

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9489,6 +9489,149 @@ public C M(scoped C c, C c1)
94899489
CreateCompilation(source, targetFramework: TargetFramework.Net70).VerifyDiagnostics();
94909490
}
94919491

9492+
[Theory]
9493+
[InlineData(LanguageVersion.CSharp10)]
9494+
[InlineData(LanguageVersion.CSharp11)]
9495+
[WorkItem("https://github.com/dotnet/roslyn/issues/63852")]
9496+
public void UserDefinedBinaryOperator_RefStruct_Compound_RegressionTest1(LanguageVersion languageVersion)
9497+
{
9498+
var tree = SyntaxFactory.ParseSyntaxTree("""
9499+
using System;
9500+
9501+
public ref struct S1
9502+
{
9503+
public S1(Span<int> span) { }
9504+
public static S1 operator +(S1 a, S1 b) => default;
9505+
9506+
static void Test()
9507+
{
9508+
S1 stackLocal = new S1(stackalloc int[1]);
9509+
S1 heapLocal = new S1(default);
9510+
9511+
stackLocal += stackLocal;
9512+
stackLocal += heapLocal;
9513+
heapLocal += heapLocal;
9514+
heapLocal += stackLocal; // 1
9515+
9516+
}
9517+
}
9518+
""", TestOptions.Regular.WithLanguageVersion(languageVersion));
9519+
var comp = CreateCompilationWithSpan(tree, TestOptions.UnsafeDebugDll);
9520+
comp.VerifyEmitDiagnostics(
9521+
// (16,9): error CS8347: Cannot use a result of 'S1.operator +(S1, S1)' in this context because it may expose variables referenced by parameter 'b' outside of their declaration scope
9522+
// heapLocal += stackLocal; // 1
9523+
Diagnostic(ErrorCode.ERR_EscapeCall, "heapLocal += stackLocal").WithArguments("S1.operator +(S1, S1)", "b").WithLocation(16, 9),
9524+
// (16,22): error CS8352: Cannot use variable 'stackLocal' in this context because it may expose referenced variables outside of their declaration scope
9525+
// heapLocal += stackLocal; // 1
9526+
Diagnostic(ErrorCode.ERR_EscapeVariable, "stackLocal").WithArguments("stackLocal").WithLocation(16, 22)
9527+
);
9528+
}
9529+
9530+
[Fact]
9531+
[WorkItem("https://github.com/dotnet/roslyn/issues/63852")]
9532+
public void UserDefinedBinaryOperator_RefStruct_Compound_RegressionTest2()
9533+
{
9534+
var tree = SyntaxFactory.ParseSyntaxTree("""
9535+
using System;
9536+
9537+
public ref struct S1
9538+
{
9539+
public S1(Span<int> span) { }
9540+
public static S1 operator +(S1 a, S1 b) => default;
9541+
9542+
static void Test()
9543+
{
9544+
S1 stackLocal = new(stackalloc int[1]);
9545+
S1 heapLocal = new(default);
9546+
9547+
stackLocal += stackLocal;
9548+
stackLocal += heapLocal;
9549+
heapLocal += heapLocal;
9550+
heapLocal += stackLocal; // 1
9551+
9552+
}
9553+
}
9554+
9555+
public ref struct S2
9556+
{
9557+
public S2(Span<int> span) { }
9558+
public static S2 operator +(S2 a, scoped S2 b) => default;
9559+
9560+
static void Test()
9561+
{
9562+
S2 stackLocal = new(stackalloc int[1]);
9563+
S2 heapLocal = new(default);
9564+
9565+
stackLocal += stackLocal;
9566+
stackLocal += heapLocal;
9567+
heapLocal += heapLocal;
9568+
heapLocal += stackLocal;
9569+
}
9570+
}
9571+
9572+
public ref struct S3
9573+
{
9574+
public S3(Span<int> span) { }
9575+
public static S3 operator +(in S3 a, in S3 b) => default;
9576+
9577+
static void Test()
9578+
{
9579+
S3 stackLocal = new(stackalloc int[1]);
9580+
S3 heapLocal = new(default);
9581+
9582+
stackLocal += stackLocal;
9583+
stackLocal += heapLocal;
9584+
heapLocal += heapLocal; // 2
9585+
heapLocal += stackLocal; // 3
9586+
}
9587+
}
9588+
9589+
public ref struct S4
9590+
{
9591+
public S4(Span<int> span) { }
9592+
public static S4 operator +(scoped in S4 a, scoped in S4 b) => default;
9593+
9594+
static void Test()
9595+
{
9596+
S4 stackLocal = new(stackalloc int[1]);
9597+
S4 heapLocal = new(default);
9598+
9599+
stackLocal += stackLocal;
9600+
stackLocal += heapLocal;
9601+
heapLocal += heapLocal;
9602+
heapLocal += stackLocal; // 4
9603+
}
9604+
}
9605+
""", TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp11));
9606+
var comp = CreateCompilationWithSpan(tree, TestOptions.UnsafeDebugDll);
9607+
comp.VerifyEmitDiagnostics(
9608+
// (16,9): error CS8347: Cannot use a result of 'S1.operator +(S1, S1)' in this context because it may expose variables referenced by parameter 'b' outside of their declaration scope
9609+
// heapLocal += stackLocal; // 1
9610+
Diagnostic(ErrorCode.ERR_EscapeCall, "heapLocal += stackLocal").WithArguments("S1.operator +(S1, S1)", "b").WithLocation(16, 9),
9611+
// (16,22): error CS8352: Cannot use variable 'stackLocal' in this context because it may expose referenced variables outside of their declaration scope
9612+
// heapLocal += stackLocal; // 1
9613+
Diagnostic(ErrorCode.ERR_EscapeVariable, "stackLocal").WithArguments("stackLocal").WithLocation(16, 22),
9614+
// (50,9): error CS8168: Cannot return local 'heapLocal' by reference because it is not a ref local
9615+
// heapLocal += heapLocal; // 2
9616+
Diagnostic(ErrorCode.ERR_RefReturnLocal, "heapLocal").WithArguments("heapLocal").WithLocation(50, 9),
9617+
// (50,9): error CS8347: Cannot use a result of 'S3.operator +(in S3, in S3)' in this context because it may expose variables referenced by parameter 'a' outside of their declaration scope
9618+
// heapLocal += heapLocal; // 2
9619+
Diagnostic(ErrorCode.ERR_EscapeCall, "heapLocal += heapLocal").WithArguments("S3.operator +(in S3, in S3)", "a").WithLocation(50, 9),
9620+
// (51,9): error CS8168: Cannot return local 'heapLocal' by reference because it is not a ref local
9621+
// heapLocal += stackLocal; // 3
9622+
Diagnostic(ErrorCode.ERR_RefReturnLocal, "heapLocal").WithArguments("heapLocal").WithLocation(51, 9),
9623+
// (51,9): error CS8347: Cannot use a result of 'S3.operator +(in S3, in S3)' in this context because it may expose variables referenced by parameter 'a' outside of their declaration scope
9624+
// heapLocal += stackLocal; // 3
9625+
Diagnostic(ErrorCode.ERR_EscapeCall, "heapLocal += stackLocal").WithArguments("S3.operator +(in S3, in S3)", "a").WithLocation(51, 9),
9626+
// (68,9): error CS8347: Cannot use a result of 'S4.operator +(scoped in S4, scoped in S4)' in this context because it may expose variables referenced by parameter 'b' outside of their declaration scope
9627+
// heapLocal += stackLocal; // 4
9628+
Diagnostic(ErrorCode.ERR_EscapeCall, "heapLocal += stackLocal").WithArguments("S4.operator +(scoped in S4, scoped in S4)", "b").WithLocation(68, 9),
9629+
// (68,22): error CS8352: Cannot use variable 'stackLocal' in this context because it may expose referenced variables outside of their declaration scope
9630+
// heapLocal += stackLocal; // 4
9631+
Diagnostic(ErrorCode.ERR_EscapeVariable, "stackLocal").WithArguments("stackLocal").WithLocation(68, 22)
9632+
);
9633+
}
9634+
94929635
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71773")]
94939636
public void UserDefinedUnaryOperator_RefStruct()
94949637
{

0 commit comments

Comments
 (0)