-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Consider relaxing restrictions of async methods in blocks that do not contain await
. (VS 17.11, .NET 9)
#1331
Comments
Are you refering to methods that directly return a Task without awaiting it? There is no need to mark that method as async. You can simply return task.
Can be rewritten as
Does this solve your problem? |
if a local variable is not accessed after yielding some results or awaiting for results that can be also allowed. For example
|
No, I don't think Vladimir is lost. |
An example: async Task<int> Test()
{
await Task.Yield();
int x = 42;
// the following block does not contain await expressions
// ref and ref-like locals are safe to use, but currently disallowed
{
Span<int> sp = stackalloc int[1];
ref int r0 = ref sp[0];
return r0 + x;
}
} A workaround that I have seen in use. async Task<int> Test1()
{
await Task.Yield();
int x = 42;
// one possible workaround is a local function, but that is not nice
return block();
int block()
{
Span<int> sp = stackalloc int[1];
ref int r0 = ref sp[0];
return r0 + x;
}
} |
Keying off "before/after await" is tricky in the presence of loops or other nontrivial control flow. "In a block with no awaits" seems much easier to reason about. |
I see, sounds reasonable. its kind of like how await is forbindden in unsafe context since c# cant get pointer of fields. But unsafe block without awaits is ok. |
It also means that you have to change your reasonable code just to make the compiler happy. I think that "fighting with the compiler" should be avoided if possible. Something like "there can be no |
If it easy to do it would also be nice if you can allow expressions that return Span to be legal in async methods (it may already be true). basically if
This avoids needing to make a explicit block {} for the trivial case where there are no local variables. |
Expressions/values are allowed. Locals are not allowed. The thing above should work fine. |
Great! |
There is an obscure case where expressions are not allowed - when we have to stack spill them, but that is very rare. async Task<int> Test1()
{
await Task.Yield();
ConsumesSpanAndStuff(ReturnsSpan(), await SomethingAsync());
await Task.Yield();
} In the case above you would need to take the Otherwise "flowing" spans is ok in async, storing into locals - no. |
Related: dotnet/roslyn#40213 |
await
.await
. (VS 17.11, .NET 9)
Async methods have several restrictions such as not allowing
ref
andref-like/span
locals.The reason is the technical difficulties that may arise if such locals need to be hoisted. In a code that tries to mix
await
andspan
this could be inconvenient.Besides there can be patterns which are obviously safe - In particular, in a block that does not contain
await
expressions, such locals would never be hoisted and therefore we could relax the restrictions.The text was updated successfully, but these errors were encountered: