Skip to content

generics with forward and circlular-reference fail to compile "identifier" expected but ";" found (syntax is correct though)

3.3.1 9236829a

Below code fails to compile, but only if TFoo.F swaps the order of generic-param.

It compiles fine, if

  • both the specialize are commented
  • TBar replaces "F" with the commented "F"
program Project1;
{$Mode objfpc}
type

  generic TBar<A,B> = class; // forward   // LINE 5

  generic TFoo<A, B> = class
    F:specialize TBar<A,B>;
    X:B;
  end;      // LINE 10

  generic TBar<A, B> = class
    F:specialize TFoo<B,A>;
    //F:specialize TFoo<A,B>;
    X:B;
  end;

  //x1 = specialize TBar<Byte, Boolean>;  // project1.lpr(5,28) Fatal: Syntax error, "identifier" expected but ";" found
  //x2 = specialize TFoo<Byte, Boolean>; // project1.lpr(10,6) Fatal: Syntax error, "identifier" expected but ";" found

begin

end. 

Note, the code (if it would go past the error) does not require an endless recursion. The 2nd time round, the "swap" goes back to the original order, that was already specialized.
Also like in other circular declarations, in the interface part it only needs to know its a class type. During implementation, it should then already have the full interface declaration.

Like with non generics, `TFoo` can't (i.e., is not expected to be able to) refer to the inside of TBar in its interface. (Click to expand) E.g. nested types (but same for any other ref) ```pascal program Project1; {$Mode objfpc} type TFoo = class;

TBar = class X: TFoo; private type Y = TFoo.Z end;

TFoo = class private type Z = integer; end;

begin

end.

</details>
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information