[assembly-preparer] Fix IL2036 unresolved type in DynamicDependency with link-all. Fixes #26017#26040
[assembly-preparer] Fix IL2036 unresolved type in DynamicDependency with link-all. Fixes #26017#26040rolfbjarne wants to merge 1 commit into
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 |
🔥 [CI Build #66caa58] Test results 🔥Test results❌ Tests failed on VSTS: test results 2 tests crashed, 0 tests failed, 193 tests passed. Failures❌ framework tests🔥 Failed catastrophically on VSTS: test results - framework (no summary found). Html Report (VSDrops) Download ❌ interdependent-binding-projects tests🔥 Failed catastrophically on VSTS: test results - interdependent-binding-projects (no summary found). Html Report (VSDrops) Download Successes✅ 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