Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested generic record

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.

like image 433
Z.B. Avatar asked Apr 18 '18 08:04

Z.B.


1 Answers

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.

like image 196
David Heffernan Avatar answered Nov 06 '22 19:11

David Heffernan