diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs
index 95c3aaa4a..42d3822fc 100644
--- a/src/runtime/methodbinder.cs
+++ b/src/runtime/methodbinder.cs
@@ -86,16 +86,17 @@ internal void AddMethod(MethodBase m)
///
/// Given a sequence of MethodInfo and a sequence of type parameters,
- /// return the MethodInfo that represents the matching closed generic.
+ /// return the MethodInfo(s) that represents the matching closed generic.
/// If unsuccessful, returns null and may set a Python error.
///
- internal static MethodInfo? MatchParameters(MethodBase[] mi, Type[]? tp)
+ internal static MethodInfo[] MatchParameters(MethodBase[] mi, Type[]? tp)
{
if (tp == null)
{
- return null;
+ return Array.Empty();
}
int count = tp.Length;
+ var result = new List();
foreach (MethodInfo t in mi)
{
if (!t.IsGenericMethodDefinition)
@@ -111,16 +112,14 @@ internal void AddMethod(MethodBase m)
{
// MakeGenericMethod can throw ArgumentException if the type parameters do not obey the constraints.
MethodInfo method = t.MakeGenericMethod(tp);
- Exceptions.Clear();
- return method;
+ result.Add(method);
}
- catch (ArgumentException e)
+ catch (ArgumentException)
{
- Exceptions.SetError(e);
// The error will remain set until cleared by a successful match.
}
}
- return null;
+ return result.ToArray();
}
@@ -381,9 +380,6 @@ public MismatchedMethod(Exception exception, MethodBase mb)
}
}
- var pynargs = (int)Runtime.PyTuple_Size(args);
- var isGeneric = false;
-
MethodBase[] _methods;
if (info != null)
{
@@ -395,11 +391,19 @@ public MismatchedMethod(Exception exception, MethodBase mb)
_methods = GetMethods();
}
- var argMatchedMethods = new List(_methods.Length);
+ return Bind(inst, args, kwargDict, _methods, matchGenerics: true);
+ }
+
+ static Binding? Bind(BorrowedReference inst, BorrowedReference args, Dictionary kwargDict, MethodBase[] methods, bool matchGenerics)
+ {
+ var pynargs = (int)Runtime.PyTuple_Size(args);
+ var isGeneric = false;
+
+ var argMatchedMethods = new List(methods.Length);
var mismatchedMethods = new List();
// TODO: Clean up
- foreach (MethodBase mi in _methods)
+ foreach (MethodBase mi in methods)
{
if (mi.IsGenericMethod)
{
@@ -535,17 +539,17 @@ public MismatchedMethod(Exception exception, MethodBase mb)
return new Binding(mi, target, margs, outs);
}
- else if (isGeneric && info == null && methodinfo != null)
+ else if (matchGenerics && isGeneric)
{
// We weren't able to find a matching method but at least one
// is a generic method and info is null. That happens when a generic
// method was not called using the [] syntax. Let's introspect the
// type of the arguments and use it to construct the correct method.
Type[]? types = Runtime.PythonArgsToTypeArray(args, true);
- MethodInfo? mi = MatchParameters(methodinfo, types);
- if (mi != null)
+ MethodInfo[] overloads = MatchParameters(methods, types);
+ if (overloads.Length != 0)
{
- return Bind(inst, args, kw, mi, null);
+ return Bind(inst, args, kwargDict, overloads, matchGenerics: false);
}
}
if (mismatchedMethods.Count > 0)
diff --git a/src/runtime/methodbinding.cs b/src/runtime/methodbinding.cs
index d9bf3aec6..6d21af01e 100644
--- a/src/runtime/methodbinding.cs
+++ b/src/runtime/methodbinding.cs
@@ -43,15 +43,18 @@ public static NewReference mp_subscript(BorrowedReference tp, BorrowedReference
return Exceptions.RaiseTypeError("type(s) expected");
}
- MethodBase? mi = self.m.IsInstanceConstructor
- ? self.m.type.Value.GetConstructor(types)
+ MethodBase[] overloads = self.m.IsInstanceConstructor
+ ? self.m.type.Value.GetConstructor(types) is { } ctor
+ ? new[] { ctor }
+ : Array.Empty()
: MethodBinder.MatchParameters(self.m.info, types);
- if (mi == null)
+ if (overloads.Length == 0)
{
return Exceptions.RaiseTypeError("No match found for given type params");
}
- var mb = new MethodBinding(self.m, self.target, self.targetType) { info = mi };
+ MethodObject overloaded = self.m.WithOverloads(overloads);
+ var mb = new MethodBinding(overloaded, self.target, self.targetType);
return mb.Alloc();
}
diff --git a/src/runtime/methodobject.cs b/src/runtime/methodobject.cs
index 397547616..b0fda49d3 100644
--- a/src/runtime/methodobject.cs
+++ b/src/runtime/methodobject.cs
@@ -27,7 +27,7 @@ internal class MethodObject : ExtensionType
internal PyString? doc;
internal MaybeType type;
- public MethodObject(Type type, string name, MethodBase[] info, bool allow_threads = MethodBinder.DefaultAllowThreads)
+ public MethodObject(MaybeType type, string name, MethodBase[] info, bool allow_threads = MethodBinder.DefaultAllowThreads)
{
this.type = type;
this.name = name;
@@ -47,6 +47,9 @@ public MethodObject(Type type, string name, MethodBase[] info, bool allow_thread
public bool IsInstanceConstructor => name == "__init__";
+ public MethodObject WithOverloads(MethodBase[] overloads)
+ => new(type, name, overloads, allow_threads: binder.allow_threads);
+
internal MethodBase[] info
{
get
diff --git a/src/testing/methodtest.cs b/src/testing/methodtest.cs
index 9eae0e9f0..fe49de88d 100644
--- a/src/testing/methodtest.cs
+++ b/src/testing/methodtest.cs
@@ -646,6 +646,9 @@ public static int Overloaded(int i, string s)
return i;
}
+ public virtual void OverloadedConstrainedGeneric(T generic) where T : MethodTest { }
+ public virtual void OverloadedConstrainedGeneric(T generic, string str) where T: MethodTest { }
+
public static string CaseSensitive()
{
return "CaseSensitive";
diff --git a/tests/test_generic.py b/tests/test_generic.py
index e03ac57af..6d514d638 100644
--- a/tests/test_generic.py
+++ b/tests/test_generic.py
@@ -762,6 +762,18 @@ def test_missing_generic_type():
with pytest.raises(TypeError):
IList[bool]
+# https://github.com/pythonnet/pythonnet/issues/1522
+def test_overload_generic_parameter():
+ from Python.Test import MethodTest, MethodTestSub
+
+ inst = MethodTest()
+ generic = MethodTestSub()
+ inst.OverloadedConstrainedGeneric(generic)
+ inst.OverloadedConstrainedGeneric[MethodTestSub](generic)
+
+ inst.OverloadedConstrainedGeneric[MethodTestSub](generic, '42')
+ inst.OverloadedConstrainedGeneric[MethodTestSub](generic, System.String('42'))
+
def test_invalid_generic_type_parameter():
from Python.Test import GenericTypeWithConstraint
with pytest.raises(TypeError):