Skip to content

Fix LoadExactInterfaceMap for sub-interfaces with complex type arguments under special marker parents#124684

Merged
davidwrighton merged 4 commits intodotnet:mainfrom
davidwrighton:fix_124369
Feb 25, 2026
Merged

Fix LoadExactInterfaceMap for sub-interfaces with complex type arguments under special marker parents#124684
davidwrighton merged 4 commits intodotnet:mainfrom
davidwrighton:fix_124369

Conversation

@davidwrighton
Copy link
Member

Summary

When pNewIntfMT is a special marker type and its sub-interface in the interface map has an exact instantiation containing complex type arguments (e.g. IList<T> rather than bare T), the previous code in LoadExactInterfaceMap would incorrectly fall through to the old case 4 logic. This checked EligibleForSpecialMarkerTypeUsage against pMT rather than pNewIntfMT, which could treat a sub-interface still containing unresolved generic variables as either eligible for special marker substitution or as an exact match — both incorrect.

Fix

The old case 4 (exact instantiation) is split into three cases to correctly handle the situation where pNewIntfMT is itself a special marker type:

  • Case 4: The sub-interface's instantiation is eligible for special marker usage relative to pNewIntfMT (e.g. ILayer1<T> where T matches pNewIntfMT's type parameter). Insert the special marker type.
  • Case 5: The sub-interface has generic variables that don't match pNewIntfMT's type parameter (e.g. ILayer1<IList<T>>). Since resolving this requires a full deep substitution, and this is a rare scenario, we fall back to the retry-with-exact-interfaces pathway which sets MayHaveOpenInterfacesInInterfaceMap and disables the special marker optimization for this type.
  • Case 6: The sub-interface is fully concrete (no generic variables) or pNewIntfMT is not a special marker type. Falls through to the existing pMT-based eligibility check, which is correct in these situations.

A regression test is added covering all 8 combinations of pre-loading the 3 interface layers' generic type definitions before constructing the concrete class, to exercise the various orderings that lead to different code paths through the special marker type logic.

Fixes #124369

davidwrighton and others added 3 commits February 20, 2026 14:45
…nts under special marker parents

When pNewIntfMT is a special marker type and its sub-interface has an
exact instantiation containing complex type arguments (e.g. IList(Of T)
rather than bare T), the previous code would fall through to case 4
which checked EligibleForSpecialMarkerTypeUsage against pMT. This could
incorrectly treat the sub-interface as an exact match when it still
contains unresolved generic variables.

Split old case 4 into three new cases:
- Case 4: pNewIntfMT is a special marker type and the sub-interface's
  instantiation is eligible for special marker usage relative to
  pNewIntfMT (e.g. ILayer1(Of T) where T matches). Insert the marker.
- Case 5: pNewIntfMT is a special marker type but the sub-interface has
  generic variables that don't match (e.g. ILayer1(Of IList(Of T))).
  Trigger retry with exact interfaces since full substitution is needed.
- Case 6: The sub-interface is fully concrete or pNewIntfMT is not a
  special marker. Fall through to the existing pMT-based eligibility
  check.

Add regression tests covering all 8 combinations of pre-loading the
3 interface layers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes CoreCLR interface-map exact-loading for the case where a special marker parent interface contains a sub-interface entry that is an exact instantiation with more complex type arguments (e.g., IList<T>), preventing incorrect eligibility checks and ensuring the algorithm falls back to the exact-interface retry path when deep substitution would be required.

Changes:

  • Split the prior “exact instantiation” handling in LoadExactInterfaceMap into additional sub-cases to correctly handle special-marker parents and open generic variables.
  • Add a VB regression test suite (with 8 preload-order combinations) to exercise the special marker interface map logic and validate the fix.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
src/coreclr/vm/methodtablebuilder.cpp Refines LoadExactInterfaceMap handling for exact sub-interfaces under special marker parents, including a controlled fallback path.
src/tests/Loader/classloader/regressions/GitHub_124369/GitHub_124369.vb Adds VB regression coverage for the reported failure mode across multiple preload orderings and interface layering shapes.
src/tests/Loader/classloader/regressions/GitHub_124369/GitHub_124369.vbproj Adds the test project definition for the new VB regression test.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

@jkotas
Copy link
Member

jkotas commented Feb 24, 2026

/azp run runtime-coreclr outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@davidwrighton
Copy link
Member Author

/ba-g Only failing case is #122345 which the build analysis tools didn't find for some reason.

@davidwrighton davidwrighton merged commit 52114b6 into dotnet:main Feb 25, 2026
155 of 167 checks passed
@davidwrighton
Copy link
Member Author

/backport to release/10.0

@github-actions
Copy link
Contributor

Started backporting to release/10.0 (link to workflow run)

iremyux pushed a commit to iremyux/dotnet-runtime that referenced this pull request Mar 2, 2026
…nts under special marker parents (dotnet#124684)

## Summary

When `pNewIntfMT` is a special marker type and its sub-interface in the
interface map has an exact instantiation containing complex type
arguments (e.g. `IList<T>` rather than bare `T`), the previous code in
`LoadExactInterfaceMap` would incorrectly fall through to the old case 4
logic. This checked `EligibleForSpecialMarkerTypeUsage` against `pMT`
rather than `pNewIntfMT`, which could treat a sub-interface still
containing unresolved generic variables as either eligible for special
marker substitution or as an exact match — both incorrect.

## Fix

The old case 4 (exact instantiation) is split into three cases to
correctly handle the situation where `pNewIntfMT` is itself a special
marker type:

- **Case 4**: The sub-interface's instantiation is eligible for special
marker usage relative to `pNewIntfMT` (e.g. `ILayer1<T>` where `T`
matches `pNewIntfMT`'s type parameter). Insert the special marker type.
- **Case 5**: The sub-interface has generic variables that don't match
`pNewIntfMT`'s type parameter (e.g. `ILayer1<IList<T>>`). Since
resolving this requires a full deep substitution, and this is a rare
scenario, we fall back to the retry-with-exact-interfaces pathway which
sets `MayHaveOpenInterfacesInInterfaceMap` and disables the special
marker optimization for this type.
- **Case 6**: The sub-interface is fully concrete (no generic variables)
or `pNewIntfMT` is not a special marker type. Falls through to the
existing `pMT`-based eligibility check, which is correct in these
situations.

A regression test is added covering all 8 combinations of pre-loading
the 3 interface layers' generic type definitions before constructing the
concrete class, to exercise the various orderings that lead to different
code paths through the special marker type logic.

Fixes dotnet#124369

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
JulieLeeMSFT pushed a commit that referenced this pull request Mar 4, 2026
…lex type arguments under special marker parents (#124835)

Backport of #124684 to release/10.0

/cc @davidwrighton

## Customer Impact

- [x] Customer reported
- [ ] Found internally

The earlier fix for #123254 did not fix all possible cases where the
incorrect type would be loaded. This fix fills out the special case
matrix some more, and I believe should fix all the issues found.

## Regression

- [x] Yes
- [ ] No

This issue was introduced with PR #120712, and mitigated somewhat with
PR #123520. This fix builds on that fix to fix additional issues found
by @reduckted.

## Testing

The fix includes a fairly large test suite covering possible ways type
loading could fail around this fix. It was missed previously in the
previous small fix as the importance of comparing the fully loaded, and
partially loaded interface maps on the generic type definition was
missed during test development. This fix has also been tested by
delivering a hotfixed build to @reduckted which which he was able to
verify fixed the issues he had seen in production as well as in testing.

## Risk

Low. Its filling out more special cases in the new codepaths added in PR
#123520.

**IMPORTANT**: If this backport is for a servicing release, please
verify that:

- For .NET 8 and .NET 9: The PR target branch is `release/X.0-staging`,
not `release/X.0`.
- For .NET 10+: The PR target branch is `release/X.0` (no `-staging`
suffix).

## Package authoring no longer needed in .NET 9

**IMPORTANT**: Starting with .NET 9, you no longer need to edit a NuGet
package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older
versions.

---------

Co-authored-by: David Wrighton <davidwr@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
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.

VB.NET program using .NET runtime 10.0.3 throws EntryPointNotFoundException

3 participants