Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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 &&

@CyrusNajmabadi CyrusNajmabadi Nov 16, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@copilot fix formatting errors (excess spaces on line). #Closed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in b7d326e. Removed trailing whitespace from lines 192-194.

(method.ReturnType.IsIAsyncEnumerableType(Compilation) ||
method.ReturnType.IsIAsyncEnumeratorType(Compilation)))
{

@CyrusNajmabadi CyrusNajmabadi Nov 17, 2025

Copy link
Copy Markdown
Contributor

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
Copy Markdown
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, don't suggest changing the return type
info = new CSDiagnosticInfo(ErrorCode.ERR_BadAwaitWithoutAsyncIterator);

@CyrusNajmabadi CyrusNajmabadi Nov 16, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@copilot instead of a new error, can you use ERR_BadAwaitWithoutAsync? #Closed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 3de3769. Using ERR_BadAwaitWithoutAsync which provides a simpler message without suggesting a return type change.

}
else
{
info = new CSDiagnosticInfo(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, method.ReturnType);
}
}
break;
}
Expand Down
3 changes: 3 additions & 0 deletions src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -3797,6 +3797,9 @@ Give the compiler some way to differentiate the methods. For example, you can gi
<data name="ERR_BadAwaitWithoutVoidAsyncMethod" xml:space="preserve">
<value>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'.</value>
</data>
<data name="ERR_BadAwaitWithoutAsyncIterator" xml:space="preserve">
<value>The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier.</value>
</data>
<data name="ERR_BadAwaitInFinally" xml:space="preserve">
<value>Cannot await in the body of a finally clause</value>
</data>
Expand Down
3 changes: 2 additions & 1 deletion src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1136,9 +1136,10 @@ internal enum ErrorCode
ERR_BadAwaitWithoutAsyncLambda = 4034,
// ERR_BadAwaitWithoutAsyncAnonMeth = 4035, Merged with ERR_BadAwaitWithoutAsyncLambda in Roslyn
ERR_NoSuchMemberOrExtensionNeedUsing = 4036,
ERR_BadAwaitWithoutAsyncIterator = 4037,
#endregion diagnostics introduced in C# 5

// unused 4037-4999
// unused 4038-4999

#region diagnostics introduced in C# 6
// WRN_UnknownOption = 5000, //unused in Roslyn
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1573,6 +1573,7 @@ or ErrorCode.ERR_SecurityCriticalOrSecuritySafeCriticalOnAsyncInClassOrStruct
or ErrorCode.ERR_BadAwaitWithoutAsyncMethod
or ErrorCode.ERR_BadAwaitWithoutVoidAsyncMethod
or ErrorCode.ERR_BadAwaitWithoutAsyncLambda
or ErrorCode.ERR_BadAwaitWithoutAsyncIterator
or ErrorCode.ERR_NoSuchMemberOrExtensionNeedUsing
or ErrorCode.ERR_UnexpectedAliasedName
or ErrorCode.ERR_UnexpectedGenericName
Expand Down
5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -1997,12 +1997,34 @@ static System.Collections.Generic.IAsyncEnumerator<int> M(int value)
// (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>>'.
// (7,9): error CS4037: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier.
// 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_BadAwaitWithoutAsyncIterator, "await System.Threading.Tasks.Task.CompletedTask").WithLocation(7, 9)
);
}

// This error message is rather poor. Tracked by https://github.com/dotnet/roslyn/issues/31113
[Fact]
[WorkItem(31057, "https://github.com/dotnet/roslyn/issues/31057")]
[WorkItem(31113, "https://github.com/dotnet/roslyn/issues/31113")]
Comment thread
CyrusNajmabadi marked this conversation as resolved.
Outdated
public void AsyncIteratorReturningEnumerable_WithoutAsync()
Comment thread
333fred marked this conversation as resolved.
{
string source = @"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@copilot use raw string literals.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in cac74c6. Converted both tests to use raw string literals and updated the line numbers in diagnostic expectations.

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(
// (4,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(4, 61),
// (7,9): error CS4037: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier.
// await System.Threading.Tasks.Task.CompletedTask;
Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncIterator, "await System.Threading.Tasks.Task.CompletedTask").WithLocation(7, 9));
}

[Fact]
Expand Down