Skip to content
Open
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
86 changes: 38 additions & 48 deletions src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,7 @@
<AbstractNode Name="BoundEarlyValuePlaceholderBase" Base="BoundValuePlaceholderBase">
</AbstractNode>

<!--
This node will not survive the local rewriting,
except in some scenarios in a Linq Expression Tree when the containing node
survives.
Copy link
Member

Choose a reason for hiding this comment

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

except in some scenarios in a Linq Expression Tree

Are these cases tested? Why doesn't the validator fail for them? Are the bound nodes flagged as erroneous?

-->
<Node Name="BoundValuePlaceholder" Base="BoundValuePlaceholderBase">
<Node Name="BoundValuePlaceholder" Base="BoundValuePlaceholderBase" DoesNotSurvive="LocalRewriting">
</Node>

<!--
Expand All @@ -113,9 +108,9 @@

<!--
This node is used to represent an expression returning value of a certain type.
It is used to perform intermediate binding, and will not survive the local rewriting.
It is used to perform intermediate binding.
-->
<Node Name="BoundDeconstructValuePlaceholder" Base="BoundValuePlaceholderBase">
<Node Name="BoundDeconstructValuePlaceholder" Base="BoundValuePlaceholderBase" DoesNotSurvive="LocalRewriting">
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
<Field Name="VariableSymbol" Type="Symbol?"/>
<Field Name="IsDiscardExpression" Type="bool" Null="NotApplicable"/>
Expand All @@ -124,24 +119,22 @@
<!--
In a tuple binary operator, this node is used to represent tuple elements in a tuple binary
operator, and to represent an element-wise comparison result to convert back to bool.
It does not survive the initial binding.
-->
<Node Name="BoundTupleOperandPlaceholder" Base="BoundValuePlaceholderBase">
<Node Name="BoundTupleOperandPlaceholder" Base="BoundValuePlaceholderBase" DoesNotSurvive="InitialBinding">
<Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/>
</Node>

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

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

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

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

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

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

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

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

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

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

Expand Down Expand Up @@ -694,7 +686,7 @@
<Field Name="Expression" Type="BoundExpression"/>
</Node>

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

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

Expand Down Expand Up @@ -843,7 +835,7 @@
Default literals can convert to the target type.
Does not survive initial lowering.
-->
<Node Name="BoundDefaultLiteral" Base="BoundExpression">
<Node Name="BoundDefaultLiteral" Base="BoundExpression" DoesNotSurvive="LocalRewriting">
<!-- Type is null. -->
<Field Name="Type" Type="TypeSymbol?" Override="true" Null="always"/>
</Node>
Expand Down Expand Up @@ -1130,7 +1122,7 @@
Bound node that represents a local function declaration:
void Foo() { }
-->
<Node Name="BoundLocalFunctionStatement" Base="BoundStatement">
<Node Name="BoundLocalFunctionStatement" Base="BoundStatement" DoesNotSurvive="ClosureConversion">
<!-- Must be a LocalFunctionSymbol until the node reaches LocalRewriter -->
<Field Name="Symbol" Type="MethodSymbol"/>
<Field Name="BlockBody" Type="BoundBlock?"/>
Expand Down Expand Up @@ -1161,11 +1153,11 @@
<Field Name="Checked" Type="bool"/>
</Node>

<Node Name="BoundYieldReturnStatement" Base="BoundStatement">
<Node Name="BoundYieldReturnStatement" Base="BoundStatement" DoesNotSurvive="StateMachineRewriting">
<Field Name="Expression" Type="BoundExpression" Null="disallow"/>
</Node>

<Node Name="BoundYieldBreakStatement" Base="BoundStatement"/>
<Node Name="BoundYieldBreakStatement" Base="BoundStatement" DoesNotSurvive="StateMachineRewriting"/>

<Node Name="BoundThrowStatement" Base="BoundStatement">
<Field Name="ExpressionOpt" Type="BoundExpression?"/>
Expand Down Expand Up @@ -1223,7 +1215,7 @@
<Field Name="LengthBasedStringSwitchDataOpt" Type="LengthBasedStringSwitchData?" />
</Node>

<Node Name="BoundIfStatement" Base="BoundStatement">
<Node Name="BoundIfStatement" Base="BoundStatement" DoesNotSurvive="LocalRewriting">
<Field Name="Condition" Type="BoundExpression"/>
<Field Name="Consequence" Type="BoundStatement"/>
<Field Name="AlternativeOpt" Type="BoundStatement?"/>
Expand Down Expand Up @@ -1292,7 +1284,7 @@
<Field Name="TargetPlaceholder" Type="BoundDeconstructValuePlaceholder" Null="disallow"/>
</Node>

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

<Node Name="BoundUnconvertedSwitchExpression" Base="BoundSwitchExpression">
<Node Name="BoundUnconvertedSwitchExpression" Base="BoundSwitchExpression" DoesNotSurvive="InitialBinding">
</Node>

<!--
Expand Down Expand Up @@ -1881,9 +1873,8 @@

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

<!--
An unconverted collection expression.
It does not survive past initial binding.
-->
<Node Name="BoundUnconvertedCollectionExpression" Base="BoundCollectionExpressionBase">
<Node Name="BoundUnconvertedCollectionExpression" Base="BoundCollectionExpressionBase" DoesNotSurvive="InitialBinding">
<!-- Type is not significant for this node type; always null -->
<Field Name="Type" Type="TypeSymbol?" Override="true" Null="always"/>
</Node>
Expand Down Expand Up @@ -1990,7 +1980,7 @@
Once converted to a target type, they cannot be target-typed again.
The tuple literal is one which has not been converted to a target type.
-->
<Node Name="BoundTupleLiteral" Base="BoundTupleExpression">
<Node Name="BoundTupleLiteral" Base="BoundTupleExpression" DoesNotSurvive="InitialBinding">
<!--
It is possible for a tuple to not have a type in a literal form
Ex:
Expand Down Expand Up @@ -2345,9 +2335,9 @@

<!--
Special node to encapsulate initializers added into a constructor.
Helps to do special optimizations in lowering, doesn't survive the lowering.
Helps to do special optimizations in lowering.
-->
<Node Name="BoundTypeOrInstanceInitializers" Base="BoundStatementList">
<Node Name="BoundTypeOrInstanceInitializers" Base="BoundStatementList" DoesNotSurvive="LocalRewriting">
</Node>

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

<Node Name="BoundUnconvertedInterpolatedString" Base="BoundInterpolatedStringBase">
<Node Name="BoundUnconvertedInterpolatedString" Base="BoundInterpolatedStringBase" DoesNotSurvive="InitialBinding">
</Node>

<Node Name="BoundInterpolatedString" Base="BoundInterpolatedStringBase">
<Field Name="InterpolationData" Type="InterpolatedStringHandlerData?"/>
</Node>

<Node Name="BoundInterpolatedStringHandlerPlaceholder" Base="BoundValuePlaceholderBase"/>
<Node Name="BoundInterpolatedStringHandlerPlaceholder" Base="BoundValuePlaceholderBase" DoesNotSurvive="LocalRewriting"/>

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

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

<!-- The node is transformed into BoundDeconstructValuePlaceholder after inference -->
<Node Name="OutDeconstructVarPendingInference" Base="BoundExpression">
Expand Down
7 changes: 7 additions & 0 deletions src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,7 @@ private void CompileSynthesizedMethods(TypeCompilationState compilationState)
}

SetGlobalErrorIfTrue(diagnosticsThisMethod.HasAnyErrors());
PipelinePhaseValidator.AssertAfterStateMachineRewriting(loweredBody);

if (_emitMethodBodies && !diagnosticsThisMethod.HasAnyErrors() && !_globalHasErrors)
{
Expand Down Expand Up @@ -1499,6 +1500,8 @@ internal static BoundStatement LowerBodyOrInitializer(
return body;
}

PipelinePhaseValidator.AssertAfterInitialBinding(body);

try
{
var loweredBody = LocalRewriter.Rewrite(
Expand Down Expand Up @@ -1585,6 +1588,8 @@ internal static BoundStatement LowerBodyOrInitializer(
return bodyWithoutLambdas;
}

PipelinePhaseValidator.AssertAfterClosureConversion(bodyWithoutLambdas);

BoundStatement bodyWithoutIterators = IteratorRewriter.Rewrite(bodyWithoutLambdas, method, methodOrdinal, stateMachineStateDebugInfoBuilder, lazyVariableSlotAllocator, compilationState, diagnostics,
out IteratorStateMachine iteratorStateMachine);

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

PipelinePhaseValidator.AssertAfterStateMachineRewriting(bodyWithoutAsync);

return bodyWithoutAsync;
}
catch (BoundTreeVisitor.CancelledByStackGuardException ex)
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 @@ -66,7 +66,7 @@ internal static BoundStatement Rewrite(
method.GetFirstLocation());

stateMachineType = null;
return bodyWithAwaitLifted;
return (BoundStatement)bodyWithAwaitLifted.WithHasErrors();
}

// 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.
Expand All @@ -82,7 +82,7 @@ internal static BoundStatement Rewrite(

if (!rewriter.VerifyPresenceOfRequiredAPIs())
{
return bodyWithAwaitLifted;
return (BoundStatement)bodyWithAwaitLifted.WithHasErrors();
}

try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ private RuntimeAsyncRewriter(SyntheticBoundNodeFactory factory, IReadOnlySet<Sym
_factory.Diagnostics.Add(ErrorCode.ERR_UnsupportedFeatureInRuntimeAsync,
node.Syntax.Location,
_factory.CurrentFunction);
return node;
return node.WithHasErrors();
}

var runtimeAsyncAwaitCall = awaitableInfo.RuntimeAsyncAwaitCall;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ internal static BoundStatement Rewrite(
var rewriter = new IteratorRewriter(body, method, isEnumerable, stateMachineType, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics);
if (!rewriter.VerifyPresenceOfRequiredAPIs())
{
return body;
return (BoundStatement)body.WithHasErrors();
}

return rewriter.Rewrite();
Expand Down
Loading