View Issue Details

IDProjectCategoryView StatusLast Update
0036285FPCCompilerpublic2019-11-11 12:15
ReporterRyan JosephAssigned To 
PrioritynormalSeverityminorReproducibilityalways
Status newResolutionopen 
Product Version3.3.1Product Build 
Target VersionFixed in Version 
Summary0036285: "Minus" class operator can't determine which overloaded function to call
DescriptionRunning the following program gives an error "Can't determine which overloaded function to call". From Sven: "Fixing it leads to some compilation problems in Generics.Collections that need to be solved as well."
Steps To Reproduce{$mode objfpc}
{$modeswitch advancedrecords}

program generic_vector;
uses
 Math;

type
 generic TVec2<TScalar> = record
   x, y: TScalar;
   function Magnitude: TScalar;
   function Distance (vec: TVec2): TScalar;
   class operator - (left, right: TVec2): TVec2;
   class operator - (left: TVec2; right: TScalar): TVec2;
 end;
 TVec2f = specialize TVec2<Float>;
 TVec2i = specialize TVec2<Integer>;

function TVec2.Magnitude: TScalar;
begin
 result := (x ** 2) + (y ** 2);
end;

function TVec2.Distance (vec: TVec2): TScalar;
begin
 // ----->>> ERROR: Can't determine which overloaded function to call
 result := (self - vec).Magnitude;
end;

class operator TVec2.- (left, right: TVec2): TVec2;
begin
 result.x := left.x - right.x;
 result.y := left.y - right.y;
end;

class operator TVec2.- (left: TVec2; right: TScalar): TVec2;
begin
 result.x := left.x - right;
 result.y := left.y - right;
end;

begin
end.
TagsNo tags attached.
Fixed in Revision
FPCOldBugId
FPCTarget
Attached Files
  • 33939_36285_htypechk.pas.patch (2,220 bytes)
    Index: compiler/htypechk.pas
    ===================================================================
    --- compiler/htypechk.pas	(revision 43438)
    +++ compiler/htypechk.pas	(working copy)
    @@ -52,6 +52,7 @@
              data         : tprocdef;
              wrongparaidx,
              firstparaidx : integer;
    +         exact_count_noconst,
              exact_count,
              equal_count,
              cl1_count,
    @@ -2864,6 +2865,7 @@
             rfh,rth  : double;
             obj_from,
             obj_to   : tobjectdef;
    +        def_to_gen,
             def_from,
             def_to   : tdef;
             currpt,
    @@ -2910,6 +2912,7 @@
                   eq:=te_incompatible;
                   def_from:=currpt.resultdef;
                   def_to:=currpara.vardef;
    +              def_to_gen:=def_to;
                   if not(assigned(def_from)) then
                    internalerror(200212091);
                   if not(
    @@ -3123,7 +3126,17 @@
                   { increase correct counter }
                   case eq of
                     te_exact :
    +                 begin
                       inc(hp^.exact_count);
    +                  if not is_constnode(currpt.left) then
    +                   begin
    +                    { no constant }
    +                    inc(hp^.exact_count_noconst);
    +                    { generic }
    +                    if (currpt.left.nodetype=loadn) and tstoreddef(def_to_gen).is_generic and tstoreddef(currpt.left.resultdef).is_generic then
    +                     inc(hp^.exact_count_noconst);
    +                   end;
    +                 end;
                     te_equal :
                       inc(hp^.equal_count);
                     te_convert_l1 :
    @@ -3263,6 +3276,10 @@
                res:=(bestpd^.coper_count-currpd^.coper_count);
                if (res=0) then
                 begin
    +             { more no constant exact count? }
    +             res:=(currpd^.exact_count_noconst-bestpd^.exact_count_noconst);
    +             if (res=0) then
    +             begin
                  { less cl6 parameters? }
                  res:=(bestpd^.cl6_count-currpd^.cl6_count);
                  if (res=0) then
    @@ -3311,6 +3328,7 @@
                        end;
                      end;
                   end;
    +              end;
                 end;
              end;
             is_better_candidate:=res;
    
  • 33939_36285_v2_htypechk.pas.patch (2,426 bytes)
    Index: compiler/htypechk.pas
    ===================================================================
    --- compiler/htypechk.pas	(revision 43449)
    +++ compiler/htypechk.pas	(working copy)
    @@ -52,6 +52,8 @@
              data         : tprocdef;
              wrongparaidx,
              firstparaidx : integer;
    +         exact_count_gen,
    +         exact_count_noconst,
              exact_count,
              equal_count,
              cl1_count,
    @@ -2864,6 +2866,7 @@
             rfh,rth  : double;
             obj_from,
             obj_to   : tobjectdef;
    +        def_to_gen,
             def_from,
             def_to   : tdef;
             currpt,
    @@ -2910,6 +2913,7 @@
                   eq:=te_incompatible;
                   def_from:=currpt.resultdef;
                   def_to:=currpara.vardef;
    +              def_to_gen:=def_to;
                   if not(assigned(def_from)) then
                    internalerror(200212091);
                   if not(
    @@ -3123,7 +3127,17 @@
                   { increase correct counter }
                   case eq of
                     te_exact :
    +                 begin
                       inc(hp^.exact_count);
    +                  if not is_constnode(currpt.left) then
    +                   begin
    +                    { no constant }
    +                    inc(hp^.exact_count_noconst);
    +                    { generic }
    +                    if (currpt.left.nodetype=loadn) and tstoreddef(def_to_gen).is_generic and tstoreddef(currpt.left.resultdef).is_generic then
    +                     inc(hp^.exact_count_gen);
    +                   end;
    +                 end;
                     te_equal :
                       inc(hp^.equal_count);
                     te_convert_l1 :
    @@ -3263,6 +3277,14 @@
                res:=(bestpd^.coper_count-currpd^.coper_count);
                if (res=0) then
                 begin
    +             { more generic exact count }
    +             res:=(currpd^.exact_count_gen-bestpd^.exact_count_gen);
    +             if (res=0) then
    +             begin
    +             { more no constant exact count? }
    +             res:=(currpd^.exact_count_noconst-bestpd^.exact_count_noconst);
    +             if (res=0) then
    +             begin
                  { less cl6 parameters? }
                  res:=(bestpd^.cl6_count-currpd^.cl6_count);
                  if (res=0) then
    @@ -3311,6 +3333,8 @@
                        end;
                      end;
                   end;
    +              end;
    +              end;
                 end;
              end;
             is_better_candidate:=res;
    

Activities

Do-wan Kim

2019-11-11 01:21

reporter   ~0119207

Tweak for fix. It has no compile error.

33939_36285_htypechk.pas.patch (2,220 bytes)
Index: compiler/htypechk.pas
===================================================================
--- compiler/htypechk.pas	(revision 43438)
+++ compiler/htypechk.pas	(working copy)
@@ -52,6 +52,7 @@
          data         : tprocdef;
          wrongparaidx,
          firstparaidx : integer;
+         exact_count_noconst,
          exact_count,
          equal_count,
          cl1_count,
@@ -2864,6 +2865,7 @@
         rfh,rth  : double;
         obj_from,
         obj_to   : tobjectdef;
+        def_to_gen,
         def_from,
         def_to   : tdef;
         currpt,
@@ -2910,6 +2912,7 @@
               eq:=te_incompatible;
               def_from:=currpt.resultdef;
               def_to:=currpara.vardef;
+              def_to_gen:=def_to;
               if not(assigned(def_from)) then
                internalerror(200212091);
               if not(
@@ -3123,7 +3126,17 @@
               { increase correct counter }
               case eq of
                 te_exact :
+                 begin
                   inc(hp^.exact_count);
+                  if not is_constnode(currpt.left) then
+                   begin
+                    { no constant }
+                    inc(hp^.exact_count_noconst);
+                    { generic }
+                    if (currpt.left.nodetype=loadn) and tstoreddef(def_to_gen).is_generic and tstoreddef(currpt.left.resultdef).is_generic then
+                     inc(hp^.exact_count_noconst);
+                   end;
+                 end;
                 te_equal :
                   inc(hp^.equal_count);
                 te_convert_l1 :
@@ -3263,6 +3276,10 @@
            res:=(bestpd^.coper_count-currpd^.coper_count);
            if (res=0) then
             begin
+             { more no constant exact count? }
+             res:=(currpd^.exact_count_noconst-bestpd^.exact_count_noconst);
+             if (res=0) then
+             begin
              { less cl6 parameters? }
              res:=(bestpd^.cl6_count-currpd^.cl6_count);
              if (res=0) then
@@ -3311,6 +3328,7 @@
                    end;
                  end;
               end;
+              end;
             end;
          end;
         is_better_candidate:=res;

Ryan Joseph

2019-11-11 01:30

reporter   ~0119208

Did you read above? "Fixing it leads to some compilation problems in Generics.Collections that need to be solved as well." Is that true?

Do-wan Kim

2019-11-11 01:55

reporter   ~0119209

Last edited: 2019-11-11 05:32

View 3 revisions

I compiled whole fpc trunk r43449 using fpclazup. fpc i386-win32 and fpc cross x86_64-win64 has no problem.

Thaddy de Koning

2019-11-11 07:13

reporter   ~0119214

I think Sven implies that the tests for rtl-generics should pass. Did you check that?

Do-wan Kim

2019-11-11 08:10

reporter   ~0119215

I don't know about tests. It only add counting code about exact non-constant and generic parameters. I guess it has less side effects.

Do-wan Kim

2019-11-11 08:35

reporter   ~0119216

Split checking non constant and generics parameter count in new patch.

33939_36285_v2_htypechk.pas.patch (2,426 bytes)
Index: compiler/htypechk.pas
===================================================================
--- compiler/htypechk.pas	(revision 43449)
+++ compiler/htypechk.pas	(working copy)
@@ -52,6 +52,8 @@
          data         : tprocdef;
          wrongparaidx,
          firstparaidx : integer;
+         exact_count_gen,
+         exact_count_noconst,
          exact_count,
          equal_count,
          cl1_count,
@@ -2864,6 +2866,7 @@
         rfh,rth  : double;
         obj_from,
         obj_to   : tobjectdef;
+        def_to_gen,
         def_from,
         def_to   : tdef;
         currpt,
@@ -2910,6 +2913,7 @@
               eq:=te_incompatible;
               def_from:=currpt.resultdef;
               def_to:=currpara.vardef;
+              def_to_gen:=def_to;
               if not(assigned(def_from)) then
                internalerror(200212091);
               if not(
@@ -3123,7 +3127,17 @@
               { increase correct counter }
               case eq of
                 te_exact :
+                 begin
                   inc(hp^.exact_count);
+                  if not is_constnode(currpt.left) then
+                   begin
+                    { no constant }
+                    inc(hp^.exact_count_noconst);
+                    { generic }
+                    if (currpt.left.nodetype=loadn) and tstoreddef(def_to_gen).is_generic and tstoreddef(currpt.left.resultdef).is_generic then
+                     inc(hp^.exact_count_gen);
+                   end;
+                 end;
                 te_equal :
                   inc(hp^.equal_count);
                 te_convert_l1 :
@@ -3263,6 +3277,14 @@
            res:=(bestpd^.coper_count-currpd^.coper_count);
            if (res=0) then
             begin
+             { more generic exact count }
+             res:=(currpd^.exact_count_gen-bestpd^.exact_count_gen);
+             if (res=0) then
+             begin
+             { more no constant exact count? }
+             res:=(currpd^.exact_count_noconst-bestpd^.exact_count_noconst);
+             if (res=0) then
+             begin
              { less cl6 parameters? }
              res:=(bestpd^.cl6_count-currpd^.cl6_count);
              if (res=0) then
@@ -3311,6 +3333,8 @@
                    end;
                  end;
               end;
+              end;
+              end;
             end;
          end;
         is_better_candidate:=res;

Thaddy de Koning

2019-11-11 09:50

reporter   ~0119218

Tests here should all work /fpc331/packages/rtl-generics/tests

Do-wan Kim

2019-11-11 10:42

reporter   ~0119219

Test result is all ok.

 Time:01.391 N:57 E:0 F:0 I:0
  TTestBugs Time:00.000 N:2 E:0 F:0 I:0
    00.000 Test_QuadraticProbing_InfinityLoop
    00.000 Test_GetEqualityComparer
  TTestHashMaps Time:00.002 N:20 E:0 F:0 I:0
    00.000 Test_CountAsKey_OpenAddressingLP
    00.000 Test_CountAsKey_OpenAddressingLPT
    00.000 Test_CountAsKey_OpenAddressingQP
    00.000 Test_CountAsKey_OpenAddressingDH
    00.000 Test_CountAsKey_CuckooD2
    00.000 Test_CountAsKey_CuckooD4
    00.000 Test_CountAsKey_CuckooD6
    00.001 Test_OpenAddressingLP_Notification
    00.000 Test_OpenAddressingLPT_Notification
    00.000 Test_OpenAddressingQP_Notification
    00.000 Test_OpenAddressingDH_Notification
    00.000 Test_CuckooD2_Notification
    00.000 Test_CuckooD4_Notification
    00.000 Test_CuckooD6_Notification
    00.001 Test_OpenAddressingLP_TrimExcess
    00.000 Test_CuckooD2_TrimExcess
    00.000 Test_ObjectDictionary
    00.000 Test_TryAddOrSetOrGetValue
    00.000 Test_TryGetValueEmpty_xxHash32
    00.000 Test_TryGetValueEmpty_xxHash32Pascal
  TTestArrayHelper Time:00.000 N:2 E:0 F:0 I:0
    00.000 Test_BinarySearch_Integers
    00.000 Test_BinarySearch_EmptyArray
  TTestTrees Time:01.388 N:5 E:0 F:0 I:0
    00.722 Test_IndexedAVLTree_Add_General
    00.000 Test_IndexedAVLTree_Add
    00.666 Test_IndexedAVLTree_Delete
    00.000 Test_IndexedAVLTree_Items
    00.000 Test_TAVLTreeMap_Notification
  TTestStdCollections Time:00.000 N:19 E:0 F:0 I:0
    00.000 Test_TList_Notification
    00.000 Test_List
    00.000 Test_FreeingManually
    00.000 Test_AddingLists
    00.000 Test_Sort
    00.000 Test_Pack
    00.000 Test_RecordsList
    00.000 Test_VectorsList
    00.000 Test_MethodsList
    00.000 Test_SortedList
    00.000 Test_Queue
    00.000 Test_GenericListBox
    00.000 Test_TSortedList_Notification
    00.000 Test_TQueue_Notification
    00.000 Test_TStack_Notification
    00.000 Test_TObjectList_Notification
    00.000 Test_TObjectQueue_Notification
    00.000 Test_TObjectStack_Notification
    00.000 Test_TrimExcess
  TTestSets Time:00.001 N:9 E:0 F:0 I:0
    00.000 Test_HashSet_General
    00.000 Test_SortedSet_General
    00.000 Test_SortedHashSet_General
    00.000 Test_HashSet
    00.000 Test_SortedSet
    00.000 Test_SortedHashSet
    00.001 Test_THashSet_Notification
    00.000 Test_TSortedSet_Notification
    00.000 Test_TSortedHashSet_Notification

Number of run tests: 57
Number of errors: 0
Number of failures: 0

Thaddy de Koning

2019-11-11 11:31

reporter   ~0119220

Last edited: 2019-11-11 11:31

View 2 revisions

I have the same results, suggest to ping Sven on the mailing list for comments. Looks all OK. (used last patch.)

Sven Barth

2019-11-11 12:15

manager   ~0119222

That patch fixes the symptom, not the cause.

Issue History

Date Modified Username Field Change
2019-11-09 20:28 Ryan Joseph New Issue
2019-11-11 01:21 Do-wan Kim File Added: 33939_36285_htypechk.pas.patch
2019-11-11 01:21 Do-wan Kim Note Added: 0119207
2019-11-11 01:30 Ryan Joseph Note Added: 0119208
2019-11-11 01:55 Do-wan Kim Note Added: 0119209
2019-11-11 01:56 Do-wan Kim Note Edited: 0119209 View Revisions
2019-11-11 05:32 Do-wan Kim Note Edited: 0119209 View Revisions
2019-11-11 07:13 Thaddy de Koning Note Added: 0119214
2019-11-11 08:10 Do-wan Kim Note Added: 0119215
2019-11-11 08:35 Do-wan Kim File Added: 33939_36285_v2_htypechk.pas.patch
2019-11-11 08:35 Do-wan Kim Note Added: 0119216
2019-11-11 09:50 Thaddy de Koning Note Added: 0119218
2019-11-11 10:42 Do-wan Kim Note Added: 0119219
2019-11-11 11:31 Thaddy de Koning Note Added: 0119220
2019-11-11 11:31 Thaddy de Koning Note Edited: 0119220 View Revisions
2019-11-11 12:15 Sven Barth Note Added: 0119222