delphigenerics

Managed record in generic type produce compile time error "Type parameter 'T' must be non-nullable value type"


I'm trying to use a managed record as data type for a generic class having a record constraint.

The compiler complains: E2512 Type parameter 'T' must be non-nullable value type

I made a minimal reproducible example:

program GenericDemo;
{$APPTYPE CONSOLE}
{$R *.res}
uses
  System.SysUtils;

type
  TDataRec1 = record
      Data : Integer;
  end;

  TDataRec2 = record
      Data : Integer;
      class operator Initialize(out Dest : TDataRec2);
  end;

  TDataGen<T : record> = class

  end;

class operator TDataRec2.Initialize(out Dest : TDataRec2);
begin

end;

var
    X : TDataGen<TDataRec1>;    // <==== This is OK
    Y : TDataGen<TDataRec2>;    // <==== Error: "Type parameter 'T' must be non-nullable value type"
begin

end.

Compiler accept variable X declaration (classic record) but refuse the declaration for variable Y (Managed record).

I use Delphi 10.4 Version 27.0.38860.1461.

My question is: How can I use a managed record in a generic class?


Solution

  • Custom managed records are incompatible with the record constraint as of now.

    Since we don't have some formal language specification we can only guess if that is on purpose or an oversight.

    You can only make this code work by removing the record contraint and use GetTypeKind(T) to put some assert on the valid typekinds you want to handle - that however will allow compilation of bad types for T but give an error at runtime.