-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Async-iterator method can return IAsyncEnumerator<T>
#31114
Conversation
a96458c
to
dd58e42
Compare
dd58e42
to
09ed675
Compare
@dotnet/roslyn-compiler for review. Thanks |
@dotnet/roslyn-compiler for review. Thanks |
async System.Collections.Generic.IAsyncEnumerator<int> M() { await Task.CompletedTask; yield return 3; } | ||
} | ||
"; | ||
private void VerifyMissingMember(WellKnownMember member, params DiagnosticDescription[] expected) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private [](start = 8, length = 7)
static
#Resolved
private static void VerifyMissingMember(string source, WellKnownMember member, params DiagnosticDescription[] expected) | ||
{ | ||
var lib = CreateCompilationWithTasksExtensions(AsyncStreamsTypes); | ||
var lib_ref = lib.EmitToImageReference(); | ||
var comp = CreateCompilationWithTasksExtensions(source, references: new[] { lib_ref }); | ||
comp.MakeMemberMissing(member); | ||
comp.VerifyEmitDiagnostics(expected); | ||
} | ||
|
||
private void VerifyMissingType(WellKnownType type, params DiagnosticDescription[] expected) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private [](start = 8, length = 7)
static
#Resolved
VerifyMissingType(WellKnownType.System_Collections_Generic_IAsyncEnumerable_T, | ||
VerifyMissingMember(_enumerator, WellKnownMember.System_Collections_Generic_IAsyncEnumerable_T__GetAsyncEnumerator); | ||
|
||
VerifyMissingType(_enumerable, WellKnownType.System_Collections_Generic_IAsyncEnumerable_T, | ||
// (5,60): error CS1983: The return type of an async method must be void, Task, Task<T>, a task-like type, or IAsyncEnumerable<T> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or IAsyncEnumerable [](start = 123, length = 22)
Should the message include IAsyncEnumerator<T>
as well? #Resolved
comp.VerifyDiagnostics(); | ||
CompileAndVerify(comp, expectedOutput: "Value:0 1 2 Value:3 4 Value:5 Done"); | ||
|
||
var comp2 = CreateCompilationWithTasksExtensions("", references: new[] { comp.EmitToImageReference() }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CreateCompilationWithTasksExtensions [](start = 24, length = 36)
Are we creating a second compilation to check PE symbols? If so, consider using CompileAndVerify(..., symbolValidator=...)
instead, for consistency with other tests. #Resolved
@@ -1008,6 +1302,37 @@ await using (var enumerator2 = enumerable.GetAsyncEnumerator()) | |||
var comp = CreateCompilationWithTasksExtensions(new[] { source, AsyncStreamsTypes }, options: TestOptions.DebugExe); | |||
comp.VerifyDiagnostics(); | |||
CompileAndVerify(comp, expectedOutput: "1 2 Stream1:3 1 2 Stream2:3 4 2 4 2 Done"); | |||
|
|||
var comp2 = CreateCompilationWithTasksExtensions("", references: new[] { comp.EmitToImageReference() }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CreateCompilationWithTasksExtensions("", [](start = 24, length = 40)
Consider adding symbolValidator=...
to the CompileAndVerify
call above instead. #Resolved
@@ -31,8 +31,12 @@ public AsyncStateMachine(VariableSlotAllocator variableAllocatorOpt, TypeCompila | |||
var elementType = TypeMap.SubstituteType(asyncMethod.IteratorElementType).TypeSymbol; | |||
this.IteratorElementType = elementType; | |||
|
|||
// IAsyncEnumerable<TResult> | |||
interfaces.Add(compilation.GetWellKnownType(WellKnownType.System_Collections_Generic_IAsyncEnumerable_T).Construct(elementType)); | |||
bool isEnumerable = asyncMethod.IsIAsyncEnumerableReturningAsync(asyncMethod.DeclaringCompilation); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
asyncMethod.DeclaringCompilation [](start = 81, length = 32)
compilation
#Resolved
@dotnet/roslyn-compiler for second review. Thanks |
@@ -9,6 +9,7 @@ | |||
|
|||
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen | |||
{ | |||
using System.Linq; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe our style guidelines specify that all using
s must go outside the namespace. #Resolved
VerifyMissingMember(_enumerator, WellKnownMember.System_Collections_Generic_IAsyncEnumerable_T__GetAsyncEnumerator); | ||
|
||
VerifyMissingType(_enumerable, WellKnownType.System_Collections_Generic_IAsyncEnumerable_T, | ||
// (5,60): error CS1983: The return type of an async method must be void, Task, Task<T>, a task-like type, IAsyncEnumerable<T>, or IAsyncEnumerator<T> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this testing what happens when you have something like
using System.Threading.Tasks;
class C
{
async System.Collections.Generic.IAsyncEnumerable<int> M() { await Task.CompletedTask; yield return 3; }
}
but IAsyncEnumerable<int>
is missing? If so, is this error message useful? Should we just skip it if the return type is an error type? #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes that's what this tests.
Unfortunately, the MakeTypeMissing
infrastructure doesn't fully simulate a type being missing. It only makes the type disappear from GetWellKnownType
.
I'll adjust the test to show what users actually would see. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM aside from minor cascading error question
Fixes #31057
Aside from not implementing the
IAsyncEnumerable<T>
interface (and itsGetAsyncEnumerator
method), the state machine also does not need to hold proxied/preserved parameters, or to preserve the original threadID.Also integrated with #31072 (nullability analysis of yield return).