Skip to content

[release/10.0] Update TypeMap attribute handling#123558

Merged
steveisok merged 7 commits intorelease/10.0from
backport/pr-120477-to-release/10.0
Jan 26, 2026
Merged

[release/10.0] Update TypeMap attribute handling#123558
steveisok merged 7 commits intorelease/10.0from
backport/pr-120477-to-release/10.0

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions bot commented Jan 23, 2026

Backport of #120477 to release/10.0

/cc @jkoritzinsky @jtschuster

Customer Impact

  • Customer reported
  • Found internally

Type maps created with the new System.Runtime.InteropServices.TypeMapAttribute would fail to work across assemblies as described when the user publishes their app with PublishTrimmed set to true. This affects our partner teams who want to take advantage of this API (.NET for Android, CsWinRT).

Regression

  • Yes
  • No

This was a new API in .NET 10

Testing

Many unit tests were added

Risk

[High/Medium/Low. Justify the indication by mentioning how risks were measured and addressed.]

Low. This only affects a new API in .NET 10 and is a targeted fix with included testing,

IMPORTANT: If this backport is for a servicing release, please verify that:

  • For .NET 8 and .NET 9: The PR target branch is release/X.0-staging, not release/X.0.
  • For .NET 10+: The PR target branch is release/X.0 (no -staging suffix).

Package authoring no longer needed in .NET 9

IMPORTANT: Starting with .NET 9, you no longer need to edit a NuGet package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older versions.

jtschuster and others added 7 commits January 23, 2026 19:35
- Mark TypeMapAssemblyTargetAttributes when a typemapuniverse is marked
- Recurse through TypeMapAssemblyTarget assemblies to find all TypeMapAttributes
- Refactor TypeMapHandler construction and initialization
- Use TypeReferenceEqualityComparer for Dictionaries
- Add more test coverage
…ap.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actions github-actions bot requested a review from marek-safar as a code owner January 23, 2026 19:35
@dotnet-policy-service dotnet-policy-service bot added the linkable-framework Issues associated with delivering a linker friendly framework label Jan 23, 2026
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/interop-contrib
See info in area-owners.md if you want to be subscribed.

@Sergio0694
Copy link
Copy Markdown
Contributor

Somehow we missed this one, I thought it had already been cherry-picked. Thank you @AaronRobinsonMSFT! 😅

Copy link
Copy Markdown
Member

@JulieLeeMSFT JulieLeeMSFT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@JulieLeeMSFT JulieLeeMSFT added the Servicing-consider Issue for next servicing release review label Jan 23, 2026
@jkoritzinsky jkoritzinsky added Servicing-approved Approved for servicing release and removed Servicing-consider Issue for next servicing release review labels Jan 23, 2026
@jkoritzinsky
Copy link
Copy Markdown
Member

Approved over email

@steveisok steveisok merged commit b118778 into release/10.0 Jan 26, 2026
86 of 90 checks passed
@steveisok steveisok deleted the backport/pr-120477-to-release/10.0 branch January 26, 2026 19:56
@jtschuster
Copy link
Copy Markdown
Member

Test app for validation

using System;
using System.Runtime.InteropServices;

[assembly: TypeMapAssemblyTarget<MyTypeMapGroup>("TypeMapLib")]

[assembly: TypeMap<MyTypeMapGroup>("LocalEntry", typeof(LocalTarget))]
[assembly: TypeMapAssociation<MyTypeMapGroup>(typeof(LocalSource), typeof(LocalProxy))]

public class LocalTarget;
public class LocalSource;
public class LocalProxy;

class Program
{
    static int Main()
    {
        int failures = 0;

        // Root the types explicitly so the trimmer keeps them.
        // This ensures any failure is purely about the TypeMap attribute discovery,
        // not about the types themselves being trimmed.
        GC.KeepAlive(typeof(LocalTarget));
        GC.KeepAlive(typeof(LocalSource));
        GC.KeepAlive(typeof(LocalProxy));
        GC.KeepAlive(typeof(GreetingTarget));
        GC.KeepAlive(typeof(FarewellTarget));
        GC.KeepAlive(typeof(FarewellTrimTarget));
        GC.KeepAlive(typeof(GreetingSource));
        GC.KeepAlive(typeof(GreetingProxy));

        var externalMap = TypeMapping.GetOrCreateExternalTypeMapping<MyTypeMapGroup>();

        failures += Check(externalMap.TryGetValue("LocalEntry", out _),
            "External map: 'LocalEntry' (same-assembly)");

        failures += Check(externalMap.TryGetValue("Greeting", out _),
            "External map: 'Greeting' from TypeMapLib (CROSS-ASSEMBLY — fails without PR fix)");

        failures += Check(externalMap.TryGetValue("Farewell", out _),
            "External map: 'Farewell' from TypeMapLib (CROSS-ASSEMBLY — fails without PR fix)");

        var proxyMap = TypeMapping.GetOrCreateProxyTypeMapping<MyTypeMapGroup>();

        _ = new LocalSource();
        failures += Check(proxyMap.TryGetValue(typeof(LocalSource), out _),
            "Proxy map: LocalSource->LocalProxy (same-assembly)");

        _ = new GreetingSource();
        failures += Check(proxyMap.TryGetValue(typeof(GreetingSource), out _),
            "Proxy map: GreetingSource->GreetingProxy from TypeMapLib (CROSS-ASSEMBLY — fails without PR fix)");

        if (failures == 0)
            Console.WriteLine("\nPASS: All cross-assembly TypeMap entries preserved after trimming.");
        else
            Console.Error.WriteLine($"\nFAILED: {failures} check(s) failed — trimmer removed cross-assembly TypeMap data.");

        return failures;
    }

    static int Check(bool condition, string description)
    {
        if (condition)
        {
            Console.WriteLine($"  OK:   {description}");
            return 0;
        }
        else
        {
            Console.Error.WriteLine($"  FAIL: {description}");
            return 1;
        }
    }
}

@github-actions github-actions bot locked and limited conversation to collaborators Mar 26, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Runtime.InteropServices linkable-framework Issues associated with delivering a linker friendly framework Servicing-approved Approved for servicing release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants