Skip to content

Commit a4faf10

Browse files
authored
Fix: Using TypeBuilder as generic argument for a parent type throws (#99771)
* Fix: Using TypeBuilder as generic argument for a parent type throws * No need to branch out for constructed generic parent * Update method name
1 parent 69340eb commit a4faf10

File tree

3 files changed

+35
-16
lines changed

3 files changed

+35
-16
lines changed

src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs

+14-14
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,7 @@ private static MemberInfo GetOriginalMemberIfConstructedType(MethodBase methodBa
609609
Type declaringType = methodBase.DeclaringType!;
610610
if (declaringType.IsConstructedGenericType &&
611611
declaringType.GetGenericTypeDefinition() is not TypeBuilderImpl &&
612-
!ContainsNotBakedTypeBuilder(declaringType.GetGenericArguments()))
612+
!ContainsTypeBuilder(declaringType.GetGenericArguments()))
613613
{
614614
return declaringType.GetGenericTypeDefinition().GetMemberWithSameMetadataDefinitionAs(methodBase);
615615
}
@@ -883,19 +883,19 @@ private static int GetTokenForHandle(EntityHandle handle)
883883

884884
private EntityHandle GetHandleForMember(MemberInfo member)
885885
{
886-
if (IsConstructedFromNotBakedTypeBuilder(member.DeclaringType!))
886+
if (IsConstructedFromTypeBuilder(member.DeclaringType!))
887887
{
888888
return default;
889889
}
890890

891891
return GetMemberReferenceHandle(member);
892892
}
893893

894-
private static bool IsConstructedFromNotBakedTypeBuilder(Type type) => type.IsConstructedGenericType &&
894+
private static bool IsConstructedFromTypeBuilder(Type type) => type.IsConstructedGenericType &&
895895
(type.GetGenericTypeDefinition() is TypeBuilderImpl ||
896-
ContainsNotBakedTypeBuilder(type.GetGenericArguments()));
896+
ContainsTypeBuilder(type.GetGenericArguments()));
897897

898-
private static bool ContainsNotBakedTypeBuilder(Type[] genericArguments)
898+
internal static bool ContainsTypeBuilder(Type[] genericArguments)
899899
{
900900
foreach (Type type in genericArguments)
901901
{
@@ -904,7 +904,7 @@ private static bool ContainsNotBakedTypeBuilder(Type[] genericArguments)
904904
return true;
905905
}
906906

907-
if (IsConstructedFromNotBakedTypeBuilder(type))
907+
if (IsConstructedFromTypeBuilder(type))
908908
{
909909
return true;
910910
}
@@ -925,7 +925,7 @@ internal EntityHandle TryGetTypeHandle(Type type)
925925
return eb._typeBuilder._handle;
926926
}
927927

928-
if (IsConstructedFromNotBakedTypeBuilder(type))
928+
if (IsConstructedFromTypeBuilder(type))
929929
{
930930
return default;
931931
}
@@ -954,20 +954,20 @@ internal EntityHandle TryGetMethodHandle(MethodInfo method)
954954
return mb._handle;
955955
}
956956

957-
if (IsConstructedMethodFromNotBakedMethodBuilder(method) ||
958-
IsArrayMethodFromNotBakedTypeBuilder(method))
957+
if (IsConstructedFromMethodBuilderOrTypeBuilder(method) ||
958+
IsArrayMethodTypeIsTypeBuilder(method))
959959
{
960960
return default;
961961
}
962962

963963
return GetHandleForMember(method);
964964
}
965965

966-
private static bool IsArrayMethodFromNotBakedTypeBuilder(MethodInfo method) => method is ArrayMethod arrayMethod &&
967-
arrayMethod.DeclaringType!.GetElementType() is TypeBuilderImpl tb && tb._handle == default;
966+
private static bool IsArrayMethodTypeIsTypeBuilder(MethodInfo method) => method is ArrayMethod arrayMethod &&
967+
arrayMethod.DeclaringType!.GetElementType() is TypeBuilderImpl;
968968

969-
private static bool IsConstructedMethodFromNotBakedMethodBuilder(MethodInfo method) => method.IsConstructedGenericMethod &&
970-
(method.GetGenericMethodDefinition() is MethodBuilderImpl mb && mb._handle == default || ContainsNotBakedTypeBuilder(method.GetGenericArguments()));
969+
private static bool IsConstructedFromMethodBuilderOrTypeBuilder(MethodInfo method) => method.IsConstructedGenericMethod &&
970+
(method.GetGenericMethodDefinition() is MethodBuilderImpl || ContainsTypeBuilder(method.GetGenericArguments()));
971971

972972
internal EntityHandle TryGetMethodHandle(MethodInfo method, Type[] optionalParameterTypes)
973973
{
@@ -982,7 +982,7 @@ internal EntityHandle TryGetMethodHandle(MethodInfo method, Type[] optionalParam
982982
return mb._handle;
983983
}
984984

985-
if (IsConstructedMethodFromNotBakedMethodBuilder(method))
985+
if (IsConstructedFromMethodBuilderOrTypeBuilder(method))
986986
{
987987
return default;
988988
}

src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,11 @@ private ConstructorBuilderImpl DefineDefaultConstructorInternal(MethodAttributes
211211
{
212212
// Get the parent class's default constructor and add it to the IL
213213
ConstructorInfo? con;
214-
if (_typeParent!.IsConstructedGenericType && _typeParent.GetGenericTypeDefinition() is TypeBuilderImpl typeBuilder)
214+
if (_typeParent!.IsConstructedGenericType &&
215+
(_typeParent.GetGenericTypeDefinition() is TypeBuilderImpl || ModuleBuilderImpl.ContainsTypeBuilder(_typeParent.GetGenericArguments())))
215216
{
216-
con = GetConstructor(_typeParent, typeBuilder.GetConstructor(
217+
// When TypeBuilder involved need to construct the parent constructor using TypeBuilder.GetConstructor() static method
218+
con = GetConstructor(_typeParent, _typeParent.GetGenericTypeDefinition().GetConstructor(
217219
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, EmptyTypes, null)!);
218220
}
219221
else

src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveTypeBuilderTests.cs

+17
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,23 @@ public void MethodBuilderGetParametersReturnParameterTest()
649649
Assert.Null(method3.ReturnParameter.Name);
650650
Assert.True(method3.ReturnParameter.IsRetval);
651651
}
652+
653+
public class BaseType<T> { }
654+
655+
[Fact]
656+
public void GenericTypeWithTypeBuilderGenericParameter_UsedAsParent()
657+
{
658+
PersistedAssemblyBuilder ab = AssemblySaveTools.PopulateAssemblyBuilderAndTypeBuilder(out TypeBuilder typeBuilder);
659+
660+
Type type = typeBuilder.CreateType();
661+
var baseType = typeof(BaseType<>).GetGenericTypeDefinition().MakeGenericType(type);
662+
663+
var typeBuilder2 = ab.GetDynamicModule("MyModule")
664+
.DefineType("TestService", TypeAttributes.Public | TypeAttributes.Class, baseType);
665+
typeBuilder2.CreateType();
666+
667+
Assert.NotNull(type.GetConstructor(Type.EmptyTypes)); // Default constructor created
668+
}
652669
}
653670

654671
// Test Types

0 commit comments

Comments
 (0)