Recent

Author Topic: can't determine which overload function to call  (Read 1699 times)

Madoc

  • New Member
  • *
  • Posts: 46
can't determine which overload function to call
« on: December 08, 2023, 06:39:07 pm »
Title really, this is what doesn't work:

Code: Pascal  [Select][+][-]
  1. function Min(const a, b: integer): integer; overload;
  2. function Min(const a, b: single): single; overload;
  3. ...
  4. type
  5.    TA2i = array[0..1] of integer;
  6. var
  7.    a: integer;
  8.    b, c: TA2i;
  9. ...
  10.    c[1] := Min(b[0]+2, a-1);
  11.  

Wha..?

BSaidus

  • Hero Member
  • *****
  • Posts: 529
  • lazarus 1.8.4 Win8.1 / cross FreeBSD
Re: can't determine which overload function to call
« Reply #1 on: December 08, 2023, 06:49:48 pm »
Try to use Double in place of single.
lazarus 1.8.4 Win8.1 / cross FreeBSD
dhukmucmur vernadh!

Madoc

  • New Member
  • *
  • Posts: 46
Re: can't determine which overload function to call
« Reply #2 on: December 08, 2023, 06:55:08 pm »
Try to use Double in place of single.

I've narrowed it down to this just to illustrate the problem, but (normally) I have at least 20 Min functions, including single and double, and I need them all.

jamie

  • Hero Member
  • *****
  • Posts: 6021
Re: can't determine which overload function to call
« Reply #3 on: December 09, 2023, 12:09:45 am »
bug
old one at that.
The only true wisdom is knowing you know nothing

ad1mt

  • Full Member
  • ***
  • Posts: 164
    • Mark Taylor's Home Page
Re: can't determine which overload function to call
« Reply #4 on: December 10, 2023, 06:34:17 pm »
I'm not sure what the rules are for inferring the type of an expression, but my guess is that the compiler could interpret the expressions as either integer or single, and hence there is an ambiguity.
If you pass plain variables like this, the compiler knows the types, and there's no error:
Code: Pascal  [Select][+][-]
  1. c[1] := Min(b[0], a);
If you tell the compiler the type of the expressions like this, then there is no error:
Code: Pascal  [Select][+][-]
  1. c[1] := Min(integer(b[0]+2), integer(a-1));
The changes I suggest do fix the problem. But my explanation of why they fix it, might not be correct.
« Last Edit: December 10, 2023, 06:40:30 pm by ad1mt »

Madoc

  • New Member
  • *
  • Posts: 46
Re: can't determine which overload function to call
« Reply #5 on: December 11, 2023, 07:25:46 pm »
You can indeed "fix it" by casting your expression as integer, but this makes for really ugly and messy code and shouldn't be necessary obviously. I've been having to do this for all my GUI functions and I've had to insert Integer()  hundreds of times. Not fun.

ASerge

  • Hero Member
  • *****
  • Posts: 2191
Re: can't determine which overload function to call
« Reply #6 on: December 11, 2023, 09:35:19 pm »
...but my guess is that the compiler could interpret the expressions as either integer or single, and hence there is an ambiguity.
Not a guess. From Ordinal types:
As a pascal compiler, Free Pascal does automatic type conversion and upgrading in expressions where different kinds of integer types are used:
  • Every platform has a “native” integer size, depending on whether the platform is 8-bit, 16-bit, 32-bit or 64-bit. E. g. on AVR this is 8-bit.
  • Every integer smaller than the “native” size is promoted to a signed version of the “native” size. Integers equal to the “native” size keep their signedness.
Thus, the expression is of type SizeInt. That is, Min(SizeInt, SizeInt), and and the compiler cannot select from Min(Integer, Integer) and Min(Single, Single). Most likely, 64-bit is used, where SizeInt <> Integer.

TRon

  • Hero Member
  • *****
  • Posts: 2182
Re: can't determine which overload function to call
« Reply #7 on: December 11, 2023, 09:51:34 pm »
@Aserge:
I wanted to reply with the same message as you but.. in practice defining a longint for my case does not help the compiler choose the correct version. There must be something else into play (perhaps the fact that single is internally stored as an int64 ?)

ASerge

  • Hero Member
  • *****
  • Posts: 2191
Re: can't determine which overload function to call
« Reply #8 on: December 11, 2023, 10:03:31 pm »
There is definitely an error somewhere, because if make a Double instead of a Single, then the compiler already selects the version (Int, Int).
And of course, if there was a version (SizeInt, SizeInt), then there would be no error.

ad1mt

  • Full Member
  • ***
  • Posts: 164
    • Mark Taylor's Home Page
Re: can't determine which overload function to call
« Reply #9 on: December 12, 2023, 12:00:49 am »
I seem to remember from my early days of programming with Pascal, that expressions with mixed types of numbers were not dealt with as well as I would have liked. And while Pascal was my first favourite language, it does a small number of faults, and this seemed to be one of them.
Unfortunately, I can't remember the rules; none of the Pascal books I have discuss this in enough detail, so I can't be specific.
Here is some of my recent code that was generating an overflow:
Code: Pascal  [Select][+][-]
  1. var R,M:single;var V:int32;
  2. R:= R + (V * M)
I'm not sure where the overflow was happening, but the final value assigned to the variable "R" was 1, so I know it wasn't R that was overflowing. I also know that none of the variables used inside the expression had overflowed.
When I forced the compiler to cast to large types, like this, it worked, even though the values passed through the expression were the same:
Code: Pascal  [Select][+][-]
  1. var R:single;var M:int64;var V:int32;
  2. R:= R + single(int64(V]) * M)
NB the actual code was more complicated than above.. this is just an "illustration".

Madoc

  • New Member
  • *
  • Posts: 46
Re: can't determine which overload function to call
« Reply #10 on: December 12, 2023, 10:05:58 am »
Either way an expression containing an integer variable and constant should never results in a floating point value, so this should be a no brainer.

Whatever is happening, whatever the specific integer type of the expression is, it's still an integer and that's what's passed to the function.

When signed and unsigned types are used together it may be necessary to expand the representation to include the sign bit for the unsigned value, but beyond that it's not the language's job to change types. The type of the expression should be determined by typed elements within it.

Considering this, it kinda looks like there's 2 bugs..? It should know which overload function to select anyway, but I also should never have to typecast an expression of type Integer to Integer.

Nitorami

  • Sr. Member
  • ****
  • Posts: 476
Re: can't determine which overload function to call
« Reply #11 on: December 12, 2023, 04:31:50 pm »
I completed your fragment to be compilable and can't reproduce the issue with FPC3.2.2 (win32)

Madoc

  • New Member
  • *
  • Posts: 46
Re: can't determine which overload function to call
« Reply #12 on: December 12, 2023, 06:53:34 pm »
I completed your fragment to be compilable and can't reproduce the issue with FPC3.2.2 (win32)

It only happens in 64 bit apparently. This would seem to confirm my suspicion that the issue stems from the expression being resolved as an int64 / nativeint instead of the integer it should be.

TRon

  • Hero Member
  • *****
  • Posts: 2182
Re: can't determine which overload function to call
« Reply #13 on: December 12, 2023, 11:29:55 pm »
It only happens in 64 bit apparently. This would seem to confirm my suspicion that the issue stems from the expression being resolved as an int64 / nativeint instead of the integer it should be.
As ASerge already pointed out, it is the correct way for the compiler to convert the expression to int64 (well, it is documented as such). The problem is in the fact that even when you declared the overload with using int64 that even then the compiler tells us it is unable to determine which overload to use/select (which can be considered, as expressed by Jamie, as a bug).  The behaviour doesn't really make sense and i was unable to find any documentation that would explain the behaviour.

Perhaps another of those pesky Delphi compatibility things ?

 

TinyPortal © 2005-2018