Example #1
0
        private TupleBinaryOperatorInfo.Multiple BindTupleBinaryOperatorNestedInfo(BinaryExpressionSyntax node, BinaryOperatorKind kind,
                                                                                   BoundExpression left, BoundExpression right, BindingDiagnosticBag diagnostics)
        {
            left  = GiveTupleTypeToDefaultLiteralIfNeeded(left, right.Type);
            right = GiveTupleTypeToDefaultLiteralIfNeeded(right, left.Type);

            if (left.IsLiteralDefaultOrImplicitObjectCreation() ||
                right.IsLiteralDefaultOrImplicitObjectCreation())
            {
                ReportBinaryOperatorError(node, diagnostics, node.OperatorToken, left, right, LookupResultKind.Ambiguous);
                return(TupleBinaryOperatorInfo.Multiple.ErrorInstance);
            }

            // Aside from default (which we fixed or ruled out above) and tuple literals,
            // we must have typed expressions at this point
            Debug.Assert((object)left.Type != null || left.Kind == BoundKind.TupleLiteral);
            Debug.Assert((object)right.Type != null || right.Kind == BoundKind.TupleLiteral);

            int leftCardinality  = GetTupleCardinality(left);
            int rightCardinality = GetTupleCardinality(right);

            if (leftCardinality != rightCardinality)
            {
                Error(diagnostics, ErrorCode.ERR_TupleSizesMismatchForBinOps, node, leftCardinality, rightCardinality);
                return(TupleBinaryOperatorInfo.Multiple.ErrorInstance);
            }

            (ImmutableArray <BoundExpression> leftParts, ImmutableArray <string> leftNames)   = GetTupleArgumentsOrPlaceholders(left);
            (ImmutableArray <BoundExpression> rightParts, ImmutableArray <string> rightNames) = GetTupleArgumentsOrPlaceholders(right);
            ReportNamesMismatchesIfAny(left, right, leftNames, rightNames, diagnostics);

            int length = leftParts.Length;

            Debug.Assert(length == rightParts.Length);

            var operatorsBuilder = ArrayBuilder <TupleBinaryOperatorInfo> .GetInstance(length);

            for (int i = 0; i < length; i++)
            {
                operatorsBuilder.Add(BindTupleBinaryOperatorInfo(node, kind, leftParts[i], rightParts[i], diagnostics));
            }

            var compilation = this.Compilation;
            var operators   = operatorsBuilder.ToImmutableAndFree();

            // typeless tuple literals are not nullable
            bool leftNullable  = left.Type?.IsNullableType() == true;
            bool rightNullable = right.Type?.IsNullableType() == true;
            bool isNullable    = leftNullable || rightNullable;

            TypeSymbol leftTupleType  = MakeConvertedType(operators.SelectAsArray(o => o.LeftConvertedTypeOpt), node.Left, leftParts, leftNames, isNullable, compilation, diagnostics);
            TypeSymbol rightTupleType = MakeConvertedType(operators.SelectAsArray(o => o.RightConvertedTypeOpt), node.Right, rightParts, rightNames, isNullable, compilation, diagnostics);

            return(new TupleBinaryOperatorInfo.Multiple(operators, leftTupleType, rightTupleType));
        }
Example #2
0
        private static bool IsTupleBinaryOperation(BoundExpression left, BoundExpression right)
        {
            bool leftDefaultOrNew  = left.IsLiteralDefaultOrImplicitObjectCreation();
            bool rightDefaultOrNew = right.IsLiteralDefaultOrImplicitObjectCreation();

            if (leftDefaultOrNew && rightDefaultOrNew)
            {
                return(false);
            }

            return((GetTupleCardinality(left) > 1 || leftDefaultOrNew) &&
                   (GetTupleCardinality(right) > 1 || rightDefaultOrNew));
        }