Write generic method, write complex signatures like array/pointer/generics (#86026)
authorBuyaa Namnan <bunamnan@microsoft.com>
Fri, 12 May 2023 21:12:45 +0000 (14:12 -0700)
committerGitHub <noreply@github.com>
Fri, 12 May 2023 21:12:45 +0000 (14:12 -0700)
* Write generic method, write complex signatures like array/pointer/generics

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

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
* Update src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/MethodBuilderImpl.cs

---------

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.cs
src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.cs
src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs
src/libraries/System.Reflection.Emit/src/Resources/Strings.resx
src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/GenericTypeParameterBuilderImpl.cs
src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/MethodBuilderImpl.cs
src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs
src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs
src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs
src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveWithVariousMembersTests.cs
src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.Mono.cs

index bac45a0..ecf34b5 100644 (file)
@@ -519,17 +519,18 @@ namespace System.Reflection.Emit
             if (m_inst != null)
                 throw new InvalidOperationException(SR.InvalidOperation_GenericParametersAlreadySet);
 
-            for (int i = 0; i < names.Length; i++)
-                ArgumentNullException.ThrowIfNull(names[i], nameof(names));
-
             if (m_token != 0)
                 throw new InvalidOperationException(SR.InvalidOperation_MethodBuilderBaked);
 
-            m_bIsGenMethDef = true;
             m_inst = new RuntimeGenericTypeParameterBuilder[names.Length];
             for (int i = 0; i < names.Length; i++)
-                m_inst[i] = new RuntimeGenericTypeParameterBuilder(new RuntimeTypeBuilder(names[i], i, this));
+            {
+                string name = names[i];
+                ArgumentNullException.ThrowIfNull(name, nameof(names));
+                m_inst[i] = new RuntimeGenericTypeParameterBuilder(new RuntimeTypeBuilder(name, i, this));
+            }
 
+            m_bIsGenMethDef = true;
             return m_inst;
         }
 
index 80b871a..47b7191 100644 (file)
@@ -1061,29 +1061,6 @@ namespace System.Reflection.Emit
             }
         }
 
-        public override Type MakePointerType()
-        {
-            return SymbolType.FormCompoundType("*", this, 0)!;
-        }
-
-        public override Type MakeByRefType()
-        {
-            return SymbolType.FormCompoundType("&", this, 0)!;
-        }
-
-        [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
-        public override Type MakeArrayType()
-        {
-            return SymbolType.FormCompoundType("[]", this, 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);
-            return SymbolType.FormCompoundType(s, this, 0)!;
-        }
-
         #endregion
 
         #region ICustomAttributeProvider Implementation
@@ -1157,13 +1134,6 @@ namespace System.Reflection.Emit
             return m_inst;
         }
 
-        [RequiresDynamicCode("The native code for this instantiation might not be available at runtime.")]
-        [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.")]
-        public override Type MakeGenericType(params Type[] typeArguments)
-        {
-            return TypeBuilderInstantiation.MakeGenericType(this, typeArguments);
-        }
-
         public override Type[] GetGenericArguments() => m_inst ?? Type.EmptyTypes;
 
         // If a TypeBuilder is generic, it must be a generic type definition
index e3f3b9a..d6b0941 100644 (file)
@@ -290,5 +290,35 @@ namespace System.Reflection.Emit
             => SetParentCore(parent);
 
         protected abstract void SetParentCore([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent);
+
+        public override Type MakePointerType()
+        {
+            return SymbolType.FormCompoundType("*", this, 0)!;
+        }
+
+        public override Type MakeByRefType()
+        {
+            return SymbolType.FormCompoundType("&", this, 0)!;
+        }
+
+        [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
+        public override Type MakeArrayType()
+        {
+            return SymbolType.FormCompoundType("[]", this, 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);
+            return SymbolType.FormCompoundType(s, this, 0)!;
+        }
+
+        [RequiresDynamicCode("The native code for this instantiation might not be available at runtime.")]
+        [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.")]
+        public override Type MakeGenericType(params Type[] typeArguments)
+        {
+            return TypeBuilderInstantiation.MakeGenericType(this, typeArguments);
+        }
     }
 }
index ad9a578..5ff83e0 100644 (file)
   <data name="Argument_SizeConstMustBeSpecified" xml:space="preserve">
     <value>SizeConst parameter must be specified for UnmanagedType.ByValTStr type.</value>
   </data>
-</root>
+  <data name="InvalidOperation_GenericParametersAlreadySet" xml:space="preserve">
+    <value>The generic parameters are already defined on this MethodBuilder.</value>
+  </data>
+</root>
\ No newline at end of file
index 0176c5f..fbaa3af 100644 (file)
@@ -4,28 +4,38 @@
 using System.Collections.Generic;
 using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
+using System.Reflection.Metadata;
 
 namespace System.Reflection.Emit
 {
     internal sealed class GenericTypeParameterBuilderImpl : GenericTypeParameterBuilder
     {
         private readonly string _name;
-        private readonly TypeBuilderImpl _type;
+        private readonly TypeBuilder _type;
         private readonly int _genParamPosition;
         private GenericParameterAttributes _genParamAttributes;
-        private bool _isGenericMethodParameter;
         [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
         private Type? _parent;
 
         internal List<CustomAttributeWrapper>? _customAttributes;
         internal List<Type>? _interfaces;
+        private MethodBuilderImpl? _methodBuilder;
+        internal EntityHandle _parentHandle;
 
-        internal GenericTypeParameterBuilderImpl(string name, int genParamPosition, TypeBuilderImpl typeBuilder)
+        internal GenericTypeParameterBuilderImpl(string name, int genParamPosition, TypeBuilderImpl typeBuilder, EntityHandle parentHandle)
         {
             _name = name;
             _genParamPosition = genParamPosition;
             _type = typeBuilder;
-            _isGenericMethodParameter = false;
+            _parentHandle = parentHandle;
+        }
+
+        public GenericTypeParameterBuilderImpl(string name, int genParamPosition, MethodBuilderImpl methodBuilder)
+        {
+            _name = name;
+            _genParamPosition = genParamPosition;
+            _methodBuilder = methodBuilder;
+            _type = methodBuilder.DeclaringType;
         }
 
         protected override void SetBaseTypeConstraintCore([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? baseTypeConstraint)
@@ -59,8 +69,8 @@ namespace System.Reflection.Emit
 
         public override Type[] GetGenericParameterConstraints() =>
             _interfaces == null ? EmptyTypes : _interfaces.ToArray();
-        public override bool IsGenericTypeParameter => !_isGenericMethodParameter;
-        public override bool IsGenericMethodParameter => _isGenericMethodParameter;
+        public override bool IsGenericTypeParameter => _methodBuilder is null;
+        public override bool IsGenericMethodParameter => _methodBuilder is not null;
         public override int GenericParameterPosition => _genParamPosition;
         public override GenericParameterAttributes GenericParameterAttributes => _genParamAttributes;
         public override string Name => _name;
index 99cdace..dbf38bc 100644 (file)
@@ -3,24 +3,23 @@
 
 using System.Buffers.Binary;
 using System.Collections.Generic;
-using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Reflection.Metadata;
-using System.Runtime.InteropServices;
 
 namespace System.Reflection.Emit
 {
     internal sealed class MethodBuilderImpl : MethodBuilder
     {
-        private readonly Type _returnType;
-        private readonly Type[]? _parameterTypes;
+        private Type _returnType;
+        private Type[]? _parameterTypes;
         private readonly ModuleBuilderImpl _module;
         private readonly string _name;
         private readonly CallingConventions _callingConventions;
         private readonly TypeBuilderImpl _declaringType;
         private MethodAttributes _attributes;
         private MethodImplAttributes _methodImplFlags;
+        private GenericTypeParameterBuilderImpl[]? _typeParameters;
 
         internal DllImportData? _dllImportData;
         internal List<CustomAttributeWrapper>? _customAttributes;
@@ -49,11 +48,43 @@ namespace System.Reflection.Emit
             _methodImplFlags = MethodImplAttributes.IL;
         }
 
-        internal BlobBuilder GetMethodSignatureBlob() =>
-            MetadataSignatureHelper.MethodSignatureEncoder(_module, _parameterTypes, ReturnType, !IsStatic);
+        internal BlobBuilder GetMethodSignatureBlob() => MetadataSignatureHelper.MethodSignatureEncoder(_module,
+            _parameterTypes, ReturnType, GetSignatureConvention(_callingConventions), GetGenericArguments().Length, !IsStatic);
 
+        internal static SignatureCallingConvention GetSignatureConvention(CallingConventions callingConventions)
+        {
+            // TODO: find out and handle other SignatureCallingConvention scenarios
+            SignatureCallingConvention convention = SignatureCallingConvention.Default;
+            if ((callingConventions & CallingConventions.HasThis) != 0 ||
+                (callingConventions & CallingConventions.ExplicitThis) != 0)
+            {
+                convention |= SignatureCallingConvention.ThisCall;
+            }
+
+            if ((callingConventions & CallingConventions.VarArgs) != 0)
+            {
+                convention |= SignatureCallingConvention.VarArgs;
+            }
+
+            return convention;
+        }
         protected override bool InitLocalsCore { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
-        protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(params string[] names) => throw new NotImplementedException();
+        protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(params string[] names)
+        {
+            if (_typeParameters != null)
+                throw new InvalidOperationException(SR.InvalidOperation_GenericParametersAlreadySet);
+
+            var typeParameters = new GenericTypeParameterBuilderImpl[names.Length];
+            for (int i = 0; i < names.Length; i++)
+            {
+                string name = names[i];
+                ArgumentNullException.ThrowIfNull(names, nameof(names));
+                typeParameters[i] = new GenericTypeParameterBuilderImpl(name, i, this);
+            }
+
+            return _typeParameters = typeParameters;
+        }
+
         protected override ParameterBuilder DefineParameterCore(int position, ParameterAttributes attributes, string? strParamName)
         {
             if (position > 0 && (_parameterTypes == null || position > _parameterTypes.Length))
@@ -66,6 +97,7 @@ namespace System.Reflection.Emit
             _parameters[position] = parameter;
             return parameter;
         }
+
         protected override ILGenerator GetILGeneratorCore(int size) => throw new NotImplementedException();
         protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
         {
@@ -106,15 +138,32 @@ namespace System.Reflection.Emit
             _methodImplFlags = attributes;
         }
         protected override void SetSignatureCore(Type? returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers, Type[]? parameterTypes,
-            Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers) => throw new NotImplementedException();
+            Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers)
+        {
+            if (returnType != null)
+            {
+                _returnType = returnType;
+            }
+
+            if (parameterTypes != null)
+            {
+                _parameterTypes = new Type[parameterTypes.Length];
+                _parameters = new ParameterBuilderImpl[parameterTypes.Length + 1]; // parameter 0 reserved for return type
+                for (int i = 0; i < parameterTypes.Length; i++)
+                {
+                    ArgumentNullException.ThrowIfNull(_parameterTypes[i] = parameterTypes[i], nameof(parameterTypes));
+                }
+            }
+            // TODO: Add support for other parameters: returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypeRequiredCustomModifiers and parameterTypeOptionalCustomModifiers
+        }
         public override string Name => _name;
         public override MethodAttributes Attributes => _attributes;
         public override CallingConventions CallingConvention => _callingConventions;
         public override TypeBuilder DeclaringType => _declaringType;
         public override Module Module => _module;
-        public override bool ContainsGenericParameters { get => throw new NotSupportedException(SR.NotSupported_DynamicModule); }
-        public override bool IsGenericMethod { get => throw new NotImplementedException(); }
-        public override bool IsGenericMethodDefinition { get => throw new NotImplementedException(); }
+        public override bool ContainsGenericParameters => throw new NotSupportedException();
+        public override bool IsGenericMethod => _typeParameters != null;
+        public override bool IsGenericMethodDefinition => _typeParameters != null;
         public override bool IsSecurityCritical => true;
         public override bool IsSecuritySafeCritical => false;
         public override bool IsSecurityTransparent => false;
@@ -131,11 +180,9 @@ namespace System.Reflection.Emit
 
         public override object[] GetCustomAttributes(Type attributeType, bool inherit) => throw new NotSupportedException(SR.NotSupported_DynamicModule);
 
-        public override Type[] GetGenericArguments()
-            => throw new NotImplementedException();
+        public override Type[] GetGenericArguments() => _typeParameters ?? Type.EmptyTypes;
 
-        public override MethodInfo GetGenericMethodDefinition()
-            => throw new NotImplementedException();
+        public override MethodInfo GetGenericMethodDefinition() => !IsGenericMethod ? throw new InvalidOperationException() : this;
 
         public override int GetHashCode()
             => throw new NotImplementedException();
index 15cbe7c..a135ed2 100644 (file)
@@ -119,6 +119,8 @@ namespace System.Reflection.Emit
 
             WriteCustomAttributes(_customAttributes, moduleHandle);
 
+            // All generic parameters for all types and methods should be written in specific order
+            List<GenericTypeParameterBuilderImpl> genericParams = new();
             // Add each type definition to metadata table.
             foreach (TypeBuilderImpl typeBuilder in _typeDefinitions)
             {
@@ -133,15 +135,9 @@ namespace System.Reflection.Emit
 
                 if (typeBuilder.IsGenericType)
                 {
-                    foreach (GenericTypeParameterBuilderImpl gParam in typeBuilder.GenericTypeParameters)
+                    foreach (GenericTypeParameterBuilderImpl param in typeBuilder.GenericTypeParameters)
                     {
-                        GenericParameterHandle handle = AddGenericTypeParameter(typeHandle, gParam);
-                        WriteCustomAttributes(gParam._customAttributes, handle);
-
-                        foreach (Type constraint in gParam.GetGenericParameterConstraints())
-                        {
-                            _metadataBuilder.AddGenericParameterConstraint(handle, GetTypeHandle(constraint));
-                        }
+                        genericParams.Add(param);
                     }
                 }
 
@@ -165,12 +161,26 @@ namespace System.Reflection.Emit
                 }
 
                 WriteCustomAttributes(typeBuilder._customAttributes, typeHandle);
-                WriteMethods(typeBuilder);
+                WriteMethods(typeBuilder, genericParams);
                 WriteFields(typeBuilder);
             }
+
+            // Now write all generic parameters in order
+            genericParams.Sort((x, y) => {
+                int primary = CodedIndex.TypeOrMethodDef(x._parentHandle).CompareTo(CodedIndex.TypeOrMethodDef(y._parentHandle));
+                if (primary != 0)
+                    return primary;
+
+                return x.GenericParameterPosition.CompareTo(y.GenericParameterPosition);
+            });
+
+            foreach (GenericTypeParameterBuilderImpl param in genericParams)
+            {
+                AddGenericTypeParametersAndConstraintsCustomAttributes(param._parentHandle, param);
+            }
         }
 
-        private void WriteMethods(TypeBuilderImpl typeBuilder)
+        private void WriteMethods(TypeBuilderImpl typeBuilder, List<GenericTypeParameterBuilderImpl> genericParams)
         {
             foreach (MethodBuilderImpl method in typeBuilder._methodDefinitions)
             {
@@ -178,6 +188,17 @@ namespace System.Reflection.Emit
                 WriteCustomAttributes(method._customAttributes, methodHandle);
                 _nextMethodDefRowId++;
 
+                if (method.IsGenericMethodDefinition)
+                {
+                    Type[] gParams = method.GetGenericArguments();
+                    for (int i = 0; i < gParams.Length; i++)
+                    {
+                        GenericTypeParameterBuilderImpl param = (GenericTypeParameterBuilderImpl)gParams[i];
+                        param._parentHandle = methodHandle;
+                        genericParams.Add(param);
+                    }
+                }
+
                 if (method._parameters != null)
                 {
                     foreach (ParameterBuilderImpl parameter in method._parameters)
@@ -289,13 +310,21 @@ namespace System.Reflection.Emit
             return handle;
         }
 
-        private GenericParameterHandle AddGenericTypeParameter(TypeDefinitionHandle typeHandle, GenericTypeParameterBuilderImpl gParam) =>
-            _metadataBuilder.AddGenericParameter(
-                parent: typeHandle,
+        private void AddGenericTypeParametersAndConstraintsCustomAttributes(EntityHandle parentHandle, GenericTypeParameterBuilderImpl gParam)
+        {
+            GenericParameterHandle handle = _metadataBuilder.AddGenericParameter(
+                parent: parentHandle,
                 attributes: gParam.GenericParameterAttributes,
                 name: _metadataBuilder.GetOrAddString(gParam.Name),
                 index: gParam.GenericParameterPosition);
 
+            WriteCustomAttributes(gParam._customAttributes, handle);
+            foreach (Type constraint in gParam.GetGenericParameterConstraints())
+            {
+                _metadataBuilder.AddGenericParameterConstraint(handle, GetTypeHandle(constraint));
+            }
+        }
+
         private void AddDefaultValue(ParameterHandle parameterHandle, object? defaultValue) =>
             _metadataBuilder.AddConstant(parent: parameterHandle, value: defaultValue);
 
index 7bdc5cf..5e00821 100644 (file)
@@ -1,6 +1,7 @@
 ï»¿// Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using System.Collections.Immutable;
 using System.Reflection.Metadata;
 using System.Reflection.Metadata.Ecma335;
 
@@ -12,8 +13,7 @@ namespace System.Reflection.Emit
         internal static BlobBuilder FieldSignatureEncoder(Type fieldType, ModuleBuilderImpl module)
         {
             BlobBuilder fieldSignature = new();
-
-            WriteSignatureForType(new BlobEncoder(fieldSignature).FieldSignature(), fieldType, module);
+            WriteSignatureForType(new BlobEncoder(fieldSignature).Field().Type(), fieldType, module);
 
             return fieldSignature;
         }
@@ -41,13 +41,14 @@ namespace System.Reflection.Emit
             return constructorSignature;
         }
 
-        internal static BlobBuilder MethodSignatureEncoder(ModuleBuilderImpl module, Type[]? parameters, Type? returnType, bool isInstance)
+        internal static BlobBuilder MethodSignatureEncoder(ModuleBuilderImpl module, Type[]? parameters,
+            Type? returnType, SignatureCallingConvention convention, int genParamCount, bool isInstance)
         {
             // Encoding return type and parameters.
             BlobBuilder methodSignature = new();
 
             new BlobEncoder(methodSignature).
-                MethodSignature(isInstanceMethod: isInstance).
+                MethodSignature(convention: convention, genericParameterCount: genParamCount, isInstanceMethod: isInstance).
                 Parameters((parameters == null) ? 0 : parameters.Length, out ReturnTypeEncoder retEncoder, out ParametersEncoder parEncoder);
 
             if (returnType != null && returnType != module.GetTypeFromCoreAssembly(CoreTypeId.Void))
@@ -72,10 +73,75 @@ namespace System.Reflection.Emit
 
         private static void WriteSignatureForType(SignatureTypeEncoder signature, Type type, ModuleBuilderImpl module)
         {
+            if (type.IsArray)
+            {
+                Type elementType = type.GetElementType()!;
+                int rank = type.GetArrayRank();
+                if (rank == 1)
+                {
+                    WriteSignatureForType(signature.SZArray(), elementType, module);
+                }
+                else
+                {
+                    signature.Array(out SignatureTypeEncoder elTypeSignature, out ArrayShapeEncoder arrayEncoder);
+                    WriteSimpleSignature(elTypeSignature, elementType, module);
+                    arrayEncoder.Shape(type.GetArrayRank(), ImmutableArray.Create<int>(), ImmutableArray.Create<int>(new int[rank]));
+                }
+            }
+            else if (type.IsPointer)
+            {
+                WriteSignatureForType(signature.Pointer(), type.GetElementType()!, module);
+            }
+            else if (type.IsByRef)
+            {
+                signature.Builder.WriteByte((byte)SignatureTypeCode.ByReference);
+                WriteSignatureForType(signature, type.GetElementType()!, module);
+            }
+            else if (type.IsGenericType)
+            {
+                Type[] genericArguments = type.GetGenericArguments();
+
+                GenericTypeArgumentsEncoder encoder = signature.GenericInstantiation(
+                    module.GetTypeHandle(type.GetGenericTypeDefinition()), genericArguments.Length, type.IsValueType);
+                foreach (Type gType in genericArguments)
+                {
+                    if (gType.IsGenericMethodParameter)
+                    {
+                        encoder.AddArgument().GenericMethodTypeParameter(gType.GenericParameterPosition);
+                    }
+                    else if (gType.IsGenericParameter)
+                    {
+                        encoder.AddArgument().GenericTypeParameter(gType.GenericParameterPosition);
+                    }
+                    else
+                    {
+                        WriteSignatureForType(encoder.AddArgument(), gType, module);
+                    }
+                }
+            }
+            else if (type.IsGenericMethodParameter)
+            {
+                signature.GenericMethodTypeParameter(type.GenericParameterPosition);
+            }
+            else if (type.IsGenericParameter)
+            {
+                signature.GenericTypeParameter(type.GenericParameterPosition);
+            }
+            else
+            {
+                WriteSimpleSignature(signature, type, module);
+            }
+        }
+
+        private static void WriteSimpleSignature(SignatureTypeEncoder signature, Type type, ModuleBuilderImpl module)
+        {
             CoreTypeId? typeId = module.GetTypeIdFromCoreTypes(type);
 
             switch (typeId)
             {
+                case CoreTypeId.Void:
+                    signature.Builder.WriteByte((byte)SignatureTypeCode.Void);
+                    return;
                 case CoreTypeId.Boolean:
                     signature.Boolean();
                     return;
@@ -125,7 +191,7 @@ namespace System.Reflection.Emit
                     signature.String();
                     return;
                 case CoreTypeId.TypedReference:
-                    signature.Builder.WriteByte((byte)SignatureTypeCode.TypedReference);
+                    signature.TypedReference();
                     return;
             }
 
index eea762e..828f3a0 100644 (file)
@@ -91,16 +91,15 @@ namespace System.Reflection.Emit
             if (_typeParameters != null)
                 throw new InvalidOperationException();
 
-            _typeParameters = new GenericTypeParameterBuilderImpl[names.Length];
-
+            var typeParameters = new GenericTypeParameterBuilderImpl[names.Length];
             for (int i = 0; i < names.Length; i++)
             {
                 string name = names[i];
                 ArgumentNullException.ThrowIfNull(name, nameof(names));
-                _typeParameters[i] = new GenericTypeParameterBuilderImpl(name, i, this);
+                typeParameters[i] = new GenericTypeParameterBuilderImpl(name, i, this, _handle);
             }
 
-            return _typeParameters;
+            return _typeParameters = typeParameters;
         }
 
         protected override FieldBuilder DefineInitializedDataCore(string name, byte[] data, FieldAttributes attributes) => throw new NotImplementedException();
@@ -320,14 +319,7 @@ namespace System.Reflection.Emit
             => throw new NotSupportedException();
         [DynamicallyAccessedMembers(GetAllMembers)]
         public override MemberInfo[] GetMembers(BindingFlags bindingAttr) => throw new NotSupportedException();
-
         public override bool IsAssignableFrom([NotNullWhen(true)] Type? c) => throw new NotSupportedException();
-        public override Type MakePointerType() => throw new NotSupportedException();
-        public override Type MakeByRefType() => throw new NotSupportedException();
-        [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
-        public override Type MakeArrayType() => throw new NotSupportedException();
-        [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
-        public override Type MakeArrayType(int rank) => throw new NotSupportedException();
 
         internal const DynamicallyAccessedMemberTypes GetAllMembers = DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields |
             DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods |
index c100984..ec9fa93 100644 (file)
@@ -1,7 +1,6 @@
 ï»¿// Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
-using System.Collections;
 using System.Collections.Generic;
 using System.Diagnostics.CodeAnalysis;
 using System.IO;
@@ -98,18 +97,14 @@ namespace System.Reflection.Emit.Tests
         {
             using (TempFile file = TempFile.Create())
             {
-                AssemblyBuilder assemblyBuilder = AssemblyTools.PopulateAssemblyBuilderAndSaveMethod(
-                    s_assemblyName, null, typeof(string), out MethodInfo saveMethod);
-                ModuleBuilder mb = assemblyBuilder.DefineDynamicModule("My Module");
-                TypeBuilder tb = mb.DefineType("TestInterface", TypeAttributes.Interface | TypeAttributes.Abstract);
+                TypeBuilder tb = CreateAssemblyAndDefineType(out AssemblyBuilder assemblyBuilder, out MethodInfo saveMethod);
                 tb.DefineMethod("TestMethod", MethodAttributes.Public);
-
                 saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
 
                 Assembly assemblyFromDisk = AssemblyTools.LoadAssemblyFromPath(file.Path);
                 Module moduleFromDisk = assemblyFromDisk.Modules.First();
 
-                Assert.Equal("My Module", moduleFromDisk.ScopeName);
+                Assert.Equal("MyModule", moduleFromDisk.ScopeName);
                 Assert.Equal(1, moduleFromDisk.GetTypes().Length);
 
                 Type testType = moduleFromDisk.GetTypes()[0];
@@ -122,6 +117,13 @@ namespace System.Reflection.Emit.Tests
             }
         }
 
+        private static TypeBuilder CreateAssemblyAndDefineType(out AssemblyBuilder assemblyBuilder, out MethodInfo saveMethod)
+        {
+            assemblyBuilder = AssemblyTools.PopulateAssemblyBuilderAndSaveMethod(s_assemblyName, null, typeof(string), out saveMethod);
+            return assemblyBuilder.DefineDynamicModule("MyModule")
+                .DefineType("TestInterface", TypeAttributes.Interface | TypeAttributes.Abstract);
+        }
+
         [Fact]
         public void AddInterfaceImplementationTest()
         {
@@ -151,33 +153,57 @@ namespace System.Reflection.Emit.Tests
             }
         }
 
-        [Fact]
-        public void SaveGenericTypeParametersForAType()
+        public static IEnumerable<object[]> TypeParameters()
+        {
+            yield return new object[] { new string[] { "TFirst", "TSecond", "TThird" } };
+            yield return new object[] { new string[] { "TFirst" } };
+        }
+
+        [Theory]
+        [MemberData(nameof(TypeParameters))]
+        public void SaveGenericTypeParametersForAType(string[] typeParamNames)
         {
             using (TempFile file = TempFile.Create())
             {
-                AssemblyBuilder assemblyBuilder = AssemblyTools.PopulateAssemblyBuilderAndSaveMethod(
-                    s_assemblyName, null, typeof(string), out MethodInfo saveMethod);
-                ModuleBuilder mb = assemblyBuilder.DefineDynamicModule("My Module");
-                TypeBuilder tb = mb.DefineType("TestInterface", TypeAttributes.Interface | TypeAttributes.Abstract);
-                string[] typeParamNames = new string[] { "TFirst", "TSecond", "TThird" };
+                TypeBuilder tb = CreateAssemblyAndDefineType(out AssemblyBuilder assemblyBuilder, out MethodInfo saveMethod);
+                MethodBuilder method = tb.DefineMethod("TestMethod", MethodAttributes.Public);
                 GenericTypeParameterBuilder[] typeParams = tb.DefineGenericParameters(typeParamNames);
-                typeParams[0].SetInterfaceConstraints(new Type[] { typeof(IAccess), typeof(INoMethod)});
-                typeParams[1].SetCustomAttribute(new CustomAttributeBuilder(typeof(DynamicallyAccessedMembersAttribute).GetConstructor(
-                    new Type[] { typeof(DynamicallyAccessedMemberTypes) }), new object[] { DynamicallyAccessedMemberTypes.PublicProperties }));
-                typeParams[2].SetBaseTypeConstraint(typeof(EmptyTestClass));
-                typeParams[2].SetGenericParameterAttributes(GenericParameterAttributes.VarianceMask);
+                if (typeParams.Length > 2)
+                {
+                    SetVariousGenericParameterValues(typeParams);
+                }
                 saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
 
-                Assembly assemblyFromDisk = AssemblyTools.LoadAssemblyFromPath(file.Path);
-                Type testType = assemblyFromDisk.Modules.First().GetTypes()[0];
+                Type testType = AssemblyTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
+                MethodInfo testMethod = testType.GetMethod("TestMethod");
                 Type[] genericTypeParams = testType.GetGenericArguments();
-                
-                Assert.Equal(3, genericTypeParams.Length);
-                Assert.Equal("TFirst", genericTypeParams[0].Name);
+
+                Assert.True(testType.IsGenericType);
+                Assert.True(testType.IsGenericTypeDefinition);
+                Assert.True(testType.ContainsGenericParameters);
+                Assert.False(testMethod.IsGenericMethod);
+                Assert.False(testMethod.IsGenericMethodDefinition);
+                Assert.True(testMethod.ContainsGenericParameters);
+                AssertGenericParameters(typeParams, genericTypeParams);
+            }
+        }
+
+        private static void SetVariousGenericParameterValues(GenericTypeParameterBuilder[] typeParams)
+        {
+            typeParams[0].SetInterfaceConstraints(new Type[] { typeof(IAccess), typeof(INoMethod) });
+            typeParams[1].SetCustomAttribute(new CustomAttributeBuilder(typeof(DynamicallyAccessedMembersAttribute).GetConstructor(
+                new Type[] { typeof(DynamicallyAccessedMemberTypes) }), new object[] { DynamicallyAccessedMemberTypes.PublicProperties }));
+            typeParams[2].SetBaseTypeConstraint(typeof(EmptyTestClass));
+            typeParams[2].SetGenericParameterAttributes(GenericParameterAttributes.VarianceMask);
+        }
+
+        private static void AssertGenericParameters(GenericTypeParameterBuilder[] typeParams, Type[] genericTypeParams)
+        {
+            Assert.Equal("TFirst", genericTypeParams[0].Name);
+            if (typeParams.Length > 2)
+            {
                 Assert.Equal("TSecond", genericTypeParams[1].Name);
                 Assert.Equal("TThird", genericTypeParams[2].Name);
-
                 Type[] constraints = genericTypeParams[0].GetTypeInfo().GetGenericParameterConstraints();
                 Assert.Equal(2, constraints.Length);
                 Assert.Equal(typeof(IAccess).FullName, constraints[0].FullName);
@@ -188,7 +214,6 @@ namespace System.Reflection.Emit.Tests
                 Assert.Equal(typeof(EmptyTestClass).FullName, constraints2[0].FullName);
                 Assert.Equal(GenericParameterAttributes.None, genericTypeParams[0].GenericParameterAttributes);
                 Assert.Equal(GenericParameterAttributes.VarianceMask, genericTypeParams[2].GenericParameterAttributes);
-
                 IList<CustomAttributeData> attributes = genericTypeParams[1].GetCustomAttributesData();
                 Assert.Equal(1, attributes.Count);
                 Assert.Equal("DynamicallyAccessedMembersAttribute", attributes[0].AttributeType.Name);
@@ -196,6 +221,262 @@ namespace System.Reflection.Emit.Tests
                 Assert.Empty(genericTypeParams[0].GetCustomAttributesData());
             }
         }
+
+        [Theory]
+        [MemberData(nameof(TypeParameters))]
+        public void SaveGenericTypeParametersForAMethod(string[] typeParamNames)
+        {
+            using (TempFile file = TempFile.Create())
+            {
+                TypeBuilder tb = CreateAssemblyAndDefineType(out AssemblyBuilder assemblyBuilder, out MethodInfo saveMethod);
+                MethodBuilder method = tb.DefineMethod("TestMethod", MethodAttributes.Public);
+                GenericTypeParameterBuilder[] typeParams = method.DefineGenericParameters(typeParamNames);
+                if (typeParams.Length > 2)
+                {
+                    SetVariousGenericParameterValues(typeParams);
+                }
+                saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
+
+                Type testType = AssemblyTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
+                MethodInfo testMethod = testType.GetMethod("TestMethod");
+                Type[] genericTypeParams = testMethod.GetGenericArguments();
+
+                Assert.False(testType.IsGenericType);
+                Assert.False(testType.IsGenericTypeDefinition);
+                Assert.False(testType.ContainsGenericParameters);
+                Assert.True(testMethod.IsGenericMethod);
+                Assert.True(testMethod.IsGenericMethodDefinition);
+                Assert.True(testMethod.ContainsGenericParameters);
+                AssertGenericParameters(typeParams, genericTypeParams);
+            }
+        }
+
+        [Theory]
+        [InlineData(0, "TestInterface[]")]
+        [InlineData(1, "TestInterface[]")] // not [*]
+        [InlineData(2, "TestInterface[,]")]
+        [InlineData(3, "TestInterface[,,]")]
+        public void SaveArrayTypeSignature(int rank, string name)
+        {
+            using (TempFile file = TempFile.Create())
+            {
+                TypeBuilder tb = CreateAssemblyAndDefineType(out AssemblyBuilder assemblyBuilder, out MethodInfo saveMethod);
+                Type arrayType = rank == 0 ? tb.MakeArrayType() : tb.MakeArrayType(rank);
+                MethodBuilder mb = tb.DefineMethod("TestMethod", MethodAttributes.Public);
+                mb.SetReturnType(arrayType);
+                mb.SetParameters(new Type[] { typeof(INoMethod), arrayType, typeof(int[,,,]) });
+                saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
+
+                Type testType = AssemblyTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
+                MethodInfo testMethod = testType.GetMethod("TestMethod");
+                Type intArray = testMethod.GetParameters()[2].ParameterType;
+
+                Assert.False(testMethod.GetParameters()[0].ParameterType.IsSZArray);
+                Assert.True(intArray.IsArray);
+                Assert.Equal(4, intArray.GetArrayRank());
+                Assert.Equal("Int32[,,,]", intArray.Name);
+                AssertArrayTypeSignature(rank, name, testMethod.ReturnType);
+                AssertArrayTypeSignature(rank, name, testMethod.GetParameters()[1].ParameterType);
+            }
+        }
+
+        private static void AssertArrayTypeSignature(int rank, string name, Type arrayType)
+        {
+            Assert.True(rank < 2 ? arrayType.IsSZArray : arrayType.IsArray);
+            rank = rank == 0 ? rank + 1 : rank;
+            Assert.Equal(rank, arrayType.GetArrayRank());
+            Assert.Equal(name, arrayType.Name);
+        }
+
+        [Fact]
+        public void SaveByRefTypeSignature()
+        {
+            using (TempFile file = TempFile.Create())
+            {
+                TypeBuilder tb = CreateAssemblyAndDefineType(out AssemblyBuilder assemblyBuilder, out MethodInfo saveMethod);
+                Type byrefType = tb.MakeByRefType();
+                MethodBuilder mb = tb.DefineMethod("TestMethod", MethodAttributes.Public);
+                mb.SetReturnType(byrefType);
+                mb.SetParameters(new Type[] { typeof(INoMethod), byrefType });
+                saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
+
+                Type testType = AssemblyTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
+                MethodInfo testMethod = testType.GetMethod("TestMethod");
+
+                Assert.False(testMethod.GetParameters()[0].ParameterType.IsByRef);
+                AssertByRefType(testMethod.GetParameters()[1].ParameterType);
+                AssertByRefType(testMethod.ReturnType);
+            }
+        }
+
+        private static void AssertByRefType(Type byrefParam)
+        {
+            Assert.True(byrefParam.IsByRef);
+            Assert.Equal("TestInterface&", byrefParam.Name);
+        }
+
+        [Fact]
+        public void SavePointerTypeSignature()
+        {
+            using (TempFile file = TempFile.Create())
+            {
+                TypeBuilder tb = CreateAssemblyAndDefineType(out AssemblyBuilder assemblyBuilder, out MethodInfo saveMethod);
+                Type pointerType = tb.MakePointerType();
+                MethodBuilder mb = tb.DefineMethod("TestMethod", MethodAttributes.Public);
+                mb.SetReturnType(pointerType);
+                mb.SetParameters(new Type[] { typeof(INoMethod), pointerType });
+                saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
+
+                Type testType = AssemblyTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
+                MethodInfo testMethod = testType.GetMethod("TestMethod");
+
+                Assert.False(testMethod.GetParameters()[0].ParameterType.IsPointer);
+                AssertPointerType(testMethod.GetParameters()[1].ParameterType);
+                AssertPointerType(testMethod.ReturnType);
+            }
+        }
+
+        private void AssertPointerType(Type testType)
+        {
+            Assert.True(testType.IsPointer);
+            Assert.Equal("TestInterface*", testType.Name);
+        }
+
+        public static IEnumerable<object[]> SaveGenericType_TestData()
+        {
+            yield return new object[] { new string[] { "U", "T" }, new Type[] { typeof(string), typeof(int) }, "TestInterface[System.String,System.Int32]" };
+            yield return new object[] { new string[] { "U", "T" }, new Type[] { typeof(MakeGenericTypeClass), typeof(MakeGenericTypeInterface) },
+                        "TestInterface[System.Reflection.Emit.Tests.MakeGenericTypeClass,System.Reflection.Emit.Tests.MakeGenericTypeInterface]" };
+            yield return new object[] { new string[] { "U" }, new Type[] { typeof(List<string>) }, "TestInterface[System.Collections.Generic.List`1[System.String]]" };
+        }
+
+        [Theory]
+        [MemberData(nameof(SaveGenericType_TestData))]
+        public void SaveGenericTypeSignature(string[] genericParams, Type[] typeArguments, string stringRepresentation)
+        {
+            using (TempFile file = TempFile.Create())
+            {
+                TypeBuilder tb = CreateAssemblyAndDefineType(out AssemblyBuilder assemblyBuilder, out MethodInfo saveMethod);
+                GenericTypeParameterBuilder[] typeGenParam = tb.DefineGenericParameters(genericParams);
+                Type genericType = tb.MakeGenericType(typeArguments);
+                MethodBuilder mb = tb.DefineMethod("TestMethod", MethodAttributes.Public);
+                mb.SetReturnType(genericType);
+                mb.SetParameters(new Type[] { typeof(INoMethod), genericType });
+                saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
+
+                Type testType = AssemblyTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
+                MethodInfo testMethod = testType.GetMethod("TestMethod");
+                Type paramType = testMethod.GetParameters()[1].ParameterType;
+
+                Assert.False(testMethod.GetParameters()[0].ParameterType.IsGenericType);
+                AssertGenericType(stringRepresentation, paramType);
+                AssertGenericType(stringRepresentation, testMethod.ReturnType);
+            }
+        }
+
+        private static void AssertGenericType(string stringRepresentation, Type paramType)
+        {
+            Assert.True(paramType.IsGenericType);
+            Assert.Equal(stringRepresentation, paramType.ToString());
+            Assert.False(paramType.IsGenericParameter);
+            Assert.False(paramType.IsGenericTypeDefinition);
+            Assert.False(paramType.IsGenericTypeParameter);
+            Assert.False(paramType.IsGenericMethodParameter);
+        }
+
+        [Fact]
+        public void SaveGenericTypeSignatureWithGenericParameter()
+        {
+            using (TempFile file = TempFile.Create())
+            {
+                TypeBuilder tb = CreateAssemblyAndDefineType(out AssemblyBuilder assemblyBuilder, out MethodInfo saveMethod);
+                GenericTypeParameterBuilder[] typeParams = tb.DefineGenericParameters(new string[] { "U", "T", "P" });
+                MethodBuilder mb = tb.DefineMethod("TestMethod", MethodAttributes.Public);
+                GenericTypeParameterBuilder[] methodParams = mb.DefineGenericParameters(new string[] { "M", "N" });
+                Type genericType = tb.MakeGenericType(typeParams);
+                mb.SetReturnType(methodParams[0]);
+                mb.SetParameters(new Type[] { typeof(INoMethod), genericType, typeParams[1] });
+                saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
+
+                Type testType = AssemblyTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
+                MethodInfo testMethod = testType.GetMethod("TestMethod");
+                Type paramType = testMethod.GetParameters()[1].ParameterType;
+                Type genericParameter = testMethod.GetParameters()[2].ParameterType;
+
+                Assert.False(testMethod.GetParameters()[0].ParameterType.IsGenericType);
+                AssertGenericType("TestInterface[U,T,P]", paramType);
+                Assert.False(genericParameter.IsGenericType);
+                Assert.True(genericParameter.IsGenericParameter);
+                Assert.False(genericParameter.IsGenericTypeDefinition);
+                Assert.True(genericParameter.IsGenericTypeParameter);
+                Assert.False(genericParameter.IsGenericMethodParameter);
+                Assert.Equal("T", genericParameter.Name);
+                Assert.False(testMethod.ReturnType.IsGenericType);
+                Assert.True(testMethod.ReturnType.IsGenericParameter);
+                Assert.False(testMethod.ReturnType.IsGenericTypeDefinition);
+                Assert.False(testMethod.ReturnType.IsGenericTypeParameter);
+                Assert.True(testMethod.ReturnType.IsGenericMethodParameter);
+                Assert.Equal("M", testMethod.ReturnType.Name);
+            }
+        }
+
+        [Fact]
+        public void SaveMultipleGenericTypeParametersToEnsureSortingWorks()
+        {
+            using (TempFile file = TempFile.Create())
+            {
+                AssemblyBuilder assemblyBuilder = AssemblyTools.PopulateAssemblyBuilderAndSaveMethod(
+                    s_assemblyName, null, typeof(string), out MethodInfo saveMethod);
+                ModuleBuilder mb = assemblyBuilder.DefineDynamicModule("My Module");
+                TypeBuilder tb = mb.DefineType("TestInterface1", TypeAttributes.Interface | TypeAttributes.Abstract);
+                GenericTypeParameterBuilder[] typeParams = tb.DefineGenericParameters(new string[] { "U", "T" });
+                typeParams[1].SetInterfaceConstraints(new Type[] { typeof(INoMethod), typeof(IOneMethod) });
+                MethodBuilder m11 = tb.DefineMethod("TwoParameters", MethodAttributes.Public);
+                MethodBuilder m12 = tb.DefineMethod("FiveTypeParameters", MethodAttributes.Public);
+                MethodBuilder m13 = tb.DefineMethod("OneParameter", MethodAttributes.Public);
+                m11.DefineGenericParameters(new string[] { "M", "N" });
+                GenericTypeParameterBuilder[] methodParams = m12.DefineGenericParameters(new string[] { "A", "B", "C", "D", "F" });
+                methodParams[2].SetInterfaceConstraints(new Type[] { typeof(IMultipleMethod) });
+                m13.DefineGenericParameters(new string[] { "T" });
+                TypeBuilder tb2 = mb.DefineType("TestInterface2", TypeAttributes.Interface | TypeAttributes.Abstract);
+                tb2.DefineGenericParameters(new string[] { "TFirst", "TSecond", "TThird" });
+                MethodBuilder m21 = tb2.DefineMethod("TestMethod", MethodAttributes.Public);
+                m21.DefineGenericParameters(new string[] { "X", "Y", "Z" });
+                TypeBuilder tb3 = mb.DefineType("TestType");
+                GenericTypeParameterBuilder[] typePar = tb3.DefineGenericParameters(new string[] { "TOne" });
+                typePar[0].SetBaseTypeConstraint(typeof(EmptyTestClass));
+                saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
+
+                Module m = AssemblyTools.LoadAssemblyFromPath(file.Path).Modules.First();
+                Type[] type1Params = m.GetTypes()[0].GetGenericArguments();
+                Type[] type2Params = m.GetTypes()[1].GetGenericArguments();
+                Type[] type3Params = m.GetTypes()[2].GetGenericArguments();
+
+                Assert.Equal("U", type1Params[0].Name);
+                Assert.Empty(type1Params[0].GetTypeInfo().GetGenericParameterConstraints());
+                Assert.Equal("T", type1Params[1].Name);
+                Assert.Equal(nameof(IOneMethod), type1Params[1].GetTypeInfo().GetGenericParameterConstraints()[1].Name);
+                Assert.Equal("TFirst", type2Params[0].Name);
+                Assert.Equal("TSecond", type2Params[1].Name);
+                Assert.Equal("TThird", type2Params[2].Name);
+                Assert.Equal("TOne", type3Params[0].Name);
+                Assert.Equal(nameof(EmptyTestClass), type3Params[0].GetTypeInfo().GetGenericParameterConstraints()[0].Name);
+
+                Type[] method11Params = m.GetTypes()[0].GetMethod("TwoParameters").GetGenericArguments();
+                Type[] method12Params = m.GetTypes()[0].GetMethod("FiveTypeParameters").GetGenericArguments();
+                Assert.Equal(nameof(IMultipleMethod), method12Params[2].GetTypeInfo().GetGenericParameterConstraints()[0].Name);
+                Type[] method13Params = m.GetTypes()[0].GetMethod("OneParameter").GetGenericArguments();
+                Type[] method21Params = m.GetTypes()[1].GetMethod("TestMethod").GetGenericArguments();
+                
+                Assert.Equal("M", method11Params[0].Name);
+                Assert.Equal("N", method11Params[1].Name);
+                Assert.Equal("A", method12Params[0].Name);
+                Assert.Equal("F", method12Params[4].Name);
+                Assert.Equal("T", method13Params[0].Name);
+                Assert.Equal("X", method21Params[0].Name);
+                Assert.Equal("Z", method21Params[2].Name);
+            }
+        }
     }
 
     // Test Types
index 469f9ef..8f4729a 100644 (file)
@@ -1357,24 +1357,6 @@ namespace System.Reflection.Emit
             }
         }
 
-        [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
-        public override Type MakeArrayType()
-        {
-            return SymbolType.FormCompoundType("[]", this, 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);
-            return SymbolType.FormCompoundType(s, this, 0)!;
-        }
-
-        public override Type MakeByRefType()
-        {
-            return SymbolType.FormCompoundType("&", this, 0)!;
-        }
-
         [RequiresDynamicCode("The native code for this instantiation might not be available at runtime.")]
         [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.")]
         public override Type MakeGenericType(params Type[] typeArguments)
@@ -1398,11 +1380,6 @@ namespace System.Reflection.Emit
             return RuntimeAssemblyBuilder.MakeGenericType(this, copy);
         }
 
-        public override Type MakePointerType()
-        {
-            return SymbolType.FormCompoundType("*", this, 0)!;
-        }
-
         public override RuntimeTypeHandle TypeHandle
         {
             get