Skip to content

fix(aot): preserve grain activation constructors - #11383

Merged
ReubenBond merged 3 commits into
dotnet:mainfrom
ReubenBond:rb-nativeaot-grain-activation
Oct 1, 2026
Merged

ReubenBond merged 3 commits into
dotnet:mainfrom
ReubenBond:rb-nativeaot-grain-activation

Conversation

@ReubenBond

@ReubenBond ReubenBond commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Problem

NativeAOT can remove the public constructor metadata of a concrete grain registered by generated metadata. The grain class resolves successfully, but DefaultGrainActivator cannot find its implicit public parameterless constructor. Manual grain registration needs the same constructor-retention guarantee.

Solution

Preserve public constructors alongside implemented interfaces in TypeManifestOptions.AddInterfaceImplementation, the source-generated registration boundary. Carry the constructor requirement through GrainClassMap and both default activation consumers.

Add GrainTypeOptions.AddClass(Type) as the annotated manual-registration path. Direct access to the legacy Classes collection and construction of a GrainClassMap from an arbitrary dictionary carry trimming warnings requiring separate constructor preservation. Production manifest construction consumes the registered options collection. Collection-boundary suppressions are confined to those established registration contracts.

Constructor selection stays with ActivatorUtilities, including preferred public constructors and activation-scoped dependency identity. Focused tests cover those outcomes in the existing test project and the shared GrainActivation NativeAOT scenario. The expanded native scenario also activates a private grain registered exclusively through AddClass and checks that generated metadata has not registered it. Removing constructor retention at either registration boundary reproduces the corresponding native activation failure; restoring it makes the same scenario pass.

The branch is rebased onto main and reuses the shared smoke harness and common CI from merged #11367. This scenario keeps the wider runtime diagnostic backlog visible while rejecting constructor-path diagnostics; generic grain closure and runtime facet construction retain their existing diagnostics.

The cumulative integration gate verified the original constructor-retention change alongside the existing series in a real Windows x64 NativeAOT executable with dynamic code disabled: ordinary Host.StartAsync, application IAdditionGrain.Add(17, 25) returning 42, and explicit StopAsync with graceful silo shutdown. It kept the original host configuration and deadline, the default-off generated-context setting, and source-generated grain registrations. This proof covers the exercised concrete, non-generic grain and local memory-storage host contract; the expanded focused native scenario verifies the manual-registration correction.

Fixes #11381.

Microsoft Reviewers: Open in CodeFlow

Copilot AI balanced review requested due to automatic review settings October 1, 2026 20:35

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.

Copilot review overview

🔵 Needs a closer look

NativeAOT linker behavior and externally owned smoke infrastructure warrant final human validation.

Review effort: Balanced
Findings: None

What changed in this PR

Preserves grain public constructors through generated metadata so default activation works under trimming and NativeAOT.

Changes:

  • Propagates constructor-preservation annotations through registration, mapping, and activation.
  • Adds managed and NativeAOT activation coverage.
  • Documents constructor selection and scoped dependency behavior.
File Description
test/​Orleans.NativeAotSmoke/​Orleans.NativeAotSmoke.csproj Configures NativeAOT scenarios.
test/​Orleans.NativeAotSmoke/​NativeAotEnvironment.cs Validates native execution.
test/​Orleans.NativeAotSmoke/​GrainActivation.smoke.json Defines diagnostic gates.
test/​Orleans.NativeAotSmoke/​GrainActivation.cs Exercises native grain activation.
test/​Orleans.Core.Tests/​Runtime/​DefaultGrainActivatorTests.cs Tests constructor and DI behavior.
src/​Orleans.Serialization/​Configuration/​TypeManifestOptions.cs Preserves public constructors at registration.
src/​Orleans.Runtime/​README.md Documents grain construction.
src/​Orleans.Runtime/​Manifest/​GrainClassMap.cs Propagates constructor metadata guarantees.
src/​Orleans.Runtime/​Facet/​GrainConstructorArgumentFactory.cs Annotates reflected grain types.
src/​Orleans.Runtime/​Activation/​DefaultGrainActivator.cs Annotates activation input types.

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

Copilot AI balanced review requested due to automatic review settings October 1, 2026 20:47

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.

Copilot review overview

🟡 Changes recommended

The trimming suppression is unsound for grain classes registered directly through GrainTypeOptions.Classes.

Review effort: Balanced
Findings: 1 High severity

Open (1)

Comment thread src/Orleans.Runtime/Manifest/GrainClassMap.cs Outdated
@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Code coverage

Metric Pull request
Lines 82.88% (115,456 / 139,303)
Branches 72.18% (33,504 / 46,419)

Report-only conclusion: current-main baseline stale.

The newest successful coverage run tested 171c262, not current main cc1a9ff.

Coverage combines every CI test matrix job, including providers, CodeGen, .NET 8/10, Linux, Windows, and macOS, using canonical physical source and branch identities.

The comparison remains report-only while normal line and branch variance is calibrated.

Coverage details

Copilot AI balanced review requested due to automatic review settings October 1, 2026 22:25
@ReubenBond
ReubenBond force-pushed the rb-nativeaot-grain-activation branch from d06349a to aae978c Compare October 1, 2026 22:25

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.

Copilot review overview

🟢 Approval recommended

Constructor-preservation requirements are consistently propagated and covered by focused managed and NativeAOT tests.

Review effort: Balanced
Findings: None

Resolved since last review (1)

@ReubenBond
ReubenBond merged commit cc1a9ff into dotnet:main Oct 1, 2026
75 checks passed
@ReubenBond
ReubenBond deleted the rb-nativeaot-grain-activation branch October 1, 2026 22:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NativeAOT grain activation cannot locate a public parameterless constructor

2 participants