View Issue Details

IDProjectCategoryView StatusLast Update
0034497FPCCompilerpublic2019-07-18 23:31
ReporterAkira1364Assigned To 
PrioritynormalSeverityminorReproducibilityalways
Status newResolutionopen 
Platformx86_64OSWindowsOS Version10
Product Version3.3.1Product Build40178 
Target VersionFixed in Version 
Summary0034497: Generic "advanced records" cannot have more than one of the same class operator overload if the parameters are fully generic
DescriptionThis is in contrast with non-operator generic member functions and procedures within generic advanced records, where it is no issue to declare two methods with the same name and the same number of parameters.

(As far as I can tell, the actual "overload" keyword has no effect on generics whatsoever in any case, also.)
Steps To ReproduceAttempt to compile the following program:

program Test;

{$mode ObjFPC}
{$modeswitch AdvancedRecords}

type
  generic TGenRec<T1, T2> = record
    A: T1;
    B: T2;
    function FuncA(const T: T1): T1;
    function FuncA(const T: T2): T2;
    class operator :=(constref Rec: TGenRec): T1;
    class operator :=(constref Rec: TGenRec): T2;
  end;

  function TGenRec.FuncA(const T: T1): T1;
  begin
    Result := T;
  end;

  function TGenRec.FuncA(const T: T2): T2;
  begin
    Result := T;
  end;

  class operator TGenRec.:=(constref Rec: TGenRec): T1;
  begin
    Result := Rec.A;
  end;

  class operator TGenRec.:=(constref Rec: TGenRec): T2;
  begin
    Result := Rec.B;
  end;

begin
end.

You should receive no less than five error messages:

Error: Function is already declared Public/Forward "operator :=(constref TGenRec$2):<undefined type>; Static;"

Error: overloaded functions have the same parameter list

Error: Found declaration: operator :=(constref TGenRec$2):<undefined type>; Static;

Error: function header doesn't match any method of this class "operator :=(constref TGenRec$2):<undefined type>; Static;"

Error: Found declaration: operator :=(constref TGenRec$2):<undefined type>; Static;

Meanwhile the compiler has no issue whatsoever with the dual declarations of "FuncA", neither of which have any concrete type parameters.
Tagsgenerics
Fixed in Revision
FPCOldBugId
FPCTarget
Attached Files

Activities

Thaddy de Koning

2018-11-02 09:18

reporter   ~0111742

With regard to your last remark:
https://freepascal.org/docs-html/ref/refse93.html
"If the overload keyword is not present, then all overloaded versions must reside in the same unit, and if it concerns methods part of a class, they must be in the same class, i.e. the compiler will not look for overloaded methods in parent classes if the overload keyword was not specified."

But indeed, it is reproducible for the operators.

Thaddy de Koning

2018-11-02 09:31

reporter   ~0111743

Last edited: 2018-11-02 09:33

View 3 revisions

Note that if you simplify the code without the operators and do something stupid, the correct error is thrown. It seems the token replay for operators differ from the token replay for methods:

{$mode ObjFPC}{$modeswitch AdvancedRecords}
type
  generic TGenRec<T1, T2> = record
    A: T1;
    B: T2;
    function FuncA(const T: T1): T1;
    function FuncA(const T: T2): T2;
  end;
  
  // this forces the overloads to be the same, which is not allowed.
  // the compiler catches this perfectly:
  // Error: Function is already declared Public/Forward "FuncA(const LongInt):LongInt;"
  // If T1 and T2 are of different types, the compiler allows this
  TMyRec = specialize TGenrec<integer,integer>;
  
  function TGenRec.FuncA(const T: T1): T1;
  begin
    Result := T;
  end;

  function TGenRec.FuncA(const T: T2): T2;
  begin
    Result := T;
  end;
begin
end.

Akira1364

2018-11-02 14:20

reporter   ~0111744

I'm aware that it will raise an error with types that are actually specialized to be the same thing, which is correct and expected. That's not really relevant here though.

The point in this case again is just that the the compiler is complaining about duplicate definitions specifically for operators before there's any specialization at all, which doesn't make sense.

Thaddy de Koning

2018-11-02 19:02

reporter   ~0111745

The point I was making is "It seems the token replay for operators differ from the token replay for methods" which was easiest to demonstrate like this.

Serge Anvarov

2018-11-02 19:08

reporter   ~0111746

Last edited: 2018-11-02 19:10

View 3 revisions

There are two different problems. First, the error in the FuncA declaration is already solved in the trunk. This compiles without problems in FPC 3.1.1:
[code]
{$MODE OBJFPC}
{$MODESWITCH ADVANCEDRECORDS}

type
  generic TGenRec<T1, T2> = record
    function FuncA(const T: T1): T1;
    function FuncA(const T: T2): T2;
  end;

  function TGenRec.FuncA(const T: T1): T1;
  begin
    Result := T;
  end;

  function TGenRec.FuncA(const T: T2): T2;
  begin
    Result := T;
  end;

begin
end.
[/code]

Second. FPC does not accept overloaded functions that differ only in the type of result. Even for operators. This compiles in Delphi, but not in FPC:
[code]
{$IFDEF FPC}{$MODE DELPHI}{$ENDIF}
type
  TGenRec<T1, T2> = record
    A: T1;
    B: T2;
    class operator Implicit(const Rec: TGenRec<T1, T2>): T1;
    class operator Implicit(const Rec: TGenRec<T1, T2>): T2;
  end;

  class operator TGenRec<T1, T2>.Implicit(const Rec: TGenRec<T1, T2>): T1;
  begin
    Result := Rec.A;
  end;

  class operator TGenRec<T1, T2>.Implicit(const Rec: TGenRec<T1, T2>): T2;
  begin
    Result := Rec.B;
  end;

begin
end.
[/code]

Akira1364

2018-11-02 23:42

reporter   ~0111749

Last edited: 2018-11-03 00:51

View 3 revisions

There's not two different problems in my example. The functions DO work, as I said. I am using trunk. The whole point was that they work, but the operators don't.

Issue History

Date Modified Username Field Change
2018-11-02 07:50 Akira1364 New Issue
2018-11-02 09:18 Thaddy de Koning Note Added: 0111742
2018-11-02 09:31 Thaddy de Koning Note Added: 0111743
2018-11-02 09:32 Thaddy de Koning Note Edited: 0111743 View Revisions
2018-11-02 09:33 Thaddy de Koning Note Edited: 0111743 View Revisions
2018-11-02 10:44 Cyrax Tag Attached: generics
2018-11-02 14:20 Akira1364 Note Added: 0111744
2018-11-02 19:02 Thaddy de Koning Note Added: 0111745
2018-11-02 19:08 Serge Anvarov Note Added: 0111746
2018-11-02 19:09 Serge Anvarov Note Edited: 0111746 View Revisions
2018-11-02 19:10 Serge Anvarov Note Edited: 0111746 View Revisions
2018-11-02 23:42 Akira1364 Note Added: 0111749
2018-11-03 00:51 Akira1364 Note Edited: 0111749 View Revisions
2018-11-03 00:51 Akira1364 Note Edited: 0111749 View Revisions