X-Sharp / XSharpPublic

Public repository for the source code for the XSharp Compiler, Runtime, Project System and Tools.
Apache License 2.0
113 stars 38 forks source link

Problem with late bound and overloads #875

Closed VolkmarR closed 2 years ago

VolkmarR commented 2 years ago

I created an example, that shows a strange behaviour with late bound calls. The first call works as expected, the second throws an "No exported method" Exception. The problem is related to the order of the method declaration.

function Start() as void strict

    local obj as object 
    // This works as expected
    obj := MyClassOk{}
    obj:Go(0)

    // This throws a "No exported method" Exception
    obj := MyClassError{}
    obj:Go(0)

    return

class MyClassOK
    public method Go() as void strict
        return
    public method Go(Dummy as int) as void strict
        return
    public method Go(text as string) as void strict
        return
end class

class MyClassError
    public method Go(Dummy as int) as void strict
        return
    public method Go(text as string) as void strict
        return
    public method Go() as void strict
        return
end class

The reason for this problem is IMHO in this part of the code

https://github.com/X-Sharp/XSharpPublic/blob/7080fd20627e1dcd6418bbfe6a1833956f761ab5/Runtime/XSharp.RT/Functions/OOP.prg#L208-L214

Here is the project as zip XSharpTests.zip

cpyrgas commented 2 years ago

Interesting, didn't know Robert had added support for late bound calls on overloaded methods! This was not allowed at all in vulcan, since this was non needed in VO either..

Not sure how easy it is to make this work in all scenarios. But in general, I think it's better to use the DYNAMIC type (instead of OBJECT) for such late bounds calls, and let the .Net runtime itself figure the best overload, and let OBJECT/USUAL late binding for VO compatibility code only.

VolkmarR commented 2 years ago

Dynamic would work for new code but in our situation, this workaround doesn't work, because we have a lot of existing code, that can not be changes easily.

RobertvanderHulst commented 2 years ago

I think I can improve this by first filtering the methods out with the right number of arguments, and then comparing these matching methods to see which one matches the best.

Tadas-Infominds commented 2 years ago

Another related example. Here the problem is with hidden methods from the base class.

function Start() as void strict
    local obj as object 
    obj := MyClass{}

    // This throws a "No exported method" Exception
    obj:Go()

    return

class MyBaseClass // This class we cannot touch (e.g., in .NET library)
    // Method NOT virtual, so cannot be overridden, only hidden.
    public method Go() as void strict
        return
end class

class MyClass inherit MyBaseClass
    public new method Go() as void strict
        return
end class
cpyrgas commented 2 years ago

@Tadas-Infominds this sample seems to work fine here, just tested it. Maybe it has to do with the specific compiler options you are using. Can you please send a zipped solution of a small sample reproducing this?

Tadas-Infominds commented 2 years ago

Here you go:

SampleNoExportedMethod.zip

RobertvanderHulst commented 2 years ago

I see it now. We can probably optimize the code that handles late bound calls to detect that there is a method in the child class that hides a method in the parent class and remove the method from the parent class from the list. In this case that would leave still 2 overloaded methods in the list: CustomForm.Show (no parameters) Form.Show(System.Windows.Forms.IWin32Window) And the late bound "binder" will then resolve the call to CustomForm.Show() because there are no arguments

RobertvanderHulst commented 2 years ago

This is working correctly with the 2.13 runtime

cpyrgas commented 2 years ago

I'm getting a runtime error that the method is overloaded, for both the original sample in https://github.com/X-Sharp/XSharpPublic/issues/875#issue-1067378331 and also the newer provided in https://github.com/X-Sharp/XSharpPublic/issues/875#issuecomment-1018993701

Description :   Method is overloaded, Cannot determine the right overload to call.
Found 2 overloads
1. MyClassError:Go(Dummy AS Int32)
2. MyClassError:Go(text AS String)

Subsystem :     BASE
GenCode :       EG_AMBIGUOUSMETHOD Method is overloaded, Cannot determine the right overload to call.
FuncSym :       GO
Severity :      ES_ERROR
Can Default :   False
Can Retry :     False
Can Substitute :        False
Argument Number :       1
Argument :      MethodName
Arguments :     {MyClassError:Go}
Stack Trace :
 OOPHELPERS:FINDBESTOVERLOAD (Line: 0)
 OOPHELPERS:SENDHELPER (Line: 0)
 OOPHELPERS:DOSEND (Line: 0)
 __INTERNALSEND (Line: 0)
 START (Line: 11)
cpyrgas commented 2 years ago

Still getting the same issues mentioned in https://github.com/X-Sharp/XSharpPublic/issues/875#issuecomment-1232082542

cpyrgas commented 2 years ago

Still getting the same issue

cpyrgas commented 2 years ago

It was due to outdated runtime dlls, confirmed fixed now!