Skip to content

Remove HoistedLocal from runtime-async spec #112918

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

Merged
merged 6 commits into from
Apr 29, 2025
Merged

Conversation

agocke
Copy link
Member

@agocke agocke commented Feb 25, 2025

No description provided.

@Copilot Copilot AI review requested due to automatic review settings February 25, 2025 18:17
@ghost ghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Feb 25, 2025
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot reviewed 1 out of 1 changed files in this pull request and generated no comments.

Comments suppressed due to low confidence (2)

docs/design/specs/runtime-async.md:49

  • The specification now states that any read of a by-ref variable after suspension will produce null, which may lead to unexpected behavior if consumers are unaware of this side effect. It would be helpful to provide clarification on how this null value is enforced and under what conditions, to avoid potential runtime issues.
Only local variables which are "hoisted" may be used across suspension points. That is, only "hoisted" local variables will have their state preserved after returning from a suspension. On methods with the `localsinit` flag set, non-"hoisted" local variables will be initialized to their default value when resuming from suspension. By-ref variables may not be hoisted across suspension, and any read of a by-ref variable after suspension will produce null.

docs/design/specs/runtime-async.md:53

  • The removal of the bullet regarding pinning locals being marked with HoistedLocal removes information about how these variables should be handled. Consider adding an equivalent clarification to describe the behavior of pinning locals in the updated specification.
* Pinning locals may not be marked `HoistedLocal`

Co-authored-by: Jakob Botsch Nielsen <Jakob.botsch.nielsen@gmail.com>

Async methods have some temporary restrictions with may be lifted later:
* The `tail` prefix is forbidden
* Usage of the `localloc` instruction is forbidden
* Pinning locals may not be marked `HoistedLocal`
Copy link
Member

Choose a reason for hiding this comment

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

Should we have a similar rule that locals marked pinned are zeroed at suspension points?

Copy link
Member

Choose a reason for hiding this comment

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

Yes. Lets break pinned locals in the same way as byrefs.

Copy link
Member

@VSadov VSadov Mar 18, 2025

Choose a reason for hiding this comment

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

Typically a pinned local is an internal pointer (&), so it is already broken by the other rule, if lives across Await.

But object references (i.e. o) can be pinned as well (some forms of fixed(..){..} actually use that), so we need a separate rule for this case.

@VSadov
Copy link
Member

VSadov commented Mar 19, 2025

Re: "* Applying MethodImplOptions.Async to methods with byref or ref-like parameters is invalid."

I think we should forbid byref or ref-like returns, since we need to transfer the return value to the caller and the caller may end up running on a different thread.

But ref/ref-like parameters seems ok, in principle. As long as they are not used after an Await, it would work.
Allowing byref parameters implicitly allows async method in structs, which we want to allow.

Roslyn can be more strict on the parameters, of course.

@jakobbotsch - any concerns about allowing byref/ref-like parameters from the JIT side?
(we could specialcase allow just struct methods)

@VSadov VSadov added runtime-async and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Mar 19, 2025
@jakobbotsch
Copy link
Member

Re: "* Applying MethodImplOptions.Async to methods with byref or ref-like parameters is invalid."

I think we should forbid byref or ref-like returns, since we need to transfer the return value to the caller and the caller may end up running on a different thread.

But ref/ref-like parameters seems ok, in principle. As long as they are not used after an Await, it would work. Allowing byref parameters implicitly allows async method in structs, which we want to allow.

Roslyn can be more strict on the parameters, of course.

@jakobbotsch - any concerns about allowing byref/ref-like parameters from the JIT side? (we could specialcase allow just struct methods)

No, I agree that we should allow these as parameters.

@@ -18,12 +18,12 @@ Applicability of `MethodImplOptions.Async`:
* The `[MethodImpl(MethodImplOptions.Async)]` only has effect when applied to method definitions with CIL implementation.
* Async method definitions are only valid inside async-capable assemblies. An async-capable assembly is one which references a corlib containing an `abstract sealed class RuntimeFeature` with a `public const string` field member named `Async`.
* Combining `MethodImplOptions.Async` with `MethodImplOptions.Synchronized` is invalid.
* Applying `MethodImplOptions.Async` to methods with `byref` or `ref-like` parameters is invalid.
* Applying `MethodImplOptions.Async` to methods with a `byref` or `ref-like` return value is invalid.
Copy link
Member

Choose a reason for hiding this comment

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

Should we rather have an item that clarifies that the return type must be Task/ValueTask/Task<T>/ValueTask<T>? The fact that T cannot be a byref type falls out naturally from the constraints on T.

Copy link
Member

Choose a reason for hiding this comment

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

I think we can be explicit here that the return value cannot be byref. - so no ambiguities whether ref Task foo() is allowed or not.

The part that return type cannot be ref-like kind of follows from requiring Task or ValueTask, but does not seem to hurt to explicitly mention that, so I think it is ok either way.

@jcouv
Copy link
Member

jcouv commented Apr 25, 2025

@333fred We'll want a corresponding roslyn design doc update to remove HoistedLocal

333fred added a commit to 333fred/roslyn that referenced this pull request Apr 29, 2025
Co-authored-by: Vladimir Sadov <vsadov@microsoft.com>
@agocke
Copy link
Member Author

agocke commented Apr 29, 2025

/ba-g doc only change

@agocke agocke merged commit 9d4faf1 into dotnet:main Apr 29, 2025
13 of 15 checks passed
@agocke agocke deleted the remove-hoisted branch April 29, 2025 17:06
@am11
Copy link
Member

am11 commented Apr 29, 2025

/ba-g doc only change

It was a real lint error with markdown, failing on other PRs. Fix #115159.

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.

5 participants