From e9bb7e59dbb4a8d85eb86aaf2cfb306ee8e3a00a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lozier?= Date: Tue, 13 Dec 2022 21:03:07 -0500 Subject: [PATCH 1/4] Don't return same method multiple times --- Src/IronPython/Runtime/ExtensionMethodSet.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Src/IronPython/Runtime/ExtensionMethodSet.cs b/Src/IronPython/Runtime/ExtensionMethodSet.cs index 3649ee2e9..0a3c1685e 100644 --- a/Src/IronPython/Runtime/ExtensionMethodSet.cs +++ b/Src/IronPython/Runtime/ExtensionMethodSet.cs @@ -176,15 +176,18 @@ public IEnumerable GetExtensionMethods(string/*!*/ name) { lock (this) { EnsureLoaded(); + var yieldedMethods = new HashSet(); + foreach (var keyValue in _loadedAssemblies) { AssemblyLoadInfo info = keyValue.Value; Debug.Assert(info.Types != null); foreach (var type in info.Types) { - List methods; - if (type.ExtensionMethods.TryGetValue(name, out methods)) { + if (type.ExtensionMethods.TryGetValue(name, out var methods)) { foreach (var method in methods) { - yield return method; + if (yieldedMethods.Add(method)) { + yield return method; + } } } } From ee64134b599facb7f36dd60ff6cc48d56b35ef20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lozier?= Date: Fri, 16 Dec 2022 13:47:36 -0500 Subject: [PATCH 2/4] Deduplicate in PythonExtensionBinder instead --- Src/IronPython/Runtime/Binding/PythonExtensionBinder.cs | 7 ++++--- Src/IronPython/Runtime/ExtensionMethodSet.cs | 9 +++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Src/IronPython/Runtime/Binding/PythonExtensionBinder.cs b/Src/IronPython/Runtime/Binding/PythonExtensionBinder.cs index 73b21e5d4..31be3aad7 100644 --- a/Src/IronPython/Runtime/Binding/PythonExtensionBinder.cs +++ b/Src/IronPython/Runtime/Binding/PythonExtensionBinder.cs @@ -23,7 +23,8 @@ public PythonExtensionBinder(PythonBinder binder, ExtensionMethodSet extensionMe public override MemberGroup GetMember(MemberRequestKind actionKind, Type type, string name) { var res = base.GetMember(actionKind, type, name); if (res.Count == 0) { - List trackers = new List(); + // GetExtensionMethods may return duplicate MethodInfo so use a HashSet - https://github.com/IronLanguages/ironpython2/issues/810 + HashSet trackers = null; foreach (var method in _extMethodSet.GetExtensionMethods(name)) { var parameters = method.GetParameters(); @@ -34,11 +35,11 @@ public override MemberGroup GetMember(MemberRequestKind actionKind, Type type, s var paramType = parameters[0].ParameterType; if (IsApplicableExtensionMethod(type, paramType)) { - trackers.Add(MemberTracker.FromMemberInfo(method, paramType)); + (trackers ??= new HashSet()).Add(MemberTracker.FromMemberInfo(method, paramType)); } } - if (trackers.Count > 0) { + if (trackers is not null) { return new MemberGroup(trackers.ToArray()); } } diff --git a/Src/IronPython/Runtime/ExtensionMethodSet.cs b/Src/IronPython/Runtime/ExtensionMethodSet.cs index 0a3c1685e..3649ee2e9 100644 --- a/Src/IronPython/Runtime/ExtensionMethodSet.cs +++ b/Src/IronPython/Runtime/ExtensionMethodSet.cs @@ -176,18 +176,15 @@ public IEnumerable GetExtensionMethods(string/*!*/ name) { lock (this) { EnsureLoaded(); - var yieldedMethods = new HashSet(); - foreach (var keyValue in _loadedAssemblies) { AssemblyLoadInfo info = keyValue.Value; Debug.Assert(info.Types != null); foreach (var type in info.Types) { - if (type.ExtensionMethods.TryGetValue(name, out var methods)) { + List methods; + if (type.ExtensionMethods.TryGetValue(name, out methods)) { foreach (var method in methods) { - if (yieldedMethods.Add(method)) { - yield return method; - } + yield return method; } } } From 6556eaefcb9f805877e050a481d407f8c6c9696a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lozier?= Date: Sat, 25 Feb 2023 10:54:03 -0500 Subject: [PATCH 3/4] Re-enable test --- Tests/test_cliclass.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Tests/test_cliclass.py b/Tests/test_cliclass.py index 279efd580..1ab27ca27 100644 --- a/Tests/test_cliclass.py +++ b/Tests/test_cliclass.py @@ -1869,9 +1869,8 @@ class MyXamlRootObject(XamlTestObject): finally: os.unlink(fname) - @unittest.skipIf(is_netcoreapp, "https://github.com/IronLanguages/ironpython2/issues/810") def test_extension_methods(self): - import clr, imp, os + import clr, os if is_netcoreapp: clr.AddReference('System.Linq') else: From a05ac85aa36481b78c6963ebe1addbcd0049c653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lozier?= Date: Sat, 25 Feb 2023 11:54:09 -0500 Subject: [PATCH 4/4] Disable on .NET Core 2.1 --- Tests/test_cliclass.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/test_cliclass.py b/Tests/test_cliclass.py index 1ab27ca27..09b8ccf20 100644 --- a/Tests/test_cliclass.py +++ b/Tests/test_cliclass.py @@ -1869,6 +1869,7 @@ class MyXamlRootObject(XamlTestObject): finally: os.unlink(fname) + @unittest.skipIf(is_netcoreapp21, "TODO: figure out") def test_extension_methods(self): import clr, os if is_netcoreapp: