Skip to content

Commit 7c8b543

Browse files
author
Julien Couvreur
committed
Assert shape of the bound tree
1 parent 6e773e2 commit 7c8b543

File tree

11 files changed

+189
-185
lines changed

11 files changed

+189
-185
lines changed

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

Lines changed: 38 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,7 @@
9595
<AbstractNode Name="BoundEarlyValuePlaceholderBase" Base="BoundValuePlaceholderBase">
9696
</AbstractNode>
9797

98-
<!--
99-
This node will not survive the local rewriting,
100-
except in some scenarios in a Linq Expression Tree when the containing node
101-
survives.
102-
-->
103-
<Node Name="BoundValuePlaceholder" Base="BoundValuePlaceholderBase">
98+
<Node Name="BoundValuePlaceholder" Base="BoundValuePlaceholderBase" DoesNotSurvive="LocalRewriting">
10499
</Node>
105100

106101
<!--
@@ -113,9 +108,9 @@
113108

114109
<!--
115110
This node is used to represent an expression returning value of a certain type.
116-
It is used to perform intermediate binding, and will not survive the local rewriting.
111+
It is used to perform intermediate binding.
117112
-->
118-
<Node Name="BoundDeconstructValuePlaceholder" Base="BoundValuePlaceholderBase">
113+
<Node Name="BoundDeconstructValuePlaceholder" Base="BoundValuePlaceholderBase" DoesNotSurvive="LocalRewriting">
119114
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
120115
<Field Name="VariableSymbol" Type="Symbol?"/>
121116
<Field Name="IsDiscardExpression" Type="bool" Null="NotApplicable"/>
@@ -124,24 +119,22 @@
124119
<!--
125120
In a tuple binary operator, this node is used to represent tuple elements in a tuple binary
126121
operator, and to represent an element-wise comparison result to convert back to bool.
127-
It does not survive the initial binding.
128122
-->
129-
<Node Name="BoundTupleOperandPlaceholder" Base="BoundValuePlaceholderBase">
123+
<Node Name="BoundTupleOperandPlaceholder" Base="BoundValuePlaceholderBase" DoesNotSurvive="InitialBinding">
130124
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
131125
</Node>
132126

133127
<!--
134128
This node is used to represent an awaitable expression of a certain type, when binding an using-await statement.
135129
-->
136-
<Node Name="BoundAwaitableValuePlaceholder" Base="BoundValuePlaceholderBase">
130+
<Node Name="BoundAwaitableValuePlaceholder" Base="BoundValuePlaceholderBase" DoesNotSurvive="StateMachineRewriting">
137131
<Field Name="Type" Type="TypeSymbol?" Override="true" Null="allow"/>
138132
</Node>
139133

140134
<!--
141135
This node is used to represent an expression of a certain type, when attempting to bind its pattern dispose method
142-
It does not survive past initial binding.
143136
-->
144-
<Node Name="BoundDisposableValuePlaceholder" Base="BoundValuePlaceholderBase">
137+
<Node Name="BoundDisposableValuePlaceholder" Base="BoundValuePlaceholderBase" DoesNotSurvive="InitialBinding">
145138
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
146139
</Node>
147140

@@ -156,29 +149,29 @@
156149
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
157150
</Node>
158151

159-
<!-- This node is used to represent the receiver for an implicit Index or Range indexer. It does not survive lowering -->
160-
<Node Name="BoundImplicitIndexerReceiverPlaceholder" Base="BoundValuePlaceholderBase">
152+
<!-- This node is used to represent the receiver for an implicit Index or Range indexer. -->
153+
<Node Name="BoundImplicitIndexerReceiverPlaceholder" Base="BoundValuePlaceholderBase" DoesNotSurvive="LocalRewriting">
161154
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
162155
<Field Name="IsEquivalentToThisReference" Type="bool" PropertyOverrides="true"/>
163156
</Node>
164157

165-
<!-- This node represents the receiver for a list pattern. It does not survive lowering -->
166-
<Node Name="BoundListPatternReceiverPlaceholder" Base="BoundEarlyValuePlaceholderBase">
158+
<!-- This node represents the receiver for a list pattern. -->
159+
<Node Name="BoundListPatternReceiverPlaceholder" Base="BoundEarlyValuePlaceholderBase" DoesNotSurvive="LocalRewriting">
167160
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
168161
</Node>
169162

170-
<!-- This node represents the Index value of accessing an element in a list pattern. It does not survive lowering -->
171-
<Node Name="BoundListPatternIndexPlaceholder" Base="BoundEarlyValuePlaceholderBase">
163+
<!-- This node represents the Index value of accessing an element in a list pattern. -->
164+
<Node Name="BoundListPatternIndexPlaceholder" Base="BoundEarlyValuePlaceholderBase" DoesNotSurvive="LocalRewriting">
172165
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
173166
</Node>
174167

175-
<!-- This node represents the receiver for a slice pattern. It does not survive lowering -->
176-
<Node Name="BoundSlicePatternReceiverPlaceholder" Base="BoundEarlyValuePlaceholderBase">
168+
<!-- This node represents the receiver for a slice pattern. -->
169+
<Node Name="BoundSlicePatternReceiverPlaceholder" Base="BoundEarlyValuePlaceholderBase" DoesNotSurvive="LocalRewriting">
177170
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
178171
</Node>
179172

180-
<!-- This node represents the Range value of accessing a range in a slice pattern. It does not survive lowering -->
181-
<Node Name="BoundSlicePatternRangePlaceholder" Base="BoundEarlyValuePlaceholderBase">
173+
<!-- This node represents the Range value of accessing a range in a slice pattern. -->
174+
<Node Name="BoundSlicePatternRangePlaceholder" Base="BoundEarlyValuePlaceholderBase" DoesNotSurvive="LocalRewriting">
182175
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
183176
</Node>
184177

@@ -393,9 +386,8 @@
393386
<Field Name="IsManaged" Type="bool"/>
394387
</Node>
395388
<!-- Represents an AddressOf operator that has not yet been assigned to a
396-
target-type. It has no natural type, and should not survive initial binding
397-
except in error cases that are observable via the SemanticModel. -->
398-
<Node Name="BoundUnconvertedAddressOfOperator" Base="BoundExpression">
389+
target-type. It has no natural type. -->
390+
<Node Name="BoundUnconvertedAddressOfOperator" Base="BoundExpression" DoesNotSurvive="InitialBinding">
399391
<Field Name="Operand" Type="BoundMethodGroup"/>
400392
<!-- Type is null. -->
401393
<Field Name="Type" Type="TypeSymbol?" Override="true" Null="always"/>
@@ -637,7 +629,7 @@
637629
<Field Name="RightOperand" Type="BoundExpression" />
638630
</Node>
639631

640-
<Node Name="BoundUnconvertedConditionalOperator" Base="BoundExpression">
632+
<Node Name="BoundUnconvertedConditionalOperator" Base="BoundExpression" DoesNotSurvive="InitialBinding">
641633
<!-- Type is null. -->
642634
<Field Name="Type" Type="TypeSymbol?" Override="true" Null="always"/>
643635

@@ -694,7 +686,7 @@
694686
<Field Name="Expression" Type="BoundExpression"/>
695687
</Node>
696688

697-
<Node Name="BoundAwaitableInfo" Base="BoundNode" HasValidate="true">
689+
<Node Name="BoundAwaitableInfo" Base="BoundNode" HasValidate="true" DoesNotSurvive="StateMachineRewriting">
698690
<!-- Used to refer to the awaitable expression in GetAwaiter -->
699691
<Field Name="AwaitableInstancePlaceholder" Type="BoundAwaitableValuePlaceholder?" Null="allow" />
700692
<Field Name="IsDynamic" Type="bool"/>
@@ -709,7 +701,7 @@
709701
<Field Name="RuntimeAsyncAwaitCallPlaceholder" Type="BoundAwaitableValuePlaceholder?" Null="allow"/>
710702
</Node>
711703

712-
<Node Name="BoundAwaitExpression" Base="BoundExpression">
704+
<Node Name="BoundAwaitExpression" Base="BoundExpression" DoesNotSurvive="StateMachineRewriting">
713705
<!-- Non-null type is required for this node kind -->
714706
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
715707

@@ -843,7 +835,7 @@
843835
Default literals can convert to the target type.
844836
Does not survive initial lowering.
845837
-->
846-
<Node Name="BoundDefaultLiteral" Base="BoundExpression">
838+
<Node Name="BoundDefaultLiteral" Base="BoundExpression" DoesNotSurvive="LocalRewriting">
847839
<!-- Type is null. -->
848840
<Field Name="Type" Type="TypeSymbol?" Override="true" Null="always"/>
849841
</Node>
@@ -1130,7 +1122,7 @@
11301122
Bound node that represents a local function declaration:
11311123
void Foo() { }
11321124
-->
1133-
<Node Name="BoundLocalFunctionStatement" Base="BoundStatement">
1125+
<Node Name="BoundLocalFunctionStatement" Base="BoundStatement" DoesNotSurvive="ClosureConversion">
11341126
<!-- Must be a LocalFunctionSymbol until the node reaches LocalRewriter -->
11351127
<Field Name="Symbol" Type="MethodSymbol"/>
11361128
<Field Name="BlockBody" Type="BoundBlock?"/>
@@ -1161,11 +1153,11 @@
11611153
<Field Name="Checked" Type="bool"/>
11621154
</Node>
11631155

1164-
<Node Name="BoundYieldReturnStatement" Base="BoundStatement">
1156+
<Node Name="BoundYieldReturnStatement" Base="BoundStatement" DoesNotSurvive="StateMachineRewriting">
11651157
<Field Name="Expression" Type="BoundExpression" Null="disallow"/>
11661158
</Node>
11671159

1168-
<Node Name="BoundYieldBreakStatement" Base="BoundStatement"/>
1160+
<Node Name="BoundYieldBreakStatement" Base="BoundStatement" DoesNotSurvive="StateMachineRewriting"/>
11691161

11701162
<Node Name="BoundThrowStatement" Base="BoundStatement">
11711163
<Field Name="ExpressionOpt" Type="BoundExpression?"/>
@@ -1223,7 +1215,7 @@
12231215
<Field Name="LengthBasedStringSwitchDataOpt" Type="LengthBasedStringSwitchData?" />
12241216
</Node>
12251217

1226-
<Node Name="BoundIfStatement" Base="BoundStatement">
1218+
<Node Name="BoundIfStatement" Base="BoundStatement" DoesNotSurvive="LocalRewriting">
12271219
<Field Name="Condition" Type="BoundExpression"/>
12281220
<Field Name="Consequence" Type="BoundStatement"/>
12291221
<Field Name="AlternativeOpt" Type="BoundStatement?"/>
@@ -1292,7 +1284,7 @@
12921284
<Field Name="TargetPlaceholder" Type="BoundDeconstructValuePlaceholder" Null="disallow"/>
12931285
</Node>
12941286

1295-
<Node Name="BoundUsingStatement" Base="BoundStatement">
1287+
<Node Name="BoundUsingStatement" Base="BoundStatement" DoesNotSurvive="LocalRewriting">
12961288
<!-- DeclarationsOpt and ExpressionOpt cannot both be non-null. -->
12971289
<Field Name="Locals" Type="ImmutableArray&lt;LocalSymbol&gt;"/>
12981290
<Field Name="DeclarationsOpt" Type="BoundMultipleLocalDeclarations?"/>
@@ -1529,7 +1521,7 @@
15291521
<Field Name="Label" Type="LabelSymbol" Null="disallow"/>
15301522
</Node>
15311523

1532-
<Node Name="BoundUnconvertedSwitchExpression" Base="BoundSwitchExpression">
1524+
<Node Name="BoundUnconvertedSwitchExpression" Base="BoundSwitchExpression" DoesNotSurvive="InitialBinding">
15331525
</Node>
15341526

15351527
<!--
@@ -1881,9 +1873,8 @@
18811873

18821874
<!--
18831875
This node is used to represent a target-typed object creation expression
1884-
It does not survive past initial binding.
18851876
-->
1886-
<Node Name="BoundUnconvertedObjectCreationExpression" Base="BoundExpression">
1877+
<Node Name="BoundUnconvertedObjectCreationExpression" Base="BoundExpression" DoesNotSurvive="InitialBinding">
18871878
<!-- Type is not significant for this node type; always null -->
18881879
<Field Name="Type" Type="TypeSymbol?" Override="true" Null="always"/>
18891880
<Field Name="Arguments" Type="ImmutableArray&lt;BoundExpression&gt;"/>
@@ -1927,9 +1918,8 @@
19271918

19281919
<!--
19291920
An unconverted collection expression.
1930-
It does not survive past initial binding.
19311921
-->
1932-
<Node Name="BoundUnconvertedCollectionExpression" Base="BoundCollectionExpressionBase">
1922+
<Node Name="BoundUnconvertedCollectionExpression" Base="BoundCollectionExpressionBase" DoesNotSurvive="InitialBinding">
19331923
<!-- Type is not significant for this node type; always null -->
19341924
<Field Name="Type" Type="TypeSymbol?" Override="true" Null="always"/>
19351925
</Node>
@@ -1990,7 +1980,7 @@
19901980
Once converted to a target type, they cannot be target-typed again.
19911981
The tuple literal is one which has not been converted to a target type.
19921982
-->
1993-
<Node Name="BoundTupleLiteral" Base="BoundTupleExpression">
1983+
<Node Name="BoundTupleLiteral" Base="BoundTupleExpression" DoesNotSurvive="InitialBinding">
19941984
<!--
19951985
It is possible for a tuple to not have a type in a literal form
19961986
Ex:
@@ -2345,9 +2335,9 @@
23452335

23462336
<!--
23472337
Special node to encapsulate initializers added into a constructor.
2348-
Helps to do special optimizations in lowering, doesn't survive the lowering.
2338+
Helps to do special optimizations in lowering.
23492339
-->
2350-
<Node Name="BoundTypeOrInstanceInitializers" Base="BoundStatementList">
2340+
<Node Name="BoundTypeOrInstanceInitializers" Base="BoundStatementList" DoesNotSurvive="LocalRewriting">
23512341
</Node>
23522342

23532343
<Node Name="BoundNameOfOperator" Base="BoundExpression">
@@ -2365,19 +2355,19 @@
23652355
<Field Name="ConstantValueOpt" Type="ConstantValue?" PropertyOverrides="true"/>
23662356
</AbstractNode>
23672357

2368-
<Node Name="BoundUnconvertedInterpolatedString" Base="BoundInterpolatedStringBase">
2358+
<Node Name="BoundUnconvertedInterpolatedString" Base="BoundInterpolatedStringBase" DoesNotSurvive="InitialBinding">
23692359
</Node>
23702360

23712361
<Node Name="BoundInterpolatedString" Base="BoundInterpolatedStringBase">
23722362
<Field Name="InterpolationData" Type="InterpolatedStringHandlerData?"/>
23732363
</Node>
23742364

2375-
<Node Name="BoundInterpolatedStringHandlerPlaceholder" Base="BoundValuePlaceholderBase"/>
2365+
<Node Name="BoundInterpolatedStringHandlerPlaceholder" Base="BoundValuePlaceholderBase" DoesNotSurvive="LocalRewriting"/>
23762366

23772367
<!-- A typed expression placeholder for the arguments to the constructor call for an interpolated string handler
23782368
conversion. We intentionally use a placeholder for overload resolution here to ensure that no conversion
2379-
from expression can occur. This node is only used for intermediate binding and does not survive local rewriting. -->
2380-
<Node Name="BoundInterpolatedStringArgumentPlaceholder" Base="BoundValuePlaceholderBase">
2369+
from expression can occur. -->
2370+
<Node Name="BoundInterpolatedStringArgumentPlaceholder" Base="BoundValuePlaceholderBase" DoesNotSurvive="LocalRewriting">
23812371
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow" />
23822372
<!-- The index in the containing member of the argument this is the placeholder for. Should be a positive number or
23832373
one of the constants in the other part of the partial class. -->
@@ -2573,7 +2563,7 @@
25732563
<Node Name="OutVariablePendingInference" Base="VariablePendingInference" />
25742564

25752565
<!-- The node is transformed into BoundLocal or BoundFieldAccess after inference -->
2576-
<Node Name="DeconstructionVariablePendingInference" Base="VariablePendingInference" />
2566+
<Node Name="DeconstructionVariablePendingInference" Base="VariablePendingInference" DoesNotSurvive="LocalRewriting" />
25772567

25782568
<!-- The node is transformed into BoundDeconstructValuePlaceholder after inference -->
25792569
<Node Name="OutDeconstructVarPendingInference" Base="BoundExpression">

src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,7 @@ private void CompileSynthesizedMethods(TypeCompilationState compilationState)
791791
}
792792

793793
SetGlobalErrorIfTrue(diagnosticsThisMethod.HasAnyErrors());
794+
PipelinePhaseValidator.Assert(loweredBody, PipelinePhase.StateMachineRewriting);
794795

795796
if (_emitMethodBodies && !diagnosticsThisMethod.HasAnyErrors() && !_globalHasErrors)
796797
{
@@ -1499,6 +1500,8 @@ internal static BoundStatement LowerBodyOrInitializer(
14991500
return body;
15001501
}
15011502

1503+
PipelinePhaseValidator.Assert(body, PipelinePhase.InitialBinding);
1504+
15021505
try
15031506
{
15041507
var loweredBody = LocalRewriter.Rewrite(
@@ -1585,6 +1588,8 @@ internal static BoundStatement LowerBodyOrInitializer(
15851588
return bodyWithoutLambdas;
15861589
}
15871590

1591+
PipelinePhaseValidator.Assert(bodyWithoutLambdas, PipelinePhase.ClosureConversion);
1592+
15881593
BoundStatement bodyWithoutIterators = IteratorRewriter.Rewrite(bodyWithoutLambdas, method, methodOrdinal, stateMachineStateDebugInfoBuilder, lazyVariableSlotAllocator, compilationState, diagnostics,
15891594
out IteratorStateMachine iteratorStateMachine);
15901595

@@ -1608,6 +1613,8 @@ internal static BoundStatement LowerBodyOrInitializer(
16081613
Debug.Assert(iteratorStateMachine is null || asyncStateMachine is null);
16091614
stateMachineTypeOpt = (StateMachineTypeSymbol)iteratorStateMachine ?? asyncStateMachine;
16101615

1616+
PipelinePhaseValidator.Assert(bodyWithoutAsync, PipelinePhase.StateMachineRewriting);
1617+
16111618
return bodyWithoutAsync;
16121619
}
16131620
catch (BoundTreeVisitor.CancelledByStackGuardException ex)

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

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

src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncRewriter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ internal static BoundStatement Rewrite(
6666
method.GetFirstLocation());
6767

6868
stateMachineType = null;
69-
return bodyWithAwaitLifted;
69+
return (BoundStatement)bodyWithAwaitLifted.WithHasErrors();
7070
}
7171

7272
// The CLR doesn't support adding fields to structs, so in order to enable EnC in an async method we need to generate a class.
@@ -82,7 +82,7 @@ internal static BoundStatement Rewrite(
8282

8383
if (!rewriter.VerifyPresenceOfRequiredAPIs())
8484
{
85-
return bodyWithAwaitLifted;
85+
return (BoundStatement)bodyWithAwaitLifted.WithHasErrors();
8686
}
8787

8888
try

src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/RuntimeAsyncRewriter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ private RuntimeAsyncRewriter(SyntheticBoundNodeFactory factory, IReadOnlySet<Sym
120120
_factory.Diagnostics.Add(ErrorCode.ERR_UnsupportedFeatureInRuntimeAsync,
121121
node.Syntax.Location,
122122
_factory.CurrentFunction);
123-
return node;
123+
return node.WithHasErrors();
124124
}
125125

126126
var runtimeAsyncAwaitCall = awaitableInfo.RuntimeAsyncAwaitCall;

src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorRewriter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ internal static BoundStatement Rewrite(
8686
var rewriter = new IteratorRewriter(body, method, isEnumerable, stateMachineType, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics);
8787
if (!rewriter.VerifyPresenceOfRequiredAPIs())
8888
{
89-
return body;
89+
return (BoundStatement)body.WithHasErrors();
9090
}
9191

9292
return rewriter.Rewrite();

0 commit comments

Comments
 (0)