Reputation: 703
The code below relies pretty heavily on generics, and I think exposes a bug in the generics handling. But maybe there is simply something I don't understand.
The compiler raises the error:
E2531 Method 'CreateBaseItem' requires explicit type arguments
on the line:
foo3 := TFactory.CreateBaseItem<TDescendentFunctionsGroup2.Select>;
yet as far as I can tell, instantiating foo1
through foo4
should all be essentially identical. This complete program highlights the issue:
program SO53568763;
type
TBaseItem = class(TInterfacedObject);
IListableItem<T> = interface
['{6FD07ACB-04BB-4BFC-A38C-9B98F86DBC25}']
end;
TSomeDescendent = class(TBaseItem, IListableItem<TSomeDescendent>)
end;
TSelectFunctionsGenerator<T: TBaseItem, IListableItem<T>> = class(TBaseItem)
end;
TFunctionsGroup<T: TBaseItem, IListableItem<T>> = class
public
type
Select = TSelectFunctionsGenerator<T>;
end;
TDescendentFunctionsGroup1 = class(TFunctionsGroup<TSomeDescendent>);
TDescendentFunctionsGroup2 = TFunctionsGroup<TSomeDescendent>;
TFactory = class
public
class function CreateBaseItem<T: TBaseItem>: T;
end;
class function TFactory.CreateBaseItem<T>;
begin
end;
procedure Foo;
var
foo: TSelectFunctionsGenerator<TSomeDescendent>;
foo1: TFunctionsGroup<TSomeDescendent>.Select;
foo2: TDescendentFunctionsGroup1.Select;
foo3: TDescendentFunctionsGroup2.Select;
begin
foo := TFactory.CreateBaseItem<TSelectFunctionsGenerator<TSomeDescendent>>;
foo1 := TFactory.CreateBaseItem<TFunctionsGroup<TSomeDescendent>.Select>;
foo2 := TFactory.CreateBaseItem<TDescendentFunctionsGroup1.Select>;
foo3 := TFactory.CreateBaseItem<TDescendentFunctionsGroup2.Select>;
end;
begin
end.
It is strange that TDescendentFunctionsGroup2.Select
is explicit enough to declare a variable of that type, but not explicit enough to use as the generic argument to CreateBaseItem
.
Upvotes: 1
Views: 1732
Reputation: 612963
This does appear to be a compiler bug. The difference between TDescendentFunctionsGroup1
and TDescendentFunctionsGroup2
is that the former is a new class derived from TFunctionsGroup<TSomeDescendent>
and the latter is an alias to TFunctionsGroup<TSomeDescendent>
.
So my guess is that the parser or compiler has an issue with aliases to generic types.
I'm really not sure what benefit the alias gives you, in any case, so I'd simply write it like this:
var
foo3: TFunctionsGroup<TSomeDescendent>.Select;
...
foo3 := TFactory.CreateBaseItem<TFunctionsGroup<TSomeDescendent>.Select>;
Upvotes: 3