示例#1
0
        /// <remarks>
        /// This method implements best type inference for the conditional operator ?:.
        /// NOTE: If either expression is an error type, we return error type as the inference result.
        /// </remarks>
        public static TypeSymbol InferBestTypeForConditionalOperator(BoundExpression expr1, BoundExpression expr2, Conversions conversions, out bool hadMultipleCandidates, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
        {
            // SPEC:    The second and third operands, x and y, of the ?: operator control the type of the conditional expression.
            // SPEC:    •	If x has type X and y has type Y then
            // SPEC:        o	If an implicit conversion (§6.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression.
            // SPEC:        o	If an implicit conversion (§6.1) exists from Y to X, but not from X to Y, then X is the type of the conditional expression.
            // SPEC:        o	Otherwise, no expression type can be determined, and a compile-time error occurs.
            // SPEC:    •	If only one of x and y has a type, and both x and y, are implicitly convertible to that type, then that is the type of the conditional expression.
            // SPEC:    •	Otherwise, no expression type can be determined, and a compile-time error occurs.

            // A type is a candidate if all expressions are convertible to that type.
            ArrayBuilder <TypeSymbol> candidateTypes = ArrayBuilder <TypeSymbol> .GetInstance();

            TypeSymbol type1 = expr1.Type;

            if ((object)type1 != null)
            {
                if (type1.IsErrorType())
                {
                    candidateTypes.Free();
                    hadMultipleCandidates = false;
                    return(type1);
                }

                if (conversions.ClassifyImplicitConversionFromExpression(expr2, type1, ref useSiteDiagnostics).Exists)
                {
                    candidateTypes.Add(type1);
                }
            }

            TypeSymbol type2 = expr2.Type;

            if ((object)type2 != null && type2 != type1)
            {
                if (type2.IsErrorType())
                {
                    candidateTypes.Free();
                    hadMultipleCandidates = false;
                    return(type2);
                }

                if (conversions.ClassifyImplicitConversionFromExpression(expr1, type2, ref useSiteDiagnostics).Exists)
                {
                    candidateTypes.Add(type2);
                }
            }

            hadMultipleCandidates = candidateTypes.Count > 1;

            return(InferBestType(candidateTypes.ToImmutableAndFree(), conversions, ref useSiteDiagnostics));
        }
示例#2
0
        /// <remarks>
        /// This method implements best type inference for the conditional operator ?:.
        /// NOTE: If either expression is an error type, we return error type as the inference result.
        /// </remarks>
        public static TypeSymbol InferBestTypeForConditionalOperator(BoundExpression expr1, BoundExpression expr2, Conversions conversions, out bool hadMultipleCandidates, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
        {
            // SPEC:    The second and third operands, x and y, of the ?: operator control the type of the conditional expression. 
            // SPEC:    •	If x has type X and y has type Y then
            // SPEC:        o	If an implicit conversion (§6.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression.
            // SPEC:        o	If an implicit conversion (§6.1) exists from Y to X, but not from X to Y, then X is the type of the conditional expression.
            // SPEC:        o	Otherwise, no expression type can be determined, and a compile-time error occurs.
            // SPEC:    •	If only one of x and y has a type, and both x and y, are implicitly convertible to that type, then that is the type of the conditional expression.
            // SPEC:    •	Otherwise, no expression type can be determined, and a compile-time error occurs.

            // A type is a candidate if all expressions are convertible to that type.
            ArrayBuilder<TypeSymbol> candidateTypes = ArrayBuilder<TypeSymbol>.GetInstance();

            TypeSymbol type1 = expr1.Type;

            if ((object)type1 != null)
            {
                if (type1.IsErrorType())
                {
                    candidateTypes.Free();
                    hadMultipleCandidates = false;
                    return type1;
                }

                if (conversions.ClassifyImplicitConversionFromExpression(expr2, type1, ref useSiteDiagnostics).Exists)
                {
                    candidateTypes.Add(type1);
                }
            }

            TypeSymbol type2 = expr2.Type;

            if ((object)type2 != null && type2 != type1)
            {
                if (type2.IsErrorType())
                {
                    candidateTypes.Free();
                    hadMultipleCandidates = false;
                    return type2;
                }

                if (conversions.ClassifyImplicitConversionFromExpression(expr1, type2, ref useSiteDiagnostics).Exists)
                {
                    candidateTypes.Add(type2);
                }
            }

            hadMultipleCandidates = candidateTypes.Count > 1;

            return InferBestType(candidateTypes.ToImmutableAndFree(), conversions, ref useSiteDiagnostics);
        }