镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Support invoking abstract constructors on existing instances in NativeAOT - #135288

Draft
jkotas with Copilot wants to merge 6 commits into
mainfrom
copilot/support-abstract-constructors
Draft

jkotas with Copilot wants to merge 6 commits into
mainfrom
copilot/support-abstract-constructors

Conversation

Copilot AI commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

NativeAOT rejects abstract constructors before MethodInvoker can invoke them on a compatible derived instance.

  • Invocation: Allow invoker creation for abstract constructors, including regular and by-ref arguments.
  • Rejection paths: Continue to reject allocation and null-target invocation with MemberAccessException.
  • Coverage: Enable the existing NativeAOT reflection tests and add allocation-rejection assertions.

Note

This description was generated with GitHub Copilot.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
16 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib
See info in area-owners.md if you want to be subscribed.

Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Copilot AI changed the title [WIP] Support invoking abstract constructors on existing instances Support invoking abstract constructors on existing instances in NativeAOT Oct 6, 2026
Copilot AI requested a review from jkotas October 6, 2026 17:12
Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>

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.

🟡 Changes recommended

Removing the guard changes allocation rejection for parameterless constructors on open abstract generic types from MemberAccessException to InvalidOperationException in both invocation paths, requiring a guard fix and regression test.

1 open issue
What changed in this PR

This PR enables NativeAOT to invoke abstract base constructors on existing compatible derived instances through MethodInvoker, addressing #134903.

Changes:

  • Moves abstract-constructor rejection from invoker creation to allocation and null-target validation.
  • Adds the abstract-allocation error resource to reflection execution.
  • Enables NativeAOT tests for existing-instance invocation and adds allocation-rejection assertions.
File Description
src/​libraries/​System.Runtime/​tests/​System.Reflection.Tests/​MethodInvokerTests.cs Enables NativeAOT coverage and adds allocation-rejection checks.
src/​coreclr/​nativeaot/​System.Private.Reflection.Execution/​src/​Resources/​Strings.resx Adds the abstract-type allocation error message.
src/​coreclr/​nativeaot/​System.Private.Reflection.Execution/​src/​Internal/​Reflection/​Execution/​MethodInvokers/​InstanceMethodInvoker.cs Rejects abstract allocation and null targets while allowing existing instances.
src/​coreclr/​nativeaot/​System.Private.CoreLib/​src/​System/​Reflection/​Runtime/​MethodInfos/​RuntimePlainConstructorInfo.cs Removes the blanket abstract-type rejection during invoker creation.

Review effort: Balanced

Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
{
if (_common.DefiningTypeInfo.IsAbstract)
if (_common.DefiningTypeInfo.IsAbstract && this.ContainsGenericParameters)
throw new MemberAccessException(SR.Format(SR.Acc_CreateAbstEx, _common.DefiningTypeInfo.FullName));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot Does this error message match the error message produced by regular CoreCLR?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not exactly. CoreCLR uses the same Acc_CreateAbstEx resource, but passes declaringType to SR.Format, whereas this guard passes _common.DefiningTypeInfo.FullName. For AbstractBase<T>, CoreCLR displays “AbstractBase1[T]”, while this code displays “AbstractBase1”. CoreCLR checks abstractness before unbound generic parameters, so the abstract-class message is correct; the type-name formatting differs.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot What is the error message and exception on CoreCLR vs. NativeAOT if a concrete instance is passed into ConstructorInfo with unbound generic parameters?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For AbstractBase, CoreCLR displays “AbstractBase1[T]”, while this code displays “AbstractBase1

@copilot Let's fix this discrepancy and update NAOT to match CoreCLR

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

For ConstructorInfo obtained from AbstractBase<>, invoking it on a concrete derived instance is rejected before target validation on both runtimes. In the current branch:

  • CoreCLR: MemberAccessException: “Cannot create an instance of AbstractBase`1[T] because it is an abstract class.”
  • NativeAOT: MemberAccessException: “Cannot create an instance of AbstractBase`1 because it is an abstract class.”

(Type names also include their namespace/nesting.)

For comparison, if the open generic declaring type is non-abstract, CoreCLR throws MemberAccessException: “Cannot create an instance of GenericBase1[T] because Type.ContainsGenericParameters is true.” NativeAOT throws InvalidOperationException`: “Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.”

This comparison is from the source paths; I haven’t run a new repro.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

invoking it on a concrete derived instance is rejected before target validation on both runtimes

@copilot Fix this case to use "Cannot create an instance of GenericBase1[T] because Type.ContainsGenericParameters is true." error message

NativeAOT throws InvalidOperationException`: “Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.”

@copilot Fix this case to match CoreCLR

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 9c21731. Both NativeAOT abstract-constructor throw sites now format the declaring Type, matching CoreCLR, instead of using FullName. Added type-name assertions for open and closed generic abstract constructors; all four cases failed before the fix. All 165 selected invoker tests pass on both NativeAOT and CoreCLR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed both in 372cb86. ConstructorInfo.Invoke with an existing target now uses MemberAccessException and the Type.ContainsGenericParameters message for open generic declaring types, including abstract types, on both CoreCLR and NativeAOT. NativeAOT also now matches CoreCLR for non-abstract open-generic allocation through ConstructorInfo and ConstructorInvoker. Abstract allocation retains its abstract-class message.

Added regression tests and verified they fail before the fix. Selected constructor/invoker tests pass on both runtimes: CoreCLR reports 236 tests with no skips; NativeAOT reports 234 run and two existing static-constructor skips.

Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[NativeAOT] Support invoking abstract constructors on existing instances through MethodInvoker

3 participants