Example #1
0
        private void UnaryOperatorEasyOut(
            UnaryOperatorKind kind,
            BoundExpression operand,
            UnaryOperatorOverloadResolutionResult result
            )
        {
            var operandType = operand.Type;

            if (operandType is null)
            {
                return;
            }

            var easyOut = UnopEasyOut.OpKind(kind, operandType);

            if (easyOut == UnaryOperatorKind.Error)
            {
                return;
            }

            UnaryOperatorSignature signature = this.Compilation.builtInOperators.GetSignature(
                easyOut
                );

            Conversion?conversion = Conversions.FastClassifyConversion(
                operandType,
                signature.OperandType
                );

            Debug.Assert(conversion.HasValue && conversion.Value.IsImplicit);

            result.Results.Add(UnaryOperatorAnalysisResult.Applicable(signature, conversion.Value));
        }
Example #2
0
        private bool CandidateOperators(
            ArrayBuilder <UnaryOperatorSignature> operators,
            BoundExpression operand,
            ArrayBuilder <UnaryOperatorAnalysisResult> results,
            ref CompoundUseSiteInfo <AssemblySymbol> useSiteInfo
            )
        {
            bool anyApplicable = false;

            foreach (var op in operators)
            {
                var conversion = Conversions.ClassifyConversionFromExpression(
                    operand,
                    op.OperandType,
                    ref useSiteInfo
                    );
                if (conversion.IsImplicit)
                {
                    anyApplicable = true;
                    results.Add(UnaryOperatorAnalysisResult.Applicable(op, conversion));
                }
                else
                {
                    results.Add(UnaryOperatorAnalysisResult.Inapplicable(op, conversion));
                }
            }

            return(anyApplicable);
        }
Example #3
0
        private void PrepareBoolConversionAndTruthOperator(TypeSymbol type, BinaryExpressionSyntax node, BinaryOperatorKind binaryOperator, BindingDiagnosticBag diagnostics,
                                                           out BoundExpression conversionForBool, out BoundValuePlaceholder conversionForBoolPlaceholder, out UnaryOperatorSignature boolOperator)
        {
            // Is the operand implicitly convertible to bool?

            CompoundUseSiteInfo <AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
            TypeSymbol boolean    = GetSpecialType(SpecialType.System_Boolean, diagnostics, node);
            Conversion conversion = this.Conversions.ClassifyImplicitConversionFromType(type, boolean, ref useSiteInfo);

            diagnostics.Add(node, useSiteInfo);

            if (conversion.IsImplicit)
            {
                conversionForBoolPlaceholder = new BoundValuePlaceholder(node, type).MakeCompilerGenerated();
                conversionForBool            = CreateConversion(node, conversionForBoolPlaceholder, conversion, isCast: false, conversionGroupOpt: null, boolean, diagnostics);
                boolOperator = default;
                return;
            }

            // It was not. Does it implement operator true (or false)?

            UnaryOperatorKind boolOpKind;

            switch (binaryOperator)
            {
            case BinaryOperatorKind.Equal:
                boolOpKind = UnaryOperatorKind.False;
                break;

            case BinaryOperatorKind.NotEqual:
                boolOpKind = UnaryOperatorKind.True;
                break;

            default:
                throw ExceptionUtilities.UnexpectedValue(binaryOperator);
            }

            LookupResultKind resultKind;
            ImmutableArray <MethodSymbol> originalUserDefinedOperators;
            BoundExpression             comparisonResult = new BoundTupleOperandPlaceholder(node, type);
            UnaryOperatorAnalysisResult best             = this.UnaryOperatorOverloadResolution(boolOpKind, comparisonResult, node, diagnostics, out resultKind, out originalUserDefinedOperators);

            if (best.HasValue)
            {
                conversionForBoolPlaceholder = new BoundValuePlaceholder(node, type).MakeCompilerGenerated();
                conversionForBool            = CreateConversion(node, conversionForBoolPlaceholder, best.Conversion, isCast: false, conversionGroupOpt: null, best.Signature.OperandType, diagnostics);
                boolOperator = best.Signature;
                return;
            }

            // It did not. Give a "not convertible to bool" error.

            GenerateImplicitConversionError(diagnostics, node, conversion, comparisonResult, boolean);
            conversionForBoolPlaceholder = null;
            conversionForBool            = null;
            boolOperator = default;
            return;
        }
Example #4
0
        /// <summary>
        /// If an element-wise binary operator returns a non-bool type, we will either:
        /// - prepare a conversion to bool if one exists
        /// - prepare a truth operator: op_false in the case of an equality (<c>a == b</c> will be lowered to <c>!((a == b).op_false)</c>) or op_true in the case of inequality,
        ///     with the conversion being used for its input.
        /// </summary>
        private void PrepareBoolConversionAndTruthOperator(TypeSymbol type, BinaryExpressionSyntax node, BinaryOperatorKind binaryOperator, DiagnosticBag diagnostics,
                                                           out Conversion conversionForBool, out UnaryOperatorSignature boolOperator)
        {
            // Is the operand implicitly convertible to bool?

            HashSet <DiagnosticInfo> useSiteDiagnostics = null;
            TypeSymbol boolean    = GetSpecialType(SpecialType.System_Boolean, diagnostics, node);
            Conversion conversion = this.Conversions.ClassifyImplicitConversionFromType(type, boolean, ref useSiteDiagnostics);

            diagnostics.Add(node, useSiteDiagnostics);

            if (conversion.IsImplicit)
            {
                ReportDiagnosticsIfObsolete(diagnostics, conversion, node, hasBaseReceiver: false);
                conversionForBool = conversion;
                boolOperator      = default;
                return;
            }

            // It was not. Does it implement operator true (or false)?

            UnaryOperatorKind boolOpKind;

            switch (binaryOperator)
            {
            case BinaryOperatorKind.Equal:
                boolOpKind = UnaryOperatorKind.False;
                break;

            case BinaryOperatorKind.NotEqual:
                boolOpKind = UnaryOperatorKind.True;
                break;

            default:
                throw ExceptionUtilities.UnexpectedValue(binaryOperator);
            }

            LookupResultKind resultKind;
            ImmutableArray <MethodSymbol> originalUserDefinedOperators;
            BoundExpression             comparisonResult = new BoundTupleOperandPlaceholder(node, type);
            UnaryOperatorAnalysisResult best             = this.UnaryOperatorOverloadResolution(boolOpKind, comparisonResult, node, diagnostics, out resultKind, out originalUserDefinedOperators);

            if (best.HasValue)
            {
                conversionForBool = best.Conversion;
                boolOperator      = best.Signature;
                return;
            }

            // It did not. Give a "not convertible to bool" error.

            GenerateImplicitConversionError(diagnostics, node, conversion, comparisonResult, boolean);
            conversionForBool = Conversion.NoConversion;
            boolOperator      = default;
            return;
        }