Skip to content

Commit eaa1254

Browse files
github-actions[bot]davidwrightonCopilotCopilot
authored
[release/10.0] Fix LoadExactInterfaceMap for sub-interfaces with complex 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>
1 parent b69bb43 commit eaa1254

File tree

3 files changed

+1491
-13
lines changed

3 files changed

+1491
-13
lines changed

src/coreclr/vm/methodtablebuilder.cpp

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9669,13 +9669,22 @@ MethodTableBuilder::LoadExactInterfaceMap(MethodTable *pMT)
96699669
{
96709670
MethodTable *pItfPossiblyApprox = intIt.GetInterfaceApprox();
96719671

9672-
// pItfPossiblyApprox can be in 4 situations
9672+
// pItfPossiblyApprox can be in 6 situations
96739673
// 1. It has no instantiation
9674-
// 2. It is a special marker type, AND pNewItfMT is a special marker type. Compute the exact instantiation as containing entirely a list of types corresponding to calling GetSpecialInstantiationType on pMT (This rule works based on the current behavior of GetSpecialInstantiationType where it treats all interfaces the same)
9675-
// 3. It is a special marker type, but pNewItfMT is NOT a special marker type. Compute the exact instantiation as containing entirely a list of types corresponding to calling GetSpecialInstantiationType on pNewItfMT
9676-
// 4. It is an exact instantiation
9674+
// 2. It is a special marker type, AND pNewIntfMT is a special marker type. Compute the exact instantiation as containing entirely a list of
9675+
// types corresponding to calling GetSpecialInstantiationType on pMT (This rule works based on the current behavior of
9676+
// GetSpecialInstantiationType where it treats all interfaces the same)
9677+
// 3. It is a special marker type, but pNewIntfMT is NOT a special marker type. Compute the exact instantiation as containing entirely a list
9678+
// of types corresponding to calling GetSpecialInstantiationType on pNewIntfMT
9679+
// 4. It is an exact instantiation, but pNewIntfMT was a special marker type, and the exact instantiation type found here could have been a
9680+
// special marker type. This should produce a result equivalent to case 2 (the special marker type)
9681+
// 5. It is an exact instantiation, but pNewIntfMT was a special marker type, and the exact instantiation type is NOT one which would have
9682+
// been on the exact instantiation of pNewIntfMT if it were not a special marker type. In theory we could reconstruct this, but this is a
9683+
// rare scenario, so we just fallback to the retry with exact interfaces pathway
9684+
// 6. It is an exact instantiation, and pNewIntfMT is NOT a special marker type, compute the result and insert either a special marker or
9685+
// the exact instantiation already found.
96779686
//
9678-
// NOTE: pItfPossiblyApprox must not be considered a special marker type if pNewItfMT has the MayHaveOpenInterfacesInInterfaceMap flag set
9687+
// NOTE: pItfPossiblyApprox must not be considered a special marker type if pNewIntfMT has the MayHaveOpenInterfacesInInterfaceMap flag set
96799688
//
96809689
// Then determine if all of the following conditions hold true.
96819690
// 1. All generic arguments are the same (always true for cases 2 and 3 above)
@@ -9725,17 +9734,40 @@ MethodTableBuilder::LoadExactInterfaceMap(MethodTable *pMT)
97259734
}
97269735
else
97279736
{
9728-
// case 4 (We have an exact interface)
9729-
if (ClassLoader::EligibleForSpecialMarkerTypeUsage(pItfPossiblyApprox->GetInstantiation(), pMT))
9737+
// case 4, 5, or 6 (We have an exact interface)
9738+
bool pNewIntfMTIsSpecialMarkerType = pNewIntfMT->IsSpecialMarkerTypeForGenericCasting() && !pMT->GetAuxiliaryData()->MayHaveOpenInterfacesInInterfaceMap();
9739+
if (pNewIntfMTIsSpecialMarkerType)
97309740
{
9731-
// Validated that all generic arguments are the same, and that the first generic argument in the instantiation is exactly the value of calling GetSpecialInstantiationType on pMT
9732-
// Then use the special marker type here
9733-
pItfToInsert = ClassLoader::LoadTypeDefThrowing(pItfPossiblyApprox->GetModule(), pItfPossiblyApprox->GetCl(), ClassLoader::ThrowIfNotFound, ClassLoader::PermitUninstDefOrRef, 0, CLASS_LOAD_EXACTPARENTS).AsMethodTable();
9741+
if (ClassLoader::EligibleForSpecialMarkerTypeUsage(pItfPossiblyApprox->GetInstantiation(), pNewIntfMT))
9742+
{
9743+
// Case 4 - we have an exact instantiation, but pNewIntfMT was a special marker type, and the exact instantiation type found here could have been a special marker type. We need to check if the exact instantiation we found
9744+
// here could have been a special marker type. If it is, we need to insert the special marker type here.
9745+
pItfToInsert = ClassLoader::LoadTypeDefThrowing(pItfPossiblyApprox->GetModule(), pItfPossiblyApprox->GetCl(), ClassLoader::ThrowIfNotFound, ClassLoader::PermitUninstDefOrRef, 0, CLASS_LOAD_EXACTPARENTS).AsMethodTable();
9746+
}
9747+
else if (pItfPossiblyApprox->ContainsGenericVariables())
9748+
{
9749+
// Case 5
9750+
// If the instantiation contains generic variables and can't be converted to the special marker type, then we would need to fully re-instantiate the type with a deep substitution to get the exact instantiation, which is complex and expensive, and we expect this to be a rare case, so we can just fallback to the retry with exact interfaces pathway in this case.
9751+
retry = true;
9752+
break;
9753+
}
9754+
// If we reach here, we've already found the correct pItfToInsert (case 4), OR we can proceed to case 6 since pItfPossiblyApprox was an exact type defined on the generic type.
97349755
}
9735-
else
9756+
9757+
if (pItfToInsert == NULL)
97369758
{
9737-
pItfToInsert = pItfPossiblyApprox;
9738-
intendedExactMatch = true;
9759+
// Case 6, this is an exact instantiation of exactly the right type. Insert it here.
9760+
if (ClassLoader::EligibleForSpecialMarkerTypeUsage(pItfPossiblyApprox->GetInstantiation(), pMT))
9761+
{
9762+
// Validated that all generic arguments are the same, and that the first generic argument in the instantiation is exactly the value of calling GetSpecialInstantiationType on pMT
9763+
// Then use the special marker type here
9764+
pItfToInsert = ClassLoader::LoadTypeDefThrowing(pItfPossiblyApprox->GetModule(), pItfPossiblyApprox->GetCl(), ClassLoader::ThrowIfNotFound, ClassLoader::PermitUninstDefOrRef, 0, CLASS_LOAD_EXACTPARENTS).AsMethodTable();
9765+
}
9766+
else
9767+
{
9768+
pItfToInsert = pItfPossiblyApprox;
9769+
intendedExactMatch = true;
9770+
}
97399771
}
97409772
}
97419773

0 commit comments

Comments
 (0)