Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upper-Bound/Lower-Bound Inferences and fixing

Tags:

c#

In the C# 4.0 Spec 7.5.2.9:

A lower-bound inference from a type U to a type V is made as follows:

  • If V is one of the unfixed Xi, then U is added to the set of lower bounds for Xi.
  • [...]

I've gone over this section many times. Lacking a section reference, this definition reads like a circular reference. So, I expect to find a grammer production or section reference nearby to clarify..which I do not. This section also ties in Fixing which suffers from similar definition issues.

What is an upper-bound inference vs a lower-bound inference?

like image 846
P.Brian.Mackey Avatar asked Feb 18 '13 14:02

P.Brian.Mackey


1 Answers

I'll try my best to describe it more clearly. Worst case, I describe it differently.

The upper/lower inference is one part of a phased approach to type inference with regard to type arguments that are used for a particular generic method call. Obviously, upper/lower inference won't be applied if in the first phase if the argument (E) is explicitly typed. e.g.:

given

public static T Choose<T>(T first, T second) {
        return (rand.Next(2) == 0)? first: second;
    }

I can invoke Choose with explicit type arguments:

Choose<String>("first", "second");

With regard to the upper- or lower-bounds inference, there are some implications throughout 7.5.2 that decide whether lower- or upper-bounds inference is even applicable. For example, 7.5.2.9 (and .10) detail that the type parameter is unfixed for either upper- or lower-bounds inference to occur. 7.5.2.5 details that a type parameter is only unfixed when that type parameter depends on another unfixed type parameter. For example

IEnumerable<TResult> Select<TSource, TResult>(IEnumerable<TSource> e,
    Func<TSource, Result> f)

TResult "depends on" TSource, because the type of TSource could possibly determine the type of TResult. e.g. with a call like Select(c, e->Name), TResult depends on the type of Name in TSource.

In terms of upper- and lower-bounds inferences, for a given unfixed type parameter (X) whose type (V) is not explicitly declared (see first paragraph), upper or lower bounds of type argument (E) of type U are deduced. If the type parameter is covariant (has out modifier) and one of the types in the lower-bound set is a candidate for the parameter, then a lower-bound inference occurred. Conversely, if the type parameter is contravariant (has 'in' modifier) and one of the types in the upper-bound set is a candidate for the parameter, then an upper-bound inference occurred. e.g. with Select(c, e->e.Name) and c was IEnumerable<Mammal> then the compiler would infer an lower bound of Mammal because the type parameter in IEnumerable is covariant (e.g. it's declared IEnumerable<out T>. If it were declared IEnumerable<in T> then an upper-bound would be inferred. And if it were declared Enumerabale<T>--with no in or out then it would be invariant and neither upper- nor lower-bounds inference would apply.)

Clearly, if parameter type can be neither covariant nor contravariant then an exact match must occur

like image 193
Peter Ritchie Avatar answered Oct 18 '22 20:10

Peter Ritchie