Skip to content

[linker] Only generate NSObject factories for generic types. Fixes #25232. - #26510

Open
rolfbjarne wants to merge 5 commits into
mainfrom
dev/rolf/generic-nsobject-factories
Open

[linker] Only generate NSObject factories for generic types. Fixes #25232.#26510
rolfbjarne wants to merge 5 commits into
mainfrom
dev/rolf/generic-nsobject-factories

Conversation

@rolfbjarne

Copy link
Copy Markdown
Member

Non-generic types are constructed through the trimmable registrar type map, so only generic NSObject types need to implement INSObjectFactory.

Remove the broad interface-preservation dependency and rely on ILLink to retain generated interface implementations through their method overrides. This avoids preserving unrelated interface implementations and reduces app size.

Add assembly-preparer coverage for generic and non-generic factory generation, and update the expected app sizes.

Tests:

  • Assembly-preparer test suite
  • Mac Catalyst monotouch-test with the trimmable static registrar and full trimming (3,650 passed; one unrelated transient network test failure)

Fixes #25232

🤖 Pull request created by Copilot

rolfbjarne and others added 2 commits September 1, 2026 14:19
Non-generic types are constructed through the trimmable registrar type map. Let ILLink retain generated interface implementations through their method overrides instead of broadly preserving every interface on each type.

Add an assembly-preparer test covering generic and non-generic factory generation.

Fixes #25232.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ef04d7c1-e5e3-4244-ac92-f7341ddac90e
Copilot AI lite review requested due to automatic review settings September 1, 2026 12:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Pull request overview

This PR refines trimmable-static registrar factory generation to reduce unnecessary interface preservation and app size impact, aligning non-generic NSObject construction with the trimmable registrar type map while keeping factory methods only where type-map construction can’t work (generic NSObject types).

Changes:

  • Generate INSObjectFactory._Xamarin_ConstructNSObject only for generic NSObject types in the trimmable-static registrar pipeline.
  • Remove the trimmable-static “preserve all interfaces” dynamic dependency from generated interface implementations and rely on the generated method overrides instead.
  • Add assembly-preparer coverage for generic vs non-generic factory generation and update expected app-size baselines.
File summaries
File Description
tools/dotnet-linker/Steps/ManagedRegistrarStep.cs Limits NSObject factory method generation to generic types under the trimmable-static registrar.
tools/dotnet-linker/AppBundleRewriter.cs Removes the interface-preservation dynamic dependency for trimmable-static; keeps marking behavior for other registrar modes.
tests/assembly-preparer/ManagedRegistrarStepTests.cs Adds test coverage verifying factory generation behavior for generic vs non-generic NSObject types.
tests/dotnet/UnitTests/expected/TVOS-NativeAOT-TrimmableStatic-size.txt Updates expected app size after preservation reduction.
tests/dotnet/UnitTests/expected/MacOSX-NativeAOT-TrimmableStatic-size.txt Updates expected app size after preservation reduction.
tests/dotnet/UnitTests/expected/MacOSX-CoreCLR-Interpreter-TrimmableStatic-size.txt Updates expected app size after preservation reduction.
tests/dotnet/UnitTests/expected/MacCatalyst-NativeAOT-TrimmableStatic-size.txt Updates expected app size after preservation reduction.
tests/dotnet/UnitTests/expected/iOS-NativeAOT-TrimmableStatic-size.txt Updates expected app size after preservation reduction.
Review details

Suppressed comments (1)

tests/assembly-preparer/ManagedRegistrarStepTests.cs:51

  • 💡 Testing — For the same reason as the non-generic case, also assert that the generated _Xamarin_ConstructINativeObject method on the generic type has an override to ObjCRuntime.INativeObject, since the trimmer-retention strategy depends on method overrides.
		var factoryMethod = genericType.Methods.Single (v => v.Name == "_Xamarin_ConstructNSObject");
		Assert.That (factoryMethod.Overrides.Select (v => v.DeclaringType.FullName), Does.Contain ("Foundation.INSObjectFactory"), "Generic method overrides");

  • Files reviewed: 8/8 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +44 to +45
Assert.That (nonGenericType.Interfaces.Select (v => v.InterfaceType.FullName), Does.Contain ("ObjCRuntime.INativeObject"), "Non-generic INativeObject interface");
Assert.That (nonGenericType.Methods.Select (v => v.Name), Does.Contain ("_Xamarin_ConstructINativeObject"), "Non-generic INativeObject methods");
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

⚠️ AppSizeTest expected files changed ⚠️

The AppSizeTest detected changes in the expected app size files.

To update the expected files, add a comment with the following command:

/apply-gist https://gist.github.com/vs-mobiletools-engineering-service2/5daef29a70e478893d0caf276efe733d
Updated files
  • iOS-CoreCLR-Interpreter-preservedapis.txt
  • iOS-CoreCLR-Interpreter-size.txt
  • iOS-CoreCLR-R2R-preservedapis.txt
  • iOS-CoreCLR-R2R-size.txt
  • iOS-NativeAOT-size.txt
  • iOS-NativeAOT-TrimmableStatic-size.txt
  • MacCatalyst-CoreCLR-Interpreter-preservedapis.txt
  • MacCatalyst-CoreCLR-Interpreter-size.txt
  • MacCatalyst-CoreCLR-R2R-preservedapis.txt
  • MacCatalyst-CoreCLR-R2R-size.txt
  • MacCatalyst-NativeAOT-size.txt
  • MacCatalyst-NativeAOT-TrimmableStatic-size.txt
  • MacOSX-CoreCLR-Interpreter-size.txt
  • MacOSX-CoreCLR-Interpreter-TrimmableStatic-size.txt
  • MacOSX-CoreCLR-R2R-size.txt
  • MacOSX-NativeAOT-size.txt
  • MacOSX-NativeAOT-TrimmableStatic-size.txt
  • TVOS-CoreCLR-Interpreter-preservedapis.txt
  • TVOS-CoreCLR-Interpreter-size.txt
  • TVOS-CoreCLR-R2R-preservedapis.txt
  • TVOS-CoreCLR-R2R-size.txt
  • TVOS-NativeAOT-size.txt
  • TVOS-NativeAOT-TrimmableStatic-size.txt

Pipeline on Agent
Hash: 76dde6bcf9c657dac5185d7715f41bb289ebe0b7 [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ API diff for current PR / commit

NET (empty diffs)

✅ API diff vs stable

NET (empty diffs)

ℹ️ Generator diff

Generator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes)

Pipeline on Agent
Hash: eb2252cf403330d59a07cdcf2c31410f9034f268 [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

🔥 [CI Build #eb2252c] Test results 🔥

Test results

❌ Tests failed on VSTS: test results

0 tests crashed, 5 tests failed, 259 tests passed.

Failures

❌ assembly-processing tests

1 tests failed, 0 tests passed.

Failed tests

  • Assembly processing tests: Failed (Execution failed with exit code 1)
    • AssemblyPreparerTests.ManagedRegistrarStepTests.NSObjectFactory: Non-generic INativeObject interface
      Assert.That(nonGenericType.Interfaces.Select (v => v.InterfaceType.FullName), Does.Contain...

Html Report (VSDrops) Download

❌ dotnettests tests (iOS)

1 tests failed, 0 tests passed.

Failed tests

  • DotNet tests: Failed (Execution failed with exit code 1)
    • Xamarin.Tests.DotNetProjectTest.LinkedWithNativeLibraries_CoreCL...: Frameworks
      Assert.That(actualFrameworks.OrderBy (v => v).ToArray (), Is.EquivalentTo (expectedFrameworks.OrderBy (v => v).ToAr...

Html Report (VSDrops) Download

❌ dotnettests tests (MacCatalyst)

1 tests failed, 0 tests passed.

Failed tests

  • DotNet tests: Failed (Execution failed with exit code 1)
    • Xamarin.Tests.DotNetProjectTest.LinkedWithNativeLibraries_CoreCL...: Frameworks
      Assert.That(actualFrameworks.OrderBy (v => v).ToArray (), Is.EquivalentTo (expectedFrameworks.OrderBy (v => v).ToAr...
    • Xamarin.Tests.TemplateTest.CreateAndBuildProjectTemplate(maccata...: '/Users/cloudtest/vss/_work/1/s/macios/tests/dotnet/UnitTests/bin/Debug/net11.0/tmp-test-dir/Xamarin.Tests.TemplateTest.CreateAn...

Html Report (VSDrops) Download

❌ dotnettests tests (macOS)

1 tests failed, 0 tests passed.

Failed tests

  • DotNet tests: Failed (Execution failed with exit code 1)
    • Xamarin.Tests.DotNetProjectTest.LinkedWithNativeLibraries_CoreCL...: Frameworks
      Assert.That(actualFrameworks.OrderBy (v => v).ToArray (), Is.EquivalentTo (expectedFrameworks.OrderBy (v => v).ToAr...

Html Report (VSDrops) Download

❌ dotnettests tests (tvOS)

1 tests failed, 0 tests passed.

Failed tests

  • DotNet tests: Failed (Execution failed with exit code 1)
    • Xamarin.Tests.DotNetProjectTest.LinkedWithNativeLibraries_CoreCL...: Frameworks
      Assert.That(actualFrameworks.OrderBy (v => v).ToArray (), Is.EquivalentTo (expectedFrameworks.OrderBy (v => v).ToAr...

Html Report (VSDrops) Download

Successes

✅ cecil: All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (Multiple platforms): All 1 tests passed. Html Report (VSDrops) Download
✅ framework: All 2 tests passed. Html Report (VSDrops) Download
✅ fsharp: All 4 tests passed. Html Report (VSDrops) Download
✅ generator: All 5 tests passed. Html Report (VSDrops) Download
✅ interdependent-binding-projects: All 4 tests passed. Html Report (VSDrops) Download
✅ introspection: All 7 tests passed. Html Report (VSDrops) Download
✅ linker (iOS): All 31 tests passed. Html Report (VSDrops) Download
✅ linker (MacCatalyst): All 31 tests passed. Html Report (VSDrops) Download
✅ linker (macOS): All 21 tests passed. Html Report (VSDrops) Download
✅ linker (tvOS): All 31 tests passed. Html Report (VSDrops) Download
✅ monotouch (iOS): All 25 tests passed. Html Report (VSDrops) Download
✅ monotouch (MacCatalyst): All 25 tests passed. Html Report (VSDrops) Download
✅ monotouch (macOS): All 20 tests passed. Html Report (VSDrops) Download
✅ monotouch (tvOS): All 25 tests passed. Html Report (VSDrops) Download
✅ msbuild: All 2 tests passed. Html Report (VSDrops) Download
✅ sharpie: All 1 tests passed. Html Report (VSDrops) Download
✅ windows: All 3 tests passed. Html Report (VSDrops) Download
✅ xcframework: All 4 tests passed. Html Report (VSDrops) Download
✅ xtro: All 1 tests passed. Html Report (VSDrops) Download

macOS tests

✅ Tests on macOS Sonoma (14): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sequoia (15): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Tahoe (26): All 5 tests passed. Html Report (VSDrops) Download

Linux Build Verification

Linux build succeeded

Pipeline on Agent
Hash: eb2252cf403330d59a07cdcf2c31410f9034f268 [PR build]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Trimmable-static-registrar: investigate why it's necessary to manually preserve the NSObject and INativeObject factory interfaces and methods

3 participants