Controlling ByRef selection in OverloadResolver

May 30, 2010 at 3:39 AM

I'm making a call equivalent to:   x.m(99)

Using DefaultOverloadResolver.  At runtime, x's class has methods named m with signatures

Object m(Object)

Int32 m(Int32&)

I want the ByRef version to be called only if I have explicitly set up a by-ref argument.  Thus, I want the 'Object m(Object)' called in this case.

I probably don't need to sketch the flow through OverloadResolver.ResolveOverload that ends up with the second version being called and returning an object array for anyone who can conceivably answer my question, but if I'm mistaken, perhaps someone could correct me. 

I can see call to OverloadResolver.AddBasicMethodTargets that calls ParameterMapping.CreateByRefReducedCandidate that automatically returns the second method as a candidate even though I'm passing an Int32 and not an Int32/StrongBox<Int32> -- I don't see a way to avoid this.  So I end up with both methods being considered, with the second one appearing to be ignoring the its by-ref-ness.  I thought perhaps deriving my own class from  DefaultBinder to override CanConvertFrom might work (if I could figure out the details), but it appears the OverloadResolver.CanConvertFrom doesn't end up calling the binder's CanConvertFrom:  it short circuits because forthe candidate produced by CreateByRefReducedCandidate, the type of the argument appears to be Int32 instead of Int32&, so it matches 99 just fine.

Where do I put some code to cause the first method to be preferred over the second?  Or, how do I prevent matches against a by-ref parameter unless I've specified that I'm passing a by-ref argument?

 

-David

Jun 3, 2010 at 2:16 AM

Unfortunately we don’t have a way how to change this behavior. If you don’t mind building your own DLR from sources you can simply add a virtual bool property ReduceByRefParameters to OverloadResolver that returns true if by-refs should be reduced (the current behavior) and false otherwise. Then you can add a condition to AddBasicMethodTargets in OverloadResolver.cs like so:

if (ReduceByRefParameters) {

var byRefReducedCandidate = mapping.CreateByRefReducedCandidate();

if (byRefReducedCandidate != null) {

AddSimpleTarget(byRefReducedCandidate);

}

}

Then you override this property in an OverloadResolver that your language implements.

This makes the additional overload candidates go away.

This is certainly a scenario we should support. The by-ref and out parameter reduction is not very well implemented today so I think we should replace it by something better.

Thanks,

Tomas

From: dmiller [mailto:notifications@codeplex.com]
Sent: Saturday, May 29, 2010 8:39 PM
To: Tomas Matousek
Subject: Controlling ByRef selection in OverloadResolver [dlr:214332]

From: dmiller

I'm making a call equivalent to: x.m(99)

Using DefaultOverloadResolver. At runtime, x's class has methods named m with signatures

Object m(Object)

Int32 m(Int32&)

I want the ByRef version to be called only if I have explicitly set up a by-ref argument. Thus, I want the 'Object m(Object)' called in this case.

I probably don't need to sketch the flow through OverloadResolver.ResolveOverload that ends up with the second version being called and returning an object array for anyone who can conceivably answer my question, but if I'm mistaken, perhaps someone could correct me.

I can see call to OverloadResolver.AddBasicMethodTargets that calls ParameterMapping.CreateByRefReducedCandidate that automatically returns the second method as a candidate even though I'm passing an Int32 and not an Int32/StrongBox<Int32> -- I don't see a way to avoid this. So I end up with both methods being considered, with the second one appearing to be ignoring the its by-ref-ness. I thought perhaps deriving my own class from DefaultBinder to override CanConvertFrom might work (if I could figure out the details), but it appears the OverloadResolver.CanConvertFrom doesn't end up calling the binder's CanConvertFrom: it short circuits because forthe candidate produced by CreateByRefReducedCandidate, the type of the argument appears to be Int32 instead of Int32&, so it matches 99 just fine.

Where do I put some code to cause the first method to be preferred over the second? Or, how do I prevent matches against a by-ref parameter unless I've specified that I'm passing a by-ref argument?

-David

Read the full discussion online.

To add a post to this discussion, reply to this email (dlr@discussions.codeplex.com)

To start a new discussion for this project, email dlr@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com

Jun 3, 2010 at 4:59 AM
Tomas,

Oh, the humanity!

Perhaps the DLR team, as an example of its magnanimity, could violate its rules of information hiding and make OverloadResolver.AddBasicMethodTargets protected virtual in the next DLR release. :)

More seriously, following your suggestion, I'm going to have to get into the DLR source code redistribution game, for at least scripting.core, scripting and dynamic.  (Else, I leave instructions for downloading and modifying the DLR source for serious hackers and develop a binary installer for the casual user, putting me in the binaries distribution game.  Pretty much the same questions arise.)  I can (more or less) read the license the DLR is distributed under and understand preserving copyright notices and the like.  My source has to be under a modified version of the Eclipse Public License.   Is there anyone around who can confirm that the EPL is 'a license that complies with with this license [Ms-PL]', as required in section 3(D) (in the case of binary installer)?  Other than including the MsPL, are there any other requirements for distributing DLR source out of my github repo?  IANAL.

David

P.S.  OverloadResolver has been a lifesaver.  Any workaround on my part is totally worth the effort.

TomasMatousek wrote:

Unfortunately we don’t have a way how to change this behavior. If you don’t mind building your own DLR from sources you can simply add a virtual bool property ReduceByRefParameters to OverloadResolver that returns true if by-refs should be reduced (the current behavior) and false otherwise. Then you can add a condition to AddBasicMethodTargets in OverloadResolver.cs like so:

if (ReduceByRefParameters) {

var byRefReducedCandidate = mapping.CreateByRefReducedCandidate();

if (byRefReducedCandidate != null) {

AddSimpleTarget(byRefReducedCandidate);

}

}

Then you override this property in an OverloadResolver that your language implements.

This makes the additional overload candidates go away.

This is certainly a scenario we should support. The by-ref and out parameter reduction is not very well implemented today so I think we should replace it by something better.

Thanks,

Tomas

Read the full discussion online.

To add a post to this discussion, reply to this email (dlr@discussions.codeplex.com)

To start a new discussion for this project, email dlr@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com