Problem understanding C# type inference as described in the language specification

Viewed 1242

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 adds string to the lower bounds for T, 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... so T 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?

1 Answers
Related