diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Await.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Await.cs index 7ac46015217f6..ef9417f95605e 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Await.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Await.cs @@ -185,9 +185,21 @@ private bool ReportBadAwaitWithoutAsync(SyntaxNodeOrToken nodeOrToken, BindingDi } else { - info = method.ReturnsVoid ? - new CSDiagnosticInfo(ErrorCode.ERR_BadAwaitWithoutVoidAsyncMethod) : - new CSDiagnosticInfo(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, method.ReturnType); + if (method.ReturnsVoid) + { + info = new CSDiagnosticInfo(ErrorCode.ERR_BadAwaitWithoutVoidAsyncMethod); + } + else if (method.IsIterator && InMethodBinder.IsAsyncStreamInterface(Compilation, method.RefKind, method.ReturnType)) + { + // For async iterators, we don't report an error on await because ERR_IteratorMustBeAsync + // is already reported by ExecutableCodeBinder.ValidateIteratorMethod, which tells the user to add 'async'. + // Reporting a second error here would be redundant. + return false; + } + else + { + info = new CSDiagnosticInfo(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, method.ReturnType); + } } break; } diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs index e0e1ebe77a8be..ee2351156ea27 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs @@ -1996,13 +1996,28 @@ static System.Collections.Generic.IAsyncEnumerator M(int value) comp.VerifyDiagnostics( // (4,61): error CS8403: Method 'C.M(int)' with an iterator block must be 'async' to return 'IAsyncEnumerator' // static System.Collections.Generic.IAsyncEnumerator M(int value) - Diagnostic(ErrorCode.ERR_IteratorMustBeAsync, "M").WithArguments("C.M(int)", "System.Collections.Generic.IAsyncEnumerator").WithLocation(4, 61), - // (7,9): error CS4032: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task>'. - // await System.Threading.Tasks.Task.CompletedTask; - Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, "await System.Threading.Tasks.Task.CompletedTask").WithArguments("System.Collections.Generic.IAsyncEnumerator").WithLocation(7, 9) + Diagnostic(ErrorCode.ERR_IteratorMustBeAsync, "M").WithArguments("C.M(int)", "System.Collections.Generic.IAsyncEnumerator").WithLocation(4, 61) ); + } - // This error message is rather poor. Tracked by https://github.com/dotnet/roslyn/issues/31113 + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/31113")] + public void AsyncIteratorReturningEnumerable_WithoutAsync() + { + string source = """ + class C + { + static System.Collections.Generic.IAsyncEnumerable M(int value) + { + yield return value; + await System.Threading.Tasks.Task.CompletedTask; + } + } + """; + var comp = CreateCompilationWithAsyncIterator(source); + comp.VerifyDiagnostics( + // (3,61): error CS8403: Method 'C.M(int)' with an iterator block must be 'async' to return 'IAsyncEnumerable' + // static System.Collections.Generic.IAsyncEnumerable M(int value) + Diagnostic(ErrorCode.ERR_IteratorMustBeAsync, "M").WithArguments("C.M(int)", "System.Collections.Generic.IAsyncEnumerable").WithLocation(3, 61)); } [Fact]