Skip to content

Commit

Permalink
Fix some core typeof(...) references (#105903)
Browse files Browse the repository at this point in the history
  • Loading branch information
buyaa-n authored Aug 8, 2024
1 parent 61b0020 commit 928d52a
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ internal sealed class ArrayMethod : MethodInfo

#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,
internal ArrayMethod(ModuleBuilderImpl module, Type arrayClass, string methodName,
CallingConventions callingConvention, Type? returnType, Type[]? parameterTypes)
{
_returnType = returnType ?? typeof(void);
_returnType = returnType ?? module.GetTypeFromCoreAssembly(CoreTypeId.Void);
if (parameterTypes != null)
{
_parameterTypes = new Type[parameterTypes.Length];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ protected override FieldBuilder DefineUninitializedDataCore(string name, int siz
return DefineDataHelper(name, new byte[size], size, attributes);
}

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072:DynamicallyAccessedMembers", Justification = "The members of 'ValueType' are not referenced in this context")]
private FieldBuilder DefineDataHelper(string name, byte[] data, int size, FieldAttributes attributes)
{
ArgumentException.ThrowIfNullOrEmpty(name);
Expand All @@ -456,7 +457,7 @@ private FieldBuilder DefineDataHelper(string name, byte[] data, int size, FieldA
TypeAttributes typeAttributes = TypeAttributes.Public | TypeAttributes.ExplicitLayout | TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.AnsiClass;

// Define the backing value class
valueClassType = (TypeBuilderImpl)_module.DefineType(strValueClassName, typeAttributes, typeof(ValueType), PackingSize.Size1, size);
valueClassType = (TypeBuilderImpl)_module.DefineType(strValueClassName, typeAttributes, _module.GetTypeFromCoreAssembly(CoreTypeId.ValueType), PackingSize.Size1, size);
valueClassType.CreateType();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public void DefineLiteral(Type underlyingType, object literalValue)
EnumBuilder enumBuilder = CreateAssemblyAndDefineEnum(out PersistedAssemblyBuilder assemblyBuilder, out TypeBuilder type, underlyingType);
FieldBuilder literal = enumBuilder.DefineLiteral("FieldOne", literalValue);
enumBuilder.CreateTypeInfo();
Assert.True(enumBuilder.IsEnum);
type.CreateTypeInfo();
assemblyBuilder.Save(file.Path);

Expand All @@ -79,15 +80,49 @@ public void DefineLiteral(Type underlyingType, object literalValue)
Assert.True(testEnum.IsEnum);
AssemblySaveTools.AssertTypeProperties(enumBuilder, testEnum);
Assert.Equal(underlyingType.FullName, testEnum.GetEnumUnderlyingType().FullName);
Assert.Equal(mlc.CoreAssembly.GetType("System.Enum"), testEnum.BaseType);

FieldInfo testField = testEnum.GetField("FieldOne");
Assert.Equal(enumBuilder.Name, testField.DeclaringType.Name);
Assert.Equal(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault, literal.Attributes);
Assert.Equal(enumBuilder.AsType().FullName, testField.FieldType.FullName);
Assert.Equal(testEnum, testField.FieldType);
}
}
}

[Fact]
public void CreateEnumWithMlc()
{
using (var stream = new MemoryStream())
using (MetadataLoadContext mlc = new MetadataLoadContext(new CoreMetadataAssemblyResolver()))
{
PersistedAssemblyBuilder ab = new PersistedAssemblyBuilder(PopulateAssemblyName(), mlc.CoreAssembly);
ModuleBuilder mb = ab.DefineDynamicModule("My Module");
Type intType = mlc.CoreAssembly.GetType("System.Int32");
EnumBuilder enumBuilder = mb.DefineEnum("TestEnum", TypeAttributes.Public, typeof(int));
FieldBuilder field = enumBuilder.DefineLiteral("Default", 0);

enumBuilder.CreateTypeInfo();
Assert.True(enumBuilder.IsEnum);
Assert.Equal(enumBuilder, field.FieldType);

ab.Save(stream);
Assembly assemblyFromStream = mlc.LoadFromStream(stream);
Type createdEnum = assemblyFromStream.GetType("TestEnum");

Assert.True(createdEnum.IsEnum);
AssemblySaveTools.AssertTypeProperties(enumBuilder, createdEnum);
Assert.Equal(mlc.CoreAssembly.GetType("System.Enum"), createdEnum.BaseType);
Assert.Equal(intType, createdEnum.GetEnumUnderlyingType());

FieldInfo testField = createdEnum.GetField("Default");
Assert.Equal(createdEnum, testField.FieldType);
Assert.Equal(typeof(int), enumBuilder.GetEnumUnderlyingType());
Assert.Equal(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault, testField.Attributes);
}
}

[Theory]
[InlineData(0, "TestEnum[]")]
[InlineData(1, "TestEnum[]")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,25 @@ public void DefineUninitializedDataTest(FieldAttributes attributes)
Assert.True(field.IsStatic);
Assert.True((field.Attributes & FieldAttributes.HasFieldRVA) != 0);
Assert.Equal(attributes | FieldAttributes.Static | FieldAttributes.HasFieldRVA, field.Attributes);
Assert.Equal(typeof(ValueType), field.FieldType.BaseType);
}
}

[Fact]
public void DefineUninitializedDataFromMLC()
{
using (MetadataLoadContext mlc = new MetadataLoadContext(new CoreMetadataAssemblyResolver()))
{
PersistedAssemblyBuilder ab = new PersistedAssemblyBuilder(new AssemblyName("MyAssembly"), mlc.CoreAssembly);
ModuleBuilder module = ab.DefineDynamicModule("MyModule");
FieldBuilder field = module.DefineUninitializedData("UninitializedDataField", 100, FieldAttributes.Public);

Assert.Equal("UninitializedDataField", field.Name);
Assert.True(field.IsStatic);
Assert.True((field.Attributes & FieldAttributes.HasFieldRVA) != 0);
Assert.Equal(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.HasFieldRVA, field.Attributes);
Assert.NotEqual(typeof(ValueType), field.FieldType.BaseType);
Assert.Equal(mlc.CoreAssembly.GetType("System.ValueType"), field.FieldType.BaseType);
}
}

Expand Down Expand Up @@ -354,5 +373,34 @@ public void GetArrayMethod_InvalidArgument_ThrowsArgumentException()
AssertExtensions.Throws<ArgumentNullException>("parameterTypes", () => module.GetArrayMethod(typeof(string[]), "TestMethod", CallingConventions.Standard, null, [null]));
AssertExtensions.Throws<ArgumentException>(null, () => module.GetArrayMethod(typeof(Array), "TestMethod", CallingConventions.Standard, null, null));
}

[Fact]
public void GetArrayMethodNullReturnType()
{
ModuleBuilder module = AssemblySaveTools.PopulateAssemblyBuilder(new AssemblyName("MyAssembly")).DefineDynamicModule("MyModule");
MethodInfo method = module.GetArrayMethod(typeof(int[]), "MethodName", CallingConventions.Standard, null, null);

Assert.Equal(typeof(int[]), method.DeclaringType);
Assert.Equal("MethodName", method.Name);
Assert.Equal(CallingConventions.Standard, method.CallingConvention);
Assert.Equal(typeof(void), method.ReturnType);
}

[Fact]
public void GetArrayMethodNullReturnTypeFromMLC()
{
using (MetadataLoadContext mlc = new MetadataLoadContext(new CoreMetadataAssemblyResolver()))
{
ModuleBuilder module = new PersistedAssemblyBuilder(new AssemblyName("MyAssembly"), mlc.CoreAssembly).DefineDynamicModule("MyModule");
Type arrayType = mlc.CoreAssembly.GetType("System.Int32").MakeArrayType();
MethodInfo method = module.GetArrayMethod(arrayType, "MethodName", CallingConventions.Standard, null, null);

Assert.Equal(arrayType, method.DeclaringType);
Assert.Equal("MethodName", method.Name);
Assert.Equal(CallingConventions.Standard, method.CallingConvention);
Assert.NotEqual(typeof(void), method.ReturnType);
Assert.Equal(mlc.CoreAssembly.GetType("System.Void"), method.ReturnType);
}
}
}
}

0 comments on commit 928d52a

Please sign in to comment.