Skip to content
Merged
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
23 changes: 13 additions & 10 deletions src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ internal static BoundStatement BindUsingStatementOrDeclarationFromParts(SyntaxNo
Debug.Assert((object)disposableInterface != null);
bool hasErrors = ReportUseSite(disposableInterface, diagnostics, hasAwait ? awaitKeyword : usingKeyword);

Conversion iDisposableConversion;
ImmutableArray<BoundLocalDeclaration> declarationsOpt = default;
BoundMultipleLocalDeclarations? multipleDeclarationsOpt = null;
BoundExpression? expressionOpt = null;
Expand All @@ -111,7 +110,7 @@ internal static BoundStatement BindUsingStatementOrDeclarationFromParts(SyntaxNo
if (isExpression)
{
expressionOpt = usingBinderOpt!.BindTargetExpression(diagnostics, originalBinder);
hasErrors |= !populateDisposableConversionOrDisposeMethod(fromExpression: true, out iDisposableConversion, out patternDisposeInfo, out awaitableTypeOpt);
hasErrors |= !bindDisposable(fromExpression: true, out patternDisposeInfo, out awaitableTypeOpt);
}
else
{
Expand All @@ -124,13 +123,12 @@ internal static BoundStatement BindUsingStatementOrDeclarationFromParts(SyntaxNo

if (declarationTypeOpt.IsDynamic())
{
iDisposableConversion = Conversion.ImplicitDynamic;
patternDisposeInfo = null;
awaitableTypeOpt = null;
}
else
{
hasErrors |= !populateDisposableConversionOrDisposeMethod(fromExpression: false, out iDisposableConversion, out patternDisposeInfo, out awaitableTypeOpt);
hasErrors |= !bindDisposable(fromExpression: false, out patternDisposeInfo, out awaitableTypeOpt);
}
}

Expand All @@ -156,7 +154,7 @@ internal static BoundStatement BindUsingStatementOrDeclarationFromParts(SyntaxNo
// In the future it might be better to have a separate shared type that we add the info to, and have the callers create the appropriate bound nodes from it
if (isUsingDeclaration)
{
return new BoundUsingLocalDeclarations(syntax, patternDisposeInfo, iDisposableConversion, awaitOpt, declarationsOpt, hasErrors);
return new BoundUsingLocalDeclarations(syntax, patternDisposeInfo, awaitOpt, declarationsOpt, hasErrors);
}
else
{
Expand All @@ -167,17 +165,16 @@ internal static BoundStatement BindUsingStatementOrDeclarationFromParts(SyntaxNo
usingBinderOpt.Locals,
multipleDeclarationsOpt,
expressionOpt,
iDisposableConversion,
boundBody,
awaitOpt,
patternDisposeInfo,
hasErrors);
}

bool populateDisposableConversionOrDisposeMethod(bool fromExpression, out Conversion iDisposableConversion, out MethodArgumentInfo? patternDisposeInfo, out TypeSymbol? awaitableType)
bool bindDisposable(bool fromExpression, out MethodArgumentInfo? patternDisposeInfo, out TypeSymbol? awaitableType)
{
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = originalBinder.GetNewCompoundUseSiteInfo(diagnostics);
iDisposableConversion = classifyConversion(fromExpression, disposableInterface, ref useSiteInfo);
Conversion iDisposableConversion = classifyConversion(fromExpression, disposableInterface, ref useSiteInfo);
patternDisposeInfo = null;
awaitableType = null;

Expand Down Expand Up @@ -261,12 +258,18 @@ Conversion classifyConversion(bool fromExpression, TypeSymbol targetInterface, r
if (fromExpression)
{
Debug.Assert(expressionOpt is { });
return conversions.ClassifyImplicitConversionFromExpression(expressionOpt, targetInterface, ref useSiteInfo);
var result = conversions.ClassifyImplicitConversionFromExpression(expressionOpt, targetInterface, ref useSiteInfo);

Debug.Assert(expressionOpt.Type?.IsDynamic() != true || result.Kind == ConversionKind.ImplicitDynamic);
return result;
}
else
{
Debug.Assert(declarationTypeOpt is { });
return conversions.ClassifyImplicitConversionFromType(declarationTypeOpt, targetInterface, ref useSiteInfo);
var result = conversions.ClassifyImplicitConversionFromType(declarationTypeOpt, targetInterface, ref useSiteInfo);

Debug.Assert(!declarationTypeOpt.IsDynamic() || result.Kind == ConversionKind.ImplicitDynamic);
return result;
}
}

Expand Down
2 changes: 0 additions & 2 deletions src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -933,7 +933,6 @@
-->
<Node Name="BoundUsingLocalDeclarations" Base="BoundMultipleLocalDeclarationsBase">
<Field Name="PatternDisposeInfoOpt" Type="MethodArgumentInfo?"/>
<Field Name="IDisposableConversion" Type="Conversion"/>
<Field Name="AwaitOpt" Type="BoundAwaitableInfo?"/>
</Node>

Expand Down Expand Up @@ -1099,7 +1098,6 @@
<Field Name="Locals" Type="ImmutableArray&lt;LocalSymbol&gt;"/>
<Field Name="DeclarationsOpt" Type="BoundMultipleLocalDeclarations?"/>
<Field Name="ExpressionOpt" Type="BoundExpression?"/>
<Field Name="IDisposableConversion" Type="Conversion" />
<Field Name="Body" Type="BoundStatement"/>
<Field Name="AwaitOpt" Type="BoundAwaitableInfo?"/>
<Field Name="PatternDisposeInfoOpt" Type="MethodArgumentInfo?"/>
Expand Down

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 @@ -52,7 +52,6 @@ public override BoundNode VisitUsingStatement(BoundUsingStatement node)
tryBlock,
node.Locals,
node.DeclarationsOpt.LocalDeclarations,
node.IDisposableConversion,
node.PatternDisposeInfoOpt,
node.AwaitOpt,
awaitKeyword);
Expand All @@ -63,7 +62,6 @@ private BoundStatement MakeDeclarationUsingStatement(SyntaxNode syntax,
BoundBlock body,
ImmutableArray<LocalSymbol> locals,
ImmutableArray<BoundLocalDeclaration> declarations,
Conversion iDisposableConversion,
MethodArgumentInfo? patternDisposeInfo,
BoundAwaitableInfo? awaitOpt,
SyntaxToken awaitKeyword)
Expand All @@ -73,7 +71,7 @@ private BoundStatement MakeDeclarationUsingStatement(SyntaxNode syntax,
BoundBlock result = body;
for (int i = declarations.Length - 1; i >= 0; i--) //NB: inner-to-outer = right-to-left
{
result = RewriteDeclarationUsingStatement(syntax, declarations[i], result, iDisposableConversion, awaitKeyword, awaitOpt, patternDisposeInfo);
result = RewriteDeclarationUsingStatement(syntax, declarations[i], result, awaitKeyword, awaitOpt, patternDisposeInfo);
}

// Declare all locals in a single, top-level block so that the scope is correct in the debugger
Expand All @@ -96,7 +94,6 @@ private BoundStatement MakeLocalUsingDeclarationStatement(BoundUsingLocalDeclara
body,
ImmutableArray<LocalSymbol>.Empty,
usingDeclarations.LocalDeclarations,
usingDeclarations.IDisposableConversion,
usingDeclarations.PatternDisposeInfoOpt,
awaitOpt: usingDeclarations.AwaitOpt,
awaitKeyword: syntax.AwaitKeyword);
Expand Down Expand Up @@ -155,7 +152,8 @@ private BoundBlock MakeExpressionUsingStatement(BoundUsingStatement node, BoundB

BoundAssignmentOperator tempAssignment;
BoundLocal boundTemp;
if (expressionType is null || expressionType.IsDynamic())

if (expressionType.IsDynamic())
{
// IDisposable temp = (IDisposable) expr;
// or
Expand All @@ -169,7 +167,7 @@ private BoundBlock MakeExpressionUsingStatement(BoundUsingStatement node, BoundB
BoundExpression tempInit = MakeConversionNode(
expressionSyntax,
rewrittenExpression,
Conversion.GetTrivialConversion(node.IDisposableConversion.Kind),
Conversion.ImplicitDynamic,
iDisposableType,
@checked: false,
constantValueOpt: rewrittenExpression.ConstantValue);
Expand Down Expand Up @@ -208,7 +206,6 @@ private BoundBlock RewriteDeclarationUsingStatement(
SyntaxNode usingSyntax,
BoundLocalDeclaration localDeclaration,
BoundBlock tryBlock,
Conversion iDisposableConversion,
SyntaxToken awaitKeywordOpt,
BoundAwaitableInfo? awaitOpt,
MethodArgumentInfo? patternDisposeInfo)
Expand Down Expand Up @@ -246,7 +243,7 @@ private BoundBlock RewriteDeclarationUsingStatement(
BoundExpression tempInit = MakeConversionNode(
declarationSyntax,
boundLocal,
iDisposableConversion,
Conversion.ImplicitDynamic,
iDisposableType,
@checked: false);

Expand Down
Loading