Skip to content

Commit d4e3c18

Browse files
committed
1776 Generic Virtual Method Causes Invalid Program: Fix + test
- If a method is virtual AND generic, it cannot be overridden by the python class. Hence the method call is deferred to the base class. - Added a unit test which verifies this behavior is now working.
1 parent 556882d commit d4e3c18

File tree

5 files changed

+28
-2
lines changed

5 files changed

+28
-2
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
1313

1414
### Fixed
1515

16+
- Fixed error occuring when inheriting a class containing a virtual generic method.
17+
1618
## [3.0.1](https://github.com/pythonnet/pythonnet/releases/tag/v3.0.1) - 2022-11-03
1719

1820
### Added

src/python_tests_runner/PythonTestRunner.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ static IEnumerable<string[]> PythonTestCases()
3535
// Add the test that you want to debug here.
3636
yield return new[] { "test_indexer", "test_boolean_indexer" };
3737
yield return new[] { "test_delegate", "test_bool_delegate" };
38+
yield return new[] { "test_subclass", "test_virtual_generic_method" };
3839
}
3940

4041
/// <summary>

src/runtime/Types/ClassDerived.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,10 @@ internal static Type CreateDerivedType(string name,
220220
foreach (MethodInfo method in methods)
221221
{
222222
if (!method.Attributes.HasFlag(MethodAttributes.Virtual) |
223-
method.Attributes.HasFlag(MethodAttributes.Final))
223+
method.Attributes.HasFlag(MethodAttributes.Final)
224+
// overriding generic virtual methods is not supported
225+
// so a call to that should be deferred to the base class method.
226+
|| method.IsGenericMethod)
224227
{
225228
continue;
226229
}

src/testing/generictest.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,12 @@ public static T[] EchoRange<T>(T[] items)
136136
return items;
137137
}
138138
}
139+
140+
public abstract class GenericVirtualMethodTest
141+
{
142+
public virtual Q VirtMethod<Q>(Q arg1)
143+
{
144+
return arg1;
145+
}
146+
}
139147
}

tests/test_subclass.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import System
1010
import pytest
1111
from Python.Test import (IInterfaceTest, SubClassTest, EventArgsTest,
12-
FunctionsTest, IGenericInterface)
12+
FunctionsTest, IGenericInterface, GenericVirtualMethodTest)
1313
from System.Collections.Generic import List
1414

1515

@@ -327,3 +327,15 @@ def test_generic_interface():
327327
obj = GenericInterfaceImpl()
328328
SpecificInterfaceUser(obj, Int32(0))
329329
GenericInterfaceUser[Int32](obj, Int32(0))
330+
331+
def test_virtual_generic_method():
332+
class OverloadingSubclass(GenericVirtualMethodTest):
333+
__namespace__ = "test_virtual_generic_method_cls"
334+
class OverloadingSubclass2(OverloadingSubclass):
335+
__namespace__ = "test_virtual_generic_method_cls"
336+
obj = OverloadingSubclass()
337+
assert obj.VirtMethod[int](5) == 5
338+
obj = OverloadingSubclass2()
339+
assert obj.VirtMethod[int](5) == 5
340+
341+

0 commit comments

Comments
 (0)