/// <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)); }
/// <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); }