Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Delphi unable to infer the type for a parameter TEnumerable<T>?

Consider the following declaration of a generic utility class in Delphi 2010:

TEnumerableUtils = class
public
  class function InferenceTest<T>(Param: T): T;
  class function Count<T>(Enumerable: TEnumerable<T>): Integer; overload;
  class function Count<T>(Enumerable: TEnumerable<T>; Filter: TPredicate<T>): Integer; overload;
end;

Somehow the compiler type inference seems to have problems here:

var
  I: Integer;
  L: TList<Integer>;
begin
  TEnumerableUtils.InferenceTest(I);  // no problem here
  TEnumerableUtils.Count(L);          // does not compile: E2250 There is no overloaded version of 'Count' that can be called with these arguments
  TEnumerableUtils.Count<Integer>(L); // compiles fine
end;

The first call works as expected and T is correctly inferred as Integer.

The second call does not work, unless I also add <Integer> -- then it works, as can be seen in the third call. Am I doing something wrong or is the type inference in Delphi just not supporting this (I don't think it is a problem in Java which is why expected it to work in Delphi, too).

like image 880
Werner Lehmann Avatar asked Apr 25 '10 23:04

Werner Lehmann


1 Answers

The compiler would need to do pattern matching to infer parameter types; it currently does not. The compiler is limited to quite simple inference - if the parameter type is of a type parameter type, then the compiler can figure it out, but not much beyond that.

The argument type in your example is not a simple type parameter, but is rather a constructed generic type (it's constructed with the method's type parameter T, but it is constructed none the less). The compiler needs to make two inferences in order to find out the value of T. First, it needs to see that the constructed type's generic type is an ancestor of TList<T>'s generic type; and it also needs to match the type parameter T in the constructed type's type parameter list with the concrete type Integer in TList<T>'s ancestor.

like image 191
Barry Kelly Avatar answered Sep 20 '22 05:09

Barry Kelly