Recent

Author Topic: Problem with Generics.Defaults / Compiler message  (Read 1599 times)

Grahame Grieve

  • Sr. Member
  • ****
  • Posts: 365
Problem with Generics.Defaults / Compiler message
« on: November 18, 2022, 11:02:19 am »
I'm compiling code. When I'm building everything, I get an error compiling:

generics.defaults.pas(1051,43) Error: No type info available for this type

I recompile, and it compiles this time. Then, clean up and build, and I'll be back there. So there's some compiler bug here. But: what's the actual problem? I can't tell, because I don't know what the type is. Just "T". What was it actually compiling when the error happens? I don't know; it's some other unit, but I don't know which one, nor which type T is that leads to this problem.

Should the error message say what the type is explicitly? I'd *really* like that, because other times, I've spent ages trying to figure out what the problem is, and it turns out I was looking at the wrong type because of scope issues. Or have I missed something and this has an obvious solution?

Version: Lazarus 2.2.5 (rev lazarus_2_2_4-3-g564e1e8244) FPC 3.2.2 aarch64-darwin-cocoa

Thaddy

  • Hero Member
  • *****
  • Posts: 14393
  • Sensorship about opinions does not belong here.
Re: Problem with Generics.Defaults / Compiler message
« Reply #1 on: November 18, 2022, 11:50:03 am »
That error is a bit strange given the documentation of TypeInfo : https://www.freepascal.org/docs-html/rtl/system/typeinfo.html states that the result is always non-nil.
Anyway, I'd still like to see what T is specialized to , because un-specialized T itself does of course never have type info, only the specialization can have type info.
Am I right it sometimes works and sometimes not? In that case some example code will help.

Maybe @PascalDragon can shed some light on it?
« Last Edit: November 18, 2022, 11:56:59 am by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

Grahame Grieve

  • Sr. Member
  • ****
  • Posts: 365
Re: Problem with Generics.Defaults / Compiler message
« Reply #2 on: November 18, 2022, 12:53:36 pm »
well, the thing is, I'm not sure how to create sample code, because my immediate problem is: I don''t know what code is compiling at that point, and that's my real question. It's a List<Something> but I don't know how to figure out which something - there's no clue in the compiler output

Thaddy

  • Hero Member
  • *****
  • Posts: 14393
  • Sensorship about opinions does not belong here.
Re: Problem with Generics.Defaults / Compiler message
« Reply #3 on: November 18, 2022, 01:03:09 pm »
Code: Pascal  [Select][+][-]
  1. Type
  2.   TMySomethingList = Tlist<something>;// from here Tsomethinglist has type info...
  3.  
  4. var
  5.   SomethingList:TMySomethingList;// from here somethinglist  can be queried for type info...
  6. begin
  7. end.
You should look for the specialization, given something is a valid something ;) and not T
« Last Edit: November 18, 2022, 01:04:58 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5486
  • Compiler Developer
Re: Problem with Generics.Defaults / Compiler message
« Reply #4 on: November 20, 2022, 03:36:08 pm »
well, the thing is, I'm not sure how to create sample code, because my immediate problem is: I don''t know what code is compiling at that point, and that's my real question. It's a List<Something> but I don't know how to figure out which something - there's no clue in the compiler output

Do you by any chance specialize somewhere with an enumeration type that has holes between values or does not start with 0? Cause that's the only case where this error message is triggered.

Grahame Grieve

  • Sr. Member
  • ****
  • Posts: 365
Re: Problem with Generics.Defaults / Compiler message
« Reply #5 on: November 21, 2022, 06:22:09 am »

Thaddy

  • Hero Member
  • *****
  • Posts: 14393
  • Sensorship about opinions does not belong here.
Re: Problem with Generics.Defaults / Compiler message
« Reply #6 on: November 21, 2022, 09:26:38 am »
It's not my code, but it's forked so I can change it. But this is valid code, isn't it?
Change the enum into constants should fix the error. In your enum there are holes, and for the holes there is no type info, only for the named enum members. The specialization needs proper type info. Your code is correct for non-generic applications. For generics you can do E.g.:
Code: Pascal  [Select][+][-]
  1. type
  2.   TBarcodeFormat = type integer;
  3.  
  4. const
  5.     /// <summary>No format set. All formats will be used</summary>
  6.     Auto = 0;
  7.  
  8.     /// <summary>Aztec 2D barcode format.</summary>
  9.     AZTEC = 1;
  10.  
  11.     /// <summary>CODABAR 1D format.</summary>
  12.     CODABAR = 2;
  13.  
  14.     /// <summary>Code 39 1D format.</summary>
  15.     CODE_39 = 4;
  16.  
  17.     /// <summary>Code 93 1D format.</summary>
  18.     CODE_93 = 8;
  19.  
  20.     /// <summary>Code 128 1D format.</summary>
  21.     CODE_128 = 16;
  22.  
  23.     /// <summary>Data Matrix 2D barcode format.</summary>
  24.     DATA_MATRIX = 32;
  25.  
  26.     /// <summary>EAN-8 1D format.</summary>
  27.     EAN_8 = 64;
  28.  
  29.     /// <summary>EAN-13 1D format.</summary>
  30.     EAN_13 = 128;
  31.  
  32.     /// <summary>ITF (Interleaved Two of Five) 1D format.</summary>
  33.     ITF = 256;
  34.  
  35.     /// <summary>MaxiCode 2D barcode format.</summary>
  36.     MAXICODE = 512;
  37.  
  38.     /// <summary>PDF417 format.</summary>
  39.     PDF_417 = 1024;
  40.  
  41.     /// <summary>QR Code 2D barcode format.</summary>
  42.     QR_CODE = 2048;
  43.  
  44.     /// <summary>RSS 14</summary>
  45.     RSS_14 = 4096;
  46.  
  47.     /// <summary>RSS EXPANDED</summary>
  48.     RSS_EXPANDED = 8192;
  49.  
  50.     /// <summary>UPC-A 1D format.</summary>
  51.     UPC_A = 16384;
  52.  
  53.     /// <summary>UPC-E 1D format.</summary>
  54.     UPC_E = 32768;
  55.  
  56.     /// <summary>UPC/EAN extension format. Not a stand-alone format.</summary>
  57.     UPC_EAN_EXTENSION = 65536;
  58.  
  59.     /// <summary>MSI</summary>
  60.     MSI = 131072;
  61.  
  62.     /// <summary>Plessey</summary>
  63.     PLESSEY = 262144;
Should have the least - if any at all - impact on your code and will work with generics.
- Anywhere TBarcodeFormat is referenced, code does not change
- The constants also fit in TBarcodeFormat so anywhere they are used the code need not change too. Untyped consts are a signed type.
- TBarcodeFormat = type Integer, because enums can be a signed type.

If you change just that unit to the above code all other units should keep working..

« Last Edit: November 21, 2022, 11:34:59 am by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

Thaddy

  • Hero Member
  • *****
  • Posts: 14393
  • Sensorship about opinions does not belong here.
Re: Problem with Generics.Defaults / Compiler message
« Reply #7 on: November 21, 2022, 11:53:12 am »
Can you test this full modified replacement unit and report back?
Code: Pascal  [Select][+][-]
  1. {
  2.   * Copyright 2008 ZXing authors
  3.   *
  4.   * Licensed under the Apache License, Version 2.0 (the "License");
  5.   * you may not use this file except in compliance with the License.
  6.   * You may obtain a copy of the License at
  7.   *
  8.   *      http://www.apache.org/licenses/LICENSE-2.0
  9.   *
  10.   * Unless required by applicable law or agreed to in writing, software
  11.   * distributed under the License is distributed on an "AS IS" BASIS,
  12.   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.   * See the License for the specific language governing permissions and
  14.   * limitations under the License.
  15.  
  16.   * Implemented by E. Spelt for Delphi
  17.   * Implemented for Freepascal by Thaddy de Koning, 2022
  18. }
  19.  
  20. unit ZXing.BarCodeFormat;
  21. {$ifdef fpc}{$mode delphi}{$endif}
  22. interface
  23. {$ifndef fpc}
  24. type
  25.   TBarcodeFormat = (
  26.     /// <summary>No format set. All formats will be used</summary>
  27.     Auto = 0,
  28.  
  29.     /// <summary>Aztec 2D barcode format.</summary>
  30.     AZTEC = 1,
  31.  
  32.     /// <summary>CODABAR 1D format.</summary>
  33.     CODABAR = 2,
  34.  
  35.     /// <summary>Code 39 1D format.</summary>
  36.     CODE_39 = 4,
  37.  
  38.     /// <summary>Code 93 1D format.</summary>
  39.     CODE_93 = 8,
  40.  
  41.     /// <summary>Code 128 1D format.</summary>
  42.     CODE_128 = 16,
  43.  
  44.     /// <summary>Data Matrix 2D barcode format.</summary>
  45.     DATA_MATRIX = 32,
  46.  
  47.     /// <summary>EAN-8 1D format.</summary>
  48.     EAN_8 = 64,
  49.  
  50.     /// <summary>EAN-13 1D format.</summary>
  51.     EAN_13 = 128,
  52.  
  53.     /// <summary>ITF (Interleaved Two of Five) 1D format.</summary>
  54.     ITF = 256,
  55.  
  56.     /// <summary>MaxiCode 2D barcode format.</summary>
  57.     MAXICODE = 512,
  58.  
  59.     /// <summary>PDF417 format.</summary>
  60.     PDF_417 = 1024,
  61.  
  62.     /// <summary>QR Code 2D barcode format.</summary>
  63.     QR_CODE = 2048,
  64.  
  65.     /// <summary>RSS 14</summary>
  66.     RSS_14 = 4096,
  67.  
  68.     /// <summary>RSS EXPANDED</summary>
  69.     RSS_EXPANDED = 8192,
  70.  
  71.     /// <summary>UPC-A 1D format.</summary>
  72.     UPC_A = 16384,
  73.  
  74.     /// <summary>UPC-E 1D format.</summary>
  75.     UPC_E = 32768,
  76.  
  77.     /// <summary>UPC/EAN extension format. Not a stand-alone format.</summary>
  78.     UPC_EAN_EXTENSION = 65536,
  79.  
  80.     /// <summary>MSI</summary>
  81.     MSI = 131072,
  82.  
  83.     /// <summary>Plessey</summary>
  84.     PLESSEY = 262144
  85.  
  86.     );
  87. {$else fpc}  
  88. type
  89.   TBarcodeFormat = type integer;
  90.  
  91. const
  92.     /// <summary>No format set. All formats will be used</summary>
  93.     Auto = 0;
  94.  
  95.     /// <summary>Aztec 2D barcode format.</summary>
  96.     AZTEC = 1;
  97.  
  98.     /// <summary>CODABAR 1D format.</summary>
  99.     CODABAR = 2;
  100.  
  101.     /// <summary>Code 39 1D format.</summary>
  102.     CODE_39 = 4;
  103.  
  104.     /// <summary>Code 93 1D format.</summary>
  105.     CODE_93 = 8;
  106.  
  107.     /// <summary>Code 128 1D format.</summary>
  108.     CODE_128 = 16;
  109.  
  110.     /// <summary>Data Matrix 2D barcode format.</summary>
  111.     DATA_MATRIX = 32;
  112.  
  113.     /// <summary>EAN-8 1D format.</summary>
  114.     EAN_8 = 64;
  115.  
  116.     /// <summary>EAN-13 1D format.</summary>
  117.     EAN_13 = 128;
  118.  
  119.     /// <summary>ITF (Interleaved Two of Five) 1D format.</summary>
  120.     ITF = 256;
  121.  
  122.     /// <summary>MaxiCode 2D barcode format.</summary>
  123.     MAXICODE = 512;
  124.  
  125.     /// <summary>PDF417 format.</summary>
  126.     PDF_417 = 1024;
  127.  
  128.     /// <summary>QR Code 2D barcode format.</summary>
  129.     QR_CODE = 2048;
  130.  
  131.     /// <summary>RSS 14</summary>
  132.     RSS_14 = 4096;
  133.  
  134.     /// <summary>RSS EXPANDED</summary>
  135.     RSS_EXPANDED = 8192;
  136.  
  137.     /// <summary>UPC-A 1D format.</summary>
  138.     UPC_A = 16384;
  139.  
  140.     /// <summary>UPC-E 1D format.</summary>
  141.     UPC_E = 32768;
  142.  
  143.     /// <summary>UPC/EAN extension format. Not a stand-alone format.</summary>
  144.     UPC_EAN_EXTENSION = 65536;
  145.  
  146.     /// <summary>MSI</summary>
  147.     MSI = 131072;
  148.  
  149.     /// <summary>Plessey</summary>
  150.     PLESSEY = 262144;
  151. {$endif}
  152. implementation
  153.  
  154. end.
Curious that the original works in Delphi with generics. Or does it?
Did you introduce the generics or is that also in the original sources? [edit] Ah, I see: ZXing.DecodeHintType;
Anyway, this unit should not require any code changes anywhere else. Not in Delphi and not in Freepascal.
I just tested that ZXing.DecodeHintType now compiles correctly which is at least an indication it should work anywhere else.
Note that IF you use this unit, you should not use scoped enums. The Lazarus example for vwf compiles with the original unit, not with mine.
« Last Edit: November 21, 2022, 01:34:16 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

Grahame Grieve

  • Sr. Member
  • ****
  • Posts: 365
Re: Problem with Generics.Defaults / Compiler message
« Reply #8 on: November 21, 2022, 01:28:04 pm »
Thanks. it compiles in Delphi, but I'm not entirely sure I'd know whether it works - I can read QR codes no problems in a web server, but is that the same as 'working?' - I don't know.

The changes weren't neutral to other code, since the code always prefixes the enum names with the type

Code: Pascal  [Select][+][-]
  1.   TBarcodeFormat.CODE_128
  2.  

but it's a simple search and replace

Code: Pascal  [Select][+][-]
  1.   {$IFNDEF FPC}TBarcodeFormat{$ELSE}ZXing.BarCodeFormat{$ENDIF}.CODE_128
  2.  

The original code should never have compiled at all, right? It shouldn't compile on the second pass, no? But the new code does compile with no problems


Thaddy

  • Hero Member
  • *****
  • Posts: 14393
  • Sensorship about opinions does not belong here.
Re: Problem with Generics.Defaults / Compiler message
« Reply #9 on: November 21, 2022, 02:11:05 pm »
It may be that because the sources use scoped enums, there is sufficient RTTI available in that case, but I will have to test that. The original demo compiles and works  at least in Lazarus without changes. Strange problem  :o :-\
Will investigate further. I will first try the original code with simply {$scopedenums on}
« Last Edit: November 21, 2022, 02:14:09 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

ASerge

  • Hero Member
  • *****
  • Posts: 2250
Re: Problem with Generics.Defaults / Compiler message
« Reply #10 on: November 21, 2022, 04:22:16 pm »
This code
Code: Pascal  [Select][+][-]
  1. {$IFDEF FPC}
  2.   {$MODE DELPHI}
  3. {$ENDIF}
  4.  
  5. uses Generics.Collections;
  6.  
  7. type
  8.   TEnumWithHole = (ewZero = 0, ewTwo = 2);
  9.   TewList = TList<TEnumWithHole>;
  10.  
  11. begin
  12. end.
compiled in Delphi, but not in FPC:
Quote
generics.collections.pas(1186,20) Note: Call to subroutine "function TEnumerable<Program.TEnumWithHole>.GetEnumerator:TEnumerator$1<PROGRAM.TEnumWithHole>;" marked as inline is not inlined
generics.defaults.pas(1051,43) Error: No type info available for this type
FPC 3.2.2.

Thaddy

  • Hero Member
  • *****
  • Posts: 14393
  • Sensorship about opinions does not belong here.
Re: Problem with Generics.Defaults / Compiler message
« Reply #11 on: November 21, 2022, 04:45:25 pm »
Yes, that was also our conclusion, see PascalDragon remark. Point in case is that the repo example from Grahame actually compiles without errors - and works! -, while it uses the enum and generics . Confused.
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5486
  • Compiler Developer
Re: Problem with Generics.Defaults / Compiler message
« Reply #12 on: November 21, 2022, 10:47:15 pm »
This code
Code: Pascal  [Select][+][-]
  1. {$IFDEF FPC}
  2.   {$MODE DELPHI}
  3. {$ENDIF}
  4.  
  5. uses Generics.Collections;
  6.  
  7. type
  8.   TEnumWithHole = (ewZero = 0, ewTwo = 2);
  9.   TewList = TList<TEnumWithHole>;
  10.  
  11. begin
  12. end.
compiled in Delphi, but not in FPC:
Quote
generics.collections.pas(1186,20) Note: Call to subroutine "function TEnumerable<Program.TEnumWithHole>.GetEnumerator:TEnumerator$1<PROGRAM.TEnumWithHole>;" marked as inline is not inlined
generics.defaults.pas(1051,43) Error: No type info available for this type
FPC 3.2.2.

It seems that Delphi's TList<> or what ever it depends on (e.g. the comparers from Generics.Defaults) does not use the type information of the type, cause TypeInfo(TEnumWithHole) does not compile in Delphi as well. This is probably something that won't be fixed anytime soon, cause that would mean reworking Generics.Collections quite a bit.

Grahame Grieve

  • Sr. Member
  • ****
  • Posts: 365
Re: Problem with Generics.Defaults / Compiler message
« Reply #13 on: November 22, 2022, 06:00:03 am »
Well, there's two different things to fix - one is using the TypeInfo, which I see is definitely hard to fix. But the other thing that would seem achievable is making the compile error consistent, that it doesn't only appear on a full build. And possibly improving the message?

Thaddy

  • Hero Member
  • *****
  • Posts: 14393
  • Sensorship about opinions does not belong here.
Re: Problem with Generics.Defaults / Compiler message
« Reply #14 on: November 22, 2022, 11:15:37 am »
It seems that Delphi's TList<> or what ever it depends on (e.g. the comparers from Generics.Defaults) does not use the type information of the type, cause TypeInfo(TEnumWithHole) does not compile in Delphi as well. This is probably something that won't be fixed anytime soon, cause that would mean reworking Generics.Collections quite a bit.
Freepascal uses a range, Delphi uses a map for enums. (AFAIKT, I may be very wrong here.). Using a map for enums does not require changes to rtl-generics.
Then again, it would slow down things a bit and I don't know if map structures are already available in the compiler, although I assume there are some.
« Last Edit: November 22, 2022, 11:17:18 am by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

 

TinyPortal © 2005-2018