diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs b/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs index 14bfd5b1e91e88a3e26023d0933807df1677b00e..f5c8b4004bc2749f54d3dba535b8bb455ccc284c 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder.ValueChecks.cs @@ -405,7 +405,7 @@ internal bool CheckValueKind(SyntaxNode node, BoundExpression expr, BindValueKin var conditional = (BoundConditionalOperator)expr; // byref conditional defers to its operands - if (conditional.IsByRef && + if (conditional.IsRef && (CheckValueKind(conditional.Consequence.Syntax, conditional.Consequence, valueKind, checkingReceiver: false, diagnostics: diagnostics) & CheckValueKind(conditional.Alternative.Syntax, conditional.Alternative, valueKind, checkingReceiver: false, diagnostics: diagnostics))) { @@ -1659,7 +1659,7 @@ internal static uint GetRefEscape(BoundExpression expr, uint scopeOfTheContainin case BoundKind.ConditionalOperator: var conditional = (BoundConditionalOperator)expr; - if (conditional.IsByRef) + if (conditional.IsRef) { // ref conditional defers to its operands return Math.Max(GetRefEscape(conditional.Consequence, scopeOfTheContainingExpression), @@ -1847,7 +1847,7 @@ internal static bool CheckRefEscape(SyntaxNode node, BoundExpression expr, uint case BoundKind.ConditionalOperator: var conditional = (BoundConditionalOperator)expr; - if (conditional.IsByRef) + if (conditional.IsRef) { return CheckRefEscape(conditional.Consequence.Syntax, conditional.Consequence, escapeFrom, escapeTo, checkingReceiver: false, diagnostics: diagnostics) && CheckRefEscape(conditional.Alternative.Syntax, conditional.Alternative, escapeFrom, escapeTo, checkingReceiver: false, diagnostics: diagnostics); @@ -2036,7 +2036,7 @@ internal static uint GetValEscape(BoundExpression expr, uint scopeOfTheContainin var consEscape = GetValEscape(conditional.Consequence, scopeOfTheContainingExpression); - if (conditional.IsByRef) + if (conditional.IsRef) { // ref conditional defers to one operand. // the other one is the same or we will be reporting errors anyways. @@ -2320,7 +2320,7 @@ internal static bool CheckValEscape(SyntaxNode node, BoundExpression expr, uint var consValid = CheckValEscape(conditional.Consequence.Syntax, conditional.Consequence, escapeFrom, escapeTo, checkingReceiver: false, diagnostics: diagnostics); - if (!consValid || conditional.IsByRef) + if (!consValid || conditional.IsRef) { // ref conditional defers to one operand. // the other one is the same or we will be reporting errors anyways. diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundExpressionExtensions.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundExpressionExtensions.cs index 3963778dd91e53a93b9f7a53bed8cee7d19f479a..aff248e5e98c7757650cd76b8b799193d0dc67d0 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/BoundExpressionExtensions.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/BoundExpressionExtensions.cs @@ -5,11 +5,38 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Text; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp { internal static partial class BoundExpressionExtensions { + /// + /// Returns the RefKind if the expression represents a symbol + /// that has a RefKind. This method is ILLEGAL to call for + /// other expressions. + /// + public static RefKind GetRefKind(this BoundExpression node) + { + switch (node.Kind) + { + case BoundKind.Local: + return ((BoundLocal)node).LocalSymbol.RefKind; + + case BoundKind.Parameter: + return ((BoundParameter)node).ParameterSymbol.RefKind; + + case BoundKind.Call: + return ((BoundCall)node).Method.RefKind; + + case BoundKind.PropertyAccess: + return ((BoundPropertyAccess)node).PropertySymbol.RefKind; + + default: + throw ExceptionUtilities.UnexpectedValue(node.Kind); + } + } + public static bool IsLiteralNull(this BoundExpression node) { return node.Kind == BoundKind.Literal && node.ConstantValue.Discriminator == ConstantValueTypeDiscriminator.Null; diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml index 2f9a3867f138b997bda03d36e3379f6ee3bd3850..560e88a72f770f55821c4b12f3cf74ed10a250eb 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml +++ b/src/Compilers/CSharp/Portable/BoundTree/BoundNodes.xml @@ -356,7 +356,7 @@ - - + @@ -400,7 +400,7 @@ - + diff --git a/src/Compilers/CSharp/Portable/BoundTree/Constructors.cs b/src/Compilers/CSharp/Portable/BoundTree/Constructors.cs index fd05b72b55635d1b9ebda448726f253c42e8586d..aae683986c57a279f57511b4735d21e263e35ac2 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/Constructors.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/Constructors.cs @@ -455,8 +455,8 @@ public BoundNamespaceExpression Update(NamespaceSymbol namespaceSymbol) internal sealed partial class BoundAssignmentOperator { public BoundAssignmentOperator(SyntaxNode syntax, BoundExpression left, BoundExpression right, - TypeSymbol type, RefKind refKind = RefKind.None, bool hasErrors = false) - : this(syntax, left, right, refKind, type, hasErrors) + TypeSymbol type, bool isRef = false, bool hasErrors = false) + : this(syntax, left, right, isRef, type, hasErrors) { } } diff --git a/src/Compilers/CSharp/Portable/CodeGen/EmitAddress.cs b/src/Compilers/CSharp/Portable/CodeGen/EmitAddress.cs index fdda4282378c0a2219b511a58c000489ea707186..a41869f60065eb3bdd741555a6474ff3dc3be73e 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/EmitAddress.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/EmitAddress.cs @@ -139,12 +139,12 @@ private LocalDefinition EmitAddress(BoundExpression expression, AddressKind addr case BoundKind.AssignmentOperator: var assignment = (BoundAssignmentOperator)expression; - if (assignment.RefKind == RefKind.None) + if (!assignment.IsRef) { goto default; } - throw ExceptionUtilities.UnexpectedValue(assignment.RefKind); + throw ExceptionUtilities.UnexpectedValue(assignment.IsRef); case BoundKind.ThrowExpression: // emit value or address is the same here. @@ -411,7 +411,7 @@ private bool HasHome(BoundExpression expression, AddressKind addressKind) return HasHome(((BoundSequence)expression).Value, addressKind); case BoundKind.AssignmentOperator: - return ((BoundAssignmentOperator)expression).RefKind != RefKind.None; + return ((BoundAssignmentOperator)expression).IsRef; case BoundKind.ComplexConditionalReceiver: Debug.Assert(HasHome(((BoundComplexConditionalReceiver)expression).ValueTypeReceiver, addressKind)); @@ -427,7 +427,7 @@ private bool HasHome(BoundExpression expression, AddressKind addressKind) var ternary = (BoundConditionalOperator)expression; // only ref ternary may be referenced as a variable - if (!ternary.IsByRef) + if (!ternary.IsRef) { return false; } diff --git a/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs b/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs index bc3431cc6ece71f0f6741df31179e05e4b8e5aed..0c82db1f4690f3b0d0a758a9170683a8534ee80a 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs @@ -1922,7 +1922,7 @@ private void EmitAssignmentExpression(BoundAssignmentOperator assignmentOperator { if (TryEmitAssignmentInPlace(assignmentOperator, useKind != UseKind.Unused)) { - Debug.Assert(assignmentOperator.RefKind == RefKind.None); + Debug.Assert(!assignmentOperator.IsRef); return; } @@ -2211,7 +2211,7 @@ private bool EmitAssignmentPreamble(BoundAssignmentOperator assignmentOperator) // and then do an indirect store. In that case we need to have the // contents of addr on the stack. - if (left.LocalSymbol.RefKind != RefKind.None && assignmentOperator.RefKind == RefKind.None) + if (left.LocalSymbol.RefKind != RefKind.None && !assignmentOperator.IsRef) { if (!IsStackLocal(left.LocalSymbol)) { @@ -2274,7 +2274,7 @@ private bool EmitAssignmentPreamble(BoundAssignmentOperator assignmentOperator) case BoundKind.ConditionalOperator: { var left = (BoundConditionalOperator)assignmentTarget; - Debug.Assert(left.IsByRef); + Debug.Assert(left.IsRef); var temp = EmitAddress(left, AddressKind.Writeable); Debug.Assert(temp == null, "taking ref of this should not create a temp"); @@ -2301,7 +2301,7 @@ private bool EmitAssignmentPreamble(BoundAssignmentOperator assignmentOperator) // Since sequence is used as a variable, we will keep the locals for the extent of the containing expression DefineAndRecordLocals(sequence); EmitSideEffects(sequence); - lhsUsesStack = EmitAssignmentPreamble(assignmentOperator.Update(sequence.Value, assignmentOperator.Right, assignmentOperator.RefKind, assignmentOperator.Type)); + lhsUsesStack = EmitAssignmentPreamble(assignmentOperator.Update(sequence.Value, assignmentOperator.Right, assignmentOperator.IsRef, assignmentOperator.Type)); CloseScopeAndKeepLocals(sequence); } break; @@ -2342,7 +2342,7 @@ private bool EmitAssignmentPreamble(BoundAssignmentOperator assignmentOperator) private void EmitAssignmentValue(BoundAssignmentOperator assignmentOperator) { - if (assignmentOperator.RefKind == RefKind.None) + if (!assignmentOperator.IsRef) { EmitExpression(assignmentOperator.Right, used: true); } @@ -2412,7 +2412,7 @@ private LocalDefinition EmitAssignmentDuplication(BoundAssignmentOperator assign // is created here. And also that either its value or its indirected value is read out // after the store, in EmitAssignmentPostfix, below. - Debug.Assert(assignmentOperator.RefKind == RefKind.None); + Debug.Assert(!assignmentOperator.IsRef); temp = AllocateTemp(assignmentOperator.Left.Type, assignmentOperator.Left.Syntax); _builder.EmitLocalStore(temp); @@ -2439,7 +2439,7 @@ private void EmitStore(BoundAssignmentOperator assignment) // See the comments in EmitAssignmentExpression above for details. BoundLocal local = (BoundLocal)expression; - if (local.LocalSymbol.RefKind != RefKind.None && assignment.RefKind == RefKind.None) + if (local.LocalSymbol.RefKind != RefKind.None && !assignment.IsRef) { EmitIndirectStore(local.LocalSymbol.Type, local.Syntax); } @@ -2477,7 +2477,7 @@ private void EmitStore(BoundAssignmentOperator assignment) break; case BoundKind.ConditionalOperator: - Debug.Assert(((BoundConditionalOperator)expression).IsByRef); + Debug.Assert(((BoundConditionalOperator)expression).IsRef); EmitIndirectStore(expression.Type, expression.Syntax); break; @@ -2490,7 +2490,7 @@ private void EmitStore(BoundAssignmentOperator assignment) case BoundKind.Sequence: { var sequence = (BoundSequence)expression; - EmitStore(assignment.Update(sequence.Value, assignment.Right, assignment.RefKind, assignment.Type)); + EmitStore(assignment.Update(sequence.Value, assignment.Right, assignment.IsRef, assignment.Type)); } break; @@ -2522,7 +2522,7 @@ private void EmitAssignmentPostfix(BoundAssignmentOperator assignment, LocalDefi FreeTemp(temp); } - if (useKind == UseKind.UsedAsValue && assignment.RefKind != RefKind.None) + if (useKind == UseKind.UsedAsValue && assignment.IsRef) { EmitLoadIndirect(assignment.Type, assignment.Syntax); } diff --git a/src/Compilers/CSharp/Portable/CodeGen/Optimizer.cs b/src/Compilers/CSharp/Portable/CodeGen/Optimizer.cs index 612e107c3e445ae8b65faabe08d0c2befc8646fe..508800629148b8709b6f510b7dec501015becb5b 100644 --- a/src/Compilers/CSharp/Portable/CodeGen/Optimizer.cs +++ b/src/Compilers/CSharp/Portable/CodeGen/Optimizer.cs @@ -870,7 +870,7 @@ public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node) // into ==> {se1, se2, se3, val = something} BoundExpression rewritten = sequence.Update(sequence.Locals, sequence.SideEffects, - node.Update(sequence.Value, node.Right, node.RefKind, node.Type), + node.Update(sequence.Value, node.Right, node.IsRef, node.Type), sequence.Type); rewritten = (BoundExpression)Visit(rewritten); @@ -895,8 +895,7 @@ public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node) Debug.Assert(_context != ExprContext.AssignmentTarget, "assignment expression cannot be a target of another assignment"); ExprContext rhsContext; - if (node.RefKind != RefKind.None || - _context == ExprContext.Address) + if (node.IsRef || _context == ExprContext.Address) { // we need the address of rhs one way or another so we cannot have it on the stack. rhsContext = ExprContext.Address; @@ -960,7 +959,7 @@ public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node) assignmentLocal = null; } - return node.Update(left, right, node.RefKind, node.Type); + return node.Update(left, right, node.IsRef, node.Type); } // indirect assignment is assignment to a value referenced indirectly @@ -971,9 +970,8 @@ private static bool IsIndirectAssignment(BoundAssignmentOperator node) { var lhs = node.Left; - Debug.Assert(node.RefKind == RefKind.None || lhs is BoundLocal local && - (local.LocalSymbol.RefKind == node.RefKind || - local.LocalSymbol.RefKind == RefKind.RefReadOnly), + Debug.Assert(!node.IsRef || lhs is BoundLocal local && + local.LocalSymbol.RefKind != RefKind.None, "only ref locals can be a target of a ref assignment"); switch (lhs.Kind) @@ -985,8 +983,7 @@ private static bool IsIndirectAssignment(BoundAssignmentOperator node) case BoundKind.Parameter: if (((BoundParameter)lhs).ParameterSymbol.RefKind != RefKind.None) { - bool isIndirect = node.RefKind == RefKind.None; - return isIndirect; + return !node.IsRef; } return false; @@ -994,8 +991,7 @@ private static bool IsIndirectAssignment(BoundAssignmentOperator node) case BoundKind.Local: if (((BoundLocal)lhs).LocalSymbol.RefKind != RefKind.None) { - bool isIndirect = node.RefKind == RefKind.None; - return isIndirect; + return !node.IsRef; } return false; @@ -1005,15 +1001,15 @@ private static bool IsIndirectAssignment(BoundAssignmentOperator node) return true; case BoundKind.ConditionalOperator: - Debug.Assert(((BoundConditionalOperator)lhs).IsByRef, "only ref ternaries are assignable"); + Debug.Assert(((BoundConditionalOperator)lhs).IsRef, "only ref ternaries are assignable"); return true; case BoundKind.AssignmentOperator: - Debug.Assert(((BoundAssignmentOperator)lhs).RefKind == RefKind.Ref, "only ref assignments are assignable"); + Debug.Assert(((BoundAssignmentOperator)lhs).IsRef, "only ref assignments are assignable"); return true; case BoundKind.Sequence: - Debug.Assert(!IsIndirectAssignment(node.Update(((BoundSequence)node.Left).Value, node.Right, node.RefKind, node.Type)), + Debug.Assert(!IsIndirectAssignment(node.Update(((BoundSequence)node.Left).Value, node.Right, node.IsRef, node.Type)), "indirect assignment to a sequence is unexpected"); return false; @@ -1251,7 +1247,7 @@ public override BoundNode VisitConditionalOperator(BoundConditionalOperator node var cookie = GetStackStateCookie(); // implicit goto here - var context = node.IsByRef ? ExprContext.Address : ExprContext.Value; + var context = node.IsRef ? ExprContext.Address : ExprContext.Value; SetStackDepth(origStack); // consequence is evaluated with original stack BoundExpression consequence = this.VisitExpression(node.Consequence, context); @@ -1263,7 +1259,7 @@ public override BoundNode VisitConditionalOperator(BoundConditionalOperator node EnsureStackState(cookie); // implicit label here - return node.Update(node.IsByRef, condition, consequence, alternative, node.ConstantValueOpt, node.Type); + return node.Update(node.IsRef, condition, consequence, alternative, node.ConstantValueOpt, node.Type); } public override BoundNode VisitBinaryOperator(BoundBinaryOperator node) @@ -1989,7 +1985,7 @@ public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node) // indirect local store is not special. (operands still could be rewritten) // NOTE: if Lhs is a stack local, it will be handled as a read and possibly duped. - var isIndirectLocalStore = left.LocalSymbol.RefKind != RefKind.None && node.RefKind == RefKind.None; + var isIndirectLocalStore = left.LocalSymbol.RefKind != RefKind.None && !node.IsRef; if (isIndirectLocalStore) { return base.VisitAssignmentOperator(node); @@ -2023,7 +2019,7 @@ public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node) { // assigned local used later - keep assignment. // codegen will keep value on stack when sees assignment "stackLocal = expr" - return node.Update(left, right, node.RefKind, node.Type); + return node.Update(left, right, node.IsRef, node.Type); } } diff --git a/src/Compilers/CSharp/Portable/Compiler/MethodBodySynthesizer.cs b/src/Compilers/CSharp/Portable/Compiler/MethodBodySynthesizer.cs index 2e167a603d0b404805b58cec63ab861fadf153af..fd9e8784f1e544f0350e998a0d421232b1487b7c 100644 --- a/src/Compilers/CSharp/Portable/Compiler/MethodBodySynthesizer.cs +++ b/src/Compilers/CSharp/Portable/Compiler/MethodBodySynthesizer.cs @@ -102,7 +102,7 @@ internal static class MethodBodySynthesizer objectType) { WasCompilerGenerated = true }, thisReference, - RefKind.None, + false, thisReference.Type) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }); diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs index 034ba0a081736838ce84372db34a0013ac051500..a136aac12ebffc2111ea394bda5c4f60c0c6a62e 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowPass.cs @@ -1156,9 +1156,9 @@ private Symbol UseNonFieldSymbolUnsafely(BoundExpression expression) return null; } - protected void Assign(BoundNode node, BoundExpression value, RefKind refKind = RefKind.None, bool read = true) + protected void Assign(BoundNode node, BoundExpression value, bool isRef = false, bool read = true) { - AssignImpl(node, value, written: true, refKind: refKind, read: read); + AssignImpl(node, value, written: true, isRef: isRef, read: read); } /// @@ -1167,9 +1167,9 @@ protected void Assign(BoundNode node, BoundExpression value, RefKind refKind = R /// Node being assigned to. /// The value being assigned. /// True if target location is considered written to. - /// Target kind (by-ref or not). + /// Ref assignment or value assignment. /// True if target location is considered read from. - protected virtual void AssignImpl(BoundNode node, BoundExpression value, RefKind refKind, bool written, bool read) + protected virtual void AssignImpl(BoundNode node, BoundExpression value, bool isRef, bool written, bool read) { switch (node.Kind) { @@ -1203,7 +1203,7 @@ protected virtual void AssignImpl(BoundNode node, BoundExpression value, RefKind case BoundKind.Local: { var local = (BoundLocal)node; - if (local.LocalSymbol.RefKind != refKind) + if (local.LocalSymbol.RefKind != RefKind.None && !isRef) { // Writing through the (reference) value of a reference local // requires us to read the reference itself. @@ -1232,7 +1232,7 @@ protected virtual void AssignImpl(BoundNode node, BoundExpression value, RefKind } case BoundKind.RangeVariable: - AssignImpl(((BoundRangeVariable)node).Value, value, refKind, written, read); + AssignImpl(((BoundRangeVariable)node).Value, value, isRef, written, read); break; case BoundKind.BadExpression: @@ -1241,13 +1241,13 @@ protected virtual void AssignImpl(BoundNode node, BoundExpression value, RefKind var bad = (BoundBadExpression)node; if (!bad.ChildBoundNodes.IsDefault && bad.ChildBoundNodes.Length == 1) { - AssignImpl(bad.ChildBoundNodes[0], value, refKind, written, read); + AssignImpl(bad.ChildBoundNodes[0], value, isRef, written, read); } break; } case BoundKind.TupleLiteral: - ((BoundTupleExpression)node).VisitAllElements((x, self) => self.Assign(x, value: null, refKind: refKind), this); + ((BoundTupleExpression)node).VisitAllElements((x, self) => self.Assign(x, value: null, isRef: isRef), this); break; default: @@ -1476,7 +1476,7 @@ private void AssignPatternVariables(BoundPattern pattern) case BoundKind.DeclarationPattern: { var pat = (BoundDeclarationPattern)pattern; - Assign(pat, null, RefKind.None, false); + Assign(pat, value: null, isRef: false, read: false); break; } case BoundKind.WildcardPattern: @@ -1854,7 +1854,7 @@ public override BoundNode VisitParameter(BoundParameter node) public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node) { base.VisitAssignmentOperator(node); - Assign(node.Left, node.Right, refKind: node.RefKind); + Assign(node.Left, node.Right, isRef: node.IsRef); return null; } diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowsOutWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowsOutWalker.cs index b25a5e2c1fa9ba9dec81d3b52c76f31f725728d4..5a9805d84470dba1e924d9415caa5371c52d4e10 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowsOutWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/DataFlowsOutWalker.cs @@ -183,7 +183,7 @@ private Symbol GetNodeSymbol(BoundNode node) } #endif - protected override void AssignImpl(BoundNode node, BoundExpression value, RefKind refKind, bool written, bool read) + protected override void AssignImpl(BoundNode node, BoundExpression value, bool isRef, bool written, bool read) { if (IsInside) { @@ -209,7 +209,7 @@ protected override void AssignImpl(BoundNode node, BoundExpression value, RefKin } } - base.AssignImpl(node, value, refKind, written, read); + base.AssignImpl(node, value, isRef, written, read); } private bool FlowsOut(ParameterSymbol param) diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass.cs index 229d825d5b9c0190a27d3faf4d47681f3a9e5aad..595ed0062a75f874e5332e2389d07602aadd333e 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/PreciseAbstractFlowPass.cs @@ -1672,9 +1672,9 @@ public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node) VisitRvalue(node.Right); // byref assignment is also a potential write - if (node.RefKind != RefKind.None) + if (node.IsRef) { - WriteArgument(node.Right, node.RefKind, method: null); + WriteArgument(node.Right, node.Left.GetRefKind(), method: null); } return null; @@ -2337,7 +2337,7 @@ public override BoundNode VisitContinueStatement(BoundContinueStatement node) public sealed override BoundNode VisitConditionalOperator(BoundConditionalOperator node) { - var isByRef = node.IsByRef; + var isByRef = node.IsRef; VisitCondition(node.Condition); var consequenceState = this.StateWhenTrue; diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/ReadWriteWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/ReadWriteWalker.cs index f2057b90a7c963a05d3ba4b1ab26bc616571d08e..2b518d52e79eb198ca1ef38faf86a49ad0e2302b 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/ReadWriteWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/ReadWriteWalker.cs @@ -172,7 +172,7 @@ private void NoteReceiverReadOrWritten(BoundFieldAccess expr, HashSet re } } - protected override void AssignImpl(BoundNode node, BoundExpression value, RefKind refKind, bool written, bool read) + protected override void AssignImpl(BoundNode node, BoundExpression value, bool isRef, bool written, bool read) { switch (node.Kind) { @@ -182,7 +182,7 @@ protected override void AssignImpl(BoundNode node, BoundExpression value, RefKin case BoundKind.QueryClause: { - base.AssignImpl(node, value, refKind, written, read); + base.AssignImpl(node, value, isRef, written, read); var symbol = ((BoundQueryClause)node).DefinedSymbol; if ((object)symbol != null) { @@ -193,7 +193,7 @@ protected override void AssignImpl(BoundNode node, BoundExpression value, RefKin case BoundKind.FieldAccess: { - base.AssignImpl(node, value, refKind, written, read); + base.AssignImpl(node, value, isRef, written, read); var fieldAccess = node as BoundFieldAccess; if (!IsInside && node.Syntax != null && node.Syntax.Span.Contains(RegionSpan)) { @@ -203,7 +203,7 @@ protected override void AssignImpl(BoundNode node, BoundExpression value, RefKin break; default: - base.AssignImpl(node, value, refKind, written, read); + base.AssignImpl(node, value, isRef, written, read); break; } } diff --git a/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs b/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs index f3ae601600bd8972f39c8389a767542aefe35494..e3dad0c56ab4845192ea506d536f44f6ec348050 100644 --- a/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/BoundNodes.xml.Generated.cs @@ -1125,7 +1125,7 @@ public BoundCompoundAssignmentOperator Update(BinaryOperatorSignature @operator, internal sealed partial class BoundAssignmentOperator : BoundExpression { - public BoundAssignmentOperator(SyntaxNode syntax, BoundExpression left, BoundExpression right, RefKind refKind, TypeSymbol type, bool hasErrors = false) + public BoundAssignmentOperator(SyntaxNode syntax, BoundExpression left, BoundExpression right, bool isRef, TypeSymbol type, bool hasErrors = false) : base(BoundKind.AssignmentOperator, syntax, type, hasErrors || left.HasErrors() || right.HasErrors()) { @@ -1133,7 +1133,7 @@ public BoundAssignmentOperator(SyntaxNode syntax, BoundExpression left, BoundExp this.Left = left; this.Right = right; - this.RefKind = refKind; + this.IsRef = isRef; } @@ -1141,18 +1141,18 @@ public BoundAssignmentOperator(SyntaxNode syntax, BoundExpression left, BoundExp public BoundExpression Right { get; } - public RefKind RefKind { get; } + public bool IsRef { get; } public override BoundNode Accept(BoundTreeVisitor visitor) { return visitor.VisitAssignmentOperator(this); } - public BoundAssignmentOperator Update(BoundExpression left, BoundExpression right, RefKind refKind, TypeSymbol type) + public BoundAssignmentOperator Update(BoundExpression left, BoundExpression right, bool isRef, TypeSymbol type) { - if (left != this.Left || right != this.Right || refKind != this.RefKind || type != this.Type) + if (left != this.Left || right != this.Right || isRef != this.IsRef || type != this.Type) { - var result = new BoundAssignmentOperator(this.Syntax, left, right, refKind, type, this.HasErrors); + var result = new BoundAssignmentOperator(this.Syntax, left, right, isRef, type, this.HasErrors); result.WasCompilerGenerated = this.WasCompilerGenerated; return result; } @@ -1239,7 +1239,7 @@ public BoundNullCoalescingOperator Update(BoundExpression leftOperand, BoundExpr internal sealed partial class BoundConditionalOperator : BoundExpression { - public BoundConditionalOperator(SyntaxNode syntax, bool isByRef, BoundExpression condition, BoundExpression consequence, BoundExpression alternative, ConstantValue constantValueOpt, TypeSymbol type, bool hasErrors = false) + public BoundConditionalOperator(SyntaxNode syntax, bool isRef, BoundExpression condition, BoundExpression consequence, BoundExpression alternative, ConstantValue constantValueOpt, TypeSymbol type, bool hasErrors = false) : base(BoundKind.ConditionalOperator, syntax, type, hasErrors || condition.HasErrors() || consequence.HasErrors() || alternative.HasErrors()) { @@ -1248,7 +1248,7 @@ public BoundConditionalOperator(SyntaxNode syntax, bool isByRef, BoundExpression Debug.Assert(alternative != null, "Field 'alternative' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); Debug.Assert(type != null, "Field 'type' cannot be null (use Null=\"allow\" in BoundNodes.xml to remove this check)"); - this.IsByRef = isByRef; + this.IsRef = isRef; this.Condition = condition; this.Consequence = consequence; this.Alternative = alternative; @@ -1256,7 +1256,7 @@ public BoundConditionalOperator(SyntaxNode syntax, bool isByRef, BoundExpression } - public bool IsByRef { get; } + public bool IsRef { get; } public BoundExpression Condition { get; } @@ -1271,11 +1271,11 @@ public override BoundNode Accept(BoundTreeVisitor visitor) return visitor.VisitConditionalOperator(this); } - public BoundConditionalOperator Update(bool isByRef, BoundExpression condition, BoundExpression consequence, BoundExpression alternative, ConstantValue constantValueOpt, TypeSymbol type) + public BoundConditionalOperator Update(bool isRef, BoundExpression condition, BoundExpression consequence, BoundExpression alternative, ConstantValue constantValueOpt, TypeSymbol type) { - if (isByRef != this.IsByRef || condition != this.Condition || consequence != this.Consequence || alternative != this.Alternative || constantValueOpt != this.ConstantValueOpt || type != this.Type) + if (isRef != this.IsRef || condition != this.Condition || consequence != this.Consequence || alternative != this.Alternative || constantValueOpt != this.ConstantValueOpt || type != this.Type) { - var result = new BoundConditionalOperator(this.Syntax, isByRef, condition, consequence, alternative, constantValueOpt, type, this.HasErrors); + var result = new BoundConditionalOperator(this.Syntax, isRef, condition, consequence, alternative, constantValueOpt, type, this.HasErrors); result.WasCompilerGenerated = this.WasCompilerGenerated; return result; } @@ -8586,7 +8586,7 @@ public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node) BoundExpression left = (BoundExpression)this.Visit(node.Left); BoundExpression right = (BoundExpression)this.Visit(node.Right); TypeSymbol type = this.VisitType(node.Type); - return node.Update(left, right, node.RefKind, type); + return node.Update(left, right, node.IsRef, type); } public override BoundNode VisitDeconstructionAssignmentOperator(BoundDeconstructionAssignmentOperator node) { @@ -8608,7 +8608,7 @@ public override BoundNode VisitConditionalOperator(BoundConditionalOperator node BoundExpression consequence = (BoundExpression)this.Visit(node.Consequence); BoundExpression alternative = (BoundExpression)this.Visit(node.Alternative); TypeSymbol type = this.VisitType(node.Type); - return node.Update(node.IsByRef, condition, consequence, alternative, node.ConstantValueOpt, type); + return node.Update(node.IsRef, condition, consequence, alternative, node.ConstantValueOpt, type); } public override BoundNode VisitArrayAccess(BoundArrayAccess node) { @@ -9585,7 +9585,7 @@ public override TreeDumperNode VisitAssignmentOperator(BoundAssignmentOperator n { new TreeDumperNode("left", null, new TreeDumperNode[] { Visit(node.Left, null) }), new TreeDumperNode("right", null, new TreeDumperNode[] { Visit(node.Right, null) }), - new TreeDumperNode("refKind", node.RefKind, null), + new TreeDumperNode("isRef", node.IsRef, null), new TreeDumperNode("type", node.Type, null) } ); @@ -9616,7 +9616,7 @@ public override TreeDumperNode VisitConditionalOperator(BoundConditionalOperator { return new TreeDumperNode("conditionalOperator", null, new TreeDumperNode[] { - new TreeDumperNode("isByRef", node.IsByRef, null), + new TreeDumperNode("isRef", node.IsRef, null), new TreeDumperNode("condition", null, new TreeDumperNode[] { Visit(node.Condition, null) }), new TreeDumperNode("consequence", null, new TreeDumperNode[] { Visit(node.Consequence, null) }), new TreeDumperNode("alternative", null, new TreeDumperNode[] { Visit(node.Alternative, null) }), diff --git a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AwaitExpressionSpiller.cs b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AwaitExpressionSpiller.cs index d98a05f54c1a85808a996afb58fe1f9fb18c1727..06b153f89b36b6c725cfa01059d99fe114a2b548 100644 --- a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AwaitExpressionSpiller.cs +++ b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AwaitExpressionSpiller.cs @@ -404,7 +404,7 @@ private BoundStatement UpdateStatement(BoundSpillSequenceBuilder builder, BoundS // The "strict" ones do not permit implicit copying, so the same situation should result in an error. if (refKind != RefKind.None && refKind != RefKind.RefReadOnly) { - Debug.Assert(conditional.IsByRef); + Debug.Assert(conditional.IsRef); _F.Diagnostics.Add(ErrorCode.ERR_RefConditionalAndAwait, _F.Syntax.Location); } refKind = RefKind.None; @@ -740,7 +740,7 @@ public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node) builder = leftBuilder; } - return UpdateExpression(builder, node.Update(left, right, node.RefKind, node.Type)); + return UpdateExpression(builder, node.Update(left, right, node.IsRef, node.Type)); } public override BoundNode VisitBadExpression(BoundBadExpression node) @@ -838,7 +838,7 @@ public override BoundNode VisitConditionalOperator(BoundConditionalOperator node if (consequenceBuilder == null && alternativeBuilder == null) { - return UpdateExpression(conditionBuilder, node.Update(node.IsByRef, condition, consequence, alternative, node.ConstantValueOpt, node.Type)); + return UpdateExpression(conditionBuilder, node.Update(node.IsRef, condition, consequence, alternative, node.ConstantValueOpt, node.Type)); } if (conditionBuilder == null) conditionBuilder = new BoundSpillSequenceBuilder(); diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs index 9d9b09d2b10f4c8c1011b4aee122a18139f6b17a..c983e668317024f59e3f8caf6f321455ac9f1431 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.cs @@ -577,7 +577,7 @@ internal static bool WouldBeAssignableIfUsedAsMethodReceiver(BoundExpression rec return true; case BoundKind.ConditionalOperator: - return ((BoundConditionalOperator)receiver).IsByRef; + return ((BoundConditionalOperator)receiver).IsRef; case BoundKind.Call: return ((BoundCall)receiver).Method.RefKind == RefKind.Ref; diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_AssignmentOperator.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_AssignmentOperator.cs index d4d8cde5835423c048f082d121d8497e1c5056cb..6d8da3f3aa9b169624268bf6740faa20fc9fe5ab 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_AssignmentOperator.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_AssignmentOperator.cs @@ -37,7 +37,7 @@ private BoundExpression VisitAssignmentOperator(BoundAssignmentOperator node, bo BoundEventAccess eventAccess = (BoundEventAccess)left; if (eventAccess.EventSymbol.IsWindowsRuntimeEvent) { - Debug.Assert(node.RefKind == RefKind.None); + Debug.Assert(!node.IsRef); return VisitWindowsRuntimeEventFieldAssignmentOperator(node.Syntax, eventAccess, loweredRight); } goto default; @@ -72,7 +72,7 @@ private BoundExpression VisitAssignmentOperator(BoundAssignmentOperator node, bo break; } - return MakeStaticAssignmentOperator(node.Syntax, loweredLeft, loweredRight, node.RefKind, node.Type, used); + return MakeStaticAssignmentOperator(node.Syntax, loweredLeft, loweredRight, node.IsRef, node.Type, used); } /// @@ -125,7 +125,7 @@ private BoundExpression VisitAssignmentOperator(BoundAssignmentOperator node, bo throw ExceptionUtilities.Unreachable; default: - return MakeStaticAssignmentOperator(syntax, rewrittenLeft, rewrittenRight, RefKind.None, type, used); + return MakeStaticAssignmentOperator(syntax, rewrittenLeft, rewrittenRight, isRef: false, type: type, used: used); } } @@ -156,7 +156,13 @@ private BoundExpression VisitAssignmentOperator(BoundAssignmentOperator node, bo /// Generates a lowered form of the assignment operator for the given left and right sub-expressions. /// Left and right sub-expressions must be in lowered form. /// - private BoundExpression MakeStaticAssignmentOperator(SyntaxNode syntax, BoundExpression rewrittenLeft, BoundExpression rewrittenRight, RefKind refKind, TypeSymbol type, bool used) + private BoundExpression MakeStaticAssignmentOperator( + SyntaxNode syntax, + BoundExpression rewrittenLeft, + BoundExpression rewrittenRight, + bool isRef, + TypeSymbol type, + bool used) { switch (rewrittenLeft.Kind) { @@ -166,7 +172,7 @@ private BoundExpression MakeStaticAssignmentOperator(SyntaxNode syntax, BoundExp case BoundKind.PropertyAccess: { - Debug.Assert(refKind == RefKind.None); + Debug.Assert(!isRef); BoundPropertyAccess propertyAccess = (BoundPropertyAccess)rewrittenLeft; BoundExpression rewrittenReceiver = propertyAccess.ReceiverOpt; PropertySymbol property = propertyAccess.PropertySymbol; @@ -186,7 +192,7 @@ private BoundExpression MakeStaticAssignmentOperator(SyntaxNode syntax, BoundExp case BoundKind.IndexerAccess: { - Debug.Assert(refKind == RefKind.None); + Debug.Assert(!isRef); BoundIndexerAccess indexerAccess = (BoundIndexerAccess)rewrittenLeft; BoundExpression rewrittenReceiver = indexerAccess.ReceiverOpt; ImmutableArray rewrittenArguments = indexerAccess.Arguments; @@ -207,13 +213,13 @@ private BoundExpression MakeStaticAssignmentOperator(SyntaxNode syntax, BoundExp case BoundKind.Local: { - Debug.Assert(refKind == RefKind.None || ((BoundLocal)rewrittenLeft).LocalSymbol.RefKind != RefKind.None); + Debug.Assert(!isRef || ((BoundLocal)rewrittenLeft).LocalSymbol.RefKind != RefKind.None); return new BoundAssignmentOperator( syntax, rewrittenLeft, rewrittenRight, type, - refKind: refKind); + isRef: isRef); } case BoundKind.DiscardExpression: @@ -223,7 +229,7 @@ private BoundExpression MakeStaticAssignmentOperator(SyntaxNode syntax, BoundExp default: { - Debug.Assert(refKind == RefKind.None); + Debug.Assert(!isRef); return new BoundAssignmentOperator( syntax, rewrittenLeft, diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CompoundAssignmentOperator.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CompoundAssignmentOperator.cs index 2d896cab1b815065caeba3560a7dd4c3da103ca7..778d92227d569a4ac558a8ba13df93de314a5673 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CompoundAssignmentOperator.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_CompoundAssignmentOperator.cs @@ -551,11 +551,11 @@ private BoundExpression TransformCompoundAssignmentLHS(BoundExpression originalL break; case BoundKind.ConditionalOperator: - Debug.Assert(((BoundConditionalOperator)originalLHS).IsByRef); + Debug.Assert(((BoundConditionalOperator)originalLHS).IsRef); break; case BoundKind.AssignmentOperator: - Debug.Assert(((BoundAssignmentOperator)originalLHS).RefKind != RefKind.None); + Debug.Assert(((BoundAssignmentOperator)originalLHS).IsRef); break; case BoundKind.PointerElementAccess: diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ConditionalOperator.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ConditionalOperator.cs index 79253d1f7ac2d2f2ba68cf07e9a812bade29a72c..b7032f8d99e2cb0bc060bc9d4c39520f61f8d502 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ConditionalOperator.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ConditionalOperator.cs @@ -24,7 +24,7 @@ public override BoundNode VisitConditionalOperator(BoundConditionalOperator node if (rewrittenCondition.ConstantValue == null) { - return node.Update(node.IsByRef, rewrittenCondition, rewrittenConsequence, rewrittenAlternative, node.ConstantValueOpt, node.Type); + return node.Update(node.IsRef, rewrittenCondition, rewrittenConsequence, rewrittenAlternative, node.ConstantValueOpt, node.Type); } return RewriteConditionalOperator( @@ -34,7 +34,7 @@ public override BoundNode VisitConditionalOperator(BoundConditionalOperator node rewrittenAlternative, node.ConstantValueOpt, node.Type, - node.IsByRef); + node.IsRef); } private static BoundExpression RewriteConditionalOperator( diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_FixedStatement.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_FixedStatement.cs index 7c58d45739225b48c6b09b2df6d09872229d1b84..810c2740ec5e348d4323a0ad74645656e1b8af9c 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_FixedStatement.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_FixedStatement.cs @@ -47,7 +47,7 @@ public override BoundNode VisitFixedStatement(BoundFixedStatement node) _factory.Syntax, _factory.Default(new PointerTypeSymbol(pinnedTemp.Type)), pinnedTemp.Type), - refKind: RefKind.Ref); + isRef: true); } } @@ -265,7 +265,7 @@ public override BoundNode VisitFixedLocalCollectionInitializer(BoundFixedLocalCo Debug.Assert(!localSymbol.IsPinned); // pinnedTemp = ref v; - BoundStatement pinnedTempInit = factory.Assignment(factory.Local(pinnedTemp), initializerExpr, refKind: RefKind.Ref); + BoundStatement pinnedTempInit = factory.Assignment(factory.Local(pinnedTemp), initializerExpr, isRef: true); // &pinnedTemp; var addr = new BoundAddressOfOperator( diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_LocalDeclaration.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_LocalDeclaration.cs index 9af493f5a6208fcc2df9740f7ef01ab3767db9f3..cee248c755e3d03c1b6f1adb9936496b32736120 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_LocalDeclaration.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_LocalDeclaration.cs @@ -62,7 +62,7 @@ private BoundStatement RewriteLocalDeclaration(BoundLocalDeclaration originalOpt ), rewrittenInitializer, localSymbol.Type, - localSymbol.RefKind), + localSymbol.IsRef), hasErrors); return InstrumentLocalDeclarationIfNecessary(originalOpt, localSymbol, rewrittenLocalDeclaration); diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ObjectOrCollectionInitializerExpression.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ObjectOrCollectionInitializerExpression.cs index 8121ec9d1f7d6ea2f696f37d8ce0a4645f4fc178..0c7c182f42b50b952fd9030c8660070bc2271024 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ObjectOrCollectionInitializerExpression.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ObjectOrCollectionInitializerExpression.cs @@ -282,7 +282,7 @@ private BoundExpression MakeCollectionInitializer(BoundExpression rewrittenRecei { // Rewrite simple assignment to field/property. var rewrittenRight = VisitExpression(assignment.Right); - result.Add(MakeStaticAssignmentOperator(assignment.Syntax, rewrittenAccess, rewrittenRight, RefKind.None, assignment.Type, used: false)); + result.Add(MakeStaticAssignmentOperator(assignment.Syntax, rewrittenAccess, rewrittenRight, false, assignment.Type, used: false)); return; } } @@ -323,7 +323,7 @@ private BoundExpression MakeCollectionInitializer(BoundExpression rewrittenRecei { // Rewrite simple assignment to field/property. var rewrittenRight = VisitExpression(assignment.Right); - result.Add(MakeStaticAssignmentOperator(assignment.Syntax, rewrittenAccess, rewrittenRight, RefKind.None, assignment.Type, used: false)); + result.Add(MakeStaticAssignmentOperator(assignment.Syntax, rewrittenAccess, rewrittenRight, false, assignment.Type, used: false)); return; } @@ -356,7 +356,7 @@ private BoundExpression MakeCollectionInitializer(BoundExpression rewrittenRecei { // Rewrite as simple assignment. var rewrittenRight = VisitExpression(assignment.Right); - result.Add(MakeStaticAssignmentOperator(assignment.Syntax, rewrittenAccess, rewrittenRight, RefKind.None, assignment.Type, used: false)); + result.Add(MakeStaticAssignmentOperator(assignment.Syntax, rewrittenAccess, rewrittenRight, false, assignment.Type, used: false)); return; } diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_PatternSwitchStatement.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_PatternSwitchStatement.cs index aeb597b2ca53e551ca51b3a066917d8b04f58288..09c6a2aec29080c838c305da99978dde224dac93 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_PatternSwitchStatement.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_PatternSwitchStatement.cs @@ -422,7 +422,7 @@ private void LowerConstantValueDecision(DecisionTree.ByValue byValue) Debug.Assert(loweredLeft.Type.Equals(loweredRight.Type, TypeCompareKind.AllIgnoreOptions)); addBindings.Add(_factory.ExpressionStatement( _localRewriter.MakeStaticAssignmentOperator( - _factory.Syntax, loweredLeft, loweredRight, RefKind.None, loweredLeft.Type, false))); + _factory.Syntax, loweredLeft, loweredRight, isRef: false, type: loweredLeft.Type, used: false))); } } } diff --git a/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs index 88856c71a968ec190773e7aa65df73f1185b676e..aeb16ff1a077ae319924d47d98f7016a0e129025 100644 --- a/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/MethodToClassRewriter.cs @@ -385,7 +385,7 @@ public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node) BoundExpression originalRight = node.Right; if (leftLocal.LocalSymbol.RefKind != RefKind.None && - node.RefKind != RefKind.None && + node.IsRef && NeedsProxy(leftLocal.LocalSymbol)) { Debug.Assert(!proxies.ContainsKey(leftLocal.LocalSymbol)); @@ -422,8 +422,8 @@ public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node) BoundAssignmentOperator tempAssignment; BoundLocal tempLocal = factory.StoreToTemp(rewrittenRight, out tempAssignment); - Debug.Assert(node.RefKind == RefKind.None); - BoundAssignmentOperator rewrittenAssignment = node.Update(rewrittenLeft, tempLocal, node.RefKind, rewrittenType); + Debug.Assert(!node.IsRef); + BoundAssignmentOperator rewrittenAssignment = node.Update(rewrittenLeft, tempLocal, node.IsRef, rewrittenType); return new BoundSequence( node.Syntax, @@ -433,7 +433,7 @@ public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node) rewrittenType); } - return node.Update(rewrittenLeft, rewrittenRight, node.RefKind, rewrittenType); + return node.Update(rewrittenLeft, rewrittenRight, node.IsRef, rewrittenType); } public override BoundNode VisitFieldInfo(BoundFieldInfo node) diff --git a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs index cc3daf8190e86c6bed67f82262a2ad4e7b8b56ea..14d1302c40f053ea118b13c73a47802136e8cb49 100644 --- a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/MethodToStateMachineRewriter.cs @@ -497,7 +497,7 @@ private BoundExpression HoistRefInitialization(SynthesizedLocal local, BoundAssi var type = TypeMap.SubstituteType(local.Type).Type; var sacrificialTemp = F.SynthesizedLocal(type, refKind: RefKind.Ref); Debug.Assert(type == replacement.Type); - return F.Sequence(ImmutableArray.Create(sacrificialTemp), sideEffects.ToImmutableAndFree(), F.AssignmentExpression(F.Local(sacrificialTemp), replacement, refKind: RefKind.Ref)); + return F.Sequence(ImmutableArray.Create(sacrificialTemp), sideEffects.ToImmutableAndFree(), F.AssignmentExpression(F.Local(sacrificialTemp), replacement, isRef: true)); } if (sideEffects.Count == 0) @@ -581,7 +581,7 @@ private BoundExpression HoistRefInitialization(SynthesizedLocal local, BoundAssi var conditional = (BoundConditionalOperator)expr; if (isRef) { - Debug.Assert(conditional.IsByRef); + Debug.Assert(conditional.IsRef); F.Diagnostics.Add(ErrorCode.ERR_RefConditionalAndAwait, F.Syntax.Location); isRef = false; // Switch to ByVal to avoid asserting later in the pipeline } @@ -755,7 +755,7 @@ public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node) if (proxies.ContainsKey(leftLocal)) { - Debug.Assert(node.RefKind == RefKind.None); + Debug.Assert(!node.IsRef); return base.VisitAssignmentOperator(node); } @@ -767,7 +767,7 @@ public override BoundNode VisitAssignmentOperator(BoundAssignmentOperator node) // being used in any other way. Debug.Assert(leftLocal.SynthesizedKind == SynthesizedLocalKind.AwaitSpill); - Debug.Assert(node.RefKind != RefKind.None); + Debug.Assert(node.IsRef); // We have an assignment to a variable that has not yet been assigned a proxy. // So we assign the proxy before translating the assignment. diff --git a/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs b/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs index a29432e820a273a410264e469325e7919fc594b7..ccb50c3603b10c542479c81ee557c93e88944635 100644 --- a/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs +++ b/src/Compilers/CSharp/Portable/Lowering/SyntheticBoundNodeFactory.cs @@ -363,9 +363,9 @@ public PropertySymbol SpecialProperty(SpecialMember sm) return (PropertySymbol)SpecialMember(sm); } - public BoundExpressionStatement Assignment(BoundExpression left, BoundExpression right, RefKind refKind = RefKind.None) + public BoundExpressionStatement Assignment(BoundExpression left, BoundExpression right, bool isRef = false) { - return ExpressionStatement(AssignmentExpression(left, right, refKind)); + return ExpressionStatement(AssignmentExpression(left, right, isRef)); } public BoundExpressionStatement ExpressionStatement(BoundExpression expr) @@ -373,12 +373,12 @@ public BoundExpressionStatement ExpressionStatement(BoundExpression expr) return new BoundExpressionStatement(Syntax, expr) { WasCompilerGenerated = true }; } - public BoundAssignmentOperator AssignmentExpression(BoundExpression left, BoundExpression right, RefKind refKind = RefKind.None) + public BoundAssignmentOperator AssignmentExpression(BoundExpression left, BoundExpression right, bool isRef = false) { Debug.Assert(left.Type.Equals(right.Type, TypeCompareKind.AllIgnoreOptions) || right.Type.IsErrorType() || left.Type.IsErrorType()); - return new BoundAssignmentOperator(Syntax, left, right, left.Type, refKind: refKind) { WasCompilerGenerated = true }; + return new BoundAssignmentOperator(Syntax, left, right, left.Type, isRef: isRef) { WasCompilerGenerated = true }; } public BoundBlock Block() @@ -1299,7 +1299,7 @@ internal static BoundExpression NullOrDefault(TypeSymbol typeSymbol, SyntaxNode syntax, local, argument, - refKind, + refKind != RefKind.None, type); return local; diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs index ad04b67ce37ae87b22a04a70bd8bf9964676cd0b..2a7fdec617bfa63b442e204785862ed7138e2cd1 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs @@ -1005,7 +1005,7 @@ private ISimpleAssignmentOperation CreateBoundAssignmentOperatorOperation(BoundA Debug.Assert(!IsMemberInitializer(boundAssignmentOperator)); Lazy target = new Lazy(() => Create(boundAssignmentOperator.Left)); - bool isRef = boundAssignmentOperator.RefKind != RefKind.None; + bool isRef = boundAssignmentOperator.IsRef; Lazy value = new Lazy(() => Create(boundAssignmentOperator.Right)); SyntaxNode syntax = boundAssignmentOperator.Syntax; ITypeSymbol type = boundAssignmentOperator.Type; @@ -1117,7 +1117,7 @@ private IConditionalOperation CreateBoundConditionalOperatorOperation(BoundCondi Lazy condition = new Lazy(() => Create(boundConditionalOperator.Condition)); Lazy whenTrue = new Lazy(() => Create(boundConditionalOperator.Consequence)); Lazy whenFalse = new Lazy(() => Create(boundConditionalOperator.Alternative)); - bool isRef = boundConditionalOperator.IsByRef; + bool isRef = boundConditionalOperator.IsRef; SyntaxNode syntax = boundConditionalOperator.Syntax; ITypeSymbol type = boundConditionalOperator.Type; Optional constantValue = ConvertToOptional(boundConditionalOperator.ConstantValue); diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Rewriters/LocalDeclarationRewriter.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Rewriters/LocalDeclarationRewriter.cs index fa7b932ff2e243ae60bae1f6835e9b7337ca3b13..897425424932d1eb652983bd0ed0e2a623aa7e17 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Rewriters/LocalDeclarationRewriter.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/Rewriters/LocalDeclarationRewriter.cs @@ -75,7 +75,7 @@ internal sealed class LocalDeclarationRewriter syntax, new BoundLocal(syntax, local, constantValueOpt: null, type: local.Type), initializer, - RefKind.None, + false, local.Type); statements.Add(new BoundExpressionStatement(syntax, assignment)); }