5

I am using Delphi XE.

The following unit fails to compile with this error:

[DCC Error] GTSJSONSerializer.pas(27): E2506 Method of parameterized type declared 
   in interface section must not use 
   local symbol 'TSuperRttiContext.AsJson<GTSJSONSerializer.TGTSJSONSerializer<T>.T>'

Why is that? Is there a workaround?

unit GTSJSONSerializer;

interface

type
   TGTSJSONSerializer<T> = class
     class function SerializeObjectToJSON(const aObject: T): string;
     class function DeserializeJSONToObject(const aJSON: string): T;
   end;

implementation

uses
        SuperObject
      ;

class function TGTSJSONSerializer<T>.SerializeObjectToJSON(const aObject: T): string;
var
  SRC: TSuperRttiContext;
begin
  SRC := TSuperRttiContext.Create;
  try
    Result := SRC.AsJson<T>(aObject).AsString;
  finally
    SRC.Free;
  end;
end;

class function TGTSJSONSerializer<T>.DeserializeJSONToObject(const aJSON: string): T;
var
  LocalSO: ISuperObject;
  SRC: TSuperRttiContext;
begin
  SRC := TSuperRttiContext.Create;
  try
    LocalSO :=  SO(aJSON);
    Result := SRC.AsType<T>(LocalSO);
  finally
    SRC.Free;
  end;
end;

end.
Jan Doggen
  • 8,799
  • 13
  • 70
  • 144
Nick Hodges
  • 16,902
  • 11
  • 68
  • 130
  • Nick, can you mark the line causing the error with a comment? A count of lines puts it at the final `end;` in `SerialObjectToJSON` - is that where it actually happens? (I don't have `SuperObject` to compile with, so I can't tell for sure.) – Ken White Dec 02 '11 at 21:57
  • Ken -- THe error is placed at the end of the first method. – Nick Hodges Dec 03 '11 at 06:03
  • Yeah, that's what I counted - the final `end;` of the first method. That's why I thought it might be in `TSuperRTTIObject` somewhere, since there doesn't seem to b an issue with the code you posted. It might be one of those compiler errors that's reported slightly after the actual issue that caused ti. – Ken White Dec 03 '11 at 06:47
  • Nick, do you have any special code in your DPR file? I am seeing some weird behavior here, when using generics directly in the DPR. (In XE2) – Olaf Monien Dec 03 '11 at 21:21
  • Nick; Did you log this in QC? Seems like a compiler glitch. – Warren P Dec 04 '11 at 13:58

2 Answers2

4

From the XE2 DocWiki:

This happens when trying to assign a literal value to a generics data field.

program E2506;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TRec<T> = record
  public
    class var x: Integer;
    class constructor Create;
  end;

class constructor TRec<T>.Create;
begin
  x := 4; // <-- e2506 Fix: overload the Create method to 
          // take one parameter x and assign it to the x field.
end;

begin
   Writeln('E2506 Method of parameterized type declared' +
           ' in interface section must not use local symbol');
end.

I can't tell which of the local variables it might be objecting to, though; you have one local in SerialObjectToJSON and two in DeserializeJSONToObject. I'm also not sure based on the linked fix exactly how that applies to the code you posted. Could it be related to TSuperRTTIContext?

Ken White
  • 123,280
  • 14
  • 225
  • 444
  • Yeah, that is the thing -- I don't do that. I'll dig a little deeper into TSuperRTTIContext..... – Nick Hodges Dec 03 '11 at 04:15
  • I have run into this as well. Any ideas why the compiler doesn't want this? It would seem to me that initializing a class var in a class constructor is pretty valid and that a literal value is something that usually causes the least problems... – Marjan Venema Dec 03 '11 at 09:32
  • 1
    The above example from XE2's docs is apparently referring to some specific situation. The compiler ONLY complains about E2506 if you put the code as suggested right into the DPR file. Once you declare it in a "regular" pas file (as you normally would do) the code would compile perfectly fine. – Olaf Monien Dec 03 '11 at 20:43
  • An other note: Nick's issue is not about class constructors (as in the doc wiki example) anyway. As a side note, class constructors don't seem to work for me in X2 in the way they should. Even the "fixed" docwiki example (with an actual variable declared as "TRec") would not call the it's constructor. – Olaf Monien Dec 03 '11 at 21:18
  • @Olaf: To your first comment, apparently the compiler WILL complain even if the code is not directly in the DPR - ask Nick. :) To your second, you'd have to talk to Embarcadero about that; I don't work for them, and therefore can't help with the compiler internals. – Ken White Dec 03 '11 at 21:37
  • @KenWhite The docwiki example /does/ compile for me if I put it into its own unit (in XE2). I knew that you are not in EMBT, I was just surprised about my finding in XE2, as this used to work afaik. I am currently checking QC/RAID to see if this has been reported yet. – Olaf Monien Dec 04 '11 at 07:42
1

I can compile your unit with D2010, DXE and DXE2 against SuperObject revision 46.

Uwe Schuster
  • 863
  • 4
  • 7