continue;
// Generic methods need to be instantiated over something.
+ // We try to make up a canonical instantiation if possible to match the
+ // general expectation that if one has a type, and a method on the uninstantiated type,
+ // one can GetMemberWithSameMetadataDefinitionAs and MakeGenericMethod the result
+ // over reference types. We promise reference type instantiations are possible.
+ MethodDesc reflectedMethod;
if (method.HasInstantiation)
- continue;
+ {
+ Instantiation inst = TypeExtensions.GetInstantiationThatMeetsConstraints(method.Instantiation, allowCanon: true);
+ if (inst.IsNull)
+ continue;
+
+ reflectedMethod = method.MakeInstantiatedMethod(inst);
+ }
+ else
+ {
+ reflectedMethod = method;
+ }
dependencies ??= new CombinedDependencyList();
dependencies.Add(new DependencyNodeCore<NodeFactory>.CombinedDependencyListEntry(
- factory.ReflectedMethod(method),
- factory.ReflectedMethod(method.GetTypicalMethodDefinition()),
+ factory.ReflectedMethod(reflectedMethod),
+ factory.ReflectedMethod(reflectedMethod.GetTypicalMethodDefinition()),
"Methods have same reflectability"));
}
}
TestVTableOfNullableUnderlyingTypes.Run();
TestInterfaceLists.Run();
TestMethodConsistency.Run();
+ TestGenericMethodOnGenericType.Run();
TestIsValueTypeWithoutTypeHandle.Run();
TestMdArrayLoad.Run();
TestByRefTypeLoad.Run();
}
}
+ class TestGenericMethodOnGenericType
+ {
+ class Gen<T, U> { }
+
+ struct Atom1 { }
+ struct Atom2 { }
+
+ class GenericType<T>
+ {
+ public static Gen<T, U> GenericMethod1<U>() => new Gen<T, U>();
+ public static Gen<T, U> GenericMethod2<U>() => new Gen<T, U>();
+ }
+
+ static MethodInfo s_genericMethod2 = typeof(GenericType<>).GetMethod("GenericMethod2");
+
+ static object Make<T>(Type t)
+ {
+ if (t.IsValueType) throw null;
+ // AOT safe because we just checked t is not a valuetype
+ return typeof(GenericType<T>).GetMethod("GenericMethod1").MakeGenericMethod(t).Invoke(null, null);
+ }
+
+ public static void Run()
+ {
+ Make<Atom1>(typeof(object));
+
+ // This is supposed to be all AOT safe because we're instantiating over a reference type
+ // Ideally there would also be no AOT warning.
+ ((MethodInfo)(typeof(GenericType<Atom2>).GetMemberWithSameMetadataDefinitionAs(s_genericMethod2)))
+ .MakeGenericMethod(typeof(object))
+ .Invoke(null, null);
+ }
+ }
+
class TestIsValueTypeWithoutTypeHandle
{
[Nothing(