Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/embed_tests/TestMethodBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1448,7 +1448,7 @@ public bool SomeMethod()
return true;
}

public virtual string OnlyClass(TestImplicitConversion data)
public virtual string OnlyClass(TestImplicitConversion data, double anotherArgument = 0)
{
return "OnlyClass impl";
}
Expand All @@ -1458,12 +1458,12 @@ public virtual string OnlyString(string data)
return "OnlyString impl: " + data;
}

public virtual string InvokeModel(string data)
public virtual string InvokeModel(string data, double anotherArgument = 0)
{
return "string impl: " + data;
}

public virtual string InvokeModel(TestImplicitConversion data)
public virtual string InvokeModel(TestImplicitConversion data, double anotherArgument = 0)
{
return "TestImplicitConversion impl";
}
Expand Down
50 changes: 34 additions & 16 deletions src/runtime/MethodBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ internal Binding Bind(BorrowedReference inst, BorrowedReference args, BorrowedRe
var margs = new object[clrArgCount];

int paramsArrayIndex = paramsArray ? pi.Length - 1 : -1; // -1 indicates no paramsArray
var usedImplicitConversion = false;
int implicitConversions = 0;
var kwargsMatched = 0;

// Conversion loop for each parameter
Expand Down Expand Up @@ -658,18 +658,26 @@ internal Binding Bind(BorrowedReference inst, BorrowedReference args, BorrowedRe
else if (matches.Count == 0)
{
// accepts non-decimal numbers in decimal parameters
if (underlyingType == typeof(decimal))
if (underlyingType == typeof(decimal) || underlyingType == typeof(double))
{
clrtype = parameter.ParameterType;
usedImplicitConversion |= typematch = Converter.ToManaged(op, clrtype, out arg, false);
typematch = Converter.ToManaged(op, clrtype, out arg, false);
if (typematch)
{
implicitConversions++;
}
}
if (!typematch)
{
// this takes care of implicit conversions
var opImplicit = parameter.ParameterType.GetMethod("op_Implicit", new[] { clrtype });
if (opImplicit != null)
{
usedImplicitConversion |= typematch = opImplicit.ReturnType == parameter.ParameterType;
typematch = opImplicit.ReturnType == parameter.ParameterType;
if (typematch)
{
implicitConversions++;
}
clrtype = parameter.ParameterType;
}
}
Expand Down Expand Up @@ -739,13 +747,10 @@ internal Binding Bind(BorrowedReference inst, BorrowedReference args, BorrowedRe
}
}

var match = new MatchedMethod(kwargsMatched, margs, outs, methodInformation);
if (usedImplicitConversion)
var match = new MatchedMethod(kwargsMatched, margs, outs, methodInformation, implicitConversions);
if (implicitConversions > 0)
{
if (matchesUsingImplicitConversion == null)
{
matchesUsingImplicitConversion = new List<MatchedMethod>();
}
matchesUsingImplicitConversion ??= new List<MatchedMethod>();
matchesUsingImplicitConversion.Add(match);
}
else
Expand All @@ -767,11 +772,22 @@ internal Binding Bind(BorrowedReference inst, BorrowedReference args, BorrowedRe
// we solve the ambiguity by taking the one with the highest precedence but only
// considering the actual arguments passed, ignoring the optional arguments for
// which the default values were used
var bestMatch = matchesTouse
.GroupBy(x => x.KwargsMatched)
.OrderByDescending(x => x.Key)
.First()
.MinBy(x => GetMatchedArgumentsPrecedence(x.MethodInformation, pyArgCount, kwArgDict?.Keys));
MatchedMethod bestMatch;
if (matchesTouse.Count == 1)
{
bestMatch = matchesTouse[0];
}
else
{
bestMatch = matchesTouse
.GroupBy(x => x.KwargsMatched)
.OrderByDescending(x => x.Key)
.First()
.GroupBy(x => x.ImplicitOperations)
.OrderBy(x => x.Key)
.First()
.MinBy(x => GetMatchedArgumentsPrecedence(x.MethodInformation, pyArgCount, kwArgDict?.Keys));
}

var margs = bestMatch.ManagedArgs;
var outs = bestMatch.Outs;
Expand Down Expand Up @@ -1135,15 +1151,17 @@ private readonly struct MatchedMethod
public int KwargsMatched { get; }
public object?[] ManagedArgs { get; }
public int Outs { get; }
public int ImplicitOperations { get; }
public MethodInformation MethodInformation { get; }
public MethodBase Method => MethodInformation.MethodBase;

public MatchedMethod(int kwargsMatched, object?[] margs, int outs, MethodInformation methodInformation)
public MatchedMethod(int kwargsMatched, object?[] margs, int outs, MethodInformation methodInformation, int implicitOperations)
{
KwargsMatched = kwargsMatched;
ManagedArgs = margs;
Outs = outs;
MethodInformation = methodInformation;
ImplicitOperations = implicitOperations;
}
}

Expand Down
Loading