Repository navigation
Conversation
|
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. |
|
Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib |
Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
There was a problem hiding this comment.
🟡 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)); |
There was a problem hiding this comment.
@copilot Does this error message match the error message produced by regular CoreCLR?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
@copilot What is the error message and exception on CoreCLR vs. NativeAOT if a concrete instance is passed into ConstructorInfo with unbound generic parameters?
There was a problem hiding this comment.
For AbstractBase, CoreCLR displays “AbstractBase1[T]”, while this code displays “AbstractBase1
@copilot Let's fix this discrepancy and update NAOT to match CoreCLR
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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>

NativeAOT rejects abstract constructors before
MethodInvokercan invoke them on a compatible derived instance.MemberAccessException.Note
This description was generated with GitHub Copilot.