In some cases, the compiler cannot determine an appropriate method overload
When compiling the following example, the compiler reports an error:
FUNCTION Start() AS VOID STRICT
LOCAL o := TestClass{} AS TestClass
o:SetItem(0)
RETURN
CLASS TestClass
METHOD SetItem(dwItem AS DWORD) AS VOID STRICT
RETURN
METHOD SetItem(pItem AS TEST_STRUCT PTR) AS VOID STRICT
RETURN
END CLASS
VOSTRUCT TEST_STRUCT
MEMBER dwItem AS DWORD
END VOSTRUCT
Error:
XS0121 The call is ambiguous between the following methods or properties: 'TestClass.SetItem(dword)' and 'TestClass.SetItem(TEST_STRUCT*)'
If you do the same example using functions instead of class methods, then the code compiles without errors. So the problem only occurs when using class methods.
Example project: XSharpBetaTest.zip
Environment: Compiler X# 2.17.0.3 IDE VS 2022
If the literal in the call is changed from 0 to 0U then there is no error.
I am not sure, should we consider this fixed with the workaround of using 0U instead of 0, or is it possible to make the compiler detect correctly the intended overload? (low priority obviously)
Hello Chris, After I created this issue a year ago, I rethought it after Robert's hint. A pointer is an address (position) in memory whose value is an integer. So passing an integer is appropriate for both methods.
Hi Leonid! Well, this is true for a language like c, but for a high level language like X# or c# technically it isn't really, an integer and a pointer are different types and shouldn't be possible to be used one instead of the other, at least not implicitly. System.Char and enumeration values are also represented by numbers under the hood, but fortunately we cannot simply pass a number to a method accepting those types.
The complication here is that unfortunately VO allowed this (passing a number instead of a pointer without explicit conversion), so we had to allow it in X# also, but I'm sure that this is one of the things that lead to unstable VO applications.
So I'd say let's just keep this on hold for now and in the future reconsider it and make it maybe possible with an option to make the compiler/runtime more strict with things like that.
The problem in this case is that the compiler cannot match the literal 0 (of type LONG) with dwItem as DWORD and pItem as TEST_STRUCT PTR. It therefore tries to detect if there is an implicit conversion, and it finds conversions from LONG to DWORD as well as from LONG to PTR.
(At this moment) we do not assign a "weight" to these conversions, so we cannot choose which of the two we want to use.
Therefore the user either has to add a cast (DWORD) 0 or 0U or (PTR) 0 to help the compiler choose the right overload.