/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml
2 720 строк
134 KB
AlekseyTs
Fix crash in code gen (#84681)
30 июл 2026, 15:07
Не верифицирован
30 июл 2026, 15:07
677eb5a
Код
Авторство
О чём код?
<?xml version="1.0" encoding="utf-8"?> <!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. --> <!-- To re-generate source from this file, run eng/generate-compiler-code.cmd Important things to know about reference types, value types, and nulls. By default, all fields of reference type are checked (in debug) to be non-null. This can be modified by used the "Null" attribute, which can be one of the following values: disallow (default) - disallow null values allow - allow null values always - always null - only used in an override to indicate that this subclass always sets this field to null. notApplicable - its a value type, so it cannot be null In order to generate code, the generator needs to know what types beyond the built-in types are value types. This is indicated via a "ValueType" declaration. --> <Tree Root="BoundNode"> <!-- Don't put ImmutableArray here, that's handled in a special way internally.--> <ValueType Name="ConversionKind"/> <ValueType Name="Conversion"/> <ValueType Name="TextSpan"/> <ValueType Name="ThreeState"/> <ValueType Name="UnaryOperatorKind"/> <ValueType Name="BinaryOperatorKind"/> <ValueType Name="LookupResultKind"/> <ValueType Name="NoOpStatementFlavor"/> <ValueType Name="RefKind"/> <ValueType Name="BoundLocalDeclarationKind"/> <ValueType Name="NullableAnnotation"/> <ValueType Name="ErrorCode"/> <ValueType Name="ReadOnlyBindingDiagnostic"/> <ValueType Name="InterpolatedStringHandlerData"/> <ValueType Name="WellKnownMember"/> <ValueType Name="CollectionExpressionTypeKind"/> <ValueType Name="AccessorKind" /> <ValueType Name="SafeContext" /> <ValueType Name="InConversionGroupFlags" /> <ValueType Name="UnionMatchingMode" /> <AbstractNode Name="BoundInitializer" Base="BoundNode"/> <AbstractNode Name="BoundEqualsValue" Base="BoundInitializer"> <Field Name="Locals" Type="ImmutableArray<LocalSymbol>"/> <!-- Expression representing the value. --> <Field Name="Value" Type="BoundExpression"/> </AbstractNode> <!-- Bound node that represents the binding of an "= Value" construct in a field declaration. Appears only in bound trees generated by a SemanticModel. --> <Node Name="BoundFieldEqualsValue" Base="BoundEqualsValue"> <!-- Field receiving the value. --> <Field Name="Field" Type="FieldSymbol"/> </Node> <!-- Bound node that represents the binding of an "= Value" construct in a property declaration. Appears only in bound trees generated by a SemanticModel. --> <Node Name="BoundPropertyEqualsValue" Base="BoundEqualsValue"> <!-- Property receiving the value. --> <Field Name="Property" Type="PropertySymbol"/> </Node> <!-- Bound node that represents the binding of an "= Value" construct in a parameter declaration. Appears only in bound trees generated by a SemanticModel. --> <Node Name="BoundParameterEqualsValue" Base="BoundEqualsValue"> <!-- Parameter receiving the value. --> <Field Name="Parameter" Type="ParameterSymbol"/> </Node> <Node Name="BoundGlobalStatementInitializer" Base="BoundInitializer"> <Field Name="Statement" Type="BoundStatement"/> </Node> <AbstractNode Name="BoundExpression" Base="BoundNode"> <Field Name="Type" Type="TypeSymbol?"/> </AbstractNode> <!-- Consider adding a val escape to all placeholder nodes. Consider marking all placeholder nodes as compiler generated. --> <AbstractNode Name="BoundValuePlaceholderBase" Base="BoundExpression"> </AbstractNode> <!-- Placeholders that are replaced by PlaceholderReplacer, ie before they get visited by LocalRewriter --> <AbstractNode Name="BoundEarlyValuePlaceholderBase" Base="BoundValuePlaceholderBase"> </AbstractNode> <Node Name="BoundValuePlaceholder" Base="BoundValuePlaceholderBase" DoesNotSurvive="LocalRewriting"> </Node> <!-- This node is used in memory safety analysis to represent a receiver that will be replaced with a copy captured in a temp during IL gen. --> <Node Name="BoundCapturedReceiverPlaceholder" Base="BoundValuePlaceholderBase"> <Field Name="Receiver" Type="BoundExpression" SkipInVisit="true"/> </Node> <!-- This node is used to represent an expression returning value of a certain type. It is used to perform intermediate binding. --> <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"/> </Node> <!-- 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. --> <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" 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 --> <Node Name="BoundDisposableValuePlaceholder" Base="BoundValuePlaceholderBase" DoesNotSurvive="InitialBinding"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> </Node> <!-- The implicit collection in an object or collection initializer expression. --> <Node Name="BoundObjectOrCollectionValuePlaceholder" Base="BoundValuePlaceholderBase"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="IsNewInstance" Type="bool" Null="NotApplicable"/> </Node> <!-- This node is used to represent the argument of type Index or Range for an implicit Index or Range indexer. It does not survive lowering --> <Node Name="BoundImplicitIndexerValuePlaceholder" Base="BoundValuePlaceholderBase"> <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. --> <Node Name="BoundImplicitIndexerReceiverPlaceholder" Base="BoundValuePlaceholderBase" DoesNotSurvive="LocalRewriting"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="IsEquivalentToThisReference" Type="bool" PropertyOverrides="true"/> <!-- The original receiver expression this placeholder stands in for. Used to delegate value checks. --> <Field Name="Receiver" Type="BoundExpression" SkipInVisit="true"/> </Node> <!-- 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. --> <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. --> <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. --> <Node Name="BoundSlicePatternRangePlaceholder" Base="BoundEarlyValuePlaceholderBase" DoesNotSurvive="LocalRewriting"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> </Node> <!-- This node represents the ReadOnlySpan<T> for the elements passed as the last argument to a collection builder method. It does not survive lowering. --> <Node Name="BoundCollectionBuilderElementsPlaceholder" Base="BoundValuePlaceholderBase" DoesNotSurvive="LocalRewriting" /> <!-- only used by codegen --> <Node Name="BoundDup" Base="BoundExpression"> <!-- when duplicating a local or parameter, must remember original ref kind --> <Field Name="RefKind" Type="RefKind" Null="NotApplicable"/> </Node> <!-- Wrapper node used to prevent passing the underlying expression by direct reference --> <Node Name="BoundPassByCopy" Base="BoundExpression"> <Field Name="Expression" Type="BoundExpression"/> </Node> <!-- An expression is classified as one of the following: A value. Every value has an associated type. A variable. Every variable has an associated type. A namespace. A type. A method group. ... A null literal. An anonymous function. A property access. An event access. An indexer access. Nothing. (An expression which is a method call that returns void.) --> <!-- This node is used when we can't create a real expression node because things are too broken. Example: lookup of a name fails to find anything. --> <Node Name="BoundBadExpression" Base="BoundExpression" HasValidate="true"> <!-- Categorizes the way in which "Symbols" is bad. --> <Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/> <!-- These symbols will be returned from the GetSemanticInfo API if it examines this bound node. --> <Field Name="Symbols" Type="ImmutableArray<Symbol?>" SkipInNullabilityRewriter="true"/> <!-- Any child bound nodes that we need to preserve are put here. --> <Field Name="ChildBoundNodes" Type="ImmutableArray<BoundExpression>"/> </Node> <!-- This node is used when we can't create a real statement because things are too broken. --> <Node Name="BoundBadStatement" Base="BoundStatement"> <!-- Any child bound nodes that we need to preserve are put here. --> <Field Name="ChildBoundNodes" Type="ImmutableArray<BoundNode>"/> </Node> <!-- This node is used to wrap the BoundBlock for a finally extracted by AsyncExceptionHandlerRewriter. It is processed and removed by AsyncIteratorRewriter. --> <Node Name="BoundExtractedFinallyBlock" Base="BoundStatement"> <Field Name="FinallyBlock" Type="BoundBlock"/> </Node> <Node Name="BoundTypeExpression" Base="BoundExpression"> <Field Name="AliasOpt" Type="AliasSymbol?"/> <!-- We're going to stash some extra information in the Color Color case so that the binding API can return the correct information. Consider the following example: class C { public class Inner { public static C M() { return null; } } } class F { public C C; void M(C c) { M(/*<bind>*/C/*</bind>*/.Inner.M()); } } The bound tree for "C.Inner.M()" is a bound call with a bound type expression (C.Inner) as its receiver. However, there is no bound node corresponding to C. As a result, the semantic model will attempt to bind it and the binder will return F.C, since it will have no context. That's why we need to have a node for C in the (initial) bound tree. It could conceivably be useful to store other types of expressions as well (e.g. BoundNamespaceExpressions), but then it would be much harder to identify the scenarios in which this property is populated. --> <Field Name="BoundContainingTypeOpt" Type="BoundTypeExpression?"/> <!-- The provided dimensions in an array type expression where dimensions were provided in error. --> <Field Name="BoundDimensionsOpt" Type="ImmutableArray<BoundExpression>" Null="allow"/> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="TypeWithAnnotations" Type="TypeWithAnnotations"/> </Node> <!-- When binding "name1.name2" we normally can tell what name1 is. There is however a case where name1 could be either a value (field, property, parameter, local) or its type. This only happens if value named exactly the same as its type - famous "Color As Color". That alone is not enough to cause trouble as we can do a lookup for name2 and see if it requires a receiver (then name1 is a value) or if it does not (then name1 is a type). The problem only arises when name2 is an overloaded method or property. In such case we must defer type/value decision until overload resolution selects one of the candidates. As a result we need this node that represents name1 in the state where we only know its type and syntax, but do not know yet if it is a Type or Value. NOTE: * The node can only be a qualifier of a method or a property group access as only those may require overload resolution. * The Binder should make sure that such a node doesn't escape the binding process, especially for success scenarios. The binder should resolve the node in a most appropriate way, usually to a member access. Asserts were added in some components to help detect a "leak". --> <Node Name="BoundTypeOrValueExpression" Base="BoundExpression" HasValidate="true" DoesNotSurvive="InitialBinding"> <!-- Type is required for this node type; may not be null --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Binder" Type="Binder" Null="disallow"/> <Field Name="ValueSymbol" Type="Symbol" Null="disallow"/> </Node> <Node Name="BoundNamespaceExpression" Base="BoundExpression"> <!-- Type is not significant for this node type; always null --> <Field Name="Type" Type="TypeSymbol?" Override="true" Null="always"/> <Field Name="NamespaceSymbol" Type="NamespaceSymbol"/> <Field Name="AliasOpt" Type="AliasSymbol?"/> </Node> <!-- EricLi thought we might need a node like this to do "Color Color" correctly. Currently we're handling that in a different way. Dev10 compiler had a node like this. [removed 3/30/2011 by petergo] <Node Name="BoundTypeOrName" Base="BoundExpression"> <Field Name="Type" Type="BoundTypeExpression"/> <Field Name="Name" Type="BoundExpression"/> </Node> --> <Node Name="BoundUnaryOperator" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="OperatorKind" Type="UnaryOperatorKind"/> <Field Name="Operand" Type="BoundExpression"/> <Field Name="ConstantValueOpt" Type="ConstantValue?" PropertyOverrides="true"/> <Field Name="MethodOpt" Type="MethodSymbol?"/> <Field Name="ConstrainedToTypeOpt" Type="TypeSymbol?" Null="allow"/> <Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/> <!--The set of method symbols from which this operator's method was chosen. Only kept in the tree if the operator was an error and overload resolution was unable to choose a best method.--> <Field Name="OriginalUserDefinedOperatorsOpt" Type="ImmutableArray<MethodSymbol>" Null="Allow" SkipInNullabilityRewriter="true"/> </Node> <Node Name="BoundIncrementOperator" Base="BoundExpression"> <!-- x++ might need a conversion from the type of x to the operand type of the ++ operator (that produces the incremented value) and a conversion from the result of the ++ operator back to x. --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="OperatorKind" Type="UnaryOperatorKind"/> <Field Name="Operand" Type="BoundExpression"/> <Field Name="MethodOpt" Type="MethodSymbol?"/> <Field Name="ConstrainedToTypeOpt" Type="TypeSymbol?" Null="allow"/> <!-- Used as an operand to bind OperandConversion --> <Field Name="OperandPlaceholder" Type="BoundValuePlaceholder?" SkipInVisitor="true" Null="allow"/> <!-- Could be a BoundConversion or, in some cases of an identity conversion, the OperandPlaceholder, or null for no conversion case --> <Field Name="OperandConversion" Type="BoundExpression?" SkipInVisitor="true" Null="allow"/> <!-- Used as an operand to bind ResultConversion --> <Field Name="ResultPlaceholder" Type="BoundValuePlaceholder?" SkipInVisitor="true" Null="allow"/> <!-- Could be a BoundConversion or, in some cases of an identity conversion, the ResultPlaceholder, or null for no conversion case --> <Field Name="ResultConversion" Type="BoundExpression?" SkipInVisitor="true" Null="allow"/> <Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/> <!--The set of method symbols from which this operator's method was chosen. Only kept in the tree if the operator was an error and overload resolution was unable to choose a best method.--> <Field Name="OriginalUserDefinedOperatorsOpt" Type="ImmutableArray<MethodSymbol>" Null="Allow" SkipInNullabilityRewriter="true"/> </Node> <!-- Not really an operator since overload resolution is never required. --> <Node Name="BoundAddressOfOperator" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Operand" Type="BoundExpression"/> <!-- True only in some lowered/synthesized nodes. It suppresses conversion of operand reference to unmanaged pointer (which has effect of losing GC-tracking) NB: The language does not have a concept of managed pointers. However, managed (GC-tracked) pointers have some limited support at IL level and could be used in lowering of certain kinds of unsafe code - such as fixed field indexing. --> <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. --> <Node Name="BoundUnconvertedAddressOfOperator" Base="BoundExpression" DoesNotSurvive="InitialBinding"> <Field Name="Operand" Type="BoundMethodGroup"/> <!-- Type is null. --> <Field Name="Type" Type="TypeSymbol?" Override="true" Null="always"/> </Node> <!-- Represents a resolved AddressOf function pointer. Not used in initial binding. --> <Node Name="BoundFunctionPointerLoad" Base="BoundExpression"> <Field Name="TargetMethod" Type="MethodSymbol"/> <Field Name="ConstrainedToTypeOpt" Type="TypeSymbol?" Null="allow"/> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> </Node> <Node Name="BoundPointerIndirectionOperator" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Operand" Type="BoundExpression"/> <!-- Used by emit to determine whether this pointer indirection is by value or by ref. If true, emit will emit the address of the target, and not actually perform an indirect load (in practice this just means emitting the Operand alone). --> <Field Name="RefersToLocation" Type="bool"/> </Node> <Node Name="BoundPointerElementAccess" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Expression" Type="BoundExpression"/> <Field Name="Index" Type="BoundExpression"/> <Field Name="Checked" Type="bool"/> <!-- Used by emit to determine whether this pointer element access is by value or by ref. If true, emit will emit the address of the target, and not actually perform an indirect load (in practice this just means emitting the Operand alone). --> <Field Name="RefersToLocation" Type="bool"/> </Node> <Node Name="BoundFunctionPointerInvocation" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="InvokedExpression" Type="BoundExpression"/> <Field Name="Arguments" Type="ImmutableArray<BoundExpression>"/> <Field Name="ArgumentRefKindsOpt" Type="ImmutableArray<RefKind>" Null="allow"/> <Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind" /> </Node> <Node Name="BoundRefTypeOperator" Base="BoundExpression"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Operand" Type="BoundExpression"/> <!-- Well-known member populated during lowering --> <Field Name="GetTypeFromHandle" Type="MethodSymbol?"/> </Node> <Node Name="BoundMakeRefOperator" Base="BoundExpression"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Operand" Type="BoundExpression"/> </Node> <Node Name="BoundRefValueOperator" Base="BoundExpression"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="NullableAnnotation" Type="NullableAnnotation" /> <Field Name="Operand" Type="BoundExpression"/> </Node> <Node Name="BoundFromEndIndexExpression" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Operand" Type="BoundExpression"/> <Field Name="MethodOpt" Type="MethodSymbol?"/> </Node> <Node Name="BoundRangeExpression" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="LeftOperandOpt" Type="BoundExpression?"/> <Field Name="RightOperandOpt" Type="BoundExpression?"/> <Field Name="MethodOpt" Type="MethodSymbol?"/> </Node> <AbstractNode Name="BoundBinaryOperatorBase" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Left" Type="BoundExpression"/> <Field Name="Right" Type="BoundExpression"/> </AbstractNode> <Node Name="BoundBinaryOperator" Base="BoundBinaryOperatorBase" SkipInNullabilityRewriter="true" HasValidate="true"> <Field Name="OperatorKind" Type="BinaryOperatorKind"/> <Field Name="Data" Type="BoundBinaryOperator.UncommonData?" /> <Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/> </Node> <Node Name="BoundTupleBinaryOperator" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Left" Type="BoundExpression"/> <Field Name="Right" Type="BoundExpression"/> <Field Name="OperatorKind" Type="BinaryOperatorKind"/> <Field Name="Operators" Type="TupleBinaryOperatorInfo.Multiple"/> </Node> <Node Name="BoundUserDefinedConditionalLogicalOperator" Base="BoundBinaryOperatorBase" SkipInNullabilityRewriter="true" HasValidate="true"> <Field Name="OperatorKind" Type="BinaryOperatorKind"/> <Field Name="LogicalOperator" Type="MethodSymbol"/> <Field Name="TrueOperator" Type="MethodSymbol"/> <Field Name="FalseOperator" Type="MethodSymbol"/> <!-- Used as an operand to bind TrueFalseOperandConversion --> <Field Name="TrueFalseOperandPlaceholder" Type="BoundValuePlaceholder?" SkipInVisitor="true" Null="allow"/> <!-- Could be a BoundConversion or, in some cases of an identity conversion, the OperandPlaceholder, or null for no conversion case If the node survives lowering, this property in it must be null. --> <Field Name="TrueFalseOperandConversion" Type="BoundExpression?" SkipInVisitor="true" Null="allow"/> <Field Name="ConstrainedToTypeOpt" Type="TypeSymbol?" Null="allow"/> <Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/> <!--The set of method symbols from which this operator's method was chosen. Only kept in the tree if the operator was an error and overload resolution was unable to choose a best method.--> <Field Name="OriginalUserDefinedOperatorsOpt" Type="ImmutableArray<MethodSymbol>" Null="Allow" SkipInNullabilityRewriter="true"/> </Node> <Node Name="BoundCompoundAssignmentOperator" Base="BoundExpression" SkipInNullabilityRewriter="true"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <!-- A compound assignment operator has the following facts that must be deduced about it for codegen to work. Suppose you have shorts "x |= y;" That will be analyzed as "x = (short)(((int)x)|((int)y));" We need to know what the left hand and right hand sides are, what the binary operator is, how the left and right sides are converted to the types expected by the operator, whether the operator should check for overflow, and how the result of the binary operator is converted to the target variable's type. We'll lower this to operations on temporaries before codegen. Thought we can represent the operation as these seven facts, in fact we can conflate three of them. We need never do the right-hand-side-of-the-operator conversion during the rewrite. We can get away with binding the conversion on the right early and just having the converted right operand in the bound node. We also conflate whether we should check for overflow with the identity of the operator. This makes it a bit easier to handle the lambda case; when we have something like d += lambda, we want to represent the lambda in its bound form, not in its unbound form to be converted to the bound form later. This helps us maintain the invariant that non-error cases never produce an "unbound" lambda from the initial binding pass. --> <Field Name="Operator" Type="BinaryOperatorSignature" Null="NotApplicable"/> <Field Name="Left" Type="BoundExpression"/> <Field Name="Right" Type="BoundExpression"/> <!-- Used as an operand to bind LeftConversion --> <Field Name="LeftPlaceholder" Type="BoundValuePlaceholder?" SkipInVisitor="true" Null="allow"/> <!-- Could be a BoundConversion or, in some cases of an identity conversion, the LeftPlaceholder, or null for no conversion case --> <Field Name="LeftConversion" Type="BoundExpression?" SkipInVisitor="true" Null="allow"/> <!-- Used as an operand to bind LeftConversion --> <Field Name="FinalPlaceholder" Type="BoundValuePlaceholder?" SkipInVisitor="true" Null="allow"/> <!-- Could be a BoundConversion or, in some cases of an identity conversion, the FinalPlaceholder, or null for no conversion case --> <Field Name="FinalConversion" Type="BoundExpression?" SkipInVisitor="true" Null="allow"/> <Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/> <!--The set of method symbols from which this operator's method was chosen. Only kept in the tree if the operator was an error and overload resolution was unable to choose a best method.--> <Field Name="OriginalUserDefinedOperatorsOpt" Type="ImmutableArray<MethodSymbol>" Null="Allow" SkipInNullabilityRewriter="true"/> </Node> <Node Name="BoundAssignmentOperator" Base="BoundExpression"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Left" Type="BoundExpression"/> <Field Name="Right" Type="BoundExpression" Null="NotApplicable"/> <!-- This is almost always false. In C# most assignments to a variable are simply writes to the logical variable. For example, when you say void M(ref int x){ x = C.y } that writes the value of C.y to the variable that x is an alias for. It does not write the address of C.y to the actual underlying storage of the parameter, which is of course actually a ref to an int variable. However, in some codegen scenarios we need to distinguish between a ref local assignment and a value assignment. When you say int s = 123; s+=10; then we generate that as int s = 123; ref int addr = ref s; int sum = addr + 10; addr = sum; Note that there are two assignment to addr; one assigns the address of s to addr; the other assigns the value of sum to s, indirectly through addr. We therefore need to disambiguate what kind of assignment we are doing based on something other than the refness of the left hand side. --> <Field Name="IsRef" Type="bool" Null="NotApplicable"/> </Node> <Node Name="BoundDeconstructionAssignmentOperator" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Left" Type="BoundTupleExpression" Null="disallow"/> <Field Name="Right" Type="BoundConversion" Null="disallow"/> <Field Name="IsUsed" Type="bool" Null="NotApplicable"/> </Node> <Node Name="BoundNullCoalescingOperator" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="LeftOperand" Type="BoundExpression"/> <Field Name="RightOperand" Type="BoundExpression"/> <!-- Used as an operand to bind LeftConversion --> <Field Name="LeftPlaceholder" Type="BoundValuePlaceholder?" SkipInVisitor="true" Null="allow"/> <!-- Could be a BoundConversion or, in some cases of an identity conversion, the LeftPlaceholder, or null for no conversion case. If the node survives lowering, this property in it must be null, unless it is part of a Linq Expression Tree. --> <Field Name="LeftConversion" Type="BoundExpression?" SkipInVisitor="true" Null="allow"/> <Field Name="OperatorResultKind" Type="BoundNullCoalescingOperatorResultKind" Null="NotApplicable"/> <!-- This flag reflects the evaluation context used by the operator for conversions. Semantics of the node is well defined without this flag because the necessary conversions, if any, are stored in the dedicated properties. Flag's value is not important for lowering or code generation. It is only used by NullableWalker when it attempts to re-apply conversions to the original operands. --> <Field Name="Checked" Type="bool"/> </Node> <Node Name="BoundNullCoalescingAssignmentOperator" Base="BoundExpression"> <Field Name="LeftOperand" Type="BoundExpression" /> <Field Name="RightOperand" Type="BoundExpression" /> </Node> <Node Name="BoundUnconvertedConditionalOperator" Base="BoundExpression" DoesNotSurvive="InitialBinding"> <!-- Type is null. --> <Field Name="Type" Type="TypeSymbol?" Override="true" Null="always"/> <Field Name="Condition" Type="BoundExpression"/> <Field Name="Consequence" Type="BoundExpression"/> <Field Name="Alternative" Type="BoundExpression"/> <Field Name="ConstantValueOpt" Type="ConstantValue?" PropertyOverrides="true"/> <Field Name="NoCommonTypeError" Type="ErrorCode"/> </Node> <Node Name="BoundConditionalOperator" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="IsRef" Type="bool"/> <Field Name="Condition" Type="BoundExpression"/> <Field Name="Consequence" Type="BoundExpression"/> <Field Name="Alternative" Type="BoundExpression"/> <Field Name="ConstantValueOpt" Type="ConstantValue?" PropertyOverrides="true"/> <Field Name="NaturalTypeOpt" Type="TypeSymbol?" Null="allow"/> <Field Name="WasTargetTyped" Type="bool" /> </Node> <Node Name="BoundArrayAccess" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Expression" Type="BoundExpression"/> <Field Name="Indices" Type="ImmutableArray<BoundExpression>"/> </Node> <!-- Represents an array access that comes from the RHS of an unused ref (non-readonly) assignment. Needed so we can emit with correct side effects (runtime element type check). --> <Node Name="BoundRefArrayAccess" Base="BoundExpression"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="ArrayAccess" Type="BoundArrayAccess" Null="disallow"/> </Node> <!-- Represents an operation that is special in both IL and Expression trees - getting length of a one-dimensional 0-based array (vector) This node should not be produced in initial binding since it is not a part of language (.Length is just a property on System.Array) and is normally introduced during the lowering phases. --> <Node Name="BoundArrayLength" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Expression" Type="BoundExpression"/> </Node> <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"/> <Field Name="GetAwaiter" Type="BoundExpression?" Null="allow"/> <Field Name="IsCompleted" Type="PropertySymbol?" Null="allow"/> <Field Name="GetResult" Type="MethodSymbol?" Null="allow"/> <!-- Refers to the runtime async helper call we use for awaiting. Either this is an instance of a BoundCall of an AsyncHelpers.Await method, and GetAwaiter, IsCompleted, and GetResult are null, or this is an instance of a AsyncHelpers.AwaitAwaiter/UnsafeAwaitAwaiter BoundCall, and the other fields are not null. --> <Field Name="RuntimeAsyncAwaitCall" Type="BoundCall?" Null="allow"/> <!-- Never null when RuntimeAsyncAwaitCall is not null --> <Field Name="RuntimeAsyncAwaitCallPlaceholder" Type="BoundAwaitableValuePlaceholder?" Null="allow"/> </Node> <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"/> <Field Name="Expression" Type="BoundExpression"/> <Field Name="AwaitableInfo" Type="BoundAwaitableInfo" Null="disallow"/> <Field Name="DebugInfo" Type="BoundAwaitExpressionDebugInfo" Null="NotApplicable"/> </Node> <AbstractNode Name="BoundTypeOf" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <!-- Well-known member populated during lowering --> <Field Name="GetTypeFromHandle" Type="MethodSymbol?"/> </AbstractNode> <Node Name="BoundTypeOfOperator" Base="BoundTypeOf"> <Field Name="SourceType" Type="BoundTypeExpression"/> </Node> <!-- Instrumentation info attached to BoundBlock --> <Node Name="BoundBlockInstrumentation" Base="BoundNode"> <!-- Local variables with scope that cover the entire block including the instrumentation prologue and epilogue. --> <Field Name="Locals" Type="ImmutableArray<LocalSymbol>" Null="disallow"/> <!-- Optional prologue emitted in front of any instructions of the block, so that it always executes. --> <Field Name="Prologue" Type="BoundStatement?" Null="allow"/> <!-- If specified, a try-finally block is emitted around the instrumented block. The epilogue is emitted to the finally clause, so that it always executes when the execution leaves the instrumented block. --> <Field Name="Epilogue" Type="BoundStatement?" Null="allow"/> </Node> <!-- Represents the raw metadata RowId value for a method definition. Used by dynamic instrumentation to index into tables or arrays of per-method information. --> <Node Name="BoundMethodDefIndex" Base="BoundExpression" HasValidate="true"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Method" Type="MethodSymbol"/> </Node> <!-- Represents local id - a unique int value that represents local variable.--> <Node Name="BoundLocalId" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <!-- Local symbol representing the variable. --> <Field Name="Local" Type="LocalSymbol" Null="disallow"/> <!-- Field symbol representing the variable if it has been lifted. --> <Field Name="HoistedField" Type="FieldSymbol?" Null="allow"/> </Node> <!-- Represents parameter id - a unique int value that represents parameter.--> <Node Name="BoundParameterId" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <!-- Local symbol representing the variable. --> <Field Name="Parameter" Type="ParameterSymbol" Null="disallow"/> <!-- Field symbol representing the parameter if it has been lifted. --> <Field Name="HoistedField" Type="FieldSymbol?" Null="allow"/> </Node> <!-- Represents state machine instance id - a unique ulong value that represents an instance of a state machine.--> <Node Name="BoundStateMachineInstanceId" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> </Node> <!-- Represents the maximum raw metadata token index value for any method definition in the current module. --> <Node Name="BoundMaximumMethodDefIndex" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> </Node> <!-- Represents the dynamic analysis instrumentation payload array for the analysis kind in the current module. Implemented as a reference to a field of PrivateImplementationDetails, which has no language-level symbol. --> <Node Name="BoundInstrumentationPayloadRoot" Base="BoundExpression"> <Field Name="AnalysisKind" Type="int"/> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> </Node> <!-- Call to PrivateImplementationDetails.ModuleCancellationToken.ThrowIfCancellationRequested(). PrivateImplementationDetails.ModuleCancellationToken has no language-level symbol. --> <Node Name="BoundThrowIfModuleCancellationRequested" Base="BoundExpression"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> </Node> <!-- Returns the value of PrivateImplementationDetails.ModuleCancellationToken. It has no language-level symbol. --> <Node Name="ModuleCancellationTokenExpression" Base="BoundExpression"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> </Node> <!-- Represents the GUID that is the current module's MVID. Implemented as a reference to PrivateImplementationDetails.MVID, which has no language-level symbol. --> <Node Name="BoundModuleVersionId" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> </Node> <!-- Represents a string encoding of the GUID that is the current module's MVID. Implemented as a reference to a string constant that is backpatched after the MVID is computed. --> <Node Name="BoundModuleVersionIdString" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> </Node> <!-- Represents the index in the documents table of the source document containing a method definition. Used by dynamic instrumentation to identify the source document containing a method. --> <Node Name="BoundSourceDocumentIndex" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Document" Type="Cci.DebugSourceDocument"/> </Node> <Node Name="BoundMethodInfo" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Method" Type="MethodSymbol"/> <!-- Well-known member populated during lowering --> <Field Name="GetMethodFromHandle" Type="MethodSymbol?"/> </Node> <Node Name="BoundFieldInfo" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Field" Type="FieldSymbol"/> <!-- Well-known member populated during lowering --> <Field Name="GetFieldFromHandle" Type="MethodSymbol?"/> </Node> <!-- Default literals can convert to the target type. Does not survive initial lowering. --> <Node Name="BoundDefaultLiteral" Base="BoundExpression" DoesNotSurvive="LocalRewriting"> <!-- Type is null. --> <Field Name="Type" Type="TypeSymbol?" Override="true" Null="always"/> </Node> <!-- The default expression is `default(T)` expression or `default` literal which has been already converted to a target type. --> <Node Name="BoundDefaultExpression" Base="BoundExpression"> <!-- Converted default expression must have a type. --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="TargetType" Type="BoundTypeExpression?" SkipInVisitor="true"/> <Field Name="ConstantValueOpt" Type="ConstantValue?" PropertyOverrides="true"/> </Node> <Node Name="BoundIsOperator" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Operand" Type="BoundExpression"/> <Field Name="TargetType" Type="BoundTypeExpression"/> <Field Name="ConversionKind" Type="ConversionKind"/> </Node> <Node Name="BoundAsOperator" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Operand" Type="BoundExpression"/> <Field Name="TargetType" Type="BoundTypeExpression"/> <!-- Used as an operand to bind OperandConversion --> <Field Name="OperandPlaceholder" Type="BoundValuePlaceholder?" SkipInVisitor="true" Null="allow"/> <!-- Could be a BoundConversion or, in some cases of an identity conversion, the OperandPlaceholder, or null for no conversion case If the node survives lowering, this property in it must be null. --> <Field Name="OperandConversion" Type="BoundExpression?" SkipInVisitor="true" Null="allow"/> </Node> <Node Name="BoundSizeOfOperator" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="SourceType" Type="BoundTypeExpression"/> <Field Name="ConstantValueOpt" Type="ConstantValue?" PropertyOverrides="true"/> </Node> <Node Name="BoundConversion" Base="BoundExpression" HasValidate="true"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Operand" Type="BoundExpression"/> <Field Name="Conversion" Type="Conversion"/> <Field Name="IsBaseConversion" Type="bool"/> <Field Name="Checked" Type="bool"/> <Field Name="ExplicitCastInCode" Type="bool"/> <Field Name="ConstantValueOpt" Type="ConstantValue?" PropertyOverrides="true"/> <!-- A group instance common to all BoundConversions that represent a single Conversion. The field is used in NullableWalker to identify the chained conversions in user-defined conversions in particular. For instance, with the following declarations, an explicit conversion from B to D: expr -> ImplicitReference conversion -> ExplicitUserDefined conversion -> ExplicitReference conversion. class A { public static explicit operator C(A a) => new D(); } class B : A { } class C { } class D : C { } ConversionGroupOpt also contains the target type specified in source in the case of explicit conversions. ConversionGroupOpt may be null for implicit conversions if the Conversion is represented by a single BoundConversion. --> <Field Name="ConversionGroupOpt" Type="ConversionGroup?"/> <Field Name="InConversionGroupFlags" Type="InConversionGroupFlags"/> </Node> <!-- A special node for emitting the implicit conversion from an array (of T) to System.ReadOnlySpan<T>. Although the conversion has an explicitly declared conversion operator, we want to retain it as something other than a method call after lowering so it can be recognized as a special case and possibly optimized during code generation. --> <Node Name="BoundReadOnlySpanFromArray" Base="BoundExpression"> <!-- The type is required to be an instance of the well-known type System.ReadOnlySpan<T> --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Operand" Type="BoundExpression"/> <Field Name="ConversionMethod" Type="MethodSymbol"/> </Node> <!-- <Node Name="BoundRefValueOperator" Base="BoundExpression"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Operand" Type="BoundExpression"/> <Field Name="SourceType" Type="BoundTypeExpression"/> </Node> --> <Node Name="BoundArgList" Base="BoundExpression"> <!-- This is the "__arglist" expression that may appear inside a varargs method. --> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> </Node> <Node Name="BoundArgListOperator" Base="BoundExpression"> <!-- This is the "__arglist(x, y, z)" expression that may appear in a call to a varargs method. --> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol?" Override="true"/> <Field Name="Arguments" Type="ImmutableArray<BoundExpression>"/> <Field Name="ArgumentRefKindsOpt" Type="ImmutableArray<RefKind>" Null="allow"/> </Node> <!-- Used when a fixed statement local is initialized with either a string or an array. Encapsulates extra info that will be required during rewriting. --> <Node Name="BoundFixedLocalCollectionInitializer" Base="BoundExpression"> <!-- Either string or an array type. --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <!-- char* for type string, T* for type T[]. --> <Field Name="ElementPointerType" Type="TypeSymbol" Null="disallow"/> <!-- Conversion from ElementPointerType to the type of the corresponding local. --> <!-- Used as an operand to bind ElementPointerConversion --> <Field Name="ElementPointerPlaceholder" Type="BoundValuePlaceholder?" SkipInVisitor="true" Null="allow"/> <!-- Could be a BoundConversion or, in some cases of an identity conversion, the ElementPointerPlaceholder, or null for no conversion case --> <Field Name="ElementPointerConversion" Type="BoundExpression?" SkipInVisitor="true" Null="allow"/> <!-- Wrapped expression. --> <Field Name="Expression" Type="BoundExpression" Null="disallow"/> <!-- optional method that returns a pinnable reference for the instance --> <Field Name="GetPinnableOpt" Type="MethodSymbol?"/> </Node> <AbstractNode Name="BoundStatement" Base="BoundNode"/> <Node Name="BoundSequencePoint" Base="BoundStatement"> <!-- if Statement is null, a NOP may be emitted, to make sure the point is not associated with next statement (which could be a fairly random statement in random scope). --> <Field Name="StatementOpt" Type="BoundStatement?"/> </Node> <!--EDMAURER Use this in the event that the span you must represent is not that of a SyntaxNode. If a SyntaxNode captures the correct span, use a BoundSequencePoint.--> <Node Name="BoundSequencePointWithSpan" Base="BoundStatement"> <!-- if Statement is null, a NOP may be emitted, to make sure the point is not associated with next statement (which could be a fairly random statement in random scope). --> <Field Name="StatementOpt" Type="BoundStatement?"/> <Field Name="Span" Type="TextSpan"/> </Node> <!-- This is used to save the debugger's idea of what the enclosing sequence point is at this location in the code so that it can be restored later by a BoundRestorePreviousSequencePoint node. When this statement appears, the previous non-hidden sequence point is saved and associated with the given Identifier. --> <Node Name="BoundSavePreviousSequencePoint" Base="BoundStatement"> <Field Name="Identifier" Type="object"/> </Node> <!-- This is used to restore the debugger's idea of what the enclosing statement is to some previous location without introducing a place where a breakpoint would cause the debugger to stop. The identifier must have previously been given in a BoundSavePreviousSequencePoint statement. This is used to implement breakpoints within expressions (e.g. a switch expression). --> <Node Name="BoundRestorePreviousSequencePoint" Base="BoundStatement"> <Field Name="Identifier" Type="object"/> </Node> <!-- This is used to set the debugger's idea of what the enclosing statement is without causing the debugger to stop here when single stepping. --> <Node Name="BoundStepThroughSequencePoint" Base="BoundStatement"> <Field Name="Span" Type="TextSpan"/> </Node> <!-- BoundBlock contains a) Statements - actions performed within the scope of the block b) Locals - local variable symbols that are visible within the scope of the block BoundBlock specify SCOPE (visibility) of a variable. TODO: it appears in C#, variable's extent (life time) never escapes its scope. Is that always guaranteed or there are exceptions? Note - in VB variable's extent is the whole method and can be larger than its scope. That is why unassigned use is just a warning and jumps into blocks are generally allowed. --> <Node Name="BoundBlock" Base="BoundStatementList"> <Field Name="Locals" Type="ImmutableArray<LocalSymbol>"/> <Field Name="LocalFunctions" Type="ImmutableArray<MethodSymbol>"/> <Field Name="HasUnsafeModifier" Type="bool" Null="NotApplicable"/> <!-- Optional block-level instrumentation info --> <Field Name="Instrumentation" Type="BoundBlockInstrumentation?" Null="allow" /> </Node> <!-- This node is used to represent a visibility scope for locals, for which lifetime is extended beyond the visibility scope. At the moment, only locals declared within CaseSwitchLabelSyntax and SwitchExpressionSyntax have their lifetime expanded to the entire switch body, whereas their visibility scope is the declaring switch section. The node is added into the tree during lowering phase. --> <Node Name="BoundScope" Base="BoundStatementList"> <Field Name="Locals" Type="ImmutableArray<LocalSymbol>"/> </Node> <!-- BoundStateMachineScope represents a scope within a translated iterator/async method. It is used to emit debugging information that allows the EE to map fields to locals. --> <Node Name="BoundStateMachineScope" Base="BoundStatement"> <Field Name="Fields" Type="ImmutableArray<StateMachineFieldSymbol>"/> <Field Name="Statement" Type="BoundStatement" Null="disallow"/> </Node> <!-- Bound node that represents a single local declaration: int x = Foo(); NOTE: The node does NOT introduce the referenced local into surrounding scope. A local must be explicitly declared in a BoundBlock to be usable inside it. NOTE: In an error recovery scenario we might have a local declaration parsed as int x[123] - This is an error commonly made by C++ developers who come to C#. We will give a good error about it at parse time, but we should preserve the semantic analysis of the argument list in the bound tree. --> <Node Name="BoundLocalDeclaration" Base="BoundStatement"> <Field Name="LocalSymbol" Type="LocalSymbol"/> <!-- Only set for the first declaration in BoundMultipleLocalDeclarations unless the type is inferred --> <Field Name="DeclaredTypeOpt" Type="BoundTypeExpression?"/> <Field Name="InitializerOpt" Type="BoundExpression?"/> <Field Name="ArgumentsOpt" Type="ImmutableArray<BoundExpression>" Null="allow"/> <!-- Was the type inferred via "var"? --> <Field Name="InferredType" Type="bool"/> </Node> <!-- Base node shared by BoundMultipleLocalDeclarations and BoundUsingLocalDeclarations --> <AbstractNode Name="BoundMultipleLocalDeclarationsBase" Base="BoundStatement"> <Field Name="LocalDeclarations" Type="ImmutableArray<BoundLocalDeclaration>"/> </AbstractNode> <!-- Bound node that represents multiple local declarations: int x =1, y =2; Works like multiple BoundLocalDeclaration nodes. --> <Node Name="BoundMultipleLocalDeclarations" Base="BoundMultipleLocalDeclarationsBase" /> <!-- Bound node that represents a using local declaration [async] using var x = ..., y = ...; --> <Node Name="BoundUsingLocalDeclarations" Base="BoundMultipleLocalDeclarationsBase"> <Field Name="PatternDisposeInfoOpt" Type="MethodArgumentInfo?"/> <Field Name="AwaitOpt" Type="BoundAwaitableInfo?"/> </Node> <!-- Bound node that represents a local function declaration: void Foo() { } --> <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?"/> <Field Name="ExpressionBody" Type="BoundBlock?"/> </Node> <Node Name="BoundNoOpStatement" Base="BoundStatement"> <!-- No operation. Empty statement. --> <!-- BoundNoOpStatement node may serve as a vehicle for passing some internal information between lowering phases and/or codegen; for example, async rewriter needs to mark some particular places in the emitted code so that we could emit proper PDB information for generated methods. --> <Field Name="Flavor" Type="NoOpStatementFlavor"/> </Node> <Node Name="BoundReturnStatement" Base="BoundStatement" HasValidate="true"> <Field Name="RefKind" Type="RefKind"/> <Field Name="ExpressionOpt" Type="BoundExpression?"/> <!-- This flag reflects the evaluation context used by the return statement to convert the original return expression. Semantics of the node is well defined without this flag because the necessary conversion is part of ExpressionOpt. Flag’s value is not important for lowering or code generation. It is only used by NullableWalker when it attempts to re-infer the best return type for a lambda expression. --> <Field Name="Checked" Type="bool"/> </Node> <Node Name="BoundYieldReturnStatement" Base="BoundStatement" DoesNotSurvive="StateMachineRewriting"> <Field Name="Expression" Type="BoundExpression" Null="disallow"/> </Node> <Node Name="BoundYieldBreakStatement" Base="BoundStatement" DoesNotSurvive="StateMachineRewriting"/> <Node Name="BoundThrowStatement" Base="BoundStatement"> <Field Name="ExpressionOpt" Type="BoundExpression?"/> </Node> <Node Name="BoundExpressionStatement" Base="BoundStatement"> <Field Name="Expression" Type="BoundExpression"/> </Node> <Node Name="BoundBreakStatement" Base="BoundStatement"> <!-- The compiler-generated label that the break jumps to (e.g. the loop's "break" label). --> <Field Name="Label" Type="LabelSymbol" /> <!-- For a labeled break (e.g. "break outer;" targeting "outer: while (true) { ... }"), holds the bound node for the "outer" identifier; null for an ordinary unlabeled "break;". Stored so that: * the bound tree contains a BoundLabel whose Syntax is the "outer" IdentifierNameSyntax, which is what SemanticModel.GetSymbolInfo walks to find the LabelSymbol referenced by that identifier; and * ControlFlowPass can mark the LabelSymbol as referenced (otherwise the "outer:" declaration would be reported as WRN_UnreferencedLabel). --> <Field Name="LabelExpressionOpt" Type="BoundLabel?" /> </Node> <Node Name="BoundContinueStatement" Base="BoundStatement"> <!-- The compiler-generated label that the continue jumps to (e.g. the loop's "continue" label). --> <Field Name="Label" Type="LabelSymbol" /> <!-- For a labeled continue (e.g. "continue outer;" targeting "outer: for (...) { ... }"), holds the bound node for the "outer" identifier; null for an ordinary unlabeled "continue;". Stored so that: * the bound tree contains a BoundLabel whose Syntax is the "outer" IdentifierNameSyntax, which is what SemanticModel.GetSymbolInfo walks to find the LabelSymbol referenced by that identifier; and * ControlFlowPass can mark the LabelSymbol as referenced (otherwise the "outer:" declaration would be reported as WRN_UnreferencedLabel). --> <Field Name="LabelExpressionOpt" Type="BoundLabel?" /> </Node> <Node Name="BoundSwitchStatement" Base="BoundStatement"> <Field Name="Expression" Type="BoundExpression"/> <!-- Locals declared immediately within the switch block. --> <Field Name="InnerLocals" Type="ImmutableArray<LocalSymbol>"/> <Field Name="InnerLocalFunctions" Type="ImmutableArray<MethodSymbol>"/> <Field Name="SwitchSections" Type="ImmutableArray<BoundSwitchSection>"/> <Field Name="ReachabilityDecisionDag" Type="BoundDecisionDag" Null="disallow" SkipInVisitor="true"/> <Field Name="DefaultLabel" Type="BoundSwitchLabel?"/> <Field Name="BreakLabel" Type="LabelSymbol"/> </Node> <!-- Part of a lowered integral switch statement. This evaluates Value, and then branches to the corresponding Target. If no Value is equal to the input, branches to the default label. The input Value and the constants must be of the same type. Currently emit only supports integral types and string. BoundSwitchDispatch is also used to mark labels in the code that will be the target of backward branches, but should be treated as having the same stack depth as the location where the BoundForwardLabels appears. Although we will necessarily produce some IL instructions for this in order to comply with the verifier constraints, the effect of the code shall be a no-op. The form of the code produced will likely be something of the form ldc.i4.m1 // load constant -1 switch ( IL_nnnn, // all of the labels of interest IL_nnnn, IL_nnnn) This is needed for the lowering of the pattern switch expression, which produces a state machine that may contain backward branches. Due to the fact that it is an expression, it may appear where the stack is not empty. A BoundSwitchDispatch statement (used inside of a BoundSequence containing the state machine) permits us to (cause the verifier to) classify all of the labels as forward labels by producing a dummy inoperable forward jump to them. --> <Node Name="BoundSwitchDispatch" Base="BoundStatement"> <Field Name="Expression" Type="BoundExpression" Null="disallow" /> <Field Name="Cases" Type="ImmutableArray<(ConstantValue value, LabelSymbol label)>" /> <Field Name="DefaultLabel" Type="LabelSymbol" Null="disallow" /> <Field Name="LengthBasedStringSwitchDataOpt" Type="LengthBasedStringSwitchData?" /> </Node> <Node Name="BoundIfStatement" Base="BoundStatement" DoesNotSurvive="LocalRewriting"> <Field Name="Condition" Type="BoundExpression"/> <Field Name="Consequence" Type="BoundStatement"/> <Field Name="AlternativeOpt" Type="BoundStatement?"/> </Node> <AbstractNode Name="BoundLoopStatement" Base="BoundStatement"> <Field Name="BreakLabel" Type="LabelSymbol"/> <Field Name="ContinueLabel" Type="LabelSymbol"/> </AbstractNode> <AbstractNode Name="BoundConditionalLoopStatement" Base="BoundLoopStatement"> <Field Name="Locals" Type="ImmutableArray<LocalSymbol>"/> <Field Name="Condition" Type="BoundExpression"/> <Field Name="Body" Type="BoundStatement"/> </AbstractNode> <Node Name="BoundDoStatement" Base="BoundConditionalLoopStatement"> </Node> <Node Name="BoundWhileStatement" Base="BoundConditionalLoopStatement"> </Node> <Node Name="BoundForStatement" Base="BoundLoopStatement"> <!-- OuterLocals are the locals declared within the loop Initializer statement and are in scope throughout the whole loop statement --> <Field Name="OuterLocals" Type="ImmutableArray<LocalSymbol>"/> <Field Name="Initializer" Type="BoundStatement?"/> <!-- InnerLocals are the locals declared within the loop Condition and are in scope throughout the Condition, Increment and Body. They are considered to be declared per iteration. --> <Field Name="InnerLocals" Type="ImmutableArray<LocalSymbol>"/> <Field Name="Condition" Type="BoundExpression?"/> <Field Name="Increment" Type="BoundStatement?"/> <Field Name="Body" Type="BoundStatement"/> </Node> <Node Name="BoundForEachStatement" Base="BoundLoopStatement"> <!-- Extracted information --> <Field Name="EnumeratorInfoOpt" Type="ForEachEnumeratorInfo?"/> <!-- Used as an operand to bind ElementConversion --> <Field Name="ElementPlaceholder" Type="BoundValuePlaceholder?" SkipInVisitor="true" Null="allow"/> <!-- Could be a BoundConversion or, in some cases of an identity conversion, the OperandPlaceholder, or null for no conversion case --> <Field Name="ElementConversion" Type="BoundExpression?" SkipInVisitor="true" Null="allow"/> <!-- Pieces corresponding to the syntax --> <!-- This is so the binding API can find produce semantic info if the type is "var". --> <!-- If there is a deconstruction, there will be no iteration variable (but we'll still have a type for it). --> <Field Name="IterationVariableType" Type="BoundTypeExpression"/> <Field Name="IterationVariables" Type="ImmutableArray<LocalSymbol>"/> <!-- In error scenarios where the iteration variable is some arbitrary expression, we stick the error recovery in this node. This will always be null in valid code. --> <Field Name="IterationErrorExpressionOpt" Type="BoundExpression?"/> <!-- If this node does not have errors, then this is the foreach expression wrapped in a conversion to the collection type used by the foreach loop. The conversion is here so that the binding API can return the correct ConvertedType in semantic info. It will be stripped off in the rewriter if it is redundant or causes extra boxing. If this node has errors, then the conversion may not be present.--> <Field Name="Expression" Type="BoundExpression"/> <Field Name="DeconstructionOpt" Type="BoundForEachDeconstructStep?"/> <Field Name="Body" Type="BoundStatement"/> </Node> <!-- All the information need to apply a deconstruction at each iteration of a foreach loop involving a deconstruction-declaration. --> <Node Name="BoundForEachDeconstructStep" Base="BoundNode"> <Field Name="DeconstructionAssignment" Type="BoundDeconstructionAssignmentOperator" Null="disallow"/> <Field Name="TargetPlaceholder" Type="BoundDeconstructValuePlaceholder" Null="disallow"/> </Node> <Node Name="BoundUsingStatement" Base="BoundStatement" DoesNotSurvive="LocalRewriting"> <!-- DeclarationsOpt and ExpressionOpt cannot both be non-null. --> <Field Name="Locals" Type="ImmutableArray<LocalSymbol>"/> <Field Name="DeclarationsOpt" Type="BoundMultipleLocalDeclarations?"/> <Field Name="ExpressionOpt" Type="BoundExpression?"/> <Field Name="Body" Type="BoundStatement"/> <Field Name="AwaitOpt" Type="BoundAwaitableInfo?"/> <Field Name="PatternDisposeInfoOpt" Type="MethodArgumentInfo?"/> </Node> <Node Name="BoundFixedStatement" Base="BoundStatement"> <Field Name="Locals" Type="ImmutableArray<LocalSymbol>"/> <Field Name="Declarations" Type="BoundMultipleLocalDeclarations"/> <Field Name="Body" Type="BoundStatement"/> </Node> <Node Name="BoundLockStatement" Base="BoundStatement"> <Field Name="Argument" Type="BoundExpression"/> <Field Name="Body" Type="BoundStatement"/> </Node> <Node Name="BoundTryStatement" Base="BoundStatement"> <Field Name="TryBlock" Type="BoundBlock"/> <Field Name="CatchBlocks" Type="ImmutableArray<BoundCatchBlock>"/> <Field Name="FinallyBlockOpt" Type="BoundBlock?"/> <!-- When lowering trys, we sometimes extract the finally clause out of the try. For example, `try { } finally { await expr; }` becomes something like `try { } catch { ... } finallyLabel: { await expr; ... }`. We need to save the label for the finally so that async-iterator rewriting can implement proper disposal. --> <Field Name="FinallyLabelOpt" Type="LabelSymbol?"/> <!-- PreferFaultHandler is a hint to the codegen to emit Finally in the following shape - try { } fault { finallyBlock } finallyBlock This pattern preserves semantics of Finally while not using finally handler. As a result any kind of analysis can continue treating Finally blocks as Finally blocks. NOTE!! When Fault emit is used - 1) The code is emitted twice 2) The second copy is outside of a handler block. 3) Branches out of the try will NOT be intercepted by the surrogate finally. User of this flag must ensure that the above caveats are acceptable. For example when this flag is used in Iterator rewrite, the second copy is always unreachable and not intercepting the return is intended behavior since the only branch out of Iterator body is "goto exitLabel". --> <Field Name="PreferFaultHandler" Type="bool"/> </Node> <Node Name="BoundCatchBlock" Base="BoundNode"> <!-- Local symbols owned by the catch block. Empty if the catch syntax doesn't declare a local variable. In the initial bound tree the first variable is the exception variable (if present). After the node is lowered the exception variable might become a field and will be removed from the array, otherwise it will stay at the first position. --> <Field Name="Locals" Type="ImmutableArray<LocalSymbol>"/> <!-- Refers to the location where the exception object is stored. The expression is a local or a BoundSequence, whose last expression refers to the location of the exception object and the sideeffects initialize its storage (e.g. if the catch identifier is lifted into a closure the sideeffects initialize the closure). Null if the exception object is not referred to. --> <Field Name="ExceptionSourceOpt" Type="BoundExpression?"/> <Field Name="ExceptionTypeOpt" Type="TypeSymbol?"/> <Field Name="ExceptionFilterPrologueOpt" Type="BoundStatementList?"/> <Field Name="ExceptionFilterOpt" Type="BoundExpression?"/> <Field Name="Body" Type="BoundBlock"/> <Field Name="IsSynthesizedAsyncCatchAll" Type="bool" /> </Node> <Node Name="BoundLiteral" Base="BoundExpression"> <Field Name="ConstantValueOpt" Type="ConstantValue?" PropertyOverrides="true"/> </Node> <Node Name="BoundUtf8String" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Value" Type="string" Null="disallow"/> </Node> <Node Name="BoundThisReference" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <!-- Note that "this" is classified as a variable in some scenarios. We'll treat it as a value generally and special-case those cases. --> </Node> <Node Name="BoundPreviousSubmissionReference" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> </Node> <Node Name="BoundHostObjectMemberReference" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> </Node> <Node Name="BoundBaseReference" Base="BoundExpression"> <!-- Type is not significant for this node type; always null --> <Field Name="Type" Type="TypeSymbol?" Override="true" /> </Node> <Node Name="BoundLocal" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="LocalSymbol" Type="LocalSymbol"/> <Field Name="DeclarationKind" Type="BoundLocalDeclarationKind" Null="NotApplicable"/> <Field Name="ConstantValueOpt" Type="ConstantValue?" PropertyOverrides="true"/> <!-- True if LocalSymbol.Type.IsNullable could not be inferred. --> <Field Name="IsNullableUnknown" Type="bool"/> </Node> <Node Name="BoundPseudoVariable" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="LocalSymbol" Type="LocalSymbol" Null="disallow"/> <Field Name="EmitExpressions" Type ="PseudoVariableExpressions" Null="disallow"/> </Node> <Node Name="BoundRangeVariable" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="RangeVariableSymbol" Type="RangeVariableSymbol"/> <Field Name="Value" Type="BoundExpression"/> </Node> <Node Name="BoundParameter" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="ParameterSymbol" Type="ParameterSymbol"/> </Node> <Node Name="BoundLabelStatement" Base="BoundStatement"> <!-- A label is not actually a statement but it is convenient to model it as one because then you can do rewrites without having to know "what comes next". For example suppose you have statement list A(); if(B()) C(); else D(); E(); If you are rewriting the "if" then it is convenient to be able to rewrite it as GotoIfFalse B() LabElse C(); Goto LabDone LabElse D(); LabDone without having to rewrite E(); as a labeled statement. Note that this statement represents the label itself as a "stand-alone" statement, unattached to any other statement. Rewriting will remove this statement and replace it with a LabeledStatement, that references both this LabelSymbol and the specific other statement it actually labels. --> <Field Name="Label" Type="LabelSymbol"/> </Node> <Node Name="BoundGotoStatement" Base="BoundStatement"> <Field Name="Label" Type="LabelSymbol"/> <Field Name="CaseExpressionOpt" Type="BoundExpression?"/> <Field Name="LabelExpressionOpt" Type="BoundLabel?"/> </Node> <!-- This represents a statement which has been labeled. This allows us to recursively bind the labeled expression during binding. --> <Node Name="BoundLabeledStatement" Base="BoundStatement"> <Field Name="Label" Type="LabelSymbol"/> <Field Name="Body" Type="BoundStatement"/> </Node> <!-- This represents the bound form of a label reference (i.e. in a goto). It is only used for the SemanticModel API. --> <Node Name="BoundLabel" Base="BoundExpression"> <Field Name="Label" Type="LabelSymbol"/> </Node> <Node Name="BoundStatementList" Base="BoundStatement"> <!-- A statement list is produced by a rewrite that turns one statement into multiple statements. It does not have the semantics of a block. --> <Field Name="Statements" Type="ImmutableArray<BoundStatement>"/> </Node> <Node Name="BoundConditionalGoto" Base="BoundStatement"> <!-- A compiler-generated conditional goto - jumps if condition == JumpIfTrue --> <Field Name="Condition" Type="BoundExpression"/> <Field Name="JumpIfTrue" Type="bool"/> <Field Name="Label" Type="LabelSymbol"/> </Node> <AbstractNode Name="BoundSwitchExpression" Base="BoundExpression"> <Field Name="Expression" Type="BoundExpression" Null="disallow"/> <Field Name="SwitchArms" Type="ImmutableArray<BoundSwitchExpressionArm>"/> <Field Name="ReachabilityDecisionDag" Type="BoundDecisionDag" Null="disallow" SkipInVisitor="true"/> <Field Name="DefaultLabel" Type="LabelSymbol?"/> <Field Name="ReportedNotExhaustive" Type="bool"/> </AbstractNode> <Node Name="BoundSwitchExpressionArm" Base="BoundNode"> <Field Name="Locals" Type="ImmutableArray<LocalSymbol>"/> <Field Name="Pattern" Type="BoundPattern" Null="disallow"/> <Field Name="HasUnionMatching" Type="bool"/> <Field Name="WhenClause" Type="BoundExpression?"/> <Field Name="Value" Type="BoundExpression" Null="disallow"/> <Field Name="Label" Type="LabelSymbol" Null="disallow"/> </Node> <Node Name="BoundUnconvertedSwitchExpression" Base="BoundSwitchExpression" DoesNotSurvive="InitialBinding"> </Node> <!-- Switch expressions can convert to the target type. Once converted to a target type, they cannot be target-typed again. The Converted switch expression is one which has been already converted to a target type. Converted switch expressions always have a type. --> <Node Name="BoundConvertedSwitchExpression" Base="BoundSwitchExpression"> <!-- Converted switch expression must have a type, even if that's an error type. --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <!-- Natural type is preserved for the purpose of semantic model. Can be `null`. --> <Field Name="NaturalTypeOpt" Type="TypeSymbol?" Null="allow"/> <Field Name="WasTargetTyped" Type="bool" /> </Node> <Node Name="BoundDecisionDag" Base="BoundNode"> <Field Name="RootNode" Type="BoundDecisionDagNode" Null="disallow"/> <Field Name="SuitableForLowering" Type="bool"/> </Node> <AbstractNode Name="BoundDecisionDagNode" Base="BoundNode"> </AbstractNode> <!-- This node is used to indicate a point in the decision dag where an evaluation is performed, such as invoking Deconstruct. --> <Node Name="BoundEvaluationDecisionDagNode" Base="BoundDecisionDagNode"> <Field Name="Evaluation" Type="BoundDagEvaluation" Null="disallow"/> <Field Name="Next" Type="BoundDecisionDagNode" Null="disallow"/> </Node> <!-- This node is used to indicate a point in the decision dag where a test may change the path of the decision dag. --> <Node Name="BoundTestDecisionDagNode" Base="BoundDecisionDagNode"> <Field Name="Test" Type="BoundDagTest" Null="disallow"/> <Field Name="WhenTrue" Type="BoundDecisionDagNode" Null="disallow"/> <Field Name="WhenFalse" Type="BoundDecisionDagNode" Null="disallow"/> </Node> <Node Name="BoundWhenDecisionDagNode" Base="BoundDecisionDagNode"> <Field Name="Bindings" Type="ImmutableArray<BoundPatternBinding>" Null="disallow"/> <!-- WhenExpression is null when there was no when clause in source but there are bindings. In that case WhenFalse is null. --> <Field Name="WhenExpression" Type="BoundExpression?"/> <Field Name="WhenTrue" Type="BoundDecisionDagNode" Null="disallow"/> <Field Name="WhenFalse" Type="BoundDecisionDagNode?"/> </Node> <!-- This node is used to indicate a point in the decision dag where the decision has been completed. --> <Node Name="BoundLeafDecisionDagNode" Base="BoundDecisionDagNode"> <Field Name="Label" Type="LabelSymbol"/> </Node> <AbstractNode Name="BoundDagTest" Base="BoundNode"> <!-- Input is the input to the decision point. --> <Field Name="Input" Type="BoundDagTemp"/> </AbstractNode> <Node Name="BoundDagTemp" Base="BoundNode"> <Field Name="Type" Type="TypeSymbol" Null="disallow"/> <Field Name="Source" Type="BoundDagEvaluation?"/> <Field Name="Index" Type="int"/> </Node> <Node Name="BoundDagTypeTest" Base="BoundDagTest"> <!--Check that the input is of the given type. Null check is separate.--> <Field Name="Type" Type="TypeSymbol" Null="disallow"/> </Node> <Node Name="BoundDagNonNullTest" Base="BoundDagTest"> <!--Check that the input is not null. Used as part of a type test.--> <Field Name="IsExplicitTest" Type="bool"/> </Node> <Node Name="BoundDagExplicitNullTest" Base="BoundDagTest" UpdateMethodModifiers="new"> <!--Check that the input is null. Used when an explicit null test appears in source.--> </Node> <Node Name="BoundDagValueTest" Base="BoundDagTest"> <!--Check that the input is the same as the given constant value (other than null).--> <Field Name="Value" Type="ConstantValue" Null="disallow"/> </Node> <Node Name="BoundDagRelationalTest" Base="BoundDagTest"> <!--Check that the input is related to (equal, not equal, less, less or equal, greater, greater or equal) the given constant value (other than null).--> <Field Name="OperatorKind" Type="BinaryOperatorKind"/> <Field Name="Value" Type="ConstantValue" Null="disallow"/> </Node> <!-- As a decision, an evaluation is considered to always succeed. --> <AbstractNode Name="BoundDagEvaluation" Base="BoundDagTest"> </AbstractNode> <Node Name="BoundDagDeconstructEvaluation" Base="BoundDagEvaluation"> <Field Name="DeconstructMethod" Type="MethodSymbol" Null="disallow"/> </Node> <Node Name="BoundDagTypeEvaluation" Base="BoundDagEvaluation"> <!--Cast to the given type, assumed to be used after a successful type check.--> <Field Name="Type" Type="TypeSymbol" Null="disallow"/> </Node> <Node Name="BoundDagFieldEvaluation" Base="BoundDagEvaluation"> <Field Name="Field" Type="FieldSymbol" Null="disallow"/> </Node> <Node Name="BoundDagPropertyEvaluation" Base="BoundDagEvaluation"> <Field Name="Property" Type="PropertySymbol" Null="disallow"/> <Field Name="IsLengthOrCount" Type="bool"/> </Node> <Node Name="BoundDagIndexEvaluation" Base="BoundDagEvaluation"> <Field Name="Property" Type="PropertySymbol" Null="disallow"/> <Field Name="Index" Type="int"/> </Node> <Node Name="BoundDagIndexerEvaluation" Base="BoundDagEvaluation" HasValidate="true"> <Field Name="IndexerType" Type="TypeSymbol"/> <Field Name="LengthTemp" Type="BoundDagTemp"/> <!-- Negative Index values indicate positions after a slice pattern --> <Field Name="Index" Type="int"/> <!-- May be BoundIndexerAccess or BoundImplicitIndexerAccess or BoundArrayAccess, which are built using placeholders for receiver and argument. --> <Field Name="IndexerAccess" Type="BoundExpression"/> <!-- The receiver placeholder for indexer access --> <Field Name="ReceiverPlaceholder" Type="BoundListPatternReceiverPlaceholder"/> <!-- The argument placeholder of type Index for indexer access --> <Field Name="ArgumentPlaceholder" Type="BoundListPatternIndexPlaceholder"/> </Node> <Node Name="BoundDagSliceEvaluation" Base="BoundDagEvaluation" HasValidate="true"> <Field Name="SliceType" Type="TypeSymbol"/> <Field Name="LengthTemp" Type="BoundDagTemp"/> <Field Name="StartIndex" Type="int"/> <Field Name="EndIndex" Type="int"/> <!-- May be BoundIndexerAccess or BoundImplicitIndexerAccess or BoundArrayAccess, which are built using placeholders for receiver and argument. --> <Field Name="IndexerAccess" Type="BoundExpression"/> <!-- The receiver placeholder for indexer access --> <Field Name="ReceiverPlaceholder" Type="BoundSlicePatternReceiverPlaceholder"/> <!-- The argument placeholder of type Range for indexer access --> <Field Name="ArgumentPlaceholder" Type="BoundSlicePatternRangePlaceholder"/> </Node> <Node Name="BoundDagAssignmentEvaluation" Base="BoundDagEvaluation"> <Field Name="Target" Type="BoundDagTemp"/> </Node> <Node Name="BoundDagPassThroughEvaluation" Base="BoundDagEvaluation" UpdateMethodModifiers="new"> </Node> <Node Name="BoundSwitchSection" Base="BoundStatementList"> <Field Name="Locals" Type="ImmutableArray<LocalSymbol>"/> <Field Name="SwitchLabels" Type="ImmutableArray<BoundSwitchLabel>"/> </Node> <Node Name="BoundSwitchLabel" Base="BoundNode"> <Field Name="Label" Type="LabelSymbol"/> <Field Name="Pattern" Type="BoundPattern"/> <Field Name="HasUnionMatching" Type="bool"/> <Field Name="WhenClause" Type="BoundExpression?"/> </Node> <AbstractNode Name="BoundMethodOrPropertyGroup" Base="BoundExpression"> <!-- Type is not significant for this node type; always null --> <Field Name="Type" Type="TypeSymbol?" Override="true" Null="always"/> <!--We wish to keep the left-hand-side of the member access in the method group even if the *instance* expression ought to be null. For example, if we have System.Console.WriteLine then we want to keep the System.Console type expression as the receiver, even though the spec says that the instance expression is null in this case. We'll add a helper property that gets the instance expression from the receiver should we need it. --> <Field Name="ReceiverOpt" Type="BoundExpression?"/> <Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/> </AbstractNode> <!-- Use this in the event that the sequence point must be applied to expression.--> <Node Name="BoundSequencePointExpression" Base="BoundExpression"> <Field Name="Expression" Type="BoundExpression" Null="disallow"/> </Node> <!-- A node specially to represent the idea of "compute this side effects while discarding results, and then compute this value" The node may also declare locals (temporaries). The sequence node is both SCOPE and EXTENT of these locals. As a result non-intersecting sequences can reuse variable slots. --> <Node Name="BoundSequence" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Locals" Type="ImmutableArray<LocalSymbol>"/> <Field Name="SideEffects" Type="ImmutableArray<BoundExpression>"/> <Field Name="Value" Type="BoundExpression"/> </Node> <!-- Like BoundSequence, but the side-effects are statements. This node is produced during initial lowering for the `await` expression and for the switch expression. A separate pass removes these nodes by moving the statements to the top level (i.e. to a statement list that is not in a BoundSpillSequence). It is called a spill sequence because the process of moving it to the top level causes values that would be on the stack during its evaluation to be spilled to temporary variables. Note: this node is also produced during async rewriting for runtime async codegen but is removed shortly thereafter. --> <Node Name="BoundSpillSequence" Base="BoundExpression" DoesNotSurvive="Spilling"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Locals" Type="ImmutableArray<LocalSymbol>"/> <Field Name="SideEffects" Type="ImmutableArray<BoundStatement>"/> <Field Name="Value" Type="BoundExpression"/> </Node> <Node Name="BoundDynamicMemberAccess" Base="BoundExpression"> <!--Non-null type is required, and will always be "dynamic". --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Receiver" Type="BoundExpression"/> <Field Name="TypeArgumentsOpt" Type="ImmutableArray<TypeWithAnnotations>" Null="allow"/> <Field Name="Name" Type="string" Null="disallow"/> <!-- TODO (tomat): do we really need these flags here? it should be possible to infer them from the context --> <Field Name="Invoked" Type="bool"/> <Field Name="Indexed" Type="bool"/> </Node> <AbstractNode Name="BoundDynamicInvocableBase" Base="BoundExpression"> <Field Name="Expression" Type="BoundExpression"/> <Field Name="Arguments" Type="ImmutableArray<BoundExpression>"/> </AbstractNode> <Node Name="BoundDynamicInvocation" Base="BoundDynamicInvocableBase"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="ArgumentNamesOpt" Type="ImmutableArray<string?>" Null="allow"/> <Field Name="ArgumentRefKindsOpt" Type="ImmutableArray<RefKind>" Null="allow"/> <!-- If the receiver is statically typed the set of applicable methods that may be invoked at runtime. Empty otherwise. --> <Field Name="ApplicableMethods" Type="ImmutableArray<MethodSymbol>" /> </Node> <Node Name="BoundConditionalAccess" Base="BoundExpression"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Receiver" Type="BoundExpression"/> <Field Name="AccessExpression" Type="BoundExpression"/> </Node> <Node Name="BoundLoweredConditionalAccess" Base="BoundExpression"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Receiver" Type="BoundExpression"/> <Field Name="HasValueMethodOpt" Type="MethodSymbol?"/> <Field Name="WhenNotNull" Type="BoundExpression"/> <Field Name="WhenNullOpt" Type="BoundExpression?"/> <!-- Async rewriter needs to replace receivers with their spilled values and for that it needs to match receivers and the containing conditional expressions. To be able to do that, during lowering, we will assign BoundLoweredConditionalAccess and corresponding BoundConditionalReceiver matching Id that are integers unique for the containing method body. --> <Field Name="Id" Type="int"/> <Field Name="ForceCopyOfNullableValueType" Type="bool"/> </Node> <!-- represents the receiver of a conditional access expression --> <Node Name="BoundConditionalReceiver" Base="BoundExpression"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <!-- See the comment in BoundLoweredConditionalAccess --> <Field Name="Id" Type="int"/> </Node> <!-- This node represents a complex receiver for a call, or a conditional access. At runtime, when its type is a value type, ValueTypeReceiver should be used as a receiver. Otherwise, ReferenceTypeReceiver should be used. This kind of receiver is created only by SpillSequenceSpiller and LocalRewriter. --> <Node Name="BoundComplexConditionalReceiver" Base="BoundExpression"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="ValueTypeReceiver" Type="BoundExpression" Null="disallow"/> <Field Name="ReferenceTypeReceiver" Type="BoundExpression" Null="disallow"/> </Node> <Node Name="BoundMethodGroup" Base="BoundMethodOrPropertyGroup"> <!-- SPEC: A method group is a set of overloaded methods resulting from a member lookup. SPEC: A method group may have an associated instance expression and SPEC: an associated type argument list. --> <Field Name="TypeArgumentsOpt" Type="ImmutableArray<TypeWithAnnotations>" Null="allow"/> <Field Name="Name" Type="string" Null="disallow"/> <Field Name="Methods" Type="ImmutableArray<MethodSymbol>" /> <Field Name="LookupSymbolOpt" Type="Symbol?"/> <Field Name="LookupError" Type="DiagnosticInfo?"/> <Field Name="Flags" Type="BoundMethodGroupFlags?"/> <Field Name="FunctionType" Type="FunctionTypeSymbol?" Null="allow"/> </Node> <Node Name="BoundPropertyGroup" Base="BoundMethodOrPropertyGroup"> <Field Name="Properties" Type="ImmutableArray<PropertySymbol>" /> </Node> <Node Name="BoundCall" Base="BoundExpression" HasValidate="true"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="ReceiverOpt" Type="BoundExpression?"/> <!-- Whether receiver will need to be cloned during emit (only valid before lowering) --> <Field Name="InitialBindingReceiverIsSubjectToCloning" Type="ThreeState"/> <Field Name="Method" Type="MethodSymbol"/> <Field Name="Arguments" Type="ImmutableArray<BoundExpression>"/> <Field Name="ArgumentNamesOpt" Type="ImmutableArray<string?>" Null="allow"/> <Field Name="ArgumentRefKindsOpt" Type="ImmutableArray<RefKind>" Null="allow"/> <Field Name="IsDelegateCall" Type="bool"/> <Field Name="Expanded" Type="bool"/> <Field Name="InvokedAsExtensionMethod" Type="bool"/> <Field Name="ArgsToParamsOpt" Type="ImmutableArray<int>" Null="allow"/> <Field Name="DefaultArguments" Type="BitVector" /> <!-- Result kind for the invocation. Never LookupResultKind.MemberGroup or LookupResultKind.StaticInstanceMismatch. If the value is something other than LookupResultKind.Viable, then the node represents a bad invocation, the consistency among information stored in other properties is not guaranteed, and the Method property might be set to an ErrorMethodSymbol. A special care should be taken when dealing with such nodes. It is recommended to treat them similar to BoundBadExpressions nodes, unless there is a good reason to have more complicated error recovery. --> <Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/> <!--The set of method symbols from which this call's method was chosen. Only kept in the tree if the call was an error and overload resolution was unable to choose a best method.--> <Field Name="OriginalMethodsOpt" Type="ImmutableArray<MethodSymbol>" Null="Allow" SkipInNullabilityRewriter="true"/> </Node> <Node Name="BoundEventAssignmentOperator" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Event" Type="EventSymbol"/> <Field Name="IsAddition" Type="bool"/> <Field Name="IsDynamic" Type="bool"/> <Field Name="ReceiverOpt" Type="BoundExpression?"/> <Field Name="Argument" Type="BoundExpression"/> </Node> <Node Name="BoundAttribute" Base="BoundExpression"> <!-- Type is required for this node type; may not be null --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Constructor" Type="MethodSymbol?"/> <Field Name="ConstructorArguments" Type="ImmutableArray<BoundExpression>"/> <Field Name="ConstructorArgumentNamesOpt" Type="ImmutableArray<string?>" Null="allow"/> <Field Name="ConstructorArgumentsToParamsOpt" Type="ImmutableArray<int>" Null="allow"/> <Field Name="ConstructorExpanded" Type="bool" /> <Field Name="ConstructorDefaultArguments" Type="BitVector"/> <Field Name="NamedArguments" Type ="ImmutableArray<BoundAssignmentOperator>"/> <Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/> </Node> <!-- This node is used to represent a target-typed object creation expression --> <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<BoundExpression>"/> <Field Name="ArgumentNamesOpt" Type="ImmutableArray<(string Name, Location Location)?>" Null="allow"/> <Field Name="ArgumentRefKindsOpt" Type="ImmutableArray<RefKind>" Null="allow"/> <Field Name="InitializerOpt" Type="InitializerExpressionSyntax?" Null="allow"/> <Field Name="Binder" Type="Binder" Null="disallow"/> </Node> <AbstractNode Name="BoundObjectCreationExpressionBase" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> </AbstractNode> <!-- Constructor is optional because value types can be created without calling any constructor - int x = new int(); --> <Node Name="BoundObjectCreationExpression" Base="BoundObjectCreationExpressionBase"> <Field Name="Constructor" Type="MethodSymbol" PropertyOverrides="true"/> <!-- These symbols will be returned from the GetSemanticInfo API if it examines this bound node. --> <Field Name="ConstructorsGroup" Type="ImmutableArray<MethodSymbol>"/> <Field Name="Arguments" Type="ImmutableArray<BoundExpression>" PropertyOverrides="true"/> <Field Name="ArgumentNamesOpt" Type="ImmutableArray<string?>" Null="allow" PropertyOverrides="true"/> <Field Name="ArgumentRefKindsOpt" Type="ImmutableArray<RefKind>" Null="allow" PropertyOverrides="true"/> <Field Name="Expanded" Type="bool" PropertyOverrides="true"/> <Field Name="ArgsToParamsOpt" Type="ImmutableArray<int>" Null="allow" PropertyOverrides="true"/> <Field Name="DefaultArguments" Type="BitVector" PropertyOverrides="true"/> <Field Name="ConstantValueOpt" Type="ConstantValue?" PropertyOverrides="true"/> <Field Name="InitializerExpressionOpt" Type="BoundObjectInitializerExpressionBase?" PropertyOverrides="true"/> <Field Name="WasTargetTyped" Type="bool" PropertyOverrides="true"/> </Node> <AbstractNode Name="BoundCollectionExpressionBase" Base="BoundExpression" HasValidate="true"> <!-- Collection expression elements. --> <Field Name="Elements" Type="ImmutableArray<BoundNode>"/> </AbstractNode> <!-- An unconverted collection expression. --> <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"/> <Field Name="WithElement" Type="BoundUnconvertedWithElement?" Null="allow"/> </Node> <Node Name="BoundUnconvertedWithElement" Base="BoundNode"> <!-- With-arguments support for collection expression with(...) syntax --> <Field Name="Arguments" Type="ImmutableArray<BoundExpression>"/> <Field Name="ArgumentNamesOpt" Type="ImmutableArray<(string Name, Location Location)?>" Null="allow"/> <Field Name="ArgumentRefKindsOpt" Type="ImmutableArray<RefKind>" Null="allow"/> </Node> <Node Name="BoundCollectionExpression" Base="BoundCollectionExpressionBase" HasValidate="true"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="CollectionTypeKind" Type="CollectionExpressionTypeKind"/> <!-- An expression placeholder value representing the initialized collection. --> <Field Name="Placeholder" Type="BoundObjectOrCollectionValuePlaceholder?" Null="allow" SkipInVisitor="true"/> <!-- Call to instantiate a collection with a constructor or through a builder method. In former case this should be a BoundObjectCreationExpression. In the latter this should be a BoundCall (possibly wrapped in a conversion). --> <Field Name="CollectionCreation" Type="BoundExpression?" Null="allow"/> <!-- Collection builder method being invoked. Null for all other collection expression types. If generic, this will be the constructed form. --> <Field Name="CollectionBuilderMethod" Type="MethodSymbol?" Null="allow"/> <!-- Placeholder location where the collection builder elements will be placed. Null for all other collection expression types. For example, if the collection is `[with(a, b, c), x, y, z]` initial binding will produce `Factory.Create(a, b, c, <placeholder>)`. The last arg will be replaced in lowering with the ReadOnlySpan for and will naturally be visited during all binding phases. It is just the packaging and movement into the final arg that the lowering phase concerns itself with. --> <Field Name="CollectionBuilderElementsPlaceholder" Type="BoundCollectionBuilderElementsPlaceholder?" Null="allow" SkipInVisitor="true"/> <Field Name="WasTargetTyped" Type="bool" /> <Field Name="HasWithElement" Type="bool" /> <Field Name="UnconvertedCollectionExpression" Type="BoundUnconvertedCollectionExpression" Null="disallow" SkipInVisitor="true"/> </Node> <Node Name="BoundCollectionExpressionSpreadExpressionPlaceholder" Base="BoundValuePlaceholderBase"/> <Node Name="BoundCollectionExpressionSpreadElement" Base="BoundNode"> <!-- Collection being spread. --> <Field Name="Expression" Type="BoundExpression"/> <!-- Collection placeholder, used in Conversion and LengthOrCount fields. --> <Field Name="ExpressionPlaceholder" Type="BoundCollectionExpressionSpreadExpressionPlaceholder?" SkipInVisitor="true" Null="allow"/> <!-- Collection conversion to the type expected for foreach. --> <Field Name="Conversion" Type="BoundExpression?" Null="allow" SkipInVisitor="true"/> <!-- Collection enumerator info. --> <Field Name="EnumeratorInfoOpt" Type="ForEachEnumeratorInfo?"/> <!-- Collection Length or Count property value. --> <Field Name="LengthOrCount" Type="BoundExpression?" SkipInVisitor="true" Null="allow"/> <!-- Collection element placeholder, used in IteratorBody. --> <Field Name="ElementPlaceholder" Type="BoundValuePlaceholder?" SkipInVisitor="true" Null="allow"/> <!-- Statement executed for each collection element. --> <Field Name="IteratorBody" Type="BoundStatement?" SkipInVisitor="true" Null="allow"/> </Node> <!-- Tuple literals can exist in two forms - literal and converted literal. This is the base node for both forms. --> <AbstractNode Name="BoundTupleExpression" Base="BoundExpression"> <Field Name="Arguments" Type="ImmutableArray<BoundExpression>"/> <Field Name="ArgumentNamesOpt" Type="ImmutableArray<string?>" Null="allow"/> <!-- Which argument names were inferred (as opposed to explicitly provided)? --> <Field Name="InferredNamesOpt" Type="ImmutableArray<bool>" Null="allow"/> </AbstractNode> <!-- Tuple literals can convert to the target type. 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" DoesNotSurvive="InitialBinding"> <!-- It is possible for a tuple to not have a type in a literal form Ex: (a:=1, b:= (c:=1, d:=Nothing)) does not have a natural type, because "Nothing" does not have one --> <Field Name="Type" Type="TypeSymbol?" Override="true" Null="allow"/> </Node> <!-- Tuple literals can convert to the target type. Once converted to a target type, they cannot be target-typed again. The Converted tuple literal is one which has already been converted to a target type. Converted tuple literal always has a type. --> <Node Name="BoundConvertedTupleLiteral" Base="BoundTupleExpression"> <!-- Original tuple is preserved for the purpose of semantic model. When tuples are created as part of lowering, this could be null. --> <Field Name="SourceTuple" Type="BoundTupleLiteral?" Null="allow" SkipInVisitor="ExceptNullabilityRewriter" /> <Field Name="WasTargetTyped" Type="bool" /> </Node> <Node Name="BoundDynamicObjectCreationExpression" Base="BoundObjectCreationExpressionBase"> <Field Name="Name" Type="string" Null="disallow"/> <Field Name="Arguments" Type="ImmutableArray<BoundExpression>" PropertyOverrides="true"/> <Field Name="ArgumentNamesOpt" Type="ImmutableArray<string?>" Null="allow" PropertyOverrides="true"/> <Field Name="ArgumentRefKindsOpt" Type="ImmutableArray<RefKind>" Null="allow" PropertyOverrides="true"/> <Field Name="InitializerExpressionOpt" Type="BoundObjectInitializerExpressionBase?" PropertyOverrides="true"/> <Field Name="ApplicableMethods" Type="ImmutableArray<MethodSymbol>" /> <Field Name="WasTargetTyped" Type="bool" PropertyOverrides="true"/> </Node> <Node Name="BoundNoPiaObjectCreationExpression" Base="BoundObjectCreationExpressionBase"> <Field Name="GuidString" Type="string?"/> <Field Name="InitializerExpressionOpt" Type="BoundObjectInitializerExpressionBase?" PropertyOverrides="true"/> <Field Name="WasTargetTyped" Type="bool" PropertyOverrides="true"/> </Node> <AbstractNode Name="BoundObjectInitializerExpressionBase" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <!-- An expression placeholder value representing the initialized object or collection. --> <Field Name="Placeholder" Type="BoundObjectOrCollectionValuePlaceholder" Null="disallow" /> <Field Name="Initializers" Type="ImmutableArray<BoundExpression>"/> </AbstractNode> <!-- Initializers of this are BoundAssignmentOperators whose Left is BadBoundExpression or BoundObjectInitializerMember or BoundDynamicObjectInitializerMember or BoundImplicitIndexerAccess or BoundArrayAccess or BoundPointerElementAccess. --> <Node Name="BoundObjectInitializerExpression" Base="BoundObjectInitializerExpressionBase"> </Node> <Node Name="BoundObjectInitializerMember" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="MemberSymbol" Type="Symbol?"/> <Field Name="Arguments" Type="ImmutableArray<BoundExpression>"/> <Field Name="ArgumentNamesOpt" Type="ImmutableArray<string?>" Null="allow"/> <Field Name="ArgumentRefKindsOpt" Type="ImmutableArray<RefKind>" Null="allow"/> <Field Name="Expanded" Type="bool"/> <Field Name="ArgsToParamsOpt" Type="ImmutableArray<int>" Null="allow"/> <Field Name="DefaultArguments" Type="BitVector" /> <Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/> <Field Name="AccessorKind" Type="AccessorKind" /> <!-- Used by IOperation to reconstruct the receiver for this expression. --> <Field Name="ReceiverType" Type="TypeSymbol" Null="disallow"/> </Node> <Node Name="BoundDynamicObjectInitializerMember" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="MemberName" Type="string" Null="disallow"/> <Field Name="ReceiverType" Type="TypeSymbol" Null="disallow" /> </Node> <Node Name="BoundCollectionInitializerExpression" Base="BoundObjectInitializerExpressionBase"> </Node> <Node Name="BoundCollectionElementInitializer" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <!-- We don't hold on BoundCall directly since dynamic invocation isn't specified explicitly in the source. --> <Field Name="AddMethod" Type="MethodSymbol"/> <Field Name="Arguments" Type="ImmutableArray<BoundExpression>"/> <!-- Used for IOperation to enable translating the initializer to a IDynamicInvocationOperation --> <Field Name="ImplicitReceiverOpt" Type="BoundExpression?" /> <Field Name="Expanded" Type="bool"/> <Field Name="ArgsToParamsOpt" Type="ImmutableArray<int>" Null="allow"/> <Field Name="DefaultArguments" Type="BitVector" /> <Field Name="InvokedAsExtensionMethod" Type="bool"/> <Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/> </Node> <Node Name="BoundDynamicCollectionElementInitializer" Base="BoundDynamicInvocableBase"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <!-- We don't hold on DynamicMethodInvocation directly since dynamic invocation isn't specified explicitly in the source. --> <!-- The set of applicable Add methods that may be invoked at runtime. Empty otherwise. --> <Field Name="ApplicableMethods" Type="ImmutableArray<MethodSymbol>" /> </Node> <Node Name="BoundImplicitReceiver" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> </Node> <Node Name="BoundAnonymousObjectCreationExpression" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Constructor" Type="MethodSymbol" Null="disallow"/> <Field Name="Arguments" Type="ImmutableArray<BoundExpression>"/> <!-- collection of BoundAnonymousPropertyDeclaration nodes representing bound identifiers for explicitly named field initializers, discarded during rewrite NOTE: 'Declarations' collection contain one node for each explicitly named field and does not have any for implicitly named ones, thus it may be empty in case there are no explicitly named fields --> <Field Name="Declarations" Type="ImmutableArray<BoundAnonymousPropertyDeclaration>"/> </Node> <Node Name="BoundAnonymousPropertyDeclaration" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Property" Type="PropertySymbol" Null="disallow"/> </Node> <Node Name="BoundNewT" Base="BoundObjectCreationExpressionBase"> <Field Name="InitializerExpressionOpt" Type="BoundObjectInitializerExpressionBase?" PropertyOverrides="true"/> <Field Name="WasTargetTyped" Type="bool" PropertyOverrides="true"/> </Node> <Node Name="BoundDelegateCreationExpression" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <!-- Argument is one of the following: 1. A method group (before local lowering only). If the method is nonstatic or converted as an extension method, the method group contains a receiver expression (mg.ReceiverOpt) for the created delegate; or 2. A value of type dynamic (before local lowering only); or 3. A bound lambda (before lambda lowering only); or 4. A value of a delegate type with MethodOpt == null; or 5. The receiver of the method being converted to a delegate (after local lowering). It may be a BoundTypeExpression if the method is static and not converted as an extension method. --> <Field Name="Argument" Type="BoundExpression"/> <Field Name="MethodOpt" Type="MethodSymbol?"/> <Field Name="IsExtensionMethod" Type="bool"/> <Field Name="WasTargetTyped" Type="bool"/> </Node> <Node Name="BoundArrayCreation" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Bounds" Type="ImmutableArray<BoundExpression>"/> <Field Name="InitializerOpt" Type="BoundArrayInitialization?"/> </Node> <Node Name="BoundArrayInitialization" Base="BoundExpression"> <!-- Type is not significant for this node type; always null --> <Field Name="Type" Type="TypeSymbol?" Override="true" Null="always"/> <!-- Whether the containing BoundArrayCreation or BoundStackAllocArrayCreationBase has an inferred vs. explicit type. --> <Field Name="IsInferred" Type="bool"/> <Field Name="Initializers" Type="ImmutableArray<BoundExpression>"/> </Node> <AbstractNode Name="BoundStackAllocArrayCreationBase" Base="BoundExpression"> <Field Name="ElementType" Type="TypeSymbol" Null="disallow"/> <Field Name="Count" Type="BoundExpression" Null="disallow" /> <Field Name="InitializerOpt" Type="BoundArrayInitialization?"/> </AbstractNode> <Node Name="BoundStackAllocArrayCreation" Base="BoundStackAllocArrayCreationBase"> <!-- A BoundStackAllocArrayCreation is given a null type when it is in a syntactic context where it could be either a pointer or a span, and in that case it requires conversion to one or the other. In the special case that it is the direct initializer of a local variable whose type is inferred, we treat it as a pointer. --> </Node> <Node Name="BoundConvertedStackAllocExpression" Base="BoundStackAllocArrayCreationBase"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> </Node> <Node Name="BoundFieldAccess" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="ReceiverOpt" Type="BoundExpression?"/> <Field Name="FieldSymbol" Type="FieldSymbol"/> <Field Name="ConstantValueOpt" Type="ConstantValue?" PropertyOverrides="true"/> <Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/> <Field Name="IsByValue" Type="bool"/> <Field Name="IsDeclaration" Type="bool" /> </Node> <!-- Used as a placeholder for synthesized fields in the expressions that are used to replace hoisted locals. When the local access expression is used, these placeholders are rewritten as field accesses on the appropriate frame object. --> <Node Name="BoundHoistedFieldAccess" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="FieldSymbol" Type="FieldSymbol"/> </Node> <Node Name="BoundPropertyAccess" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="ReceiverOpt" Type="BoundExpression?"/> <!-- Whether receiver will need to be cloned during emit (only valid before lowering) --> <Field Name="InitialBindingReceiverIsSubjectToCloning" Type="ThreeState"/> <Field Name="PropertySymbol" Type="PropertySymbol"/> <!-- The property accessor kind, set for properties with synthesized backing field only. --> <Field Name="AutoPropertyAccessorKind" Type="AccessorKind" /> <Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/> </Node> <Node Name="BoundEventAccess" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="ReceiverOpt" Type="BoundExpression?"/> <Field Name="EventSymbol" Type="EventSymbol"/> <Field Name="IsUsableAsField" Type="bool"/> <Field Name="ResultKind" PropertyOverrides="true" Type="LookupResultKind"/> </Node> <Node Name="BoundIndexerAccess" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="ReceiverOpt" Type="BoundExpression?"/> <!-- Whether receiver will need to be cloned during emit (only valid before lowering) --> <Field Name="InitialBindingReceiverIsSubjectToCloning" Type="ThreeState"/> <Field Name="Indexer" Type="PropertySymbol"/> <Field Name="Arguments" Type="ImmutableArray<BoundExpression>"/> <Field Name="ArgumentNamesOpt" Type="ImmutableArray<string?>" Null="allow"/> <Field Name="ArgumentRefKindsOpt" Type="ImmutableArray<RefKind>" Null="allow"/> <Field Name="Expanded" Type="bool"/> <Field Name="AccessorKind" Type="AccessorKind" /> <Field Name="ArgsToParamsOpt" Type="ImmutableArray<int>" Null="allow"/> <Field Name="DefaultArguments" Type="BitVector" /> <!--The set of indexer symbols from which this call's indexer was chosen. Only kept in the tree if the call was an error and overload resolution was unable to choose a best indexer.--> <Field Name="OriginalIndexersOpt" Type="ImmutableArray<PropertySymbol>" Null="allow" SkipInNullabilityRewriter="true"/> </Node> <Node Name="BoundImplicitIndexerAccess" Base="BoundExpression" SkipInNullabilityRewriter="true" HasValidate="true"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow" /> <!-- The target of the index operation --> <Field Name="Receiver" Type="BoundExpression" Null="disallow" /> <!-- An expression with type Index or Range --> <Field Name="Argument" Type="BoundExpression" Null="disallow" /> <Field Name="LengthOrCountAccess" Type="BoundExpression" SkipInVisitor="true" /> <!-- The receiver placeholder for length access and IndexerOrSliceAccess--> <Field Name="ReceiverPlaceholder" Type="BoundImplicitIndexerReceiverPlaceholder" SkipInVisitor="true" /> <!-- May be BoundIndexerAccess or BoundCall or BoundArrayAccess --> <Field Name="IndexerOrSliceAccess" Type="BoundExpression" Null="disallow" SkipInVisitor="true" /> <!-- The receiver placeholder(s) of type Int32 for indexer access (one if implicit Index indexer, two if implicit Range indexer) --> <Field Name="ArgumentPlaceholders" Type="ImmutableArray<BoundImplicitIndexerValuePlaceholder>" Null="disallow" SkipInVisitor="true" /> </Node> <Node Name="BoundInlineArrayAccess" Base="BoundExpression" HasValidate="true"> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow" /> <!-- The target of the operation --> <Field Name="Expression" Type="BoundExpression" Null="disallow" /> <!-- An expression with type int, Index or Range --> <Field Name="Argument" Type="BoundExpression" Null="disallow" /> <!-- The access is an element access rather than a slice access, and it produces a value rather than a variable --> <Field Name="IsValue" Type="bool" /> <Field Name="GetItemOrSliceHelper" Type="WellKnownMember"/> </Node> <Node Name="BoundDynamicIndexerAccess" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Receiver" Type="BoundExpression"/> <Field Name="Arguments" Type="ImmutableArray<BoundExpression>"/> <Field Name="ArgumentNamesOpt" Type="ImmutableArray<string?>" Null="allow"/> <Field Name="ArgumentRefKindsOpt" Type="ImmutableArray<RefKind>" Null="allow"/> <!-- If the receiver is statically typed the set of applicable methods that may be invoked at runtime. Empty otherwise. --> <Field Name="ApplicableIndexers" Type="ImmutableArray<PropertySymbol>" /> </Node> <Node Name="BoundLambda" Base="BoundExpression"> <Field Name="UnboundLambda" Type="UnboundLambda" Null="disallow" SkipInVisitor="true"/> <!-- Must be a LambdaSymbol until the node reaches LocalRewriter --> <!-- LambdaSymbol may differ from Binder.MemberSymbol after rewriting. --> <Field Name="Symbol" Type="MethodSymbol" Null="disallow"/> <Field Name="Type" Type="TypeSymbol?" Override="true"/> <Field Name="Body" Type="BoundBlock"/> <Field Name="Diagnostics" Type="ReadOnlyBindingDiagnostic<AssemblySymbol>"/> <Field Name="Binder" Type="Binder" Null="disallow" /> </Node> <Node Name="UnboundLambda" Base="BoundExpression"> <!-- Type is not significant for this node type; always null --> <Field Name="Type" Type="TypeSymbol?" Override="true" Null="always"/> <Field Name="Data" Type="UnboundLambdaState" Null="disallow"/> <Field Name="FunctionType" Type="FunctionTypeSymbol?" Null="allow"/> <!-- Track dependencies while binding body, etc. --> <Field Name="WithDependencies" Type="Boolean"/> </Node> <Node Name="BoundQueryClause" Base="BoundExpression"> <!-- Equal to Value.Type. --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <!-- The value computed for this query clause. --> <Field Name="Value" Type="BoundExpression" Null="disallow"/> <!-- The query variable introduced by this query clause, if any. --> <Field Name="DefinedSymbol" Type="RangeVariableSymbol?"/> <!-- The bound expression that invokes the operation of the query clause. --> <Field Name="Operation" Type="BoundExpression?" SkipInVisitor="true"/> <!-- The bound expression that is the invocation of a "Cast" method specified by the query translation. --> <Field Name="Cast" Type="BoundExpression?" SkipInVisitor="true"/> <!-- The enclosing binder in which the query clause was evaluated. --> <Field Name="Binder" Type="Binder" Null="disallow" /> <!-- The bound expression that is the query expression in "unoptimized" form. Specifically, a final ".Select" invocation that is omitted by the specification is included here. --> <Field Name="UnoptimizedForm" Type="BoundExpression?" SkipInVisitor="true"/> </Node> <!-- Special node to encapsulate initializers added into a constructor. Helps to do special optimizations in lowering. --> <Node Name="BoundTypeOrInstanceInitializers" Base="BoundStatementList" DoesNotSurvive="LocalRewriting"> </Node> <Node Name="BoundNameOfOperator" Base="BoundExpression" HasValidate="true"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Argument" Type="BoundExpression" Null="disallow"/> <Field Name="ConstantValueOpt" Type="ConstantValue" PropertyOverrides="true"/> </Node> <AbstractNode Name="BoundInterpolatedStringBase" Base="BoundExpression"> <!-- The sequence of parts of an interpolated string. The even numbered positions (starting with 0) are from the literal parts of the input. The odd numbered positions are the string inserts. If the interpolated string has been bound using the builder pattern, literals are replaced with calls. --> <Field Name="Parts" Type="ImmutableArray<BoundExpression>"/> <Field Name="ConstantValueOpt" Type="ConstantValue?" PropertyOverrides="true"/> </AbstractNode> <Node Name="BoundUnconvertedInterpolatedString" Base="BoundInterpolatedStringBase" DoesNotSurvive="InitialBinding"> </Node> <Node Name="BoundInterpolatedString" Base="BoundInterpolatedStringBase"> <Field Name="InterpolationData" Type="InterpolatedStringHandlerData?"/> </Node> <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. --> <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. --> <Field Name="ArgumentIndex" Type="int" /> </Node> <Node Name="BoundStringInsert" Base="BoundExpression"> <Field Name="Type" Type="TypeSymbol?" Override="true" Null="always"/> <Field Name="Value" Type="BoundExpression" Null="disallow"/> <Field Name="Alignment" Type="BoundExpression?"/> <Field Name="Format" Type="BoundLiteral?"/> <Field Name="IsInterpolatedStringHandlerAppendCall" Type="bool"/> </Node> <!-- An 'is pattern'. The fields DecisionDag, WhenTrueLabel, and WhenFalseLabel represent the inner pattern after removing any outer 'not's, so consumers (such as lowering and definite assignment of the local in 'is not Type t') will need to compensate for negated patterns. IsNegated is set if Pattern is the negated form of the inner pattern represented by DecisionDag. --> <Node Name="BoundIsPatternExpression" Base="BoundExpression"> <Field Name="Expression" Type="BoundExpression" Null="disallow"/> <Field Name="Pattern" Type="BoundPattern" Null="disallow"/> <Field Name="HasUnionMatching" Type="bool"/> <Field Name="IsNegated" Type="bool"/> <Field Name="ReachabilityDecisionDag" Type="BoundDecisionDag" Null="disallow" SkipInVisitor="true"/> <Field Name="WhenTrueLabel" Type="LabelSymbol" Null="disallow"/> <Field Name="WhenFalseLabel" Type="LabelSymbol" Null="disallow"/> </Node> <AbstractNode Name="BoundPattern" Base="BoundNode" HasValidate="true"> <Field Name="InputType" Type="TypeSymbol" Null="disallow"/> <Field Name="NarrowedType" Type="TypeSymbol" Null="disallow"/> </AbstractNode> <!-- NarrowedType is either the Value.Type, or 'object' for Union matching, and the InputType otherwise. --> <Node Name="BoundConstantPattern" Base="BoundPattern" HasValidate="true"> <Field Name="Value" Type="BoundExpression"/> <Field Name="ConstantValue" Type="ConstantValue" Null="disallow"/> <Field Name="UnionMatchingMode" Type="UnionMatchingMode" PropertyOverrides="true"/> </Node> <!-- This node is a transient node used by UnionMatchingRewriter. It does not escape the rewriter. This node cannot be used as a child of any bound node, except another BoundPatternWithUnionMatching node. In which case, it must be the LeftOfPendingConjunction child. The ExclusiveInstancePattern, ValueProperty, ExclusiveValuePattern and SharedRightOfPendingConjunction represent a Union matching operation pending a rewrite to a BoundRecursivePattern and possibly a disjunction. The BoundPatternWithUnionMatching node represents either a standalone Union matching operation (LeftOfPendingConjunction is null), or a conjunction with a Union matching operation on the right hand side. The left hand side of the conjunction is then represented by the LeftOfPendingConjunction child. It represents a pattern that is matched immediately before the union match. A Union matching operation corresponding to the top most BoundPatternWithUnionMatching node represents the last Union matching operation in evaluation order in the entire hierarchy. The preceding union matching operation in evaluation order, if any, corresponds to the BoundPatternWithUnionMatching node stored in the LeftOfPendingConjunction child. Etc. InputType is LeftOfPendingConjunction.InputType ?? UnionMatchingInputType NarrowedType is (SharedRightOfPendingConjunction ?? ExclusiveValuePattern).NarrowedType --> <Node Name="BoundPatternWithUnionMatching" Base="BoundPattern" HasValidate="true" DoesNotSurvive="InitialBinding"> <!-- The Union or Nullable<Union> type matched --> <Field Name="UnionMatchingInputType" Type="TypeSymbol" Null="disallow"/> <Field Name="LeftOfPendingConjunction" Type="BoundPattern?"/> <Field Name="ExclusiveInstancePattern" Type="BoundPattern?" Null="allow"/> <!-- Info for the corresponding union Value property --> <Field Name="ValueProperty" Type="BoundPropertySubpatternMember"/> <!-- The pattern to match against the union Value property --> <Field Name="ExclusiveValuePattern" Type="BoundPattern"/> <!-- The pattern that is conjunctively combined with ExclusiveInstancePattern and with ExclusiveValuePattern --> <Field Name="SharedRightOfPendingConjunction" Type="BoundPattern?"/> </Node> <!-- NarrowedType is always the InputType --> <Node Name="BoundDiscardPattern" Base="BoundPattern" HasValidate="true"> </Node> <AbstractNode Name="BoundObjectPattern" Base="BoundPattern"> <!-- Variable is a local symbol, or in the case of top-level code in scripts and interactive, a field that is a member of the script class. Variable is null if `_` is used or if the identifier is omitted. --> <Field Name="Variable" Type="Symbol?"/> <!-- VariableAccess is an access to the declared variable, suitable for use in the lowered form in either an lvalue or rvalue position. We maintain it separately from the Symbol to facilitate lowerings in which the variable is no longer a simple variable access (e.g. in the expression evaluator). It is expected to be logically side-effect free. The necessity of this member is a consequence of a design issue documented in https://github.com/dotnet/roslyn/issues/13960 . When that is fixed this field can be removed. --> <Field Name="VariableAccess" Type="BoundExpression?"/> </AbstractNode> <!-- NarrowedType is the DeclaredType if given, or an InputType --> <Node Name="BoundDeclarationPattern" Base="BoundObjectPattern" HasValidate="true"> <Field Name="DeclaredType" Type="BoundTypeExpression" Null="disallow"/> <Field Name="IsVar" Type="bool"/> <Field Name="UnionMatchingMode" Type="UnionMatchingMode" PropertyOverrides="true"/> </Node> <!-- NarrowedType is the DeclaredType if given, or 'object' for Union matching, and an InputType, or its underlying type when the InputType is a Nullable of T otherwise --> <Node Name="BoundRecursivePattern" Base="BoundObjectPattern" HasValidate="true"> <Field Name="DeclaredType" Type="BoundTypeExpression?"/> <Field Name="DeconstructMethod" Type="MethodSymbol?"/> <Field Name="Deconstruction" Type="ImmutableArray<BoundPositionalSubpattern>" Null="allow"/> <Field Name="Properties" Type="ImmutableArray<BoundPropertySubpattern>" Null="allow"/> <Field Name="IsExplicitNotNullTest" Type="bool"/> <Field Name="UnionMatchingMode" Type="UnionMatchingMode" PropertyOverrides="true"/> </Node> <!-- NarrowedType is 'object' for Union matching, and it is always an InputType, or its underlying type when the InputType is a Nullable of T otherwise. --> <Node Name="BoundListPattern" Base="BoundObjectPattern" HasValidate="true"> <Field Name="Subpatterns" Type="ImmutableArray<BoundPattern>" Null="disallow"/> <Field Name="HasSlice" Type="bool"/> <Field Name="LengthAccess" Type="BoundExpression?" SkipInVisitor="true"/> <!-- May be BoundIndexerAccess or BoundImplicitIndexerAccess or BoundArrayAccess or BoundBadExpression or BoundDynamicIndexerAccess, which are built using placeholders for receiver and argument. --> <Field Name="IndexerAccess" Type="BoundExpression?" SkipInVisitor="true"/> <!-- The receiver placeholder for length and indexer access --> <Field Name="ReceiverPlaceholder" Type="BoundListPatternReceiverPlaceholder?" SkipInVisitor="true"/> <!-- The argument placeholder of type Index for indexer indexer access --> <Field Name="ArgumentPlaceholder" Type="BoundListPatternIndexPlaceholder?" SkipInVisitor="true"/> </Node> <!-- NarrowedType is always the InputType --> <Node Name="BoundSlicePattern" Base="BoundPattern" HasValidate="true"> <Field Name="Pattern" Type="BoundPattern?"/> <!-- May be BoundIndexerAccess or BoundImplicitIndexerAccess or BoundArrayAccess or BoundBadExpression or BoundDynamicIndexerAccess, which are built using placeholders for receiver and argument. --> <Field Name="IndexerAccess" Type="BoundExpression?" SkipInVisitor="true"/> <!-- The receiver placeholder for indexer access --> <Field Name="ReceiverPlaceholder" Type="BoundSlicePatternReceiverPlaceholder?" SkipInVisitor="true"/> <!-- The argument placeholder of type Range for indexer access --> <Field Name="ArgumentPlaceholder" Type="BoundSlicePatternRangePlaceholder?" SkipInVisitor="true"/> </Node> <!-- Narrowed type is always System.Runtime.CompilerServices.ITuple --> <Node Name="BoundITuplePattern" Base="BoundPattern" HasValidate="true"> <Field Name="GetLengthMethod" Type="MethodSymbol" Null="disallow"/> <Field Name="GetItemMethod" Type="MethodSymbol" Null="disallow"/> <Field Name="Subpatterns" Type="ImmutableArray<BoundPositionalSubpattern>" Null="disallow"/> </Node> <AbstractNode Name="BoundSubpattern" Base="BoundNode" HasValidate="true"> <Field Name="Pattern" Type="BoundPattern"/> </AbstractNode> <Node Name="BoundPositionalSubpattern" Base="BoundSubpattern"> <!-- The tuple element or parameter in a positional pattern. --> <Field Name="Symbol" Type="Symbol?"/> </Node> <Node Name="BoundPropertySubpattern" Base="BoundSubpattern"> <!-- The property or field access in a property pattern. --> <Field Name="Member" Type="BoundPropertySubpatternMember?"/> <Field Name="IsLengthOrCount" Type="bool"/> </Node> <Node Name="BoundPropertySubpatternMember" Base="BoundNode"> <Field Name="Receiver" Type="BoundPropertySubpatternMember?"/> <Field Name="Symbol" Type="Symbol?"/> <Field Name="Type" Type="TypeSymbol"/> </Node> <!-- NarrowedType is always the DeclaredType --> <Node Name="BoundTypePattern" Base="BoundPattern" HasValidate="true"> <Field Name="DeclaredType" Type="BoundTypeExpression"/> <Field Name="IsExplicitNotNullTest" Type="bool"/> <Field Name="UnionMatchingMode" Type="UnionMatchingMode" PropertyOverrides="true"/> </Node> <!-- For Disjunction NarrowedType is the least specific NarrowedType type across all leafs of constituent disjunctions, or the InputType if one cannot be determined Left.InputType is the InputType Right.InputType is the InputType For Conjunction NarrowedType is the Right.NarrowedType Left.InputType is the InputType Right.InputType is the Left.NarrowedType --> <Node Name="BoundBinaryPattern" Base="BoundPattern" HasValidate="true" SkipInNullabilityRewriter="true"> <!-- When true, denotes an 'or' pattern. When false, denotes an 'and' pattern. --> <Field Name="Disjunction" Type="bool"/> <Field Name="Left" Type="BoundPattern"/> <Field Name="Right" Type="BoundPattern"/> </Node> <!-- NarrowedType is the InputType --> <Node Name="BoundNegatedPattern" Base="BoundPattern" HasValidate="true"> <Field Name="Negated" Type="BoundPattern"/> </Node> <!-- NarrowedType is either the Value.Type, or 'object' for Union matching, and the InputType otherwise. --> <Node Name="BoundRelationalPattern" Base="BoundPattern" HasValidate="true"> <Field Name="Relation" Type="BinaryOperatorKind"/> <Field Name="Value" Type="BoundExpression"/> <Field Name="ConstantValue" Type="ConstantValue" Null="disallow"/> <Field Name="UnionMatchingMode" Type="UnionMatchingMode" PropertyOverrides="true"/> </Node> <Node Name="BoundDiscardExpression" Base="BoundExpression"> <!-- A discarded value, when a designator uses `_`. When the type is given as `var, its Type is null before type inference, and it is replaced by a BoundDiscardExpression with a non-null type after inference. --> <Field Name="Type" Type="TypeSymbol?" Override="true"/> <Field Name="NullableAnnotation" Type="NullableAnnotation"/> <Field Name="IsInferred" Type="bool"/> </Node> <Node Name="BoundThrowExpression" Base="BoundExpression"> <Field Name="Expression" Type="BoundExpression" Null="disallow"/> </Node> <AbstractNode Name="VariablePendingInference" Base="BoundExpression"> <!-- Type is not significant for this node type; always null --> <Field Name="Type" Type="TypeSymbol?" Override="true" Null="always"/> <!-- A local symbol or a field symbol representing the variable --> <Field Name="VariableSymbol" Type="Symbol"/> <!-- A field receiver when VariableSymbol is a field --> <Field Name="ReceiverOpt" Type="BoundExpression?"/> </AbstractNode> <!-- The node is transformed into BoundLocal or BoundFieldAccess after inference --> <Node Name="OutVariablePendingInference" Base="VariablePendingInference" /> <!-- The node is transformed into BoundLocal or BoundFieldAccess after inference --> <Node Name="DeconstructionVariablePendingInference" Base="VariablePendingInference" DoesNotSurvive="LocalRewriting" /> <!-- The node is transformed into BoundDeconstructValuePlaceholder after inference --> <Node Name="OutDeconstructVarPendingInference" Base="BoundExpression"> <!-- Type is not significant for this node type; always null --> <Field Name="Type" Type="TypeSymbol?" Override="true" Null="always"/> <Field Name="VariableSymbol" Type="Symbol?"/> <Field Name="IsDiscardExpression" Type="bool" Null="NotApplicable"/> </Node> <AbstractNode Name="BoundMethodBodyBase" Base="BoundNode"> <Field Name="BlockBody" Type="BoundBlock?"/> <Field Name="ExpressionBody" Type="BoundBlock?"/> </AbstractNode> <Node Name="BoundNonConstructorMethodBody" Base="BoundMethodBodyBase"> </Node> <Node Name="BoundConstructorMethodBody" Base="BoundMethodBodyBase"> <Field Name="Locals" Type="ImmutableArray<LocalSymbol>"/> <Field Name="Initializer" Type="BoundStatement?"/> </Node> <!-- Node only used during nullability flow analysis to represent an expression with an updated nullability --> <Node Name="BoundExpressionWithNullability" Base="BoundExpression" DoesNotSurvive="InitialBinding"> <Field Name="Expression" Type="BoundExpression" Null="disallow"/> <Field Name="Type" Type="TypeSymbol?" Override="true"/> <!-- We use null Type for placeholders representing out vars --> <Field Name="NullableAnnotation" Type="NullableAnnotation"/> </Node> <!-- Node only used during nullability flow analysis. --> <Node Name="BoundValueForNullableAnalysis" Base="BoundExpression" DoesNotSurvive="InitialBinding"> <Field Name="OriginalExpression" Type="BoundExpression?" Null="allow"/> </Node> <Node Name="BoundWithExpression" Base="BoundExpression"> <!-- Non-null type is required for this node kind --> <Field Name="Type" Type="TypeSymbol" Override="true" Null="disallow"/> <Field Name="Receiver" Type="BoundExpression" /> <!-- CloneMethod may be null in error scenarios--> <Field Name="CloneMethod" Type="MethodSymbol?" /> <!-- Members and expressions passed as arguments to the With expression. --> <Field Name="InitializerExpression" Type="BoundObjectInitializerExpressionBase" /> </Node> </Tree>