Recent

Author Topic: Generics.Collections TDictionary issue  (Read 1525 times)

JdeHaan

  • Full Member
  • ***
  • Posts: 115
Generics.Collections TDictionary issue
« on: January 29, 2023, 12:32:24 pm »
Hi, I'm experiencing some inconsistencies with TDictionary. If I run the below program I would expect all written values to be TRUE but I get 1 FALSE. The result is both in ObjFpc and Delphi modes with ShortString as the key.

Code: Pascal  [Select][+][-]
  1. program dictionary;
  2.  
  3. {$mode delphi}
  4.  
  5. uses Generics.Collections;
  6.  
  7. var
  8.   Map: TDictionary<ShortString, Integer>;
  9.   s: ShortString;
  10.  
  11. begin
  12.   Map := TDictionary<ShortString, Integer>.Create;
  13.   Map.Add('one', 1);
  14.   Map.Add('two', 2);
  15.   Map.Add('three', 3);
  16.   Map.Add('four', 4);
  17.   Map.Add('five', 5);
  18.   Map.Add('six', 6);
  19.   Map.Add('seven', 7);
  20.   Map.Add('eight', 8);
  21.  
  22.   for s in Map.Keys do
  23.     writeln(s);
  24.  
  25.   writeln('one:   ', Map.ContainsKey('one'));
  26.   writeln('two:   ', Map.ContainsKey('two'));
  27.   writeln('three: ', Map.ContainsKey('three')); // <-- returns FALSE
  28.   writeln('four:  ', Map.ContainsKey('four'));
  29.   writeln('five:  ', Map.ContainsKey('five'));
  30.   writeln('six:   ', Map.ContainsKey('six'));
  31.   writeln('seven: ', Map.ContainsKey('seven'));
  32.   writeln('eight: ', Map.ContainsKey('eight'));
  33.  
  34.   Map.Free;
  35. end.
  36.  

Can anyone confirm this? Or has an explanation for this behaviour ?


MacOS Ventura 13.2
Lazarus 2.3.0 (rev main-2_3-3328-g448bb20ba6) FPC 3.3.1 x86_64-darwin-cocoa

TRon

  • Hero Member
  • *****
  • Posts: 2435
Re: Generics.Collections TDictionary issue
« Reply #1 on: January 29, 2023, 12:47:29 pm »
perhaps typo somewhere ?

Code: [Select]
./dictionary
two
five
six
seven
one
eight
three
four
one:   TRUE
two:   TRUE
three: TRUE
four:  TRUE
five:  TRUE
six:   TRUE
seven: TRUE
eight: TRUE


JdeHaan

  • Full Member
  • ***
  • Posts: 115
Re: Generics.Collections TDictionary issue
« Reply #2 on: January 29, 2023, 12:51:18 pm »
I used the program as is, so no typo's...

What OS are you using?

TRon

  • Hero Member
  • *****
  • Posts: 2435
Re: Generics.Collections TDictionary issue
« Reply #3 on: January 29, 2023, 12:53:41 pm »
Linux Debian bookwork (rolling) x86-64 bit. FPC 3.2.2 & 3.3.1.

make sure to do a rebuild: e.g. fpc -B dictionary.pas

edit: adjusted answer as I've just checked with fresh compiled trunk as well.
« Last Edit: January 29, 2023, 02:01:23 pm by TRon »

dseligo

  • Hero Member
  • *****
  • Posts: 1196
Re: Generics.Collections TDictionary issue
« Reply #4 on: January 29, 2023, 01:40:52 pm »
Works fine with Lazarus 2.2.4 and Windows 11.

Thaddy

  • Hero Member
  • *****
  • Posts: 14213
  • Probably until I exterminate Putin.
Re: Generics.Collections TDictionary issue
« Reply #5 on: January 29, 2023, 01:43:03 pm »
Same here with trunk, both linux debian bookworm and windows 10/11. Works OK.
Specialize a type, not a var.

JdeHaan

  • Full Member
  • ***
  • Posts: 115
Re: Generics.Collections TDictionary issue
« Reply #6 on: January 29, 2023, 02:33:14 pm »
Thanks all for testing.

If someone could also test it on MacOS Ventura (13.2), that would be appreciated...

Because it didn't happen before ( I just updated this week to Ventura 13.2 and also installed latest trunk of FPC).

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Generics.Collections TDictionary issue
« Reply #7 on: January 29, 2023, 03:13:06 pm »
IMHO, Generics.Collections looks broken at the moment. At least this simple test:
Code: Pascal  [Select][+][-]
  1. program test;
  2.  
  3. {$mode objfpc}{$h+}
  4.  
  5. uses
  6.   SysUtils, Generics.Collections, Generics.Defaults, Generics.Hashes;
  7.  
  8. type
  9.   TByte8 = array[0..7] of byte;
  10.   TByteMap = specialize TDictionary<TByte8, Integer>;
  11.  
  12. function EqualB8(const L, R: TByte8): Boolean;
  13. begin
  14.   Result := CompareByte(L, R, SizeOf(TByte8)) = 0;
  15. end;
  16.  
  17. function B8Hash(const aValue: TByte8): UInt32;
  18. begin
  19.   Result := xxHash32(0, @aValue, SizeOf(TByte8));
  20. end;
  21.  
  22. var
  23.   b8: TByte8 = (1,2,3,4,5,6,7,8);
  24.   Map: TByteMap;
  25. begin
  26.   Map := TByteMap.Create;
  27.   if Map.TryAdd(b8, 42) then
  28.     WriteLn('Ok, added');
  29.   if Map.ContainsKey(b8) then
  30.     WriteLn('Ok, contains')
  31.   else
  32.     WriteLn('No such key');
  33.   Map.Free;
  34.   /////////////////
  35.   WriteLn;
  36.   Map := TByteMap.Create(specialize TEqualityComparer<TByte8>.Construct(@EqualB8, @B8Hash));
  37.   if Map.TryAdd(b8, 42) then
  38.     WriteLn('Ok, added');
  39.   if Map.ContainsKey(b8) then
  40.     WriteLn('Ok, contains')
  41.   else
  42.     WriteLn('No such key');
  43.   Map.Free;
  44. end.
  45.  

produces the following result:
Code: Text  [Select][+][-]
  1. Ok, added
  2. No such key
  3.  
  4. Ok, added
  5. Ok, contains
  6.  

dseligo

  • Hero Member
  • *****
  • Posts: 1196
Re: Generics.Collections TDictionary issue
« Reply #8 on: January 29, 2023, 03:17:16 pm »
IMHO, Generics.Collections looks broken at the moment. At least this simple test:

This doesn't compile in Lazarus 2.2.4 (rev lazarus_2_2_4) FPC 3.2.2 x86_64-win64-win32/win64.
Code: Text  [Select][+][-]
  1. test2.lpr(36,90) Error: Incompatible type for arg no. 2: Got "<address of function(const TByte8):DWord;Register>", expected "<procedure variable type of function(constref TByte8):DWord;Register>"

TRon

  • Hero Member
  • *****
  • Posts: 2435
Re: Generics.Collections TDictionary issue
« Reply #9 on: January 29, 2023, 03:28:29 pm »
@deseligo:
compiles with trunk but with result as shown by avk.

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Generics.Collections TDictionary issue
« Reply #10 on: January 29, 2023, 03:30:12 pm »
I compiled with the current version of FPC-3.3.1. For FPC-3.2.2, it is required to replace the const modifier with constref.

TRon

  • Hero Member
  • *****
  • Posts: 2435
Re: Generics.Collections TDictionary issue
« Reply #11 on: January 29, 2023, 03:33:33 pm »
... and in which case the result differ (e.g. with 3.2.2 it seem to work as expected).

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Generics.Collections TDictionary issue
« Reply #12 on: January 29, 2023, 03:34:40 pm »
If I change to Delphi mode. it works. ( remove 2 times specialize and two @'s.

And then const is no problem either. It might be some problem with objfpc  64-bit mode signature mismatching a mode delphi const (which is a constref) somehow rather than generics.collections
 
It might be worth a bug report.
« Last Edit: January 29, 2023, 04:17:15 pm by marcov »

dseligo

  • Hero Member
  • *****
  • Posts: 1196
Re: Generics.Collections TDictionary issue
« Reply #13 on: January 29, 2023, 03:38:43 pm »
... and in which case the result differ (e.g. with 3.2.2 it seem to work as expected).

Yes, with 3.2.2 and constref it works:
Code: Text  [Select][+][-]
  1. Ok, added
  2. Ok, contains
  3.  
  4. Ok, added
  5. Ok, contains

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Generics.Collections TDictionary issue
« Reply #14 on: January 29, 2023, 06:37:29 pm »
...
It might be worth a bug report.

It seems a similar issue has already been reported in #40074.
« Last Edit: January 30, 2023, 09:39:22 am by avk »

 

TinyPortal © 2005-2018