Skip to content

Commit 6d2f0bd

Browse files
authored
Improve "No constructor matches given arguments" message with more details (#1143)
Similar to #900, but for constructors (reuses the same code) Related issues: #811, #265, #1116
1 parent 2699fdc commit 6d2f0bd

File tree

2 files changed

+46
-24
lines changed

2 files changed

+46
-24
lines changed

src/runtime/constructorbinder.cs

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Reflection;
3+
using System.Text;
34

45
namespace Python.Runtime
56
{
@@ -93,7 +94,15 @@ internal object InvokeRaw(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info)
9394

9495
if (binding == null)
9596
{
96-
Exceptions.SetError(Exceptions.TypeError, "no constructor matches given arguments");
97+
var errorMessage = new StringBuilder("No constructor matches given arguments");
98+
if (info != null && info.IsConstructor && info.DeclaringType != null)
99+
{
100+
errorMessage.Append(" for ").Append(info.DeclaringType.Name);
101+
}
102+
103+
errorMessage.Append(": ");
104+
AppendArgumentTypes(to: errorMessage, args);
105+
Exceptions.SetError(Exceptions.TypeError, errorMessage.ToString());
97106
return null;
98107
}
99108
}

src/runtime/methodbinder.cs

+36-23
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,40 @@ internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase i
599599
return Invoke(inst, args, kw, info, null);
600600
}
601601

602+
protected static void AppendArgumentTypes(StringBuilder to, IntPtr args)
603+
{
604+
long argCount = Runtime.PyTuple_Size(args);
605+
to.Append("(");
606+
for (long argIndex = 0; argIndex < argCount; argIndex++)
607+
{
608+
var arg = Runtime.PyTuple_GetItem(args, argIndex);
609+
if (arg != IntPtr.Zero)
610+
{
611+
var type = Runtime.PyObject_Type(arg);
612+
if (type != IntPtr.Zero)
613+
{
614+
try
615+
{
616+
var description = Runtime.PyObject_Unicode(type);
617+
if (description != IntPtr.Zero)
618+
{
619+
to.Append(Runtime.GetManagedString(description));
620+
Runtime.XDecref(description);
621+
}
622+
}
623+
finally
624+
{
625+
Runtime.XDecref(type);
626+
}
627+
}
628+
}
629+
630+
if (argIndex + 1 < argCount)
631+
to.Append(", ");
632+
}
633+
to.Append(')');
634+
}
635+
602636
internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
603637
{
604638
Binding binding = Bind(inst, args, kw, info, methodinfo);
@@ -613,29 +647,8 @@ internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, MethodBase i
613647
value.Append($" for {methodinfo[0].Name}");
614648
}
615649

616-
long argCount = Runtime.PyTuple_Size(args);
617-
value.Append(": (");
618-
for(long argIndex = 0; argIndex < argCount; argIndex++) {
619-
var arg = Runtime.PyTuple_GetItem(args, argIndex);
620-
if (arg != IntPtr.Zero) {
621-
var type = Runtime.PyObject_Type(arg);
622-
if (type != IntPtr.Zero) {
623-
try {
624-
var description = Runtime.PyObject_Unicode(type);
625-
if (description != IntPtr.Zero) {
626-
value.Append(Runtime.GetManagedString(description));
627-
Runtime.XDecref(description);
628-
}
629-
} finally {
630-
Runtime.XDecref(type);
631-
}
632-
}
633-
}
634-
635-
if (argIndex + 1 < argCount)
636-
value.Append(", ");
637-
}
638-
value.Append(')');
650+
value.Append(": ");
651+
AppendArgumentTypes(to: value, args);
639652
Exceptions.SetError(Exceptions.TypeError, value.ToString());
640653
return IntPtr.Zero;
641654
}

0 commit comments

Comments
 (0)