The C# language specification describes type inference in Section §7.5.2. There is a detail in it that I don’t understand. Consider the following case:
// declaration
void Method<T>(T obj, Func<string, T> func);
// call
Method("obj", s => (object) s);
Both the Microsoft and Mono C# compilers correctly infer T
= object
, but my understanding of the algorithm in the specification would yield T
= string
and then fail. Here is how I understand it:
The first phase
If Ei is an anonymous function, an explicit parameter type inference (§7.5.2.7) is made from Ei to Ti
⇒ has no effect, because the lambda expression has no explicit parameter types. Right?
Otherwise, if Ei has a type U and xi is a value parameter then a lower-bound inference is made from U to Ti.
⇒ the first parameter is of static type
string
, so this addsstring
to the lower bounds forT
, right?
The second phase
All unfixed type variables Xi which do not depend on (§7.5.2.5) any Xj are fixed (§7.5.2.10).
⇒
T
is unfixed;T
doesn’t depend on anything... soT
should be fixed, right?
§7.5.2.11 Fixing
The set of candidate types Uj starts out as the set of all types in the set of bounds for Xi.
⇒ {
string
(lower bound) }We then examine each bound for Xi in turn: [...] 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. [...]
⇒ doesn’t remove anything from the candidate set, right?
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.
⇒ Since there is only one candidate type, this is vacuously true, so Xi is fixed to
string
. Right?
So where am I going wrong?