| Anonymous | Login | Signup for a new account | 2013-05-23 14:28 CEST | ![]() |
| All Projects | FPC | Lazarus: Packages, Patches | Lazarus CCR | Mantis | fpGUI | fpcprojects: fpprofiler |
| Main | My View | View Issues | Change Log | Roadmap |
| View Issue Details [ Jump to Notes ] | [ Issue History ] [ Print ] | ||||||||||||
| ID | Project | Category | View Status | Date Submitted | Last Update | ||||||||
| 0022019 | FPC | Compiler | public | 2012-05-12 20:10 | 2012-05-12 20:14 | ||||||||
| Reporter | Anthony Walter | ||||||||||||
| Assigned To | |||||||||||||
| Priority | normal | Severity | major | Reproducibility | always | ||||||||
| Status | new | Resolution | open | ||||||||||
| Platform | Linux | OS | Ubuntu | OS Version | 12.04 | ||||||||
| Product Version | 2.7.1 | Product Build | trunk | ||||||||||
| Target Version | Fixed in Version | ||||||||||||
| Summary | 0022019: Cannot return generic derived class | ||||||||||||
| Description | It 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 Reproduce | Example: 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 Information | The problem can be demonstrated to not be "real" by adding a variable of the derived type somewhere. See "uncomment" section in steps to reproduce. | ||||||||||||
| Tags | generics | ||||||||||||
| FPCOldBugId | |||||||||||||
| Fixed in Revision | |||||||||||||
| Attached Files | |||||||||||||
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. |
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 | |
| Main | My View | View Issues | Change Log | Roadmap |



