From 5a2fffed6e15cd6c45da28bb5f0f41f042f6a777 Mon Sep 17 00:00:00 2001 From: Neal Gafter Date: Tue, 4 Apr 2017 14:47:39 -0700 Subject: [PATCH] Add precise proposed spec for improved common type. (#386) --- proposals/improved-common-type.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/proposals/improved-common-type.md b/proposals/improved-common-type.md index 063a7dc..342cfb7 100644 --- a/proposals/improved-common-type.md +++ b/proposals/improved-common-type.md @@ -28,6 +28,29 @@ This is expected to affect the following aspects of the language: - implicitly types [array creation expression](https://github.com/dotnet/csharplang/blob/master/spec/expressions.md#array-creation-expressions) - inferring the [return type of a lambda](https://github.com/dotnet/csharplang/blob/master/spec/expressions.md#inferred-return-type) for type inference +More precisely, we change the following sections of the specification (insertions in bold, deletions in strikethrough): + +> #### Output type inferences +> +> An *output type inference* is made *from* an expression `E` *to* a type `T` in the following way: +> +> * If `E` is an anonymous function with inferred return type `U` ([Inferred return type](expressions.md#inferred-return-type)) and `T` is a delegate type or expression tree type with return type `Tb`, then a *lower-bound inference* ([Lower-bound inferences](expressions.md#lower-bound-inferences)) is made *from* `U` *to* `Tb`. +> * Otherwise, if `E` is a method group and `T` is a delegate type or expression tree type with parameter types `T1...Tk` and return type `Tb`, and overload resolution of `E` with the types `T1...Tk` yields a single method with return type `U`, then a *lower-bound inference* is made *from* `U` *to* `Tb`. +> * Otherwise, if `E` is an expression with type `U`, then a *lower-bound inference* is made *from* `U` *to* `T`. +> * **Otherwise, if `E` is a constant expression with value `null`, then a *null bound* is added to `T`** +> * Otherwise, no inferences are made. + +> #### Fixing +> +> An *unfixed* type variable `Xi` with a set of bounds is *fixed* as follows: +> +> * The set of *candidate types* `Uj` starts out as the set of all types in the set of bounds for `Xi`. +> * We then examine each bound for `Xi` in turn: For each exact bound `U` of `Xi` all types `Uj` which are not identical to `U` are removed from the candidate set. For each lower bound `U` of `Xi` all types `Uj` to which there is *not* an implicit conversion from `U` are removed from the candidate set. For each upper bound `U` of `Xi` all types `Uj` from which there is *not* an implicit conversion to `U` are removed from the candidate set. +> * If among the remaining candidate types `Uj` there is a unique type `V` from which there is an implicit conversion to all the other candidate types, then ~~`Xi` is fixed to `V`.~~ +> - **If `V` is a value type and there is a *null bound* for `Xi`, then `Xi` is fixed to `V?`** +> - **Otherwise `Xi` is fixed to `V`** +> * Otherwise, type inference fails. + ## Drawbacks [drawbacks]: #drawbacks