You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue was filed with AI (Copilot) assistance.
Currently, when ILLink marks an ExportedType (type forwarder) row — whether through rooting an assembly with -a, or through copy/save action — it preserves the forwarder metadata but does not mark the target TypeDefinition the forwarder resolves to. This means the forwarder can become dangling, pointing to a type or assembly that was trimmed away.
This is tested and documented as expected behavior:
// From RootAllLibraryBehavior.cs:// Type forwarders are kept (but not necessarily the type definition that the forwarder points to)[KeptTypeInAssembly("library.dll",typeof(RootAllLibrary_ExportedType))][RemovedAssembly("exportedtype.dll")]
The same behavior applies for copy action assemblies (RootAllLibraryCopyBehavior.cs, UnusedForwarderWithAssemblyCopyIsKept.cs).
Why the current behavior may be correct
Shim assemblies like mscorlib.dll and netstandard.dll are composed almost entirely of type forwarders pointing to dozens of implementation assemblies. If marking a forwarder also marked its target, rooting one of these assemblies would pull in a large portion of the .NET surface area — defeating the purpose of trimming.
Some forwarder targets may not even be resolvable. The mscorlib shim forwards to assemblies like System.Drawing.Common, System.Data.SqlClient, and System.Security.Permissions that may not be present in the app. This is an established pattern that --skip-unresolved true was designed to accommodate (see #103831).
Why it might be a problem
A dangling forwarder is broken at runtime — if any code attempts to load a type through the forwarder, it will fail. Issue #99592 reported a real-world case where rooting assemblies with forwarded types caused runtime failures because the forwarder targets were trimmed. @filipnavara also noted a production scenario with System.Windows.Forms serialized resources depending on forwarders being functional after trimming.
Questions for discussion
Is the current behavior (dangling forwarders are acceptable) the right default?
Should there be an opt-in mechanism to mark forwarder targets? For example, a per-assembly or per-forwarder option to say "keep this forwarder and its target."
Should ILLink warn when a marked forwarder's target is not marked, so users can take action?
Note
This issue was filed with AI (Copilot) assistance.
Currently, when ILLink marks an
ExportedType(type forwarder) row — whether through rooting an assembly with-a, or throughcopy/saveaction — it preserves the forwarder metadata but does not mark the targetTypeDefinitionthe forwarder resolves to. This means the forwarder can become dangling, pointing to a type or assembly that was trimmed away.This is tested and documented as expected behavior:
The same behavior applies for
copyaction assemblies (RootAllLibraryCopyBehavior.cs,UnusedForwarderWithAssemblyCopyIsKept.cs).Why the current behavior may be correct
Shim assemblies like
mscorlib.dllandnetstandard.dllare composed almost entirely of type forwarders pointing to dozens of implementation assemblies. If marking a forwarder also marked its target, rooting one of these assemblies would pull in a large portion of the .NET surface area — defeating the purpose of trimming.Some forwarder targets may not even be resolvable. The mscorlib shim forwards to assemblies like
System.Drawing.Common,System.Data.SqlClient, andSystem.Security.Permissionsthat may not be present in the app. This is an established pattern that--skip-unresolved truewas designed to accommodate (see #103831).Why it might be a problem
A dangling forwarder is broken at runtime — if any code attempts to load a type through the forwarder, it will fail. Issue #99592 reported a real-world case where rooting assemblies with forwarded types caused runtime failures because the forwarder targets were trimmed. @filipnavara also noted a production scenario with
System.Windows.Formsserialized resources depending on forwarders being functional after trimming.Questions for discussion
Related