diff --git a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs index 977bcdebaf49e5..c48273e97439f9 100644 --- a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs +++ b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs @@ -3515,7 +3515,7 @@ static bool TypeIsInlineArrayType(TypeDefinition type) return false; } - protected virtual void MarkRequirementsForInstantiatedTypes(TypeDefinition type) + protected internal virtual void MarkRequirementsForInstantiatedTypes(TypeDefinition type) { if (Annotations.IsInstantiated(type)) return; diff --git a/src/tools/illink/src/linker/Linker/TypeMapHandler.cs b/src/tools/illink/src/linker/Linker/TypeMapHandler.cs index dce5132369f3d3..2b1d2e4a55e8c4 100644 --- a/src/tools/illink/src/linker/Linker/TypeMapHandler.cs +++ b/src/tools/illink/src/linker/Linker/TypeMapHandler.cs @@ -109,7 +109,7 @@ void MarkTypeMapAttribute(CustomAttributeWithOrigin entry, DependencyInfo info) // Mark the target type as instantiated if (entry.TargetType is { } targetType && _context.Resolve(UnwrapToResolvableType(targetType)) is TypeDefinition targetTypeDef) - _context.Annotations.MarkInstantiated(targetTypeDef); + _markStep.MarkRequirementsForInstantiatedTypes(targetTypeDef); } public void ProcessType(TypeDefinition definition) diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeMap.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeMap.cs index ce887a9d5e8458..ce57e247f86e27 100644 --- a/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeMap.cs +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeMap.cs @@ -85,6 +85,12 @@ [assembly: TypeMapAssemblyTarget("library")] [assembly: TypeMapAssemblyTarget("library")] // Should be removed +// Verify that a type can be kept if it's used for both TypeMap and TypeMapAssociation +[assembly: TypeMap("BothInExternalAndProxy", typeof(BothInExternalAndProxy), typeof(BothInExternalAndProxy))] // Kept +[assembly: TypeMapAssociation(typeof(BothInExternalAndProxy), typeof(BothInExternalAndProxyTarget))] // Kept +[assembly: KeptAttributeAttribute(typeof(TypeMapAttribute), "BothInExternalAndProxy", typeof(BothInExternalAndProxy), typeof(BothInExternalAndProxy))] +[assembly: KeptAttributeAttribute(typeof(TypeMapAssociationAttribute), typeof(BothInExternalAndProxy), typeof(BothInExternalAndProxyTarget))] + namespace Mono.Linker.Tests.Cases.Reflection { [SetupLinkerAction("link", "System.Private.CoreLib")] // Needed to get the RemoveAttributeInstances in embedded xml @@ -234,6 +240,9 @@ static void ConstrainedStaticCall(T t) where T : IStaticInterface _ = new int(); _ = TypeMapping.GetOrCreateExternalTypeMapping(); _ = TypeMapping.GetOrCreateProxyTypeMapping(); + + // Use BothInExternalAndProxy in a way that preserves any corresponding typemap entries. + Console.WriteLine(new BothInExternalAndProxy()); } [ExpectBodyModified] @@ -562,6 +571,12 @@ class UsedProxyTarget2; [Kept] class PreservedTargetType; + [Kept] + [KeptMember(".ctor()")] + class BothInExternalAndProxy; + [Kept] + class BothInExternalAndProxyTarget; + [Kept] class ArrayTypeTrimTargetTarget;