View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0022019FPCCompilerpublic2012-05-12 20:102013-09-26 09:38
ReporterAnthony Walter 
Assigned ToSven Barth 
PrioritynormalSeveritymajorReproducibilityalways
StatusresolvedResolutionduplicate 
PlatformLinuxOSUbuntuOS Version12.04
Product Version2.7.1Product Buildtrunk 
Target VersionFixed in Version 
Summary0022019: Cannot return generic derived class
DescriptionIt would seem there is a problem with the compiler when returning a generic class if the class is not specifically referenced elsewhere. See example in steps to reproduce as well as the attached example.

When the error occurs you will see a message like "Error: Forward declaration not solved"

The effect of this problem is that it's not current possible to derive from generic classes unless the derived class has a variable (reference) of it's specific type placed somewhere in the open.

I've encountered a few places where this problem creeps up. One place is in my generic TEnumerator<T> class where I attempt to return a TListEnumerator<T> from a overridden virtual "GetEnumerator: TEnumerator<T>" method. The code will not compile and I am left with the "Error: Forward declaration not solved" message referring to my TListEnumerator<T> methods.
Steps To ReproduceExample:

type TA<T> = class
public
  function Foo(Value: T): T; virtual; abstract;
end;

type TB<T> = class(TA<T>)
public
  // Error: Forward declaration not solved
  function Foo(Value: T): T; override;
end;

function TB<T>.Foo(Value: T): T;
begin
  Result := Value;
end;

type TC<T> = class
public
  function GetA: TA<T>;
end;

function TC<T>.GetA: TA<T>;
begin
  Result := TB<T>.Create;
end;

procedure Test;
var
  C: TC<String>;
  A: TA<String>;
  // Uncomment this one line below and the error goes away
  // B: TB<String>;
begin
  C := TC<String>.Create;
  A := C.GetA;
  A.Free;
  C.Free;
end;
Additional InformationThe problem can be demonstrated to not be "real" by adding a variable of the derived type somewhere. See "uncomment" section in steps to reproduce.
Tagsgenerics
FPCOldBugId
Fixed in Revision
Attached Files? file icon GenericVirtualTest.pas [^] (1,279 bytes) 2012-05-12 20:10

- Relationships
duplicate of 0021051resolvedSven Barth Problem when using nested generic class descendant in a generic class method 

-  Notes
(0059538)
Anthony Walter (reporter)
2012-05-12 20:14
edited on: 2012-05-12 23:43

Click "view advanced" at the top of this page to see the example with steps to reproduce. The example is referenced in my issue description.

Small edit:

It would seem that the workaround which is to declare variable references to all derived generic types (i.e. uncomment the lines in the examples) needs to be repeated for every pascal unit.

If GenericUnit.pas defines "TDerivedGeneric<T> = class(TBaseGeneric<T>)", then any unit which uses GenericUnit will have to create a its own reference to TDerivedGeneric<T>. This means you need to declare "var DummyDerivedGeneric: TDerivedGeneric<Integer>;" or something thereof again and again in every unit or the compiler will stop with "Error: Forward declaration not solved"

Another edit:

It seems the workaround also fails if the type parameters are different. If you place "var DummyDerivedGeneric: TDerivedGeneric<Integer>;" in your unit, but your actual derive generic is of type TDerivedGeneric<String>, then you'll get the same "Error: Forward declaration not solved" error. Currently to workaround you need a dummy type variable for every derived type multiplied by the number of type variables which you reference multiplied by the number of units using GenericUnit. In short, the workaround doesn't really work.

(0070136)
Peter-Jan Roes (reporter)
2013-09-17 13:19

I too encountered this problem with using generics in Delphi mode. Just like the original poster indicated the problem occurs when I try to return a generic enumerator from a generic collection class.

- Issue History
Date Modified Username Field Change
2012-05-12 20:10 Anthony Walter New Issue
2012-05-12 20:10 Anthony Walter File Added: GenericVirtualTest.pas
2012-05-12 20:10 Anthony Walter Tag Attached: generics
2012-05-12 20:14 Anthony Walter Note Added: 0059538
2012-05-12 20:22 Anthony Walter Note Edited: 0059538
2012-05-12 21:53 Anthony Walter Note Edited: 0059538
2012-05-12 21:54 Anthony Walter Note Edited: 0059538
2012-05-12 21:55 Anthony Walter Note Edited: 0059538
2012-05-12 23:43 Anthony Walter Note Edited: 0059538
2013-09-17 13:19 Peter-Jan Roes Note Added: 0070136
2013-09-23 12:11 Sven Barth Assigned To => Sven Barth
2013-09-23 12:11 Sven Barth Status new => assigned
2013-09-26 09:31 Sven Barth Relationship added duplicate of 0021051
2013-09-26 09:38 Sven Barth Status assigned => resolved
2013-09-26 09:38 Sven Barth Resolution open => duplicate



MantisBT 1.2.12[^]
Copyright © 2000 - 2012 MantisBT Group
Powered by Mantis Bugtracker