Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type inference fails mysteriously

Why does the following fail to infer R:

static R Foo<R>(Func<Action<R>, R> call) { ... }

While pretty much the 'same', works:

static R Foo<R>(Func<Action, R> call) { ... }

Usage:

var i = Foo(ec => -1);

Ways the first sample 'must' be called to compile:

var i = Foo<int>(ec => -1);

-- or --

var i = Foo((Action<int> ec) => -1);

Thoughts: As can be seen in the second snippet, R is already determined by the return type of the 'lambda'. Why can't the same apply to the first? Even with usage of ec (which should be another compiler hint), it fails to infer.

like image 680
leppie Avatar asked Jun 04 '12 15:06

leppie


1 Answers

I think that the problem is not that the compiler if failing to infer R for the function CallWithEscapeContinuation, it is that it is failing to infer a type for the lambda:

ec =>
{
  Enumerable.Range(0, 100).Select(x =>
  {
              // Called here, the compiler has no idea what signature to expect for `ec`
              // Could be Action<Int>, could be Action<Decimal> (for example).
    if (x == 40) ec(x);
    return x;
  }).ToList();
  return -1;
}

Whereas when you provide the int hint, it can infer what type the lambda is from that and the signature of CallWithEscapeContinuation.

When you just have Action (as opposed to Action<R>) the above is irrelevant because there are no type parameters affecting the possible signatures of the lambda.

like image 54
Chris Shain Avatar answered Oct 23 '22 18:10

Chris Shain