Skip to content

Commit a1e3aa4

Browse files
authored
Better betterness (#484)
* Incorporate Better Betterness This commit adds the notes from https://github.com/dotnet/roslyn/blob/main/docs/specs/CSharp%206/Better%20Betterness.md * Incorporate changes from #283 Issue #283 contains notes for how the implementation differed from the proposed better betterness text. * compat for delegate conversion This commit brings in the method group conversion fix that caused dotnet/roslyn#6750 It needs wordsmithing for a number of reasons: - "corresponding argument" isn't defined. - the section references itself. - I think there may have been requirements from the prior commit regarding delegates and expressions that are still needed. * initial feedback. * section reference * a bit of editing * I think this gets close This gets close to what's implemented in C# 6.0. I think this fails as a description in the case of #499 For 7.3, it would be better to describe that change in the section on Method Group conversion. * review from the meeting. * fix awkward grammar * limit bullet to method group conversion.
1 parent 7c6320e commit a1e3aa4

File tree

2 files changed

+20
-21
lines changed

2 files changed

+20
-21
lines changed

standard/delegates.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ A method or delegate type `M` is ***compatible*** with a delegate type `D` if al
8080
8181
- `D` and `M` have the same number of parameters, and each parameter in `D` has the same `ref` or `out` modifiers as the corresponding parameter in `M`.
8282
- For each value parameter (a parameter with no `ref` or `out` modifier), an identity conversion ([§10.2.2](conversions.md#1022-identity-conversion)) or implicit reference conversion ([§10.2.8](conversions.md#1028-implicit-reference-conversions)) exists from the parameter type in `D` to the corresponding parameter type in `M`.
83-
8483
- For each `ref` or `out` parameter, the parameter type in `D` is the same as the parameter type in `M`.
8584
- An identity or implicit reference conversion exists from the return type of `M` to the return type of `D`.
8685

standard/expressions.md

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -956,34 +956,34 @@ In case the parameter type sequences `{P₁, P₂, ..., Pᵥ}` and `{Q₁, Q₂
956956
957957
#### 11.6.4.4 Better conversion from expression
958958
959-
Given an implicit conversion `C₁` that converts from an expression `E` to a type `T₁`, and an implicit conversion `C₂` that converts from an expression `E` to a type `T₂`, `C₁` is a ***better conversion*** than `C₂` if at least one of the following holds:
959+
Given an implicit conversion `C₁` that converts from an expression `E` to a type `T₁`, and an implicit conversion `C₂` that converts from an expression `E` to a type `T₂`, `C₁` is a better conversion than `C₂` if one of the following holds:
960960
961-
- `E` has a type `S` and an identity conversion exists from `S` to `T₁` but not from `S` to `T₂`
962-
- `E` is not an anonymous function and `T₁` is a better conversion target than `T₂` ([§11.6.4.6](expressions.md#11646-better-conversion-target))
963-
- `E` is an anonymous function, `T₁` is either a delegate type `D₁` or an expression tree type `Expression<D₁>`, `T₂` is either a delegate type `D₂` or an expression tree type `Expression<D₂>` and one of the following holds:
964-
- `D₁` is a better conversion target than `D₂`
965-
- `D₁` and `D₂` have identical parameter lists, and one of the following holds:
966-
- `D₁` has a return type `Y₁`, and `D₂` has a return type `Y₂`, an inferred return type `X` exists for `E` in the context of that parameter list ([§11.6.3.13](expressions.md#116313-inferred-return-type)), and the conversion from `X` to `Y₁` is better than the conversion from `X` to `Y₂`
967-
- `E` is async, `D₁` has a return type `Task<Y>`, and `D₂` has a return type `Task<Y>`, an inferred return type `Task<X>` exists for `E` in the context of that parameter list ([§11.6.3.13](expressions.md#116313-inferred-return-type)), and the conversion from `X` to `Y₁` is better than the conversion from `X` to `Y₂`
968-
- `D₁` has a return type `Y`, and `D₂` is void returning
961+
- `E` exactly matches `T₁` and `E` does not exactly match `T₂` (§11.6.4.5)
962+
- `E` exactly matches both or neither of `T₁` and `T₂`, and `T₁` is a better conversion target than `T₂` (§11.6.4.6)
969963
970-
#### 11.6.4.5 Better conversion from type
964+
#### 11.6.4.5 Exactly matching expression
971965
972-
Given a conversion `C₁` that converts from a type `S` to a type `T₁`, and a conversion `C₂` that converts from a type `S` to a type `T`, `C₁` is a *better conversion* than `C` if at least one of the following holds:
966+
Given an expression `E` and a type `T`, `E` ***exactly matches*** `T` if one of the following holds:
973967
974-
- An identity conversion exists from `S` to `T₁` but not from `S` to `T₂`
975-
- `T₁` is a better conversion target than `T₂` ([§11.6.4.6](expressions.md#11646-better-conversion-target))
968+
- `E` has a type `S`, and an identity conversion exists from `S` to `T`
969+
- `E` is an anonymous function, `T` is either a delegate type `D` or an expression tree type `Expression<D>` and one of the following holds:
970+
- An inferred return type `X` exists for `E` in the context of the parameter list of `D` (§11.6.3.12), and an identity conversion exists from `X` to the return type of `D`
971+
- Either `E` is non-async and `D` has a return type `Y` or `E` is async and `D` has a return type `Task<Y>`, and one of the following holds:
972+
- The body of `E` is an expression that exactly matches `Y`
973+
- The body of `E` is a statement block where every return statement returns an expression that exactly matches `Y`
976974
977975
#### 11.6.4.6 Better conversion target
978976
979-
Given two different types `T₁` and `T₂`, `T₁` is a better conversion target than `T₂` if at least one of the following holds:
977+
Given an expression `E` and two types `T₁` and `T₂`, `T₁` is a ***better conversion target*** than `T₂` for `E` if one of the following holds:
980978
981-
- An implicit conversion from `T₁` to `T₂` exists, and no implicit conversion from `T₂` to `T₁` exists
982-
- `T₁` is a signed integral type and `T₂` is an unsigned integral type. Specifically:
983-
- `T₁` is `sbyte` and `T₂` is `byte`, `ushort`, `uint`, or `ulong`
984-
- `T₁` is `short` and `T₂` is `ushort`, `uint`, or `ulong`
985-
- `T₁` is `int` and `T₂` is `uint`, or `ulong`
986-
- `T₁` is `long` and `T₂` is `ulong`
979+
- An implicit conversion from `T₁` to `T₂` exists
980+
- `T₁` is `Task<S₁>`, `T₂` is `Task<S₂>`, and `S₁` is a better conversion target than `S₂`
981+
- `T₁` is `S₁` or `S₁?` where `S₁` is a signed integral type, and `T₂` is `S₂` or `S₂?` where `S₂` is an unsigned integral type. Specifically:
982+
- `S₁` is `sbyte` and `S₂` is `byte`, `ushort`, `uint`, or `ulong`
983+
- `S₁` is `short` and `S₂` is `ushort`, `uint`, or `ulong`
984+
- `S₁` is `int` and `S₂` is `uint`, or `ulong`
985+
- `S₁` is `long` and `S₂` is `ulong`
986+
- `E` is a method group conversion10.8() and `T₁` is compatible19.4) with the single best method from the method group
987987
988988
#### 11.6.4.7 Overloading in generic classes
989989

0 commit comments

Comments
 (0)