Skip to content

Commit

Permalink
Consider GetEnumerator when computing foreach variable escape
Browse files Browse the repository at this point in the history
  • Loading branch information
jjonescz committed Sep 27, 2022
1 parent 784a29c commit ae8e2c2
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 1 deletion.
5 changes: 4 additions & 1 deletion src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,10 @@ private BoundForEachStatement BindForEachPartsWorker(BindingDiagnosticBag diagno
bool hasNameConflicts = false;
BoundForEachDeconstructStep deconstructStep = null;
BoundExpression iterationErrorExpression = null;
uint collectionEscape = GetValEscape(collectionExpr, this.LocalScopeDepth);
uint collectionEscape = getEnumeratorMethod != null
// Get escape of `collection.GetEnumerator()` call if possible.
? GetValEscape(BoundCall.Synthesized(_syntax, collectionExpr, getEnumeratorMethod), this.LocalScopeDepth)
: GetValEscape(collectionExpr, this.LocalScopeDepth);
switch (_syntax.Kind())
{
case SyntaxKind.ForEachStatement:
Expand Down
51 changes: 51 additions & 0 deletions src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11532,6 +11532,57 @@ ref struct Enumerator1
);
}

[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 Enumerable1.Create(ref i1)) {
s0 = s1;
break;
}
}
{
int i2 = 1;
foreach (S s2 in Enumerable2.Create(ref i2)) {
s0 = s2;
break;
}
}
}
}
ref struct S
{
public S(ref int i) { }
}
ref struct Enumerable1
{
public static Enumerable1 Create(ref int p) => default;
public Enumerator1 GetEnumerator() => default;
}
class Enumerable2
{
public static Enumerable2 Create(ref int p) => default;
public Enumerator1 GetEnumerator() => default;
}
class Enumerator1
{
public S Current => throw null;
public bool MoveNext() => false;
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
}

[Fact]
public void ScopedRefAndRefStructOnly_06_Foreach()
{
Expand Down

0 comments on commit ae8e2c2

Please sign in to comment.