Skip to content

Commit e87d5d9

Browse files
Add implementations for MakePointerType(), MakeArrayType() for GenericTypeParameterBuilder (#97350)
* Add implementations for MakePointerType(), MakeArrayType() for GenericTypeParameterBuilder * Fix issue in loading constructed generic method, apply feedbacks * Fix valdiations bugs, issue in constructed generic constuctor reference * Fix more issues related to generic method/type validations and reference, add more test and other implementations * Fix bug with setting constant value for a enum field * Add MethodBuilder.GetArrayMethodCore(...) implementation * Fix bug in Array method, MethodOnTypeBuilderInstantiation and ConstructorInfo reference, remove abstract method validation * Fix token issue with nested generic type, add test for derived type returning different type on method override * Apply suggestions from code review Co-authored-by: Aaron Robinson <arobins@microsoft.com> * Use ActiveIssue attribute for failing test on mono, add comment for enum type case * Rename Get***Handle methods into TryGet***Handle --------- Co-authored-by: Aaron Robinson <arobins@microsoft.com>
1 parent d31ce26 commit e87d5d9

20 files changed

+932
-168
lines changed

src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/ConstructorOnTypeBuilderInstantiation.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public override object Invoke(object? obj, BindingFlags invokeAttr, Binder? bind
5858
public override CallingConventions CallingConvention => _ctor.CallingConvention;
5959
public override Type[] GetGenericArguments() { return _ctor.GetGenericArguments(); }
6060
public override bool IsGenericMethodDefinition => false;
61-
public override bool ContainsGenericParameters => false;
61+
public override bool ContainsGenericParameters => _type.ContainsGenericParameters;
6262

6363
public override bool IsGenericMethod => false;
6464
#endregion

src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/MethodOnTypeBuilderInstantiation.cs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,26 @@ public override bool ContainsGenericParameters
7979
{
8080
get
8181
{
82-
if (_method.ContainsGenericParameters)
82+
if (_method.ContainsGenericParameters || _type.ContainsGenericParameters)
83+
{
8384
return true;
84-
if (!_method.IsGenericMethodDefinition)
85-
throw new NotSupportedException();
85+
}
8686

87-
return _method.ContainsGenericParameters;
87+
if (!IsGenericMethod)
88+
{
89+
return false;
90+
}
91+
92+
Type[] args = GetGenericArguments();
93+
for (int i = 0; i < args.Length; i++)
94+
{
95+
if (args[i].ContainsGenericParameters)
96+
{
97+
return true;
98+
}
99+
}
100+
101+
return false;
88102
}
89103
}
90104
[RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")]

src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/SymbolType.cs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,18 +271,30 @@ public override Type MakeByRefType()
271271
return FormCompoundType(_format + "&", _baseType, 0)!;
272272
}
273273

274+
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
274275
public override Type MakeArrayType()
275276
{
276277
return FormCompoundType(_format + "[]", _baseType, 0)!;
277278
}
278279

280+
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
279281
public override Type MakeArrayType(int rank)
280282
{
281-
string s = GetRankString(rank);
283+
string s = FormatRank(rank);
282284
SymbolType? st = FormCompoundType(_format + s, _baseType, 0) as SymbolType;
283285
return st!;
284286
}
285287

288+
internal static string FormatRank(int rank)
289+
{
290+
if (rank <= 0)
291+
{
292+
throw new IndexOutOfRangeException();
293+
}
294+
295+
return rank == 1 ? "[*]" : "[" + new string(',', rank - 1) + "]";
296+
}
297+
286298
public override int GetArrayRank()
287299
{
288300
if (!IsArray)
@@ -440,18 +452,25 @@ public override Type GetNestedType(string name, BindingFlags bindingAttr)
440452
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
441453
}
442454

443-
[DynamicallyAccessedMembers(GetAllMembers)]
455+
[DynamicallyAccessedMembers(GetAllMembersInternal)]
444456
public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr)
445457
{
446458
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
447459
}
448460

449-
[DynamicallyAccessedMembers(GetAllMembers)]
461+
[DynamicallyAccessedMembers(GetAllMembersInternal)]
450462
public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
451463
{
452464
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
453465
}
454466

467+
private const DynamicallyAccessedMemberTypes GetAllMembersInternal = DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields |
468+
DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods |
469+
DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents |
470+
DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties |
471+
DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors |
472+
DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes;
473+
455474
public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type interfaceType)
456475
{
457476
throw new NotSupportedException(SR.NotSupported_NonReflectedType);

src/libraries/System.Reflection.Emit/src/Resources/Strings.resx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,4 +288,16 @@
288288
<data name="InvalidOperation_TokenNotPopulated" xml:space="preserve">
289289
<value>MetadataToken for the member is not generated until the assembly saved.</value>
290290
</data>
291+
<data name="Argument_BadSigFormat" xml:space="preserve">
292+
<value>Incorrect signature format.</value>
293+
</data>
294+
<data name="Argument_HasToBeArrayClass" xml:space="preserve">
295+
<value>Must be an array type.</value>
296+
</data>
297+
<data name="NotSupported_NonReflectedType" xml:space="preserve">
298+
<value>Not supported in a non-reflected type.</value>
299+
</data>
300+
<data name="NotSupported_SymbolMethod" xml:space="preserve">
301+
<value>Not supported in an array method of a type definition that is not complete.</value>
302+
</data>
291303
</root>

src/libraries/System.Reflection.Emit/src/System.Reflection.Emit.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99

1010
<ItemGroup>
1111
<Compile Include="$(CoreLibSharedDir)System\Reflection\Emit\MethodBuilderInstantiation.cs" Link="System\Reflection\Emit\MethodBuilderInstantiation.cs" />
12+
<Compile Include="$(CoreLibSharedDir)System\Reflection\Emit\SymbolType.cs" Link="System\Reflection\Emit\SymbolType.cs" />
1213
<Compile Include="$(CoreLibSharedDir)System\Reflection\Emit\TypeNameBuilder.cs" Link="System\Reflection\Emit\TypeNameBuilder.cs" />
14+
<Compile Include="System\Reflection\Emit\ArrayMethod.cs" />
1315
<Compile Include="System\Reflection\Emit\ConstructorBuilderImpl.cs" />
1416
<Compile Include="System\Reflection\Emit\CustomAttributeWrapper.cs" />
1517
<Compile Include="System\Reflection\Emit\AssemblyBuilderImpl.cs" />
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Globalization;
5+
6+
namespace System.Reflection.Emit
7+
{
8+
internal sealed class ArrayMethod : MethodInfo
9+
{
10+
#region Private Data Members
11+
private readonly ModuleBuilder _module;
12+
private readonly Type _containingType;
13+
private readonly string _name;
14+
private readonly CallingConventions _callingConvention;
15+
private readonly Type _returnType;
16+
private readonly Type[] _parameterTypes;
17+
#endregion
18+
19+
#region Constructor
20+
// This is a kind of MethodInfo to represent methods for array type of unbaked type
21+
internal ArrayMethod(ModuleBuilder module, Type arrayClass, string methodName,
22+
CallingConventions callingConvention, Type? returnType, Type[]? parameterTypes)
23+
{
24+
_returnType = returnType ?? typeof(void);
25+
if (parameterTypes != null)
26+
{
27+
_parameterTypes = new Type[parameterTypes.Length];
28+
for (int i = 0; i < parameterTypes.Length; i++)
29+
{
30+
ArgumentNullException.ThrowIfNull(_parameterTypes[i] = parameterTypes[i], nameof(parameterTypes));
31+
}
32+
}
33+
else
34+
{
35+
_parameterTypes = Type.EmptyTypes;
36+
}
37+
38+
_module = module;
39+
_containingType = arrayClass;
40+
_name = methodName;
41+
_callingConvention = callingConvention;
42+
}
43+
#endregion
44+
45+
#region Internal Members
46+
internal Type[] ParameterTypes => _parameterTypes;
47+
#endregion
48+
49+
#region MemberInfo Overrides
50+
public override Module Module => _module;
51+
52+
public override Type? ReflectedType => _containingType;
53+
54+
public override string Name => _name;
55+
56+
public override Type? DeclaringType => _containingType;
57+
#endregion
58+
59+
#region MethodBase Overrides
60+
public override ParameterInfo[] GetParameters() => throw new NotSupportedException(SR.NotSupported_SymbolMethod);
61+
62+
public override MethodImplAttributes GetMethodImplementationFlags() => throw new NotSupportedException(SR.NotSupported_SymbolMethod);
63+
64+
public override MethodAttributes Attributes => MethodAttributes.PrivateScope;
65+
66+
public override CallingConventions CallingConvention => _callingConvention;
67+
68+
public override RuntimeMethodHandle MethodHandle => throw new NotSupportedException(SR.NotSupported_SymbolMethod);
69+
#endregion
70+
71+
#region MethodInfo Overrides
72+
public override Type ReturnType => _returnType;
73+
74+
public override ICustomAttributeProvider ReturnTypeCustomAttributes => throw new NotSupportedException(SR.NotSupported_SymbolMethod);
75+
76+
public override object Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture)
77+
=> throw new NotSupportedException(SR.NotSupported_SymbolMethod);
78+
79+
public override MethodInfo GetBaseDefinition() => this;
80+
#endregion
81+
82+
#region ICustomAttributeProvider Implementation
83+
public override object[] GetCustomAttributes(bool inherit) => throw new NotSupportedException(SR.NotSupported_SymbolMethod);
84+
85+
public override object[] GetCustomAttributes(Type attributeType, bool inherit) => throw new NotSupportedException(SR.NotSupported_SymbolMethod);
86+
87+
public override bool IsDefined(Type attributeType, bool inherit) => throw new NotSupportedException(SR.NotSupported_SymbolMethod);
88+
#endregion
89+
}
90+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ protected override FieldBuilder DefineLiteralCore(string literalName, object? li
3232
{
3333
FieldBuilder fieldBuilder = _typeBuilder.DefineField(
3434
literalName,
35-
_typeBuilder,
35+
this,
3636
FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal);
3737
fieldBuilder.SetConstant(literalValue);
3838
return fieldBuilder;

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,14 @@ internal static void ValidateDefaultValueType(object? defaultValue, Type destina
7474
{
7575
underlyingType = enumBldr.GetEnumUnderlyingType();
7676

77-
if (sourceType != enumBldr._typeBuilder.UnderlyingSystemType && sourceType != underlyingType)
77+
if (sourceType != enumBldr._typeBuilder.UnderlyingSystemType &&
78+
sourceType != underlyingType &&
79+
// If the source type is an enum, should not throw when the underlying types match
80+
sourceType.IsEnum &&
81+
sourceType.GetEnumUnderlyingType() != underlyingType)
82+
{
7883
throw new ArgumentException(SR.Argument_ConstantDoesntMatch);
84+
}
7985
}
8086
else if (destinationType is TypeBuilderImpl typeBldr)
8187
{

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public override Type[] GetGenericParameterConstraints() =>
8383
public override bool IsGenericType => false;
8484
public override bool IsGenericParameter => true;
8585
public override bool IsConstructedGenericType => false;
86-
public override bool ContainsGenericParameters => _type.ContainsGenericParameters;
86+
public override bool ContainsGenericParameters => false;
8787
public override MethodBase? DeclaringMethod => _type.DeclaringMethod;
8888
public override Type? BaseType => _parent;
8989
public override RuntimeTypeHandle TypeHandle => throw new NotSupportedException();
@@ -137,5 +137,19 @@ public override Type[] GetGenericParameterConstraints() =>
137137
public override MemberInfo[] GetMembers(BindingFlags bindingAttr) => throw new NotSupportedException();
138138
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
139139
public override object InvokeMember(string name, BindingFlags invokeAttr, Binder? binder, object? target, object?[]? args, ParameterModifier[]? modifiers, CultureInfo? culture, string[]? namedParameters) => throw new NotSupportedException();
140+
141+
public override Type MakePointerType() =>
142+
SymbolType.FormCompoundType("*", this, 0)!;
143+
144+
public override Type MakeByRefType() =>
145+
SymbolType.FormCompoundType("&", this, 0)!;
146+
147+
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
148+
public override Type MakeArrayType() =>
149+
SymbolType.FormCompoundType("[]", this, 0)!;
150+
151+
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
152+
public override Type MakeArrayType(int rank) =>
153+
SymbolType.FormCompoundType(SymbolType.FormatRank(rank), this, 0)!;
140154
}
141155
}

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

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ public override void Emit(OpCode opcode, ConstructorInfo con)
418418

419419
EmitOpcode(opcode);
420420
UpdateStackSize(stackChange);
421-
WriteOrReserveToken(_moduleBuilder.GetConstructorHandle(con), con);
421+
WriteOrReserveToken(_moduleBuilder.TryGetConstructorHandle(con), con);
422422
}
423423

424424
private void WriteOrReserveToken(EntityHandle handle, object member)
@@ -553,7 +553,7 @@ public override void Emit(OpCode opcode, FieldInfo field)
553553
ArgumentNullException.ThrowIfNull(field);
554554

555555
EmitOpcode(opcode);
556-
WriteOrReserveToken(_moduleBuilder.GetFieldHandle(field), field);
556+
WriteOrReserveToken(_moduleBuilder.TryGetFieldHandle(field), field);
557557
}
558558

559559
public override void Emit(OpCode opcode, MethodInfo meth)
@@ -567,7 +567,7 @@ public override void Emit(OpCode opcode, MethodInfo meth)
567567
else
568568
{
569569
EmitOpcode(opcode);
570-
WriteOrReserveToken(_moduleBuilder.GetMethodHandle(meth), meth);
570+
WriteOrReserveToken(_moduleBuilder.TryGetMethodHandle(meth), meth);
571571
}
572572
}
573573

@@ -576,7 +576,7 @@ public override void Emit(OpCode opcode, Type cls)
576576
ArgumentNullException.ThrowIfNull(cls);
577577

578578
EmitOpcode(opcode);
579-
WriteOrReserveToken(_moduleBuilder.GetTypeHandle(cls), cls);
579+
WriteOrReserveToken(_moduleBuilder.TryGetTypeHandle(cls), cls);
580580
}
581581

582582
public override void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[]? optionalParameterTypes)
@@ -592,11 +592,11 @@ public override void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[]? opti
592592
UpdateStackSize(GetStackChange(opcode, methodInfo, optionalParameterTypes));
593593
if (optionalParameterTypes == null || optionalParameterTypes.Length == 0)
594594
{
595-
WriteOrReserveToken(_moduleBuilder.GetMethodHandle(methodInfo), methodInfo);
595+
WriteOrReserveToken(_moduleBuilder.TryGetMethodHandle(methodInfo), methodInfo);
596596
}
597597
else
598598
{
599-
WriteOrReserveToken(_moduleBuilder.GetMethodHandle(methodInfo, optionalParameterTypes),
599+
WriteOrReserveToken(_moduleBuilder.TryGetMethodHandle(methodInfo, optionalParameterTypes),
600600
new KeyValuePair<MethodInfo, Type[]>(methodInfo, optionalParameterTypes));
601601
}
602602
}
@@ -616,6 +616,10 @@ private static int GetStackChange(OpCode opcode, MethodInfo methodInfo, Type[]?
616616
{
617617
stackChange -= builder.ParameterCount;
618618
}
619+
else if (methodInfo is ArrayMethod sm)
620+
{
621+
stackChange -= sm.ParameterTypes.Length;
622+
}
619623
else
620624
{
621625
stackChange -= methodInfo.GetParameters().Length;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ protected override void SetSignatureCore(Type? returnType, Type[]? returnTypeReq
243243
public override CallingConventions CallingConvention => _callingConventions;
244244
public override Type? DeclaringType => _declaringType._isHiddenGlobalType ? null : _declaringType;
245245
public override Module Module => _module;
246-
public override bool ContainsGenericParameters => throw new NotSupportedException();
246+
public override bool ContainsGenericParameters => _typeParameters != null;
247247
public override bool IsGenericMethod => _typeParameters != null;
248248
public override bool IsGenericMethodDefinition => _typeParameters != null;
249249
public override bool IsSecurityCritical => true;

0 commit comments

Comments
 (0)