Skip to content

Commit d8b839e

Browse files
authored
BoundUsingLocalDeclarations/BoundUsingStatement - don't store Conversion in the node. (#56954)
1 parent 6142dbe commit d8b839e

File tree

5 files changed

+30
-57
lines changed

5 files changed

+30
-57
lines changed

src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ internal static BoundStatement BindUsingStatementOrDeclarationFromParts(SyntaxNo
100100
Debug.Assert((object)disposableInterface != null);
101101
bool hasErrors = ReportUseSite(disposableInterface, diagnostics, hasAwait ? awaitKeyword : usingKeyword);
102102

103-
Conversion iDisposableConversion;
104103
ImmutableArray<BoundLocalDeclaration> declarationsOpt = default;
105104
BoundMultipleLocalDeclarations? multipleDeclarationsOpt = null;
106105
BoundExpression? expressionOpt = null;
@@ -111,7 +110,7 @@ internal static BoundStatement BindUsingStatementOrDeclarationFromParts(SyntaxNo
111110
if (isExpression)
112111
{
113112
expressionOpt = usingBinderOpt!.BindTargetExpression(diagnostics, originalBinder);
114-
hasErrors |= !populateDisposableConversionOrDisposeMethod(fromExpression: true, out iDisposableConversion, out patternDisposeInfo, out awaitableTypeOpt);
113+
hasErrors |= !bindDisposable(fromExpression: true, out patternDisposeInfo, out awaitableTypeOpt);
115114
}
116115
else
117116
{
@@ -124,13 +123,12 @@ internal static BoundStatement BindUsingStatementOrDeclarationFromParts(SyntaxNo
124123

125124
if (declarationTypeOpt.IsDynamic())
126125
{
127-
iDisposableConversion = Conversion.ImplicitDynamic;
128126
patternDisposeInfo = null;
129127
awaitableTypeOpt = null;
130128
}
131129
else
132130
{
133-
hasErrors |= !populateDisposableConversionOrDisposeMethod(fromExpression: false, out iDisposableConversion, out patternDisposeInfo, out awaitableTypeOpt);
131+
hasErrors |= !bindDisposable(fromExpression: false, out patternDisposeInfo, out awaitableTypeOpt);
134132
}
135133
}
136134

@@ -156,7 +154,7 @@ internal static BoundStatement BindUsingStatementOrDeclarationFromParts(SyntaxNo
156154
// 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
157155
if (isUsingDeclaration)
158156
{
159-
return new BoundUsingLocalDeclarations(syntax, patternDisposeInfo, iDisposableConversion, awaitOpt, declarationsOpt, hasErrors);
157+
return new BoundUsingLocalDeclarations(syntax, patternDisposeInfo, awaitOpt, declarationsOpt, hasErrors);
160158
}
161159
else
162160
{
@@ -167,17 +165,16 @@ internal static BoundStatement BindUsingStatementOrDeclarationFromParts(SyntaxNo
167165
usingBinderOpt.Locals,
168166
multipleDeclarationsOpt,
169167
expressionOpt,
170-
iDisposableConversion,
171168
boundBody,
172169
awaitOpt,
173170
patternDisposeInfo,
174171
hasErrors);
175172
}
176173

177-
bool populateDisposableConversionOrDisposeMethod(bool fromExpression, out Conversion iDisposableConversion, out MethodArgumentInfo? patternDisposeInfo, out TypeSymbol? awaitableType)
174+
bool bindDisposable(bool fromExpression, out MethodArgumentInfo? patternDisposeInfo, out TypeSymbol? awaitableType)
178175
{
179176
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = originalBinder.GetNewCompoundUseSiteInfo(diagnostics);
180-
iDisposableConversion = classifyConversion(fromExpression, disposableInterface, ref useSiteInfo);
177+
Conversion iDisposableConversion = classifyConversion(fromExpression, disposableInterface, ref useSiteInfo);
181178
patternDisposeInfo = null;
182179
awaitableType = null;
183180

@@ -261,12 +258,18 @@ Conversion classifyConversion(bool fromExpression, TypeSymbol targetInterface, r
261258
if (fromExpression)
262259
{
263260
Debug.Assert(expressionOpt is { });
264-
return conversions.ClassifyImplicitConversionFromExpression(expressionOpt, targetInterface, ref useSiteInfo);
261+
var result = conversions.ClassifyImplicitConversionFromExpression(expressionOpt, targetInterface, ref useSiteInfo);
262+
263+
Debug.Assert(expressionOpt.Type?.IsDynamic() != true || result.Kind == ConversionKind.ImplicitDynamic);
264+
return result;
265265
}
266266
else
267267
{
268268
Debug.Assert(declarationTypeOpt is { });
269-
return conversions.ClassifyImplicitConversionFromType(declarationTypeOpt, targetInterface, ref useSiteInfo);
269+
var result = conversions.ClassifyImplicitConversionFromType(declarationTypeOpt, targetInterface, ref useSiteInfo);
270+
271+
Debug.Assert(!declarationTypeOpt.IsDynamic() || result.Kind == ConversionKind.ImplicitDynamic);
272+
return result;
270273
}
271274
}
272275

src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,6 @@
956956
-->
957957
<Node Name="BoundUsingLocalDeclarations" Base="BoundMultipleLocalDeclarationsBase">
958958
<Field Name="PatternDisposeInfoOpt" Type="MethodArgumentInfo?"/>
959-
<Field Name="IDisposableConversion" Type="Conversion"/>
960959
<Field Name="AwaitOpt" Type="BoundAwaitableInfo?"/>
961960
</Node>
962961

@@ -1122,7 +1121,6 @@
11221121
<Field Name="Locals" Type="ImmutableArray&lt;LocalSymbol&gt;"/>
11231122
<Field Name="DeclarationsOpt" Type="BoundMultipleLocalDeclarations?"/>
11241123
<Field Name="ExpressionOpt" Type="BoundExpression?"/>
1125-
<Field Name="IDisposableConversion" Type="Conversion" />
11261124
<Field Name="Body" Type="BoundStatement"/>
11271125
<Field Name="AwaitOpt" Type="BoundAwaitableInfo?"/>
11281126
<Field Name="PatternDisposeInfoOpt" Type="MethodArgumentInfo?"/>

src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs

Lines changed: 11 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_UsingStatement.cs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ public override BoundNode VisitUsingStatement(BoundUsingStatement node)
5252
tryBlock,
5353
node.Locals,
5454
node.DeclarationsOpt.LocalDeclarations,
55-
node.IDisposableConversion,
5655
node.PatternDisposeInfoOpt,
5756
node.AwaitOpt,
5857
awaitKeyword);
@@ -63,7 +62,6 @@ private BoundStatement MakeDeclarationUsingStatement(SyntaxNode syntax,
6362
BoundBlock body,
6463
ImmutableArray<LocalSymbol> locals,
6564
ImmutableArray<BoundLocalDeclaration> declarations,
66-
Conversion iDisposableConversion,
6765
MethodArgumentInfo? patternDisposeInfo,
6866
BoundAwaitableInfo? awaitOpt,
6967
SyntaxToken awaitKeyword)
@@ -73,7 +71,7 @@ private BoundStatement MakeDeclarationUsingStatement(SyntaxNode syntax,
7371
BoundBlock result = body;
7472
for (int i = declarations.Length - 1; i >= 0; i--) //NB: inner-to-outer = right-to-left
7573
{
76-
result = RewriteDeclarationUsingStatement(syntax, declarations[i], result, iDisposableConversion, awaitKeyword, awaitOpt, patternDisposeInfo);
74+
result = RewriteDeclarationUsingStatement(syntax, declarations[i], result, awaitKeyword, awaitOpt, patternDisposeInfo);
7775
}
7876

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

156153
BoundAssignmentOperator tempAssignment;
157154
BoundLocal boundTemp;
158-
if (expressionType is null || expressionType.IsDynamic())
155+
156+
if (expressionType.IsDynamic())
159157
{
160158
// IDisposable temp = (IDisposable) expr;
161159
// or
@@ -169,7 +167,7 @@ private BoundBlock MakeExpressionUsingStatement(BoundUsingStatement node, BoundB
169167
BoundExpression tempInit = MakeConversionNode(
170168
expressionSyntax,
171169
rewrittenExpression,
172-
Conversion.GetTrivialConversion(node.IDisposableConversion.Kind),
170+
Conversion.ImplicitDynamic,
173171
iDisposableType,
174172
@checked: false,
175173
constantValueOpt: rewrittenExpression.ConstantValue);
@@ -208,7 +206,6 @@ private BoundBlock RewriteDeclarationUsingStatement(
208206
SyntaxNode usingSyntax,
209207
BoundLocalDeclaration localDeclaration,
210208
BoundBlock tryBlock,
211-
Conversion iDisposableConversion,
212209
SyntaxToken awaitKeywordOpt,
213210
BoundAwaitableInfo? awaitOpt,
214211
MethodArgumentInfo? patternDisposeInfo)
@@ -246,7 +243,7 @@ private BoundBlock RewriteDeclarationUsingStatement(
246243
BoundExpression tempInit = MakeConversionNode(
247244
declarationSyntax,
248245
boundLocal,
249-
iDisposableConversion,
246+
Conversion.ImplicitDynamic,
250247
iDisposableType,
251248
@checked: false);
252249

0 commit comments

Comments
 (0)