Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/tools/illink/src/linker/Linker.Steps/MarkStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/tools/illink/src/linker/Linker/TypeMapHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,15 @@
[assembly: TypeMapAssemblyTarget<UsedTypeMapUniverse>("library")]
[assembly: TypeMapAssemblyTarget<UnusedTypeMap2>("library")] // Should be removed

// Verify that when a TypeMapAttribute's target type is instantiated by TypeMap processing,
// the associated TypeMapAssociation entry is also kept. Without the fix, only MarkInstantiated
// was called (not MarkRequirementsForInstantiatedTypes), preventing ProcessInstantiated from
// being called and leaving TypeMapAssociation entries unmarked.
[assembly: TypeMap<UsedTypeMap>("BothInExternalAndProxy", typeof(BothInExternalAndProxy), typeof(BothInExternalAndProxyTrimTarget))] // Kept
[assembly: TypeMapAssociation<UsedTypeMap>(typeof(BothInExternalAndProxy), typeof(BothInExternalAndProxyTarget))] // Kept
[assembly: KeptAttributeAttribute(typeof(TypeMapAttribute<UsedTypeMap>), "BothInExternalAndProxy", typeof(BothInExternalAndProxy), typeof(BothInExternalAndProxyTrimTarget))]
[assembly: KeptAttributeAttribute(typeof(TypeMapAssociationAttribute<UsedTypeMap>), typeof(BothInExternalAndProxy), typeof(BothInExternalAndProxyTarget))]

namespace Mono.Linker.Tests.Cases.Reflection
{
[SetupLinkerAction("link", "System.Private.CoreLib")] // Needed to get the RemoveAttributeInstances in embedded xml
Expand Down Expand Up @@ -234,6 +243,11 @@ static void ConstrainedStaticCall<T>(T t) where T : IStaticInterface
_ = new int();
_ = TypeMapping.GetOrCreateExternalTypeMapping<string>();
_ = TypeMapping.GetOrCreateProxyTypeMapping<string>();

// Instantiate BothInExternalAndProxyTrimTarget to trigger the TypeMap entry for BothInExternalAndProxy.
// BothInExternalAndProxy is only instantiated via TypeMap processing (not directly), which verifies
// that MarkRequirementsForInstantiatedTypes is called to propagate instantiation to TypeMapAssociation.
_ = new BothInExternalAndProxyTrimTarget();
}

[ExpectBodyModified]
Expand Down Expand Up @@ -572,4 +586,12 @@ class ArrayTypeTrimTargetClass;
class ArrayTypeTrimTargetUnusedTarget;

class ArrayTypeTrimTargetUnusedClass;

[Kept]
[KeptMember(".ctor()")]
class BothInExternalAndProxyTrimTarget;
[Kept]
class BothInExternalAndProxy;
[Kept]
class BothInExternalAndProxyTarget;
}
Loading