@@ -1053,6 +1053,24 @@ public static IEnumerable<object[]> GetInterfaceMap_TestData()
10531053 }
10541054 } ;
10551055 yield return new object [ ]
1056+ {
1057+ typeof ( DIMs . I2 ) ,
1058+ typeof ( DIMs . C3 ) ,
1059+ new Tuple < MethodInfo , MethodInfo > [ ]
1060+ {
1061+ new Tuple < MethodInfo , MethodInfo > ( typeof ( DIMs . I2 ) . GetMethod ( "System.Tests.TypeTestsExtended.DIMs.I1.M" , BindingFlags . Instance | BindingFlags . NonPublic ) , null )
1062+ }
1063+ } ;
1064+ yield return new object [ ]
1065+ {
1066+ typeof ( DIMs . I1 ) ,
1067+ typeof ( DIMs . C3 ) ,
1068+ new Tuple < MethodInfo , MethodInfo > [ ]
1069+ {
1070+ new Tuple < MethodInfo , MethodInfo > ( typeof ( DIMs . I1 ) . GetMethod ( "M" ) , typeof ( DIMs . I3 ) . GetMethod ( "System.Tests.TypeTestsExtended.DIMs.I1.M" , BindingFlags . Instance | BindingFlags . NonPublic ) )
1071+ }
1072+ } ;
1073+ yield return new object [ ]
10561074 {
10571075 typeof ( DIMs . I4 ) ,
10581076 typeof ( DIMs . C4 ) ,
@@ -1062,6 +1080,15 @@ public static IEnumerable<object[]> GetInterfaceMap_TestData()
10621080 }
10631081 } ;
10641082 yield return new object [ ]
1083+ {
1084+ typeof ( DIMs . I3 ) ,
1085+ typeof ( DIMs . C4 ) ,
1086+ new Tuple < MethodInfo , MethodInfo > [ ]
1087+ {
1088+ new Tuple < MethodInfo , MethodInfo > ( typeof ( DIMs . I3 ) . GetMethod ( "System.Tests.TypeTestsExtended.DIMs.I1.M" , BindingFlags . Instance | BindingFlags . NonPublic ) , typeof ( DIMs . I3 ) . GetMethod ( "System.Tests.TypeTestsExtended.DIMs.I1.M" , BindingFlags . Instance | BindingFlags . NonPublic ) )
1089+ }
1090+ } ;
1091+ yield return new object [ ]
10651092 {
10661093 typeof ( DIMs . I2 ) ,
10671094 typeof ( DIMs . C4 ) ,
@@ -1070,6 +1097,148 @@ public static IEnumerable<object[]> GetInterfaceMap_TestData()
10701097 new Tuple < MethodInfo , MethodInfo > ( typeof ( DIMs . I2 ) . GetMethod ( "System.Tests.TypeTestsExtended.DIMs.I1.M" , BindingFlags . Instance | BindingFlags . NonPublic ) , null )
10711098 }
10721099 } ;
1100+ yield return new object [ ]
1101+ {
1102+ typeof ( DIMs . I1 ) ,
1103+ typeof ( DIMs . C4 ) ,
1104+ new Tuple < MethodInfo , MethodInfo > [ ]
1105+ {
1106+ new Tuple < MethodInfo , MethodInfo > ( typeof ( DIMs . I1 ) . GetMethod ( "M" ) , typeof ( DIMs . C4 ) . GetMethod ( "M" ) )
1107+ }
1108+ } ;
1109+
1110+ // Test all combinations of the following:
1111+ // Static method
1112+ // Implementation by having the same name, explicit implementation, & default implementation (where applicable - only level 2)
1113+ // Non-generic interface, generic interface
1114+ // Non-generic type, generic type
1115+ // 3 levels of inheritance (of the interfaces): 1 - static abstract method, 2 - add a default implementation, 3 - re-abstractify it
1116+ // Checks that all the applicable interfaces are working properly
1117+ ( Type Type , bool IncludePrefix , bool AnyTarget , Type InterfaceGenericParameter , int Index ) [ ] classTypes = new ( Type , bool , bool , Type , int ) [ ]
1118+ {
1119+ // List of every type we are going to test
1120+ // (Type, whether it's implemented explicitly, whether it's not implemented in the level 2 interface, the generic parameter for Ix<T>, the level)
1121+ ( typeof ( SIMs . C1 ) , false , true , typeof ( int ) , 1 ) ,
1122+ ( typeof ( SIMs . C1Explicit ) , true , true , typeof ( int ) , 1 ) ,
1123+ ( typeof ( SIMs . C1 < string > ) , false , true , typeof ( string ) , 1 ) ,
1124+ ( typeof ( SIMs . C1Explicit < string > ) , true , true , typeof ( string ) , 1 ) ,
1125+ ( typeof ( SIMs . C1 < > ) , false , true , typeof ( SIMs . C1 < > ) . GetGenericArguments ( ) [ 0 ] , 1 ) ,
1126+ ( typeof ( SIMs . C1Explicit < > ) , true , true , typeof ( SIMs . C1Explicit < > ) . GetGenericArguments ( ) [ 0 ] , 1 ) ,
1127+ ( typeof ( SIMs . C2Implicit ) , false , false , typeof ( int ) , 2 ) ,
1128+ ( typeof ( SIMs . C2 ) , false , true , typeof ( int ) , 2 ) ,
1129+ ( typeof ( SIMs . C2Explicit ) , true , true , typeof ( int ) , 2 ) ,
1130+ ( typeof ( SIMs . C2Implicit < string > ) , false , false , typeof ( string ) , 2 ) ,
1131+ ( typeof ( SIMs . C2 < string > ) , false , true , typeof ( string ) , 2 ) ,
1132+ ( typeof ( SIMs . C2Explicit < string > ) , true , true , typeof ( string ) , 2 ) ,
1133+ ( typeof ( SIMs . C2Implicit < > ) , false , false , typeof ( SIMs . C2Implicit < > ) . GetGenericArguments ( ) [ 0 ] , 2 ) ,
1134+ ( typeof ( SIMs . C2 < > ) , false , true , typeof ( SIMs . C2 < > ) . GetGenericArguments ( ) [ 0 ] , 2 ) ,
1135+ ( typeof ( SIMs . C2Explicit < > ) , true , true , typeof ( SIMs . C2Explicit < > ) . GetGenericArguments ( ) [ 0 ] , 2 ) ,
1136+ ( typeof ( SIMs . C3 ) , false , true , typeof ( int ) , 3 ) ,
1137+ ( typeof ( SIMs . C3Explicit ) , true , true , typeof ( int ) , 3 ) ,
1138+ ( typeof ( SIMs . C3 < string > ) , false , true , typeof ( string ) , 3 ) ,
1139+ ( typeof ( SIMs . C3Explicit < string > ) , true , true , typeof ( string ) , 3 ) ,
1140+ ( typeof ( SIMs . C3 < > ) , false , true , typeof ( SIMs . C3 < > ) . GetGenericArguments ( ) [ 0 ] , 3 ) ,
1141+ ( typeof ( SIMs . C3Explicit < > ) , true , true , typeof ( SIMs . C3Explicit < > ) . GetGenericArguments ( ) [ 0 ] , 3 ) ,
1142+ } ;
1143+ foreach ( ( Type Type , bool IncludePrefix , bool AnyTarget , Type InterfaceGenericParameter , int Index ) classType in classTypes )
1144+ {
1145+ BindingFlags bindingFlags = BindingFlags . Static | BindingFlags . Public | BindingFlags . NonPublic ;
1146+
1147+ // This is the member name of the explicit interface implementation method in the class for the generic interface
1148+ string level1MethodNamePrefixTyped = "System.Tests.TypeTestsExtended.SIMs.I1<" + ( classType . Type . GetGenericArguments ( ) . Length == 0 ? "System.Int32" : "S" ) + ">." ;
1149+
1150+ // Check we have the expected implementation for the level 1 interfaces (abstract definitions - M and G methods)
1151+ Type level1GenericInterface = typeof ( SIMs . I1 < > ) . MakeGenericType ( classType . InterfaceGenericParameter ) ;
1152+ Type level2GenericInterface = typeof ( SIMs . I2 < > ) . MakeGenericType ( classType . InterfaceGenericParameter ) ;
1153+ Type level3GenericInterface = typeof ( SIMs . I3 < > ) . MakeGenericType ( classType . InterfaceGenericParameter ) ;
1154+ foreach ( ( Type Type , Type Level2InterfaceType , string MethodNamePrefix , string MethodNamePrefixTyped ) interfaceType in new ( Type , Type , string , string ) [ ]
1155+ {
1156+ ( typeof ( SIMs . I1 ) , typeof ( SIMs . I2 ) , "System.Tests.TypeTestsExtended.SIMs.I1." , "System.Tests.TypeTestsExtended.SIMs.I1." ) ,
1157+ ( level1GenericInterface , level2GenericInterface , "System.Tests.TypeTestsExtended.SIMs.I1<S>." , level1MethodNamePrefixTyped ) ,
1158+ } )
1159+ {
1160+ // Look up the interface method which should be implemented
1161+ MethodInfo MInterface = interfaceType . Type . GetMethod ( "M" , bindingFlags ) ;
1162+ MethodInfo GInterface = interfaceType . Type . GetMethod ( "G" , bindingFlags ) ;
1163+
1164+ // Look up the implementation
1165+ MethodInfo MTarget , GTarget ;
1166+ if ( classType . AnyTarget )
1167+ {
1168+ // The class implements it, either implicitly or explicitly (if IncludePrefix is specified)
1169+ MTarget = classType . Type . GetMethod ( ( classType . IncludePrefix ? interfaceType . MethodNamePrefixTyped : "" ) + "M" , bindingFlags ) ;
1170+ GTarget = classType . Type . GetMethod ( ( classType . IncludePrefix ? interfaceType . MethodNamePrefixTyped : "" ) + "G" , bindingFlags ) ;
1171+ }
1172+ else
1173+ {
1174+ // [ActiveIssue("https://github.com/dotnet/runtime/issues/90863")]
1175+ if ( classType . Type == typeof ( SIMs . C2Implicit < string > ) && interfaceType . Type == typeof ( SIMs . I1 < string > ) ) continue ;
1176+
1177+ // It's implemented implicitly by the level 2 interface
1178+ MTarget = interfaceType . Level2InterfaceType . GetMethod ( interfaceType . MethodNamePrefix + "M" , bindingFlags ) ;
1179+ GTarget = interfaceType . Level2InterfaceType . GetMethod ( interfaceType . MethodNamePrefix + "G" , bindingFlags ) ;
1180+ }
1181+
1182+ // Return our test case
1183+ yield return new object [ ]
1184+ {
1185+ interfaceType . Type ,
1186+ classType . Type ,
1187+ new Tuple < MethodInfo , MethodInfo > [ ]
1188+ {
1189+ new Tuple < MethodInfo , MethodInfo > ( MInterface , MTarget ) ,
1190+ new Tuple < MethodInfo , MethodInfo > ( GInterface , GTarget )
1191+ }
1192+ } ;
1193+ }
1194+
1195+ // Check we have the expected implementation for the level 2 interfaces (virtual explicit default implementations - none)
1196+ if ( classType . Index >= 2 )
1197+ {
1198+ // There should be no methods for these interfaces
1199+ // Return our test cases
1200+ yield return new object [ ]
1201+ {
1202+ typeof ( SIMs . I2 ) ,
1203+ classType . Type ,
1204+ new Tuple < MethodInfo , MethodInfo > [ 0 ]
1205+ } ;
1206+ yield return new object [ ]
1207+ {
1208+ level2GenericInterface ,
1209+ classType . Type ,
1210+ new Tuple < MethodInfo , MethodInfo > [ 0 ]
1211+ } ;
1212+ }
1213+
1214+ // Check we have the expected implementation for the level 3 interfaces (abstract explicit implementations - I1.M and I1.G methods)
1215+ // Fails on mono: [ActiveIssue("https://github.com/dotnet/runtime/issues/91027")]
1216+ if ( ! PlatformDetection . IsMonoRuntime && classType . Index >= 3 )
1217+ {
1218+ foreach ( ( Type Type , string MethodNamePrefix ) interfaceType in new ( Type , string ) [ ]
1219+ {
1220+ ( typeof ( SIMs . I3 ) , "System.Tests.TypeTestsExtended.SIMs.I1." ) ,
1221+ ( level3GenericInterface , "System.Tests.TypeTestsExtended.SIMs.I1<S>." ) ,
1222+ } )
1223+ {
1224+ // There should be no implementation for these methods - null
1225+ MethodInfo MInterface = interfaceType . Type . GetMethod ( interfaceType . MethodNamePrefix + "M" , bindingFlags ) ;
1226+ MethodInfo GInterface = interfaceType . Type . GetMethod ( interfaceType . MethodNamePrefix + "G" , bindingFlags ) ;
1227+
1228+ // Return our test cases
1229+ yield return new object [ ]
1230+ {
1231+ interfaceType . Type ,
1232+ classType . Type ,
1233+ new Tuple < MethodInfo , MethodInfo > [ ]
1234+ {
1235+ new Tuple < MethodInfo , MethodInfo > ( MInterface , null ) ,
1236+ new Tuple < MethodInfo , MethodInfo > ( GInterface , null )
1237+ }
1238+ } ;
1239+ }
1240+ }
1241+ }
10731242 }
10741243
10751244 [ ActiveIssue ( "https://github.com/dotnet/runtime/issues/89157" , typeof ( PlatformDetection ) , nameof ( PlatformDetection . IsNativeAot ) ) ]
@@ -1167,6 +1336,136 @@ internal abstract class C4 : I4
11671336 public abstract void M ( ) ;
11681337 }
11691338 }
1339+
1340+ static class SIMs
1341+ {
1342+ internal interface I1
1343+ {
1344+ static abstract void M ( ) ;
1345+ static abstract void G < T > ( ) ;
1346+ }
1347+ internal interface I1 < S >
1348+ {
1349+ static abstract void M ( ) ;
1350+ static abstract void G < T > ( ) ;
1351+ }
1352+
1353+ internal class C1 : I1 , I1 < int >
1354+ {
1355+ public static void M ( ) { }
1356+ public static void G < T > ( ) { }
1357+ }
1358+
1359+ internal class C1Explicit : I1 , I1 < int >
1360+ {
1361+ static void I1 . M ( ) { }
1362+ static void I1 . G < T > ( ) { }
1363+ static void I1 < int > . M ( ) { }
1364+ static void I1 < int > . G < T > ( ) { }
1365+ }
1366+
1367+ internal class C1 < S > : I1 , I1 < S >
1368+ {
1369+ public static void M ( ) { }
1370+ public static void G < T > ( ) { }
1371+ }
1372+
1373+ internal class C1Explicit < S > : I1 , I1 < S >
1374+ {
1375+ static void I1 . M ( ) { }
1376+ static void I1 . G < T > ( ) { }
1377+ static void I1 < S > . M ( ) { }
1378+ static void I1 < S > . G < T > ( ) { }
1379+ }
1380+
1381+
1382+ internal interface I2 : I1
1383+ {
1384+ // add a default implementation
1385+ static void I1 . M ( ) { }
1386+ static void I1 . G < T > ( ) { }
1387+ }
1388+ internal interface I2 < S > : I1 < S >
1389+ {
1390+ // add a default implementation
1391+ static void I1 < S > . M ( ) { }
1392+ static void I1 < S > . G < T > ( ) { }
1393+ }
1394+
1395+ internal class C2Implicit : I2 , I2 < int > { }
1396+
1397+ internal class C2 : I2 , I2 < int >
1398+ {
1399+ public static void M ( ) { }
1400+ public static void G < T > ( ) { }
1401+ }
1402+
1403+ internal class C2Explicit : I2 , I2 < int >
1404+ {
1405+ static void I1 . M ( ) { }
1406+ static void I1 . G < T > ( ) { }
1407+ static void I1 < int > . M ( ) { }
1408+ static void I1 < int > . G < T > ( ) { }
1409+ }
1410+
1411+ internal class C2Implicit < S > : I2 , I2 < S > { }
1412+
1413+ internal class C2 < S > : I2 , I2 < S >
1414+ {
1415+ public static void M ( ) { }
1416+ public static void G < T > ( ) { }
1417+ }
1418+
1419+ internal class C2Explicit < S > : I2 , I2 < S >
1420+ {
1421+ static void I1 . M ( ) { }
1422+ static void I1 . G < T > ( ) { }
1423+ static void I1 < S > . M ( ) { }
1424+ static void I1 < S > . G < T > ( ) { }
1425+ }
1426+
1427+
1428+ internal interface I3 : I2
1429+ {
1430+ // reabstract it
1431+ static abstract void I1 . M ( ) ;
1432+ static abstract void I1 . G < T > ( ) ;
1433+ }
1434+ internal interface I3 < S > : I2 < S >
1435+ {
1436+ // reabstract it
1437+ static abstract void I1 < S > . M ( ) ;
1438+ static abstract void I1 < S > . G < T > ( ) ;
1439+ }
1440+
1441+ internal class C3 : I3 , I3 < int >
1442+ {
1443+ public static void M ( ) { }
1444+ public static void G < T > ( ) { }
1445+ }
1446+
1447+ internal class C3Explicit : I3 , I3 < int >
1448+ {
1449+ static void I1 . M ( ) { }
1450+ static void I1 . G < T > ( ) { }
1451+ static void I1 < int > . M ( ) { }
1452+ static void I1 < int > . G < T > ( ) { }
1453+ }
1454+
1455+ internal class C3 < S > : I3 , I3 < S >
1456+ {
1457+ public static void M ( ) { }
1458+ public static void G < T > ( ) { }
1459+ }
1460+
1461+ internal class C3Explicit < S > : I3 , I3 < S >
1462+ {
1463+ static void I1 . M ( ) { }
1464+ static void I1 . G < T > ( ) { }
1465+ static void I1 < S > . M ( ) { }
1466+ static void I1 < S > . G < T > ( ) { }
1467+ }
1468+ }
11701469#endregion
11711470
11721471 [ Fact ]
0 commit comments