Skip to content

Commit

Permalink
Add implementations for MakePointerType(), MakeArrayType() for Generi…
Browse files Browse the repository at this point in the history
…cTypeParameterBuilder (dotnet#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>
  • Loading branch information
buyaa-n and AaronRobinsonMSFT committed Feb 8, 2024
1 parent d31ce26 commit e87d5d9
Show file tree
Hide file tree
Showing 20 changed files with 932 additions and 168 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public override object Invoke(object? obj, BindingFlags invokeAttr, Binder? bind
public override CallingConventions CallingConvention => _ctor.CallingConvention;
public override Type[] GetGenericArguments() { return _ctor.GetGenericArguments(); }
public override bool IsGenericMethodDefinition => false;
public override bool ContainsGenericParameters => false;
public override bool ContainsGenericParameters => _type.ContainsGenericParameters;

public override bool IsGenericMethod => false;
#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,26 @@ public override bool ContainsGenericParameters
{
get
{
if (_method.ContainsGenericParameters)
if (_method.ContainsGenericParameters || _type.ContainsGenericParameters)
{
return true;
if (!_method.IsGenericMethodDefinition)
throw new NotSupportedException();
}

return _method.ContainsGenericParameters;
if (!IsGenericMethod)
{
return false;
}

Type[] args = GetGenericArguments();
for (int i = 0; i < args.Length; i++)
{
if (args[i].ContainsGenericParameters)
{
return true;
}
}

return false;
}
}
[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.")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,18 +271,30 @@ public override Type MakeByRefType()
return FormCompoundType(_format + "&", _baseType, 0)!;
}

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

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

internal static string FormatRank(int rank)
{
if (rank <= 0)
{
throw new IndexOutOfRangeException();
}

return rank == 1 ? "[*]" : "[" + new string(',', rank - 1) + "]";
}

public override int GetArrayRank()
{
if (!IsArray)
Expand Down Expand Up @@ -440,18 +452,25 @@ public override Type GetNestedType(string name, BindingFlags bindingAttr)
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}

[DynamicallyAccessedMembers(GetAllMembers)]
[DynamicallyAccessedMembers(GetAllMembersInternal)]
public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}

[DynamicallyAccessedMembers(GetAllMembers)]
[DynamicallyAccessedMembers(GetAllMembersInternal)]
public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
}

private const DynamicallyAccessedMemberTypes GetAllMembersInternal = DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields |
DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods |
DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents |
DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties |
DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors |
DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes;

public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type interfaceType)
{
throw new NotSupportedException(SR.NotSupported_NonReflectedType);
Expand Down
12 changes: 12 additions & 0 deletions src/libraries/System.Reflection.Emit/src/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -288,4 +288,16 @@
<data name="InvalidOperation_TokenNotPopulated" xml:space="preserve">
<value>MetadataToken for the member is not generated until the assembly saved.</value>
</data>
<data name="Argument_BadSigFormat" xml:space="preserve">
<value>Incorrect signature format.</value>
</data>
<data name="Argument_HasToBeArrayClass" xml:space="preserve">
<value>Must be an array type.</value>
</data>
<data name="NotSupported_NonReflectedType" xml:space="preserve">
<value>Not supported in a non-reflected type.</value>
</data>
<data name="NotSupported_SymbolMethod" xml:space="preserve">
<value>Not supported in an array method of a type definition that is not complete.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

<ItemGroup>
<Compile Include="$(CoreLibSharedDir)System\Reflection\Emit\MethodBuilderInstantiation.cs" Link="System\Reflection\Emit\MethodBuilderInstantiation.cs" />
<Compile Include="$(CoreLibSharedDir)System\Reflection\Emit\SymbolType.cs" Link="System\Reflection\Emit\SymbolType.cs" />
<Compile Include="$(CoreLibSharedDir)System\Reflection\Emit\TypeNameBuilder.cs" Link="System\Reflection\Emit\TypeNameBuilder.cs" />
<Compile Include="System\Reflection\Emit\ArrayMethod.cs" />
<Compile Include="System\Reflection\Emit\ConstructorBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\CustomAttributeWrapper.cs" />
<Compile Include="System\Reflection\Emit\AssemblyBuilderImpl.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Globalization;

namespace System.Reflection.Emit
{
internal sealed class ArrayMethod : MethodInfo
{
#region Private Data Members
private readonly ModuleBuilder _module;
private readonly Type _containingType;
private readonly string _name;
private readonly CallingConventions _callingConvention;
private readonly Type _returnType;
private readonly Type[] _parameterTypes;
#endregion

#region Constructor
// This is a kind of MethodInfo to represent methods for array type of unbaked type
internal ArrayMethod(ModuleBuilder module, Type arrayClass, string methodName,
CallingConventions callingConvention, Type? returnType, Type[]? parameterTypes)
{
_returnType = returnType ?? typeof(void);
if (parameterTypes != null)
{
_parameterTypes = new Type[parameterTypes.Length];
for (int i = 0; i < parameterTypes.Length; i++)
{
ArgumentNullException.ThrowIfNull(_parameterTypes[i] = parameterTypes[i], nameof(parameterTypes));
}
}
else
{
_parameterTypes = Type.EmptyTypes;
}

_module = module;
_containingType = arrayClass;
_name = methodName;
_callingConvention = callingConvention;
}
#endregion

#region Internal Members
internal Type[] ParameterTypes => _parameterTypes;
#endregion

#region MemberInfo Overrides
public override Module Module => _module;

public override Type? ReflectedType => _containingType;

public override string Name => _name;

public override Type? DeclaringType => _containingType;
#endregion

#region MethodBase Overrides
public override ParameterInfo[] GetParameters() => throw new NotSupportedException(SR.NotSupported_SymbolMethod);

public override MethodImplAttributes GetMethodImplementationFlags() => throw new NotSupportedException(SR.NotSupported_SymbolMethod);

public override MethodAttributes Attributes => MethodAttributes.PrivateScope;

public override CallingConventions CallingConvention => _callingConvention;

public override RuntimeMethodHandle MethodHandle => throw new NotSupportedException(SR.NotSupported_SymbolMethod);
#endregion

#region MethodInfo Overrides
public override Type ReturnType => _returnType;

public override ICustomAttributeProvider ReturnTypeCustomAttributes => throw new NotSupportedException(SR.NotSupported_SymbolMethod);

public override object Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture)
=> throw new NotSupportedException(SR.NotSupported_SymbolMethod);

public override MethodInfo GetBaseDefinition() => this;
#endregion

#region ICustomAttributeProvider Implementation
public override object[] GetCustomAttributes(bool inherit) => throw new NotSupportedException(SR.NotSupported_SymbolMethod);

public override object[] GetCustomAttributes(Type attributeType, bool inherit) => throw new NotSupportedException(SR.NotSupported_SymbolMethod);

public override bool IsDefined(Type attributeType, bool inherit) => throw new NotSupportedException(SR.NotSupported_SymbolMethod);
#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ protected override FieldBuilder DefineLiteralCore(string literalName, object? li
{
FieldBuilder fieldBuilder = _typeBuilder.DefineField(
literalName,
_typeBuilder,
this,
FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal);
fieldBuilder.SetConstant(literalValue);
return fieldBuilder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,14 @@ internal static void ValidateDefaultValueType(object? defaultValue, Type destina
{
underlyingType = enumBldr.GetEnumUnderlyingType();

if (sourceType != enumBldr._typeBuilder.UnderlyingSystemType && sourceType != underlyingType)
if (sourceType != enumBldr._typeBuilder.UnderlyingSystemType &&
sourceType != underlyingType &&
// If the source type is an enum, should not throw when the underlying types match
sourceType.IsEnum &&
sourceType.GetEnumUnderlyingType() != underlyingType)
{
throw new ArgumentException(SR.Argument_ConstantDoesntMatch);
}
}
else if (destinationType is TypeBuilderImpl typeBldr)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public override Type[] GetGenericParameterConstraints() =>
public override bool IsGenericType => false;
public override bool IsGenericParameter => true;
public override bool IsConstructedGenericType => false;
public override bool ContainsGenericParameters => _type.ContainsGenericParameters;
public override bool ContainsGenericParameters => false;
public override MethodBase? DeclaringMethod => _type.DeclaringMethod;
public override Type? BaseType => _parent;
public override RuntimeTypeHandle TypeHandle => throw new NotSupportedException();
Expand Down Expand Up @@ -137,5 +137,19 @@ public override Type[] GetGenericParameterConstraints() =>
public override MemberInfo[] GetMembers(BindingFlags bindingAttr) => throw new NotSupportedException();
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
public override object InvokeMember(string name, BindingFlags invokeAttr, Binder? binder, object? target, object?[]? args, ParameterModifier[]? modifiers, CultureInfo? culture, string[]? namedParameters) => throw new NotSupportedException();

public override Type MakePointerType() =>
SymbolType.FormCompoundType("*", this, 0)!;

public override Type MakeByRefType() =>
SymbolType.FormCompoundType("&", this, 0)!;

[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
public override Type MakeArrayType() =>
SymbolType.FormCompoundType("[]", this, 0)!;

[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
public override Type MakeArrayType(int rank) =>
SymbolType.FormCompoundType(SymbolType.FormatRank(rank), this, 0)!;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ public override void Emit(OpCode opcode, ConstructorInfo con)

EmitOpcode(opcode);
UpdateStackSize(stackChange);
WriteOrReserveToken(_moduleBuilder.GetConstructorHandle(con), con);
WriteOrReserveToken(_moduleBuilder.TryGetConstructorHandle(con), con);
}

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

EmitOpcode(opcode);
WriteOrReserveToken(_moduleBuilder.GetFieldHandle(field), field);
WriteOrReserveToken(_moduleBuilder.TryGetFieldHandle(field), field);
}

public override void Emit(OpCode opcode, MethodInfo meth)
Expand All @@ -567,7 +567,7 @@ public override void Emit(OpCode opcode, MethodInfo meth)
else
{
EmitOpcode(opcode);
WriteOrReserveToken(_moduleBuilder.GetMethodHandle(meth), meth);
WriteOrReserveToken(_moduleBuilder.TryGetMethodHandle(meth), meth);
}
}

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

EmitOpcode(opcode);
WriteOrReserveToken(_moduleBuilder.GetTypeHandle(cls), cls);
WriteOrReserveToken(_moduleBuilder.TryGetTypeHandle(cls), cls);
}

public override void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[]? optionalParameterTypes)
Expand All @@ -592,11 +592,11 @@ public override void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[]? opti
UpdateStackSize(GetStackChange(opcode, methodInfo, optionalParameterTypes));
if (optionalParameterTypes == null || optionalParameterTypes.Length == 0)
{
WriteOrReserveToken(_moduleBuilder.GetMethodHandle(methodInfo), methodInfo);
WriteOrReserveToken(_moduleBuilder.TryGetMethodHandle(methodInfo), methodInfo);
}
else
{
WriteOrReserveToken(_moduleBuilder.GetMethodHandle(methodInfo, optionalParameterTypes),
WriteOrReserveToken(_moduleBuilder.TryGetMethodHandle(methodInfo, optionalParameterTypes),
new KeyValuePair<MethodInfo, Type[]>(methodInfo, optionalParameterTypes));
}
}
Expand All @@ -616,6 +616,10 @@ private static int GetStackChange(OpCode opcode, MethodInfo methodInfo, Type[]?
{
stackChange -= builder.ParameterCount;
}
else if (methodInfo is ArrayMethod sm)
{
stackChange -= sm.ParameterTypes.Length;
}
else
{
stackChange -= methodInfo.GetParameters().Length;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ protected override void SetSignatureCore(Type? returnType, Type[]? returnTypeReq
public override CallingConventions CallingConvention => _callingConventions;
public override Type? DeclaringType => _declaringType._isHiddenGlobalType ? null : _declaringType;
public override Module Module => _module;
public override bool ContainsGenericParameters => throw new NotSupportedException();
public override bool ContainsGenericParameters => _typeParameters != null;
public override bool IsGenericMethod => _typeParameters != null;
public override bool IsGenericMethodDefinition => _typeParameters != null;
public override bool IsSecurityCritical => true;
Expand Down
Loading

0 comments on commit e87d5d9

Please sign in to comment.