[fpc-pascal] Feature announcement: implicit generic function specializations

Sven Barth pascaldragon at googlemail.com
Fri Apr 22 23:12:34 CEST 2022

Am 22.04.2022 um 20:51 schrieb Martin Frb via fpc-pascal:
> I created a little test program (see bottom of mail).
> And it gives a strange warning:
> Compile Project, Target: 
> C:\Users\martin\AppData\Local\Temp\project1.exe: Success, Warnings: 1, 
> Hints: 3
> project1.lpr(67,52) Warning: Range check error while evaluating 
> constants (100000 must be between -128 and 127)
> project1.lpr(41,18) Hint: Local proc "Add$1" is not used
> 72 lines compiled, 0.2 sec, 105136 bytes code, 5476 bytes data
> Line 41 is the declaration of the generic
>    generic function Add<T>(aArg1, aArg2: T): T;
> So why does it generate "Add$1" if it does not use it? (Or rather why 
> does it warn, if this is some internal details?)

Add$1 is the symbol of the generic itself, *not* the specialization. But 
please report it, cause that definitely shouldn't be the case anyway, as 
the generic is after all used by the specializations (and I should 
compile with -vh more often...)

> --------------------------------
> And if you add to the app (at the top)
> function Add(aArg1, aArg2: Int64): Int64; overload;
> begin
> //  write(' Int64 overload ');
>   Result := aArg1 + aArg2;
> end;
> Then the line  (Shortint, because the first param is ShortInt)
>  writeln('#### 1,CK = ',Add(0, 100000) ); // ShortInt
> Will no longer call the specialized function, but instead use the 
> int64 version.

Correct, because a matching non-generic variant is available and the 
compiler then picks that.

> If you comment all "Add(...)" calls, except that one
> => Then you get an additional hint: "project1.lpr(81,41) Hint: Local 
> proc "Add$1$crc9AB0BCED" is not used"
> So then that very line generates a specialized version for the call, 
> and then the compiler does not use it.

The compiler essentially works like this: it generates a suitable set of 
overloads. This includes the non-generic routines as well as all generic 
routines for which suitable type parameters can be found. Out of this 
set the compiler will then pick the function it will finally use with a 
preference for non-generic functions (even if parameters might be a 
worse, though not incompatible match).

That said: if the compiler does not pick one of the specializations it 
should totally discard them, so please report a bug for this as well.

> Yet if INSTEAD of adding the hardcoded Int64 variant (as given above), 
> I let the compile create a Int64 version by adding
>     writeln('#### 1,CK = ',Add(int64(0), 100000) ); // ShortInt
> before the line above... Well the line above will not use that int64 
> version, but use its own specialization...

The compiler determines the generic type parameters for each call. In 
this case it will be Int64 due to the typecast. However that will not 
change what the other, previous Add calls use and it also won't affect 
one any following Add call, cause it will simply determine the set of 
elligible functions (and other implicit specializations as well as 
explicit specializaitons are *not* part of this) and then determine 
which one to call out of this set (the compiler might specialize the 
same generic function with the same generic type parameters multiple 
times then, but the part that's dealing with specializations in general 
will detect that and point to the existing symbol instead).


More information about the fpc-pascal mailing list