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