Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d0feb90

Browse files
Improve numeric implicit conversion handling (#107)
1 parent d2a06ce commit d0feb90

File tree

2 files changed

+37
-19
lines changed

2 files changed

+37
-19
lines changed

src/embed_tests/TestMethodBinder.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,7 +1448,7 @@ public bool SomeMethod()
14481448
return true;
14491449
}
14501450

1451-
public virtual string OnlyClass(TestImplicitConversion data)
1451+
public virtual string OnlyClass(TestImplicitConversion data, double anotherArgument = 0)
14521452
{
14531453
return "OnlyClass impl";
14541454
}
@@ -1458,12 +1458,12 @@ public virtual string OnlyString(string data)
14581458
return "OnlyString impl: " + data;
14591459
}
14601460

1461-
public virtual string InvokeModel(string data)
1461+
public virtual string InvokeModel(string data, double anotherArgument = 0)
14621462
{
14631463
return "string impl: " + data;
14641464
}
14651465

1466-
public virtual string InvokeModel(TestImplicitConversion data)
1466+
public virtual string InvokeModel(TestImplicitConversion data, double anotherArgument = 0)
14671467
{
14681468
return "TestImplicitConversion impl";
14691469
}

src/runtime/MethodBinder.cs

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ internal Binding Bind(BorrowedReference inst, BorrowedReference args, BorrowedRe
546546
var margs = new object[clrArgCount];
547547

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

552552
// Conversion loop for each parameter
@@ -658,18 +658,26 @@ internal Binding Bind(BorrowedReference inst, BorrowedReference args, BorrowedRe
658658
else if (matches.Count == 0)
659659
{
660660
// accepts non-decimal numbers in decimal parameters
661-
if (underlyingType == typeof(decimal))
661+
if (underlyingType == typeof(decimal) || underlyingType == typeof(double))
662662
{
663663
clrtype = parameter.ParameterType;
664-
usedImplicitConversion |= typematch = Converter.ToManaged(op, clrtype, out arg, false);
664+
typematch = Converter.ToManaged(op, clrtype, out arg, false);
665+
if (typematch)
666+
{
667+
implicitConversions++;
668+
}
665669
}
666670
if (!typematch)
667671
{
668672
// this takes care of implicit conversions
669673
var opImplicit = parameter.ParameterType.GetMethod("op_Implicit", new[] { clrtype });
670674
if (opImplicit != null)
671675
{
672-
usedImplicitConversion |= typematch = opImplicit.ReturnType == parameter.ParameterType;
676+
typematch = opImplicit.ReturnType == parameter.ParameterType;
677+
if (typematch)
678+
{
679+
implicitConversions++;
680+
}
673681
clrtype = parameter.ParameterType;
674682
}
675683
}
@@ -739,13 +747,10 @@ internal Binding Bind(BorrowedReference inst, BorrowedReference args, BorrowedRe
739747
}
740748
}
741749

742-
var match = new MatchedMethod(kwargsMatched, margs, outs, methodInformation);
743-
if (usedImplicitConversion)
750+
var match = new MatchedMethod(kwargsMatched, margs, outs, methodInformation, implicitConversions);
751+
if (implicitConversions > 0)
744752
{
745-
if (matchesUsingImplicitConversion == null)
746-
{
747-
matchesUsingImplicitConversion = new List<MatchedMethod>();
748-
}
753+
matchesUsingImplicitConversion ??= new List<MatchedMethod>();
749754
matchesUsingImplicitConversion.Add(match);
750755
}
751756
else
@@ -767,11 +772,22 @@ internal Binding Bind(BorrowedReference inst, BorrowedReference args, BorrowedRe
767772
// we solve the ambiguity by taking the one with the highest precedence but only
768773
// considering the actual arguments passed, ignoring the optional arguments for
769774
// which the default values were used
770-
var bestMatch = matchesTouse
771-
.GroupBy(x => x.KwargsMatched)
772-
.OrderByDescending(x => x.Key)
773-
.First()
774-
.MinBy(x => GetMatchedArgumentsPrecedence(x.MethodInformation, pyArgCount, kwArgDict?.Keys));
775+
MatchedMethod bestMatch;
776+
if (matchesTouse.Count == 1)
777+
{
778+
bestMatch = matchesTouse[0];
779+
}
780+
else
781+
{
782+
bestMatch = matchesTouse
783+
.GroupBy(x => x.KwargsMatched)
784+
.OrderByDescending(x => x.Key)
785+
.First()
786+
.GroupBy(x => x.ImplicitOperations)
787+
.OrderBy(x => x.Key)
788+
.First()
789+
.MinBy(x => GetMatchedArgumentsPrecedence(x.MethodInformation, pyArgCount, kwArgDict?.Keys));
790+
}
775791

776792
var margs = bestMatch.ManagedArgs;
777793
var outs = bestMatch.Outs;
@@ -1135,15 +1151,17 @@ private readonly struct MatchedMethod
11351151
public int KwargsMatched { get; }
11361152
public object?[] ManagedArgs { get; }
11371153
public int Outs { get; }
1154+
public int ImplicitOperations { get; }
11381155
public MethodInformation MethodInformation { get; }
11391156
public MethodBase Method => MethodInformation.MethodBase;
11401157

1141-
public MatchedMethod(int kwargsMatched, object?[] margs, int outs, MethodInformation methodInformation)
1158+
public MatchedMethod(int kwargsMatched, object?[] margs, int outs, MethodInformation methodInformation, int implicitOperations)
11421159
{
11431160
KwargsMatched = kwargsMatched;
11441161
ManagedArgs = margs;
11451162
Outs = outs;
11461163
MethodInformation = methodInformation;
1164+
ImplicitOperations = implicitOperations;
11471165
}
11481166
}
11491167

0 commit comments

Comments
 (0)