-
Notifications
You must be signed in to change notification settings - Fork 92
[Version 9.0] Feature support for target-typed conditional expression #1465
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: draft-v9
Are you sure you want to change the base?
Conversation
jskeet
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably discuss #1469 and ideally get it improved and merged before we do much more with this PR. I definitely need to look at it in more detail, and would probably benefit from a chat with Bill about it.
| 1. there is no common type for `e1` and `e2`, or | ||
| 1. for which a common type exists, but one of the expressions `e1` or `e2` has no implicit conversion to that type | ||
| an implicit ***conditional expression conversion*** exists that permits an implicit conversion from *conditional_expression* to any type `T` for which there is a conversion-from-expression from `e1` to `T` and also from `e2` to `T`. It is an error if *conditional_expression* neither has a common type between `e1` and `e2` nor is subject to a conditional expression conversion. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this makes available a conversion to a specific type... and I'm assuming we expect the rules to just drop out for which types are "tested" for this? For example, if I have
void M(int x) { ... }
void M(string y) { ... }... then overload resolution of M(true ? new(new char[0]) : new(new char[1])) would detect that there's an implicit conversion from both of those target-typed new expressions to string, but not to int?
| - `E` exactly matches `T₁` and `E` does not exactly match `T₂` ([§12.6.4.6](expressions.md#12646-exactly-matching-expression)) | ||
| - `E` exactly matches both or neither of `T₁` and `T₂`, and `T₁` is a better conversion target than `T₂` ([§12.6.4.7](expressions.md#12647-better-conversion-target)) | ||
| - `C₁` is not a conditional expression conversion and `C₂` is a conditional expression conversion. | ||
| - `E` exactly matches both or neither of `T₁` and `T₂`, and `T₁` is a better conversion target than `T₂` ([§12.6.4.7](expressions.md#12647-better-conversion-target)) and either `C₁` and `C₂` are both conditional expression conversions or neither is a conditional expression conversion. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to figure out what this is about - but E can't exactly match T2 given line 1113, so it can't match both T1 and T2...
| ``` | ||
|
|
||
| A *cast_expression* of the form `(T)E`, where `T` is a type and `E` is a *unary_expression*, performs an explicit conversion ([§10.3](conversions.md#103-explicit-conversions)) of the value of `E` to type `T`. If no explicit conversion exists from `E` to `T`, a binding-time error occurs. Otherwise, the result is the value produced by the explicit conversion. The result is always classified as a value, even if `E` denotes a variable. | ||
| A *cast_expression* of the form `(T)E`, where `T` is a type and `E` is a *unary_expression*, performs an explicit conversion ([§10.3](conversions.md#103-explicit-conversions)) of the value of `E` to type `T`. In the presence of a conditional expression conversion (§imp-cond-expr-conv) there may be more than one possible conversion from `E` to `T`, in which case, the conditional expression conversion shall only be used as a last resort. If no explicit conversion exists from `E` to `T`, a binding-time error occurs. Otherwise, the result is the value produced by the explicit conversion. The result is always classified as a value, even if `E` denotes a variable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused about this and think it would benefit from an example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The examples are in the design notes of the speclet:
|
|
||
| - If `x` has type `X` and `y` has type `Y` then, | ||
| - If an identity conversion exists between `X` and `Y`, then the result is the best common type of a set of expressions ([§12.6.3.16](expressions.md#126316-finding-the-best-common-type-of-a-set-of-expressions)). If either type is `dynamic`, type inference prefers `dynamic` ([§8.7](types.md#87-the-dynamic-type)). If either type is a tuple type ([§8.3.11](types.md#8311-tuple-types)), type inference includes the element names when the element names in the same ordinal position match in both tuples. | ||
| - If an identity conversion exists between `X` and `Y`, then the result is the best common type of a set of expressions ([§12.6.3.16](expressions.md#126316-finding-the-best-common-type-of-a-set-of-expressions)). ***placeholder for words somehow referring to “12.6.4.5 Better conversion from expression.”*** If either type is `dynamic`, type inference prefers `dynamic` ([§8.7](types.md#87-the-dynamic-type)). If either type is a tuple type ([§8.3.11](types.md#8311-tuple-types)), type inference includes the element names when the element names in the same ordinal position match in both tuples. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm hoping @BillWagner can provide motivation for this via an example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this needs to be updated per this text in the speclet: https://github.com/dotnet/csharplang/blob/main/proposals/csharp-9.0/target-typed-conditional-expression.md#better-conversion-from-expression
BillWagner
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added notes on Jon's comments.
| ``` | ||
|
|
||
| A *cast_expression* of the form `(T)E`, where `T` is a type and `E` is a *unary_expression*, performs an explicit conversion ([§10.3](conversions.md#103-explicit-conversions)) of the value of `E` to type `T`. If no explicit conversion exists from `E` to `T`, a binding-time error occurs. Otherwise, the result is the value produced by the explicit conversion. The result is always classified as a value, even if `E` denotes a variable. | ||
| A *cast_expression* of the form `(T)E`, where `T` is a type and `E` is a *unary_expression*, performs an explicit conversion ([§10.3](conversions.md#103-explicit-conversions)) of the value of `E` to type `T`. In the presence of a conditional expression conversion (§imp-cond-expr-conv) there may be more than one possible conversion from `E` to `T`, in which case, the conditional expression conversion shall only be used as a last resort. If no explicit conversion exists from `E` to `T`, a binding-time error occurs. Otherwise, the result is the value produced by the explicit conversion. The result is always classified as a value, even if `E` denotes a variable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The examples are in the design notes of the speclet:
|
|
||
| - If `x` has type `X` and `y` has type `Y` then, | ||
| - If an identity conversion exists between `X` and `Y`, then the result is the best common type of a set of expressions ([§12.6.3.16](expressions.md#126316-finding-the-best-common-type-of-a-set-of-expressions)). If either type is `dynamic`, type inference prefers `dynamic` ([§8.7](types.md#87-the-dynamic-type)). If either type is a tuple type ([§8.3.11](types.md#8311-tuple-types)), type inference includes the element names when the element names in the same ordinal position match in both tuples. | ||
| - If an identity conversion exists between `X` and `Y`, then the result is the best common type of a set of expressions ([§12.6.3.16](expressions.md#126316-finding-the-best-common-type-of-a-set-of-expressions)). ***placeholder for words somehow referring to “12.6.4.5 Better conversion from expression.”*** If either type is `dynamic`, type inference prefers `dynamic` ([§8.7](types.md#87-the-dynamic-type)). If either type is a tuple type ([§8.3.11](types.md#8311-tuple-types)), type inference includes the element names when the element names in the same ordinal position match in both tuples. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this needs to be updated per this text in the speclet: https://github.com/dotnet/csharplang/blob/main/proposals/csharp-9.0/target-typed-conditional-expression.md#better-conversion-from-expression
This PR is my formal version of the corresponding MS spec. Previously, I created PR #1071 to address this, but when Bill went to push that work into the new v9 process, he found it badly compromised. As such, that PR will be retired and this one will be used in its place.
12.18 Conditional operator has an open issue; see the following words in that section: placeholder for words somehow referring to “12.6.4.5 Better conversion from expression.”
Here are the details:
Mail to Bill on 2024-03-18: The MS spec suggests the text for “12.6.4.5 Better conversion from expression” be augmented; OK. However, “12.18 Conditional operator“ does not reference that section; instead, it points to “12.6.3.15 Finding the best common type of a set of expressions.” So, I don’t see how the proposed changes to “better conversion” will be seen in the context of “best common type.” Unless these two are somehow linked and I’m not seeing where.
Bill’s reply on 2024-04-01: I think the conditional expression section should reference both sections, as sometimes the conditional expression applies when there is no best common type.