Skip to content

Commit fc8030f

Browse files
authored
Improve compiler error recovery for null coalesce assignment operator (#80907)
Redo of #74218 Fixes #73894
1 parent 454a193 commit fc8030f

File tree

4 files changed

+853
-19
lines changed

4 files changed

+853
-19
lines changed

src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5777,12 +5777,10 @@ private BoundExpression BindNullCoalescingAssignmentOperator(AssignmentExpressio
57775777
ReportSuppressionIfNeeded(leftOperand, diagnostics);
57785778
BoundExpression rightOperand = BindValue(node.Right, diagnostics, BindValueKind.RValue);
57795779

5780-
// If either operand is bad, bail out preventing more cascading errors
5780+
// Prevent more cascading errors if there are any on either operand
57815781
if (leftOperand.HasAnyErrors || rightOperand.HasAnyErrors)
57825782
{
5783-
leftOperand = BindToTypeForErrorRecovery(leftOperand);
5784-
rightOperand = BindToTypeForErrorRecovery(rightOperand);
5785-
return new BoundNullCoalescingAssignmentOperator(node, leftOperand, rightOperand, CreateErrorType(), hasErrors: true);
5783+
diagnostics = BindingDiagnosticBag.Discarded;
57865784
}
57875785

57885786
// Given a ??= b, the type of a is A, the type of B is b, and if A is a nullable value type, the underlying

src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_ICoalesceAssignmentOperation.cs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -598,12 +598,12 @@ static void M(object o1, object o2, string s1, string s2)
598598
Predecessors: [B0]
599599
Statements (1)
600600
IFlowCaptureOperation: 0 (OperationKind.FlowCapture, Type: null, IsInvalid, IsImplicit) (Syntax: 'o1')
601-
Value:
601+
Value:
602602
IParameterReferenceOperation: o1 (OperationKind.ParameterReference, Type: System.Object, IsInvalid) (Syntax: 'o1')
603603
604604
Jump if True (Regular) to Block[B3]
605605
IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsInvalid, IsImplicit) (Syntax: 'o1')
606-
Operand:
606+
Operand:
607607
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, IsInvalid, IsImplicit) (Syntax: 'o1')
608608
Leaving: {R3}
609609
@@ -612,7 +612,7 @@ static void M(object o1, object o2, string s1, string s2)
612612
Predecessors: [B1]
613613
Statements (1)
614614
IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsInvalid, IsImplicit) (Syntax: 'o1')
615-
Value:
615+
Value:
616616
IFlowCaptureReferenceOperation: 0 (OperationKind.FlowCaptureReference, Type: System.Object, IsInvalid, IsImplicit) (Syntax: 'o1')
617617
618618
Next (Regular) Block[B4]
@@ -623,15 +623,15 @@ static void M(object o1, object o2, string s1, string s2)
623623
Predecessors: [B1]
624624
Statements (1)
625625
IFlowCaptureOperation: 1 (OperationKind.FlowCapture, Type: null, IsInvalid, IsImplicit) (Syntax: 'o2')
626-
Value:
626+
Value:
627627
IParameterReferenceOperation: o2 (OperationKind.ParameterReference, Type: System.Object, IsInvalid) (Syntax: 'o2')
628628
629629
Next (Regular) Block[B4]
630630
Block[B4] - Block
631631
Predecessors: [B2] [B3]
632632
Statements (1)
633633
IFlowCaptureOperation: 2 (OperationKind.FlowCapture, Type: null, IsInvalid, IsImplicit) (Syntax: 'o1 ?? o2')
634-
Value:
634+
Value:
635635
IInvalidOperation (OperationKind.Invalid, Type: System.Object, IsInvalid, IsImplicit) (Syntax: 'o1 ?? o2')
636636
Children(1):
637637
IFlowCaptureReferenceOperation: 1 (OperationKind.FlowCaptureReference, Type: System.Object, IsInvalid, IsImplicit) (Syntax: 'o1 ?? o2')
@@ -647,12 +647,12 @@ static void M(object o1, object o2, string s1, string s2)
647647
Predecessors: [B4]
648648
Statements (1)
649649
IFlowCaptureOperation: 3 (OperationKind.FlowCapture, Type: null, IsInvalid, IsImplicit) (Syntax: 'o1 ?? o2')
650-
Value:
650+
Value:
651651
IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Object, IsInvalid, IsImplicit) (Syntax: 'o1 ?? o2')
652652
653653
Jump if True (Regular) to Block[B6]
654654
IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsInvalid, IsImplicit) (Syntax: 'o1 ?? o2')
655-
Operand:
655+
Operand:
656656
IFlowCaptureReferenceOperation: 3 (OperationKind.FlowCaptureReference, Type: System.Object, IsInvalid, IsImplicit) (Syntax: 'o1 ?? o2')
657657
Leaving: {R4}
658658
Entering: {R5} {R6}
@@ -670,12 +670,12 @@ static void M(object o1, object o2, string s1, string s2)
670670
Predecessors: [B5]
671671
Statements (1)
672672
IFlowCaptureOperation: 4 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 's1')
673-
Value:
673+
Value:
674674
IParameterReferenceOperation: s1 (OperationKind.ParameterReference, Type: System.String) (Syntax: 's1')
675675
676676
Jump if True (Regular) to Block[B8]
677677
IIsNullOperation (OperationKind.IsNull, Type: System.Boolean, IsImplicit) (Syntax: 's1')
678-
Operand:
678+
Operand:
679679
IFlowCaptureReferenceOperation: 4 (OperationKind.FlowCaptureReference, Type: System.String, IsImplicit) (Syntax: 's1')
680680
Leaving: {R6}
681681
@@ -684,7 +684,7 @@ static void M(object o1, object o2, string s1, string s2)
684684
Predecessors: [B6]
685685
Statements (1)
686686
IFlowCaptureOperation: 5 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 's1')
687-
Value:
687+
Value:
688688
IFlowCaptureReferenceOperation: 4 (OperationKind.FlowCaptureReference, Type: System.String, IsImplicit) (Syntax: 's1')
689689
690690
Next (Regular) Block[B9]
@@ -695,18 +695,22 @@ static void M(object o1, object o2, string s1, string s2)
695695
Predecessors: [B6]
696696
Statements (1)
697697
IFlowCaptureOperation: 5 (OperationKind.FlowCapture, Type: null, IsImplicit) (Syntax: 's2')
698-
Value:
698+
Value:
699699
IParameterReferenceOperation: s2 (OperationKind.ParameterReference, Type: System.String) (Syntax: 's2')
700700
701701
Next (Regular) Block[B9]
702702
Block[B9] - Block
703703
Predecessors: [B7] [B8]
704704
Statements (1)
705-
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: ?, IsInvalid, IsImplicit) (Syntax: '(o1 ?? o2) ... (s1 ?? s2)')
706-
Left:
705+
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Object, IsInvalid, IsImplicit) (Syntax: '(o1 ?? o2) ... (s1 ?? s2)')
706+
Left:
707707
IFlowCaptureReferenceOperation: 2 (OperationKind.FlowCaptureReference, Type: System.Object, IsInvalid, IsImplicit) (Syntax: 'o1 ?? o2')
708-
Right:
709-
IFlowCaptureReferenceOperation: 5 (OperationKind.FlowCaptureReference, Type: System.String, IsImplicit) (Syntax: 's1 ?? s2')
708+
Right:
709+
IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Object, IsImplicit) (Syntax: 's1 ?? s2')
710+
Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: True, IsUserDefined: False) (MethodSymbol: null)
711+
(ImplicitReference)
712+
Operand:
713+
IFlowCaptureReferenceOperation: 5 (OperationKind.FlowCaptureReference, Type: System.String, IsImplicit) (Syntax: 's1 ?? s2')
710714
711715
Next (Regular) Block[B10]
712716
Leaving: {R5} {R1}

0 commit comments

Comments
 (0)