diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
index e5aa839827019..5eb230f1c009e 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
@@ -635,16 +635,25 @@ private BoundStatement BindUsingDeclarationStatementParts(LocalDeclarationStatem
{
Conversion iDisposableConversion;
MethodSymbol disposeMethod;
+ bool hasAwait = node.AwaitKeyword != default;
var declarations = BindUsingVariableDeclaration(
this,
diagnostics,
diagnostics.HasAnyErrors(),
node,
node.Declaration,
- hasAwait: false,
+ hasAwait,
out iDisposableConversion,
out disposeMethod);
- return new BoundUsingLocalDeclarations(node, disposeMethod, iDisposableConversion, declarations);
+
+ AwaitableInfo awaitOpt = null;
+ bool hasErrors = false;
+ if (hasAwait)
+ {
+ awaitOpt = BindAsyncDisposeAwaiter(node, node.AwaitKeyword, disposeMethod, diagnostics, ref hasErrors);
+ }
+
+ return new BoundUsingLocalDeclarations(node, disposeMethod, iDisposableConversion, awaitOpt, declarations, hasErrors);
}
private BoundStatement BindDeclarationStatementParts(LocalDeclarationStatementSyntax node, DiagnosticBag diagnostics)
@@ -762,6 +771,29 @@ internal MethodSymbol TryFindDisposePatternMethod(BoundExpression expr, SyntaxNo
return disposeMethod;
}
+ ///
+ /// Binds an awaiter for asynchronous dispose
+ ///
+ /// The syntax node to bind for
+ /// The await keyword of the syntax
+ /// The dispose method to call, or null to use IAsyncDisposable.DisposeAsync
+ /// Populated with any errors
+ /// True if errors occurred during binding
+ /// An with the bound information
+ protected AwaitableInfo BindAsyncDisposeAwaiter(SyntaxNode node, SyntaxToken awaitKeyword, MethodSymbol disposeMethodOpt, DiagnosticBag diagnostics, ref bool hasErrors)
+ {
+ TypeSymbol taskType = disposeMethodOpt is null
+ ? this.Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_ValueTask)
+ : disposeMethodOpt.ReturnType.TypeSymbol;
+
+ hasErrors |= ReportUseSiteDiagnostics(taskType, diagnostics, awaitKeyword);
+
+ BoundExpression placeholder = new BoundAwaitableValuePlaceholder(node, taskType).MakeCompilerGenerated();
+ AwaitableInfo awaitOpt = BindAwaitInfo(placeholder, node, awaitKeyword.GetLocation(), diagnostics, ref hasErrors);
+ return awaitOpt;
+ }
+
+
private TypeSymbolWithAnnotations BindVariableType(CSharpSyntaxNode declarationNode, DiagnosticBag diagnostics, TypeSyntax typeSyntax, ref bool isConst, out bool isVar, out AliasSymbol alias)
{
Debug.Assert(
diff --git a/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs b/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs
index 24a6800968cef..991e9dcec9eca 100644
--- a/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs
@@ -112,12 +112,8 @@ internal override BoundStatement BindUsingStatementParts(DiagnosticBag diagnosti
if (hasAwait)
{
- TypeSymbol taskType = this.Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_ValueTask);
- hasErrors |= ReportUseSiteDiagnostics(taskType, diagnostics, _syntax.AwaitKeyword);
-
var resource = (SyntaxNode)expressionSyntax ?? declarationSyntax;
- BoundExpression placeholder = new BoundAwaitableValuePlaceholder(resource, taskType).MakeCompilerGenerated();
- awaitOpt = BindAwaitInfo(placeholder, resource, _syntax.AwaitKeyword.GetLocation(), diagnostics, ref hasErrors);
+ awaitOpt = BindAsyncDisposeAwaiter(resource, _syntax.AwaitKeyword, disposeMethod, diagnostics, ref hasErrors);
}
BoundStatement boundBody = originalBinder.BindPossibleEmbeddedStatement(_syntax.Statement, diagnostics);
diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
index 50acf21978677..eae3fdc86172c 100644
--- a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
+++ b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
@@ -794,6 +794,7 @@
+