internal SubsumptionDiagnosticBuilder(Symbol enclosingSymbol, Conversions conversions, BoundExpression expression) : base(enclosingSymbol, conversions) { _subsumptionTree = DecisionTree.Create(expression, expression.Type, enclosingSymbol); }
private DecisionTree LowerToDecisionTree( BoundExpression loweredExpression, BoundPatternSwitchStatement node) { var loweredDecisionTree = DecisionTree.Create(loweredExpression, loweredExpression.Type, _enclosingSymbol); BoundPatternSwitchLabel defaultLabel = null; SyntaxNode defaultSection = null; foreach (var section in node.SwitchSections) { var sectionSyntax = (SyntaxNode)section.Syntax; foreach (var label in section.SwitchLabels) { var loweredLabel = LowerSwitchLabel(label); if (loweredLabel.Syntax.Kind() == SyntaxKind.DefaultSwitchLabel) { if (defaultLabel != null) { // duplicate switch label will have been reported during initial binding. } else { defaultLabel = loweredLabel; defaultSection = sectionSyntax; } } else { Syntax = label.Syntax; AddToDecisionTree(loweredDecisionTree, sectionSyntax, loweredLabel); } } } if (defaultLabel != null) { Add(loweredDecisionTree, (e, t) => new DecisionTree.Guarded(loweredExpression, loweredExpression.Type, default(ImmutableArray <KeyValuePair <BoundExpression, BoundExpression> >), defaultSection, null, defaultLabel)); } // We discard use-site diagnostics, as they have been reported during initial binding. _useSiteDiagnostics.Clear(); return(loweredDecisionTree); }
internal DecisionTree ComputeDecisionTree() { Debug.Assert(_section == null); var expression = _switchStatement.Expression; if (expression.ConstantValue == null && expression.Kind != BoundKind.Local) { // unless the expression is simple enough, copy it into a local var localSymbol = new SynthesizedLocal(_enclosingSymbol as MethodSymbol, expression.Type, SynthesizedLocalKind.PatternMatchingTemp, _switchStatement.Syntax, false, RefKind.None); expression = new BoundLocal(expression.Syntax, localSymbol, null, expression.Type); } var result = DecisionTree.Create(_switchStatement.Expression, _switchStatement.Expression.Type, _enclosingSymbol); var subsumptionTree = DecisionTree.Create(_switchStatement.Expression, _switchStatement.Expression.Type, _enclosingSymbol); BoundPatternSwitchLabel defaultLabel = null; BoundPatternSwitchSection defaultSection = null; foreach (var section in _switchStatement.SwitchSections) { this._section = section; foreach (var label in section.SwitchLabels) { if (label.Syntax.Kind() == SyntaxKind.DefaultSwitchLabel) { if (defaultLabel != null) { // duplicate switch label will have been reported during initial binding. } else { defaultLabel = label; defaultSection = section; } } else { this._syntax = label.Syntax; // For purposes of subsumption, we do not take into consideration the value // of the input expression. Therefore we consider null possible if the type permits. var subsumedErrorCode = CheckSubsumed(label.Pattern, subsumptionTree, inputCouldBeNull: true); if (subsumedErrorCode != 0 && subsumedErrorCode != ErrorCode.ERR_NoImplicitConvCast) { if (!label.HasErrors) { _diagnostics.Add(subsumedErrorCode, label.Pattern.Syntax.Location); } } else { AddToDecisionTree(result, label); if (label.Guard == null || label.Guard.ConstantValue == ConstantValue.True) { // Only unconditional switch labels contribute to subsumption AddToDecisionTree(subsumptionTree, label); } } } } } if (defaultLabel != null) { Add(result, (e, t) => new DecisionTree.Guarded(_switchStatement.Expression, _switchStatement.Expression.Type, default(ImmutableArray <KeyValuePair <BoundExpression, BoundExpression> >), defaultSection, null, defaultLabel)); } return(result); }