Due to an interesting code example, behind which Kim Madsen first suspected a possible bug in the Delphi compiler, I took a closer look at the calling behavior of overloaded methods that also contain generic type parameters. I was surprised by the possible bug since I use overloads with combinations of generic and non-generic methods in current projects without any obvious errors.
Here is a simplified version of Kim’s code:
TFoo = class(TObject)
public
function DoSomething(SomeObject: TValue): string; overload;
function DoSomething<T>(SomeObject: T): string; overload;
end;
TBar = class(TObject)
end;
//...
var Foo := TFoo.Create;
var Bar := TBar.Create;
Foo.DoSomething(Bar);
Which of the two possible variants of DoSomething should be called by Foo.DoSomething(Bar)?
At a first glance, I was inclined to say that the non-generic variant, i.e. function DoSomething(SomeObject: TValue): string; should be called, since after all no type parameter is specified and therefore the first variant matches best.
But in fact, the generic, second variant is called. I initially suspected „TValue“ of „blocking“ the overload resolution here, since TValue is actually an „artificial“ RTTI.driven type.
Stefan Glienke came up with the correct hint:
Generic parameters are actually optional and the type is automatically inferred by the type of the variable that is passed. This „type inference“ takes precedence over overload resolution and thus produces a better match than the „TValue“ method.
Type-inference of generic methods is documented here btw.
So the following code actually calls a generic implementation, although no type parameter is specified in the call:
function DoSomething<T>(SomeObject: T): string;
//...
Foo.DoSomething(Bar); //<T> is inferred from "Bar"
Here is a Gist with full code to try:
https://gist.github.com/omonien/24b9b4ba64d46bdfa478615e8e9b0ae6
Kim Madsen
17. Februar 2021 at 16:53There definitely is a bug.
It may be that type inference is being done (imo very incorrectly), but the compiler should have complained about ambiguity since there clearly are two matching methods that could be choosed.
I however will continue to claim that it is a bad decision to do type inference on generics since it suddenly becomes a complete hit and miss what method will be called when, potentially by simply including another unit (globals).
Didier Cabalé
21. Februar 2021 at 18:30hmm. that is one of those compiler subtleties