Enhancing the Common Type Specification #8924
Unanswered
gafter
asked this question in
Language Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Enhancing the Common type spec
The common type (C# 5 ECMA spec section 12.6.3.1.5) says
First, we note that the code would be an error if any of the expressions
Ei
cannot be converted to the type to whichX
was fixed. In order to recognize this as a form of failure, we modify the penultimate bullet to beThis change has no effect on the legality or meaning of any C# 8 program, but it simplifies the generalization to target typing and the discussion below.
This best common type algorithm is used for three things in the specification:
new [] { e1, e2 }
),(b, e1, e2) => {if (b) return e1; else return e2; }
), andb switch { true => e1, false => e2 }
).It is not used for the conditional expression
b?e1:e2
, or the null coalescing operatore1??e2
which each has has its own specification for the common type that is based on the existence of a conversion from expression rather than a conversion from type.These distinct common type specifications can produce different results. For example, there is no best common type for a value of an enumeration type and the integer constant zero, but the specification for the conditional operator selects the enumeration type as the result. Given that we have these three different specifications for best common type (for different constructs) that produce different results, I propose that we not attempt to unify them.
Proposed changes
There are five pending proposals to make changes to these common type algorithms:
null
such asc?1:null
and expressions with typeint?
anddouble
.??
) expression #2473 Similarly for the null coalescing expression.new[]
#2701 Similarly for the array creation expression.There was some concern expressed in the LDM that once we enable target typing for a construct (whether as a fallback or always available), adding new enhancements to the common type algorithm would be a breaking change because it would give the expression a type, which could affect overload resolution. For this reason we fear that if we add target typing to a construct this might be our last opportunity to add any further enhancements to the common type algorithm.
Moreover, the fact that we have target typing for the switch-expression may mean that our window to enhance the common type algorithm has already closed. Here is an illustration of the kind of break that would concern us:
In C# 8, we select the second overload (it is a better conversion from expression because the conversion to
short?
is a better conversion than the conversion toint?
). However, if we extend the common type algorithm to assign the typeint?
to the switch expression, we would select the first overload (it is a better conversion from expression becauseint?
is the type of the expression).Let us survey the set of user requests for enhancements:
Target-typing only as a fallback?
There was some concern expressed in the LDM that it would be nice to align the handling of the conditional and null coalescing expressions (where target typing is proposed only as a fallback) with the handling of the switch expression (where target typing is available even if there is a common type). However, it is a breaking change to add target typing to an existing construct that has a type. Here is a demonstration:
The incompatibility arises when there is a language-defined conversion from expression for an expression that has a type and that depends on some aspect of the expression aside from its type (e.g. its value). It arises due to
If we elect to permit target-typing of conditional expressions and null coalescing expressions (when they have a common type), those would also be added to this list.
We can avoid this breaking change by adding support for target-typing of conditional expressions and null coalescing expressions only when they have no common type.
Recommendation
I believe that the proposed enhancements to the three common type algorithms are less compelling once the relevant constructs are target-typed. I believe we should add target-typing as a fallback to the conditional expression and the null coalescing expression to minimize the break to existing code. The other enhancements to the common type algorithms invent result types not appearing among the inputs (e.g.
long?
for input typesint?
andlong
), which violates one of the principle design invariants for type inference (only produce as a result a type which was one of the inputs), and which can also change the meaning of existing code.The disadvantage of taking target-typing as a fallback only is that code such as this will not compile:
This is something we have long lived with, and (perhaps surprisingly) it not among the use cases called out by customers in public discussions.
Beta Was this translation helpful? Give feedback.
All reactions