Nested generic record
Asked Answered
S

1

10

I just faced a strange compiler error when trying to define nested generic record.

Nesting works fine with classes and interfaces, but not with records somehow.

type
  TRec<T> = record
    Value: T;
  end;

  TCls = class
  public
    Rec: TRec<TRec<Integer>>;
  end;

This is not compiled on Delphi Berlin 10.1.2 and also no luck on Tokyo 10.2.3. Is this a limitation of language or a compiler issue?

The error message is:

[dcc32 Error] Project1.dpr(22): E2564 Undefined type 'TRec<T>'

I just wanted once to nest the Spring.Nullable<> types and that did not work. After that I quickly reproduced that with a simple generic record.

Southsouthwest answered 18/4, 2018 at 8:17 Comment(11)
Is this working for you: TCls = class private type Trec1<T1> = record Value : T1; end; public Rec: TRec<TRec1<Integer>>; end;Bybee
@LURD: Nope. Same error.Southsouthwest
Hmm, at least it compiles in my Delphi 10.2 Tokyo update 2.Bybee
@LURD That does compile fine, in all Delphi versions. Pretty sure that asker didn't compile your code, and misread your comment. I also found that same workaround independently.Martinemartineau
@DavidHeffernan: program Project1; {$APPTYPE CONSOLE} {$R *.res} type TCls = class private type Trec1<T1> = record Value : T1; end; public Rec: TRec<TRec1<Integer>>; end; begin end. Error: [dcc32 Error] Project84.dpr(8): E2003 Undeclared identifier: 'TRec<>'Southsouthwest
on Berlin 10.1 update 2. 24.0.25048.9432.Southsouthwest
@Southsouthwest Well, you didn't define TRec did you! LURD is proposing the exact same workaround as can be found in my answer.Martinemartineau
Same on Tokyo 10.2 Update 3 (25.0.29899.2631)Southsouthwest
oh.. I see :) I just copied LURD code and tried and by error assumed it's the same issue. Excuse me both please.Southsouthwest
Does it work with an intermediate TRecInteger = TRec<Integer>; and later, in the class: Rec: TRec<TRecInteger>;? I can't test this (no Delphi here), but I guess it compiles. That is the first thing I would try.Bergren
No, that does not compile either. Not even using an intermediate TRecRecInteger = TRec<TRecInteger>; does, nor does making the class generic TCls<T> = class.Bergren
M
9

This is a compiler bug, and you should submit a bug report. Consider the following:

type
  TRec<T> = record
    Value: T;
  end;

var
  Rec: TRec<TRec<Integer>>; // compiles successfully
  RecArray: TArray<TRec<TRec<Integer>>>; // compiles successfully

procedure foo;
var
  Rec: TRec<TRec<Integer>>; // compiles successfully
begin
end;

type
  TContainingClass = class
    Rec: TRec<TRec<Integer>>; // E2564 Undefined type 'TRec<T>'
  end;

  TContainingRecord = record
    Rec: TRec<TRec<Integer>>; // E2564 Undefined type 'TRec<T>'
  end;

  TContainingObject = object
    Rec: TRec<TRec<Integer>>; // E2564 Undefined type 'TRec<T>'
  end;

The defect appears to arise when using the type inside an aggregate compound type.

It's somewhat lame, but this is the only workaround I can find:

type
  TRec<T> = record
    Value: T;
  end;

  TRecRec<T> = record
    Value: TRec<T>;
  end;

  TContainingClass = class
    Rec: TRecRec<Integer>;
  end;

But that's not going to be at all useful in any real world scenario.

Martinemartineau answered 18/4, 2018 at 9:4 Comment(10)
Let's hope Idera will fix this. Otherwise sometimes it can be nasty limitation to define each time you want to nest a separate record type. Thanks for your time, David.Southsouthwest
Idera won't, but perhaps Embarcadero will fix it. It is still Embarcadero Delphi.Bergren
Can't check this right now, but what if you have Unit1.TRec<Unit1.TRec<Integer>> as the type inside the class/record/object declaration (Assuming Unit1 is the unit name in which TRec is defined)?Bergren
@RudyVelthuis E2564 Undefined type 'TRec<T>'Martinemartineau
@Southsouthwest They won't fix it if it's not reported - please do or let me know and I do.Ventage
@David: thanks. That is indeed weird, or wrong, or a bug, depending on your POV.Bergren
@DavidHeffernan can you report that? As the licensing and login info is on the company management side and I have no access to quality portal.Southsouthwest
I don't think that is the case. You don't need licensing information to be able to submit a bug report.Martinemartineau
@Z.B.: everyone can report and everyone can access QP, if you have a (free) EDN login.Bergren
Reminds me of this problem. Emba seems to stumble frequently with self reference.Rattlesnake

© 2022 - 2024 — McMap. All rights reserved.