diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs index 3c9a7a6440c654..111c24eb6a48af 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs @@ -695,7 +695,14 @@ private EntityHandle GetTypeReferenceOrSpecificationHandle(Type type) } else { - typeHandle = AddTypeReference(type, GetResolutionScopeHandle(type)); + if (type.IsNested) + { + typeHandle = AddTypeReference(GetTypeReferenceOrSpecificationHandle(type.DeclaringType!), null, type.Name); + } + else + { + typeHandle = AddTypeReference(GetAssemblyReference(type.Assembly), type.Namespace, type.Name); + } } _typeReferences.Add(type, typeHandle); @@ -704,16 +711,6 @@ private EntityHandle GetTypeReferenceOrSpecificationHandle(Type type) return typeHandle; } - private EntityHandle GetResolutionScopeHandle(Type type) - { - if (type.IsNested) - { - return GetTypeReferenceOrSpecificationHandle(type.DeclaringType!); - } - - return GetAssemblyReference(type.Assembly); - } - private TypeSpecificationHandle AddTypeSpecification(Type type) => _metadataBuilder.AddTypeSpecification( signature: _metadataBuilder.GetOrAddBlob(MetadataSignatureHelper.GetTypeSpecificationSignature(type, this))); @@ -944,11 +941,11 @@ private MethodDefinitionHandle AddMethodDefinition(MethodBuilderImpl method, Blo bodyOffset: offset, parameterList: MetadataTokens.ParameterHandle(parameterToken)); - private TypeReferenceHandle AddTypeReference(Type type, EntityHandle resolutionScope) => + private TypeReferenceHandle AddTypeReference(EntityHandle resolutionScope, string? ns, string name) => _metadataBuilder.AddTypeReference( resolutionScope: resolutionScope, - @namespace: (type.Namespace == null) ? default : _metadataBuilder.GetOrAddString(type.Namespace), - name: _metadataBuilder.GetOrAddString(type.Name)); + @namespace: (ns == null) ? default : _metadataBuilder.GetOrAddString(ns), + name: _metadataBuilder.GetOrAddString(name)); private MemberReferenceHandle AddMemberReference(string memberName, EntityHandle parent, BlobBuilder signature) => _metadataBuilder.AddMemberReference( diff --git a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveILGeneratorTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveILGeneratorTests.cs index a9b766abf767af..90abf0d7342bf9 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveILGeneratorTests.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveILGeneratorTests.cs @@ -2673,5 +2673,30 @@ public void TypeBuilderByRefReferencedInIL() tlc.Unload(); } } + + [Fact] + public void NestedTypeTokenReferencedCorrectlyInIL() + { + using (TempFile file = TempFile.Create()) + { + PersistedAssemblyBuilder ab = AssemblySaveTools.PopulateAssemblyBuilderAndTypeBuilder(out TypeBuilder typeBuilder); + typeBuilder.DefineDefaultConstructor(MethodAttributes.Public); + MethodBuilder writeMethod = typeBuilder.DefineMethod("Test", MethodAttributes.Public | MethodAttributes.Static); + ILGenerator il = writeMethod.GetILGenerator(); + il.DeclareLocal(typeof(HashSet.Enumerator)); + il.Emit(OpCodes.Newobj, typeof(HashSet).GetConstructors().First(c => c.GetParameters().Length == 0)); + il.Emit(OpCodes.Callvirt, typeof(HashSet).GetMethod("GetEnumerator")!); + il.Emit(OpCodes.Stloc_0); + il.Emit(OpCodes.Ret); + typeBuilder.CreateType(); + ab.Save(file.Path); + + TestAssemblyLoadContext tlc = new TestAssemblyLoadContext(); + Type typeFromDisk = tlc.LoadFromAssemblyPath(file.Path).GetType("MyType"); + MethodInfo method = typeFromDisk.GetMethod("Test")!; + method.Invoke(null, null); // just make sure token works + tlc.Unload(); + } + } } }