[assembly-preparer] Fix IL2036 unresolved type in DynamicDependency with link-all. Fixes #26017 - #26040
Conversation
…ith link-all. Fixes #26017 When building with `PrepareAssemblies=true` and link all (`MtouchLink=Full`), ILLink failed with: error IL2036: <Module>..cctor(): Unresolved type 'Foundation.NSExpression' in 'DynamicDependencyAttribute'. error NETSDK1144: Optimizing assemblies for size failed. The assembly-preparer's `ApplyPreserveAttributeStep` translates `[Preserve (typeof (X))]` into a `[DynamicDependency]` attribute on the module's static constructor. `CreateDynamicDependencyAttribute (DynamicallyAccessedMemberTypes, TypeDefinition)` passed the raw cross-assembly `TypeDefinition` as the `Type` argument. Cecil serializes such an argument *without* an assembly-qualified name, because a `TypeDefinition`'s `Scope` is its own module (so `RequiresFullyQualifiedName` returns false). The resulting attribute referenced `Foundation.NSExpression` with no assembly, which ILLink couldn't resolve once the app assembly was trimmed in full-link mode. Fix: import the type into the current assembly's module before using it as the `Type` argument, so Cecil emits a proper assembly-qualified name (`Foundation.NSExpression, Microsoft.iOS, ...`). This only affected the assembly-preparer path: the regular linker step emits an XML descriptor instead of `[DynamicDependency]` attributes. It also only surfaced with link all, since the module cctor's attributes are only processed by ILLink when the app assembly is trimmed. No new test is needed: on .NET 11 (where `PrepareAssemblies` defaults to true) the existing xharness `monotouch-test` "Release (link all)" variation builds monotouch-test with link all + PrepareAssemblies, and monotouch-test contains `[assembly: Preserve (typeof (NSExpression))]`, which reproduces this exact failure. Fixes #26017. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes a trimming/link-all failure in the assembly-preparer path where [Preserve (typeof (X))] is translated into a module-level [DynamicDependency] that ILLink couldn’t resolve due to a non-assembly-qualified Type argument.
Changes:
- Import cross-assembly
TypeDefinitionvalues into the current module before emitting them as theTypeconstructor argument for[DynamicDependency], ensuring Cecil serializes an assembly-qualified type name. - Prevents
IL2036“Unresolved type … in DynamicDependencyAttribute” whenPrepareAssemblies=trueandMtouchLink=Full/ full trim is enabled.
✅ API diff for current PR / commitNET (empty diffs)✅ API diff vs stableNET (empty diffs)ℹ️ Generator diffGenerator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes) Pipeline on Agent |
This comment has been minimized.
This comment has been minimized.
🚀 [CI Build #66caa58] Test results 🚀Test results✅ All tests passed on VSTS: test results. 🎉 All 199 tests passed 🎉 Tests counts✅ assembly-processing: All 1 tests passed. Html Report (VSDrops) Download macOS tests✅ Tests on macOS Monterey (12): All 5 tests passed. Html Report (VSDrops) Download Linux Build VerificationPipeline on Agent |
When building with
PrepareAssemblies=trueand link all (MtouchLink=Full), ILLink failed with:The assembly-preparer's
ApplyPreserveAttributeSteptranslates[Preserve (typeof (X))]into a[DynamicDependency]attribute on the module's static constructor.CreateDynamicDependencyAttribute (DynamicallyAccessedMemberTypes, TypeDefinition)passed the raw cross-assemblyTypeDefinitionas theTypeargument. Cecil serializes such an argument without an assembly-qualified name, because aTypeDefinition'sScopeis its own module (soRequiresFullyQualifiedNamereturns false). The resulting attribute referencedFoundation.NSExpressionwith no assembly, which ILLink couldn't resolve once the app assembly was trimmed in full-link mode.Fix: import the type into the current assembly's module before using it as the
Typeargument, so Cecil emits a proper assembly-qualified name (Foundation.NSExpression, Microsoft.iOS, ...).This only affected the assembly-preparer path: the regular linker step emits an XML descriptor instead of
[DynamicDependency]attributes. It also only surfaced with link all, since the module cctor's attributes are only processed by ILLink when the app assembly is trimmed.No new test is needed: on .NET 11 (where
PrepareAssembliesdefaults to true) the existing xharnessmonotouch-test"Release (link all)" variation builds monotouch-test with link all + PrepareAssemblies, and monotouch-test contains[assembly: Preserve (typeof (NSExpression))](tests/monotouch-test/Foundation/NSExpressionTest.cs), which reproduces this exact failure.Fixes #26017
🤖 Pull request created by Copilot