Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions src/Compilers/CSharp/Portable/Binder/Binder_Await.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
{
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi Nov 17, 2025

Choose a reason for hiding this comment

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

@copilot mention which method reports this ERR_IteratorMustBeAsync error. Also, if possible, can we share code between that location and this location to ensure that we're checking all the same conditions to report an error there and not report an error here? #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in 5b4c38e. Now using the shared InMethodBinder.IsAsyncStreamInterface method to ensure we check the same conditions, and updated the comment to mention ExecutableCodeBinder.ValidateIteratorMethod as the location that reports the error.

// 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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1996,13 +1996,28 @@ static System.Collections.Generic.IAsyncEnumerator<int> M(int value)
comp.VerifyDiagnostics(
// (4,61): error CS8403: Method 'C.M(int)' with an iterator block must be 'async' to return 'IAsyncEnumerator<int>'
// static System.Collections.Generic.IAsyncEnumerator<int> M(int value)
Diagnostic(ErrorCode.ERR_IteratorMustBeAsync, "M").WithArguments("C.M(int)", "System.Collections.Generic.IAsyncEnumerator<int>").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<IAsyncEnumerator<int>>'.
// await System.Threading.Tasks.Task.CompletedTask;
Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, "await System.Threading.Tasks.Task.CompletedTask").WithArguments("System.Collections.Generic.IAsyncEnumerator<int>").WithLocation(7, 9)
Diagnostic(ErrorCode.ERR_IteratorMustBeAsync, "M").WithArguments("C.M(int)", "System.Collections.Generic.IAsyncEnumerator<int>").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<int> 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<int>'
// static System.Collections.Generic.IAsyncEnumerable<int> M(int value)
Diagnostic(ErrorCode.ERR_IteratorMustBeAsync, "M").WithArguments("C.M(int)", "System.Collections.Generic.IAsyncEnumerable<int>").WithLocation(3, 61));
}

[Fact]
Expand Down