[fpc-devel] Inconsistency in generics ?

Martin Frb lazarus at mfriebe.de
Fri Mar 3 12:55:49 CET 2023


To me the below behaviour appears inconsistent.
But before I file a bug, I want to double check, if maybe this is 
intention....

Tested with 3.2.3  and 3.3.1

Apparently
- when the generic TGen is compiled, it does check if a type "TRec1" and 
"TRec2" is in scope at all.
- it verifies that the generic itself compiles with that type
- **but** then it allows that type to be replaced by another, if the 
specialized param contains such another type

So if the specialized class, can have a type of it's own choosing for 
"TRec1" then why insist that a random other type of that name exists 
when the generic is declared.
(And why reject "TRec2" as it too could be available at the time of 
specialization?)

Or should the specialized class "TClass1" use the global TRec1? and 
ignore TBase2.TRec1 ?


program testgen;
{$mode objfpc}{$H+}
type
   TRec1 = record r1: integer; end; // this will be used to check the 
generic itself

   TBase1 = class
   end;

   { TBase2 }

   TBase2 = class(TBase1)
   public type
     TRec1 = record r1_b2: integer; end; // this will be used in specialize
     TRec2 = record r2_b2: integer; end;
   end;

   generic TGen<B: TBase1> = class(B)
     f1: Trec1;  // here TBase2.Rec is not known
     //f2: Trec2;  //  Error: Identifier not found "Trec2"
     procedure x;
   end;

   TClass1 = class(specialize TGen<TBase2>)
     procedure Bar;
   end;

procedure TGen.x; // neither works...
begin
   //f1.r1 := 2;  // fails when specialized
   //f1.r1_b2 := 2;  // fails for the generic
end;

procedure TClass1.Bar;
begin
   f1.r1_b2 := 1; // This is TBase2.Rec, and compiles with 3.2.3  and 3.3.1
end;

begin
end.


More information about the fpc-devel mailing list