private DataType InferBinaryExpressionType( BinaryExpressionSyntax binaryExpression) { InferExpressionType(binaryExpression.LeftOperand); var leftType = binaryExpression.LeftOperand.Type; var @operator = binaryExpression.Operator; InferExpressionType(binaryExpression.RightOperand); var rightType = binaryExpression.RightOperand.Type; // If either is unknown, then we can't know whether there is a a problem. // Note that the operator could be overloaded if (leftType == DataType.Unknown || rightType == DataType.Unknown) { return(binaryExpression.Type = DataType.Unknown); } bool compatible; switch (@operator) { case BinaryOperator.Plus: case BinaryOperator.Minus: case BinaryOperator.Asterisk: case BinaryOperator.Slash: compatible = NumericOperatorTypesAreCompatible(ref binaryExpression.LeftOperand, ref binaryExpression.RightOperand, null); binaryExpression.Type = compatible ? leftType : DataType.Unknown; break; case BinaryOperator.EqualsEquals: case BinaryOperator.NotEqual: case BinaryOperator.LessThan: case BinaryOperator.LessThanOrEqual: case BinaryOperator.GreaterThan: case BinaryOperator.GreaterThanOrEqual: compatible = (leftType == DataType.Bool && rightType == DataType.Bool) || NumericOperatorTypesAreCompatible(ref binaryExpression.LeftOperand, ref binaryExpression.RightOperand, null); binaryExpression.Type = DataType.Bool; break; case BinaryOperator.And: case BinaryOperator.Or: compatible = leftType == DataType.Bool && rightType == DataType.Bool; binaryExpression.Type = DataType.Bool; break; default: throw NonExhaustiveMatchException.ForEnum(@operator); } if (!compatible) { diagnostics.Add(TypeError.OperatorCannotBeAppliedToOperandsOfType(file, binaryExpression.Span, @operator, binaryExpression.LeftOperand.Type, binaryExpression.RightOperand.Type)); } return(binaryExpression.Type); }