Skip to content

Async-streams: disposal should continue without jump within a finally#46188

Merged
jcouv merged 5 commits intodotnet:masterfrom
jcouv:async-finally
Jul 25, 2020
Merged

Async-streams: disposal should continue without jump within a finally#46188
jcouv merged 5 commits intodotnet:masterfrom
jcouv:async-finally

Conversation

@jcouv
Copy link
Member

@jcouv jcouv commented Jul 21, 2020

When we lower a finally in an async-iterator method, we follow it with a if (disposeMode) goto <nextDisposalLabel>;.
But when we're inside an outer finally, then we should have no jump. We just want to execute the remainder of the outer finally.

Fixes #43936

@jcouv jcouv added this to the 16.8 milestone Jul 21, 2020
@jcouv jcouv self-assigned this Jul 21, 2020
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 this additional condition is the core of the change.
We don't want to generate a jump when inside a finally. We achieve that by stacking a null disposal label when visiting finally blocks (both real and extracted ones).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That last line "We don't want... We achieve..." would be a great comment here.


In reply to: 458340690 [](ancestors = 458340690)

@jcouv jcouv marked this pull request as ready for review July 21, 2020 23:02
@jcouv jcouv requested a review from a team as a code owner July 21, 2020 23:02
@RikkiGibson
Copy link
Member

Taking a look this morning.

Copy link
Member

@RikkiGibson RikkiGibson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Welp, forgot to submit my pending review yesterday. LGTM.

node = node.Update(
tryBlock: F.Block(node.TryBlock, F.Label(finallyEntry)),
node.CatchBlocks, F.Block(node.FinallyBlockOpt, F.Label(finallyExit)), node.FinallyLabelOpt, node.PreferFaultHandler);
tryBlock: F.Block(node.TryBlock, F.Label(finallyEntry)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: indentation is off here

finally
{
Console.Write(""BEFORE "");
try { Console.Write(""INSIDE ""); } finally { Console.Write(""INSIDE2 ""); }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider formatting this in a conventional style so it is easier to scan.

@gafter gafter self-requested a review July 24, 2020 20:07
// goto _enclosingFinallyOrExitLabel;
// goto currentDisposalLabel;

return F.Block(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put a similar assertion: Debug.Assert(CurrentDisposalLabel is object); // no yield return allowed inside a finally

finally
{
Console.Write(""BEFORE "");
try { Console.Write(""INSIDE ""); } finally { Console.Write(""INSIDE2 ""); await Task.Yield(); }
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

format please

private readonly AsyncIteratorInfo _asyncIteratorInfo;

/// <summary>
/// Where should we jump to to continue the execution of disposal path.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where [](start = 12, length = 5)

We usually implement a "stack" using the compiler's execution stack (i.e. "previous=current; current=newvalue; dostuff; current=previous;" and a simple variable rather than a stack data structure.
I have no problem using an explicit stack data structure - it is certainly more clear. But please say that it is a stack in the doc here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that you mention it, I think I'll change to use a simple variable (typical pattern) rather than an explicit stack data structure.

Copy link
Member

@gafter gafter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😷 Looks good with minor comments about comments.


// When exiting the try statement, we restore the previous disposal label.
_enclosingFinallyEntryOrFinallyExitOrExitLabel = _previousDisposalLabels.Pop();
if (changedDisposalLabel)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changedDisposalLabel [](start = 16, length = 20)

You don't need to track whether or not it changed. You can just unconditionally set it to what it used to be.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do. Thanks

Copy link
Member

@gafter gafter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😷 Looks good, with a small suggestion to further simplify.

@jcouv jcouv merged commit a1fcf0a into dotnet:master Jul 25, 2020
@ghost ghost modified the milestones: 16.8, Next Jul 25, 2020
@jcouv jcouv deleted the async-finally branch July 25, 2020 05:17
333fred added a commit to 333fred/roslyn that referenced this pull request Jul 28, 2020
…-pointers

* upstream/master: (207 commits)
  Update argument state when parameter has not-null type (dotnet#46072)
  Fix TypeWithAnnotations.ToTypeWithState() for (untyped) null literal (dotnet#46344)
  Update README (dotnet#46136)
  Revert "Revert "Support nullable annotations on unconstrained type parameters""
  Revert "Support nullable annotations on unconstrained type parameters (dotnet#45993)"
  Fix type in publish data
  Update VSIXExpInstaller version to one available on ADO
  Update publish data for 16.8
  Update version of RichCodeNav.EnvVarDump
  A fixed initializer must be bound to its natural type (dotnet#46293)
  Update features merged into 16.7p4 (dotnet#46229)
  Async-streams: disposal should continue without jump within a finally (dotnet#46188)
  Recommend default in type constraint, but not record (dotnet#46311)
  Add use site diagnostics to IsUnmanaged (dotnet#46114)
  Add another flaky test.
  Ensure NuGet connections use TLS 1.2
  Update to Microsoft.CodeAnalysis.Testing 1.0.1-beta1.20374.2
  Skip flaky test.
  Fix build break. (dotnet#46303)
  Skip a flaky test Relates to dotnet#46304
  ...
333fred added a commit to 333fred/roslyn that referenced this pull request Jul 28, 2020
…to function-pointer-type-lookup

* upstream/features/function-pointers: (212 commits)
  Correct public API number.
  Update argument state when parameter has not-null type (dotnet#46072)
  Fix TypeWithAnnotations.ToTypeWithState() for (untyped) null literal (dotnet#46344)
  Update README (dotnet#46136)
  Revert "Revert "Support nullable annotations on unconstrained type parameters""
  Revert "Support nullable annotations on unconstrained type parameters (dotnet#45993)"
  Fix type in publish data
  Update VSIXExpInstaller version to one available on ADO
  Update publish data for 16.8
  Update version of RichCodeNav.EnvVarDump
  A fixed initializer must be bound to its natural type (dotnet#46293)
  Update features merged into 16.7p4 (dotnet#46229)
  Async-streams: disposal should continue without jump within a finally (dotnet#46188)
  Recommend default in type constraint, but not record (dotnet#46311)
  Add use site diagnostics to IsUnmanaged (dotnet#46114)
  Add another flaky test.
  Ensure NuGet connections use TLS 1.2
  Update to Microsoft.CodeAnalysis.Testing 1.0.1-beta1.20374.2
  Skip flaky test.
  Fix build break. (dotnet#46303)
  ...
@RikkiGibson RikkiGibson modified the milestones: Next, 16.8.P2 Aug 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Code after finally in IAsyncEnumerable is not executed in some cases.

3 participants