Skip to content

Do not allow generic inlining of ldftn requiring a fat function pointer - #131439

Merged
MichalStrehovsky merged 2 commits into
dotnet:mainfrom
agocke:issue-129093
Jul 28, 2026
Merged

Do not allow generic inlining of ldftn requiring a fat function pointer#131439
MichalStrehovsky merged 2 commits into
dotnet:mainfrom
agocke:issue-129093

Conversation

@agocke

@agocke agocke commented Jul 27, 2026

Copy link
Copy Markdown
Member

Fixes #129093.

When ldftn targets a method that needs a hidden generic context argument, ILC asks the JIT to build a fat function pointer and creates a ReadyToRunHelperId.MethodEntry generic lookup helper for it. Unlike every other lookup path in CorInfoImpl (ComputeLookup, and the delegate ctor path fixed in #102299), this one did not check whether the token came from an inlinee's generic context.

The result is that the runtime determined method - expressed in terms of the inlinee's generic parameters - ends up recorded in the inliner's dictionary. ShadowMethodNode.GetStaticDependencies then substitutes it with the inliner's instantiations, which throws IndexOutOfRangeException in GetNonRuntimeDeterminedTypeFromRuntimeDeterminedSubtypeViaSubstitution when the arities don't line up (and would silently look up the wrong dictionary slot when they do).

Repro (crashes ilc with the stack reported in #129093):

class Gen<T>
{
    [MethodImpl(MethodImplOptions.NoInlining)]
    public static Type Method() => typeof(T);
}

static unsafe nint GetPtr<U>() => (nint)(delegate*<Type>)&Gen<U>.Method;

class Caller<X>
{
    [MethodImpl(MethodImplOptions.NoInlining)]
    public static nint Run() => GetPtr<X>();
}

The fix aborts the inline in that case, which the JIT already knows how to handle (impLookupToTree notes CALLSITE_GENERIC_DICTIONARY_LOOKUP for CORINFO_LOOKUP_NOT_SUPPORTED, and both impMethodPointer callers check compDonotInline).

Validation:

  • The added smoke test fails with the reported Index was outside the bounds of the array error without the compiler change, and passes with it.
  • Full src/tests/nativeaot tree builds and the produced binaries run clean on linux-x64.

Cc @dotnet/ilc-contrib

Note

This change was authored with GitHub Copilot.

When `ldftn` targets a method that needs a hidden generic context argument,
ILC asks the JIT to build a fat function pointer and creates a `MethodEntry`
generic lookup helper for it. Unlike every other lookup path, this one did not
check whether the token came from an inlinee's generic context, so the runtime
determined method (expressed in the inlinee's generic parameters) ended up
recorded in the inliner's dictionary. Instantiating those dependencies then
threw `IndexOutOfRangeException` in
`GetNonRuntimeDeterminedTypeFromRuntimeDeterminedSubtypeViaSubstitution`, or
silently produced a lookup against the wrong dictionary.

Abort the inline in that case, the same way we do for delegate creation
(dotnet#102299) and for `ComputeLookup`.

Fixes dotnet#129093.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4a16e444-be00-4ff2-a37a-f3c3ea4eef4e
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 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.

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.

Pull request overview

Prevents NativeAOT/ILC from allowing inlining when importing an ldftn that would require a fat function pointer lookup expressed in the inlinee’s generic context, by reporting the lookup as unsupported in that situation. Adds a NativeAOT smoke-test regression to cover the crash scenario.

Changes:

  • In CorInfoImpl.getCallInfo, detect ldftn fat-function-pointer runtime lookups coming from an inlinee token context and return CORINFO_LOOKUP_NOT_SUPPORTED to force the JIT to abort the inline.
  • Add a NativeAOT smoke-test regression (Test129093Regression) that takes a function pointer to a generic method requiring a generic context and validates correctness for multiple instantiations.
Show a summary per file
File Description
src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs Returns CORINFO_LOOKUP_NOT_SUPPORTED for fat-function-pointer ldftn lookups when the token context doesn’t match the method being compiled (inlining case).
src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs Adds Test129093Regression and wires it into the NativeAOT Generics smoke test run list.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 1

Comment thread src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 27, 2026 21:21

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's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new

@MichalStrehovsky MichalStrehovsky left a comment

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.

Good catch! Seems like not async specific and not a .NET 11 regression. Looks like I almost fixed this in #129560 when someone on Discord was asking why we're even doing a R2R helper here (we shouldn't be doing a R2R helper in the first place, but the R2R helper is an easier way out considering everything else).

@MichalStrehovsky
MichalStrehovsky merged commit 0174775 into dotnet:main Jul 28, 2026
116 checks passed
@github-project-automation github-project-automation Bot moved this to Done in AppModel Jul 28, 2026
@flucas1

flucas1 commented Jul 28, 2026

Copy link
Copy Markdown

Bravo!

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

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Compiler Crash with PublishAot and .NET 11 preview 4

4 participants