Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitfabb22c

Browse files
committed
improved support for generic method overloading
Prior to this change if method had multiple generic overloads, only 1 of them could be matched (whichever one reflection would return first)Now MethodBinder.MatchParameters returns all matching generic overloads, not just the first one.fixes#1522
1 parentc4238d9 commitfabb22c

File tree

5 files changed

+47
-22
lines changed

5 files changed

+47
-22
lines changed

‎src/runtime/methodbinder.cs

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,17 @@ internal void AddMethod(MethodBase m)
8686

8787
/// <summary>
8888
/// Given a sequence of MethodInfo and a sequence of type parameters,
89-
/// return the MethodInfo that represents the matching closed generic.
89+
/// return the MethodInfo(s) that represents the matching closed generic.
9090
/// If unsuccessful, returns null and may set a Python error.
9191
/// </summary>
92-
internalstaticMethodInfo?MatchParameters(MethodBase[]mi,Type[]?tp)
92+
internalstaticMethodInfo[]MatchParameters(MethodBase[]mi,Type[]?tp)
9393
{
9494
if(tp==null)
9595
{
96-
returnnull;
96+
returnArray.Empty<MethodInfo>();
9797
}
9898
intcount=tp.Length;
99+
varresult=newList<MethodInfo>();
99100
foreach(MethodInfotinmi)
100101
{
101102
if(!t.IsGenericMethodDefinition)
@@ -111,16 +112,14 @@ internal void AddMethod(MethodBase m)
111112
{
112113
// MakeGenericMethod can throw ArgumentException if the type parameters do not obey the constraints.
113114
MethodInfomethod=t.MakeGenericMethod(tp);
114-
Exceptions.Clear();
115-
returnmethod;
115+
result.Add(method);
116116
}
117-
catch(ArgumentExceptione)
117+
catch(ArgumentException)
118118
{
119-
Exceptions.SetError(e);
120119
// The error will remain set until cleared by a successful match.
121120
}
122121
}
123-
returnnull;
122+
returnresult.ToArray();
124123
}
125124

126125

@@ -381,9 +380,6 @@ public MismatchedMethod(Exception exception, MethodBase mb)
381380
}
382381
}
383382

384-
varpynargs=(int)Runtime.PyTuple_Size(args);
385-
varisGeneric=false;
386-
387383
MethodBase[]_methods;
388384
if(info!=null)
389385
{
@@ -395,11 +391,19 @@ public MismatchedMethod(Exception exception, MethodBase mb)
395391
_methods=GetMethods();
396392
}
397393

398-
varargMatchedMethods=newList<MatchedMethod>(_methods.Length);
394+
returnBind(inst,args,kwargDict,_methods,matchGenerics:true);
395+
}
396+
397+
staticBinding?Bind(BorrowedReferenceinst,BorrowedReferenceargs,Dictionary<string,PyObject>kwargDict,MethodBase[]methods,boolmatchGenerics)
398+
{
399+
varpynargs=(int)Runtime.PyTuple_Size(args);
400+
varisGeneric=false;
401+
402+
varargMatchedMethods=newList<MatchedMethod>(methods.Length);
399403
varmismatchedMethods=newList<MismatchedMethod>();
400404

401405
// TODO: Clean up
402-
foreach(MethodBasemiin_methods)
406+
foreach(MethodBasemiinmethods)
403407
{
404408
if(mi.IsGenericMethod)
405409
{
@@ -535,17 +539,17 @@ public MismatchedMethod(Exception exception, MethodBase mb)
535539

536540
returnnewBinding(mi,target,margs,outs);
537541
}
538-
elseif(isGeneric&&info==null&&methodinfo!=null)
542+
elseif(matchGenerics&&isGeneric)
539543
{
540544
// We weren't able to find a matching method but at least one
541545
// is a generic method and info is null. That happens when a generic
542546
// method was not called using the [] syntax. Let's introspect the
543547
// type of the arguments and use it to construct the correct method.
544548
Type[]?types=Runtime.PythonArgsToTypeArray(args,true);
545-
MethodInfo?mi=MatchParameters(methodinfo,types);
546-
if(mi!=null)
549+
MethodInfo[]overloads=MatchParameters(methods,types);
550+
if(overloads.Length!=0)
547551
{
548-
returnBind(inst,args,kw,mi,null);
552+
returnBind(inst,args,kwargDict,overloads,matchGenerics:false);
549553
}
550554
}
551555
if(mismatchedMethods.Count>0)

‎src/runtime/methodbinding.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,18 @@ public static NewReference mp_subscript(BorrowedReference tp, BorrowedReference
4343
returnExceptions.RaiseTypeError("type(s) expected");
4444
}
4545

46-
MethodBase?mi=self.m.IsInstanceConstructor
47-
?self.m.type.Value.GetConstructor(types)
46+
MethodBase[]overloads=self.m.IsInstanceConstructor
47+
?self.m.type.Value.GetConstructor(types)is{}ctor
48+
?new[]{ctor}
49+
:Array.Empty<MethodBase>()
4850
:MethodBinder.MatchParameters(self.m.info,types);
49-
if(mi==null)
51+
if(overloads.Length==0)
5052
{
5153
returnExceptions.RaiseTypeError("No match found for given type params");
5254
}
5355

54-
varmb=newMethodBinding(self.m,self.target,self.targetType){info=mi};
56+
MethodObjectoverloaded=self.m.WithOverloads(overloads);
57+
varmb=newMethodBinding(overloaded,self.target,self.targetType);
5558
returnmb.Alloc();
5659
}
5760

‎src/runtime/methodobject.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ internal class MethodObject : ExtensionType
2727
internalPyString?doc;
2828
internalMaybeTypetype;
2929

30-
publicMethodObject(Typetype,stringname,MethodBase[]info,boolallow_threads=MethodBinder.DefaultAllowThreads)
30+
publicMethodObject(MaybeTypetype,stringname,MethodBase[]info,boolallow_threads=MethodBinder.DefaultAllowThreads)
3131
{
3232
this.type=type;
3333
this.name=name;
@@ -47,6 +47,9 @@ public MethodObject(Type type, string name, MethodBase[] info, bool allow_thread
4747

4848
publicboolIsInstanceConstructor=>name=="__init__";
4949

50+
publicMethodObjectWithOverloads(MethodBase[]overloads)
51+
=>new(type,name,overloads,allow_threads:binder.allow_threads);
52+
5053
internalMethodBase[]info
5154
{
5255
get

‎src/testing/methodtest.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,9 @@ public static int Overloaded(int i, string s)
646646
returni;
647647
}
648648

649+
publicvirtualvoidOverloadedConstrainedGeneric<T>(Tgeneric)whereT:MethodTest{}
650+
publicvirtualvoidOverloadedConstrainedGeneric<T>(Tgeneric,stringstr)whereT:MethodTest{}
651+
649652
publicstaticstringCaseSensitive()
650653
{
651654
return"CaseSensitive";

‎tests/test_generic.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,18 @@ def test_missing_generic_type():
762762
withpytest.raises(TypeError):
763763
IList[bool]
764764

765+
# https://github.com/pythonnet/pythonnet/issues/1522
766+
deftest_overload_generic_parameter():
767+
fromPython.TestimportMethodTest,MethodTestSub
768+
769+
inst=MethodTest()
770+
generic=MethodTestSub()
771+
inst.OverloadedConstrainedGeneric(generic)
772+
inst.OverloadedConstrainedGeneric[MethodTestSub](generic)
773+
774+
inst.OverloadedConstrainedGeneric[MethodTestSub](generic,'42')
775+
inst.OverloadedConstrainedGeneric[MethodTestSub](generic,System.String('42'))
776+
765777
deftest_invalid_generic_type_parameter():
766778
fromPython.TestimportGenericTypeWithConstraint
767779
withpytest.raises(TypeError):

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp