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

Update ref foreach tests #64276

Merged
merged 4 commits into from
Oct 6, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 144 additions & 21 deletions src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11239,8 +11239,10 @@ class Enumerator1
comp.VerifyDiagnostics();
}

[Fact]
public void LocalScope_10_Foreach_02()
[Theory]
[InlineData("class")]
[InlineData("ref struct")]
public void LocalScope_10_Foreach_02(string kind)
{
var source =
@"int i = 0;
Expand All @@ -11253,7 +11255,7 @@ ref struct S
public S(ref int i) { }
}

class Enumerable1
" + kind + @" Enumerable1
{
public static Enumerable1 Create(ref int p) => default;
public Enumerator1 GetEnumerator() => default;
Expand All @@ -11279,33 +11281,47 @@ static void Main()
{
S s0 = default;
scoped ref S r0 = ref s0;
foreach (scoped ref S r1 in Enumerable1.Create(ref s0)) {
foreach (scoped ref S r1 in ClassEnumerable.Create(ref s0)) {
r0 = ref r1; // 1
break;
}
foreach (scoped ref S r2 in Enumerable1.Create(ref s0)) {
foreach (scoped ref S r2 in ClassEnumerable.Create(ref s0)) {
r0 = ref r2; // 2
break;
}
foreach (ref S r3 in Enumerable1.Create(ref s0)) {
foreach (ref S r3 in ClassEnumerable.Create(ref s0)) {
r0 = ref r3;
break;
}
foreach (ref S r4 in Enumerable1.Create(ref s0)) {
foreach (ref S r4 in ClassEnumerable.Create(ref s0)) {
r0 = ref r4;
break;
}
foreach (scoped ref S r5 in RefStructEnumerable.Create(ref s0)) {
r0 = ref r5; // 3
break;
}
foreach (ref S r6 in RefStructEnumerable.Create(ref s0)) {
r0 = ref r6; // 4
break;
}
}
}
ref struct S { }

class Enumerable1
class ClassEnumerable
{
public static Enumerable1 Create(ref S p) => default;
public Enumerator1 GetEnumerator() => default;
public static ClassEnumerable Create(ref S p) => default;
public ClassEnumerator GetEnumerator() => default;
}

class Enumerator1
ref struct RefStructEnumerable
{
public static RefStructEnumerable Create(ref S p) => default;
public ClassEnumerator GetEnumerator() => default;
}

class ClassEnumerator
{
public ref S Current => throw null;
public bool MoveNext() => false;
Expand All @@ -11318,11 +11334,19 @@ class Enumerator1
Diagnostic(ErrorCode.ERR_RefAssignNarrower, "r0 = ref r1").WithArguments("r0", "r1").WithLocation(8, 13),
// (12,13): error CS8374: Cannot ref-assign 'r2' to 'r0' because 'r2' has a narrower escape scope than 'r0'.
// r0 = ref r2; // 2
Diagnostic(ErrorCode.ERR_RefAssignNarrower, "r0 = ref r2").WithArguments("r0", "r2").WithLocation(12, 13));
Diagnostic(ErrorCode.ERR_RefAssignNarrower, "r0 = ref r2").WithArguments("r0", "r2").WithLocation(12, 13),
// (24,13): error CS8374: Cannot ref-assign 'r5' to 'r0' because 'r5' has a narrower escape scope than 'r0'.
// r0 = ref r5; // 3
Diagnostic(ErrorCode.ERR_RefAssignNarrower, "r0 = ref r5").WithArguments("r0", "r5").WithLocation(24, 13),
// (28,22): error CS8352: Cannot use variable 'r6' in this context because it may expose referenced variables outside of their declaration scope
// r0 = ref r6; // 4
Diagnostic(ErrorCode.ERR_EscapeVariable, "r6").WithArguments("r6").WithLocation(28, 22));
}

[Fact]
public void LocalScope_11_Foreach_02()
[Theory]
[InlineData("class")]
[InlineData("ref struct")]
public void LocalScope_11_Foreach_02(string kind)
{
var source =
@"class Program
Expand Down Expand Up @@ -11350,7 +11374,7 @@ static void Main()
}
ref struct S { }

class Enumerable1
" + kind + @" Enumerable1
{
public static Enumerable1 Create(ref S p) => default;
public Enumerator1 GetEnumerator() => default;
Expand Down Expand Up @@ -11393,12 +11417,12 @@ static void Main()
{
int i1 = 1;
foreach (S s1 in Enumerable1.Create(ref i1)) {
s0 = s1; // <-- An error is expected here, see https://github.com/dotnet/roslyn/issues/64218
s0 = s1;
break;
}
}
foreach (scoped S s2 in Enumerable1.Create(s0)) {
s0 = s2; // 2
s0 = s2; // 1
break;
}
foreach (S s3 in Enumerable1.Create(s0)) {
Expand Down Expand Up @@ -11428,13 +11452,15 @@ class Enumerator1
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (15,18): error CS8352: Cannot use variable 's2' in this context because it may expose referenced variables outside of their declaration scope
// s0 = s2; // 2
// s0 = s2; // 1
Diagnostic(ErrorCode.ERR_EscapeVariable, "s2").WithArguments("s2").WithLocation(15, 18)
);
}

[Fact]
public void LocalScope_12_Foreach_02()
[Theory]
[InlineData("class")]
[InlineData("ref struct")]
public void LocalScope_12_Foreach_02(string kind)
{
var source =
@"class Program
Expand Down Expand Up @@ -11463,7 +11489,7 @@ ref struct S
public S(ref int i) { }
}

class Enumerable1
" + kind + @" Enumerable1
{
public static Enumerable1 Create(ref int p) => default;
public Enumerator1 GetEnumerator() => default;
Expand All @@ -11489,6 +11515,103 @@ class Enumerator1
);
}

[Fact]
[WorkItem(64218, "https://github.com/dotnet/roslyn/issues/64218")]
public void LocalScope_12_Foreach_03()
{
var source =
@"class Program
{
static void Main()
{
int i0 = 0;
S s0 = new S(ref i0);
{
int i1 = 1;
foreach (S s1 in Enumerable1.Create(ref i1)) {
s0 = s1;
break;
}
}
}
}
ref struct S
{
public S(ref int i) { }
}
ref struct Enumerable1
{
public static Enumerable1 Create(ref int p) => default;
jjonescz marked this conversation as resolved.
Show resolved Hide resolved
public Enumerator1 GetEnumerator() => default;
}
ref struct Enumerator1
{
public S Current => throw null;
public bool MoveNext() => false;
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (10,22): error CS8352: Cannot use variable 's1' in this context because it may expose referenced variables outside of their declaration scope
// s0 = s1;
Diagnostic(ErrorCode.ERR_EscapeVariable, "s1").WithArguments("s1").WithLocation(10, 22)
);
}

[Fact]
[WorkItem(64218, "https://github.com/dotnet/roslyn/issues/64218")]
public void LocalScope_12_Foreach_04()
{
var source =
@"class Program
{
static void Main()
{
int i0 = 0;
S s0 = new S(ref i0);
{
int i1 = 1;
foreach (S s1 in RefStructEnumerable.Create(ref i1)) {
s0 = s1;
break;
}
}
{
int i2 = 1;
foreach (S s2 in ClassEnumerable.Create(ref i2)) {
s0 = s2;
break;
}
}
}
}
ref struct S
{
public S(ref int i) { }
}
ref struct RefStructEnumerable
{
public static RefStructEnumerable Create(ref int p) => default;
public ClassEnumerator GetEnumerator() => default;
}
class ClassEnumerable
{
public static ClassEnumerable Create(ref int p) => default;
public ClassEnumerator GetEnumerator() => default;
}
class ClassEnumerator
{
public S Current => throw null;
public bool MoveNext() => false;
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (10,22): error CS8352: Cannot use variable 's1' in this context because it may expose referenced variables outside of their declaration scope
// s0 = s1;
Diagnostic(ErrorCode.ERR_EscapeVariable, "s1").WithArguments("s1").WithLocation(10, 22));
}

[Fact]
public void ScopedRefAndRefStructOnly_06_Foreach()
{
Expand Down