Skip to content

Commit e2d3497

Browse files
authored
Fix generic interface method dispatch for multi-argument types (#3453)
***NO_CI***
1 parent 7bddd3e commit e2d3497

1 file changed

Lines changed: 26 additions & 13 deletions

File tree

src/CLR/Core/TypeSystem.cpp

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9086,6 +9086,21 @@ bool CLR_RT_TypeSystem::FindVirtualMethodDef(
90869086
// method uses generic type parameter T (VAR N) while the concrete implementation uses
90879087
// a closed generic instance (e.g. KeyValuePair<TKey,TValue>). The inner sub-elements
90889088
// of the GENERICINST are drained from the parser so Available() stays consistent.
9089+
static bool DrainGenericInstSubtree(CLR_RT_SignatureParser &parser, int targetAvail)
9090+
{
9091+
while (parser.Available() > targetAvail)
9092+
{
9093+
CLR_RT_SignatureParser::Element drained{};
9094+
9095+
if (FAILED(parser.Advance(drained)))
9096+
{
9097+
return false;
9098+
}
9099+
}
9100+
9101+
return true;
9102+
}
9103+
90899104
static bool MatchSignatureForVirtualDispatch(CLR_RT_SignatureParser &parserLeft, CLR_RT_SignatureParser &parserRight)
90909105
{
90919106
if (parserLeft.Type != parserRight.Type)
@@ -9114,30 +9129,28 @@ static bool MatchSignatureForVirtualDispatch(CLR_RT_SignatureParser &parserLeft,
91149129
// Relaxed VAR <-> GENERICINST matching for interface virtual dispatch:
91159130
// the interface method may use a type parameter (VAR N) while the concrete
91169131
// implementation uses the expanded generic type (GENERICINST ...). Drain the
9117-
// GENERICINST inner elements so the parser position stays consistent.
9132+
// whole GENERICINST sub-tree on the expanded side so the parser position stays
9133+
// consistent.
91189134
if (resLeft.DataType == DATATYPE_VAR && resRight.DataType == DATATYPE_GENERICINST)
91199135
{
9120-
CLR_RT_SignatureParser::Element inner{};
9121-
if (FAILED(parserRight.Advance(inner)))
9122-
return false; // type element (CLASS/VALUETYPE + TypeRef)
9123-
for (int i = 0; i < inner.GenParamCount; i++)
9136+
int targetAvail = iAvailLeft - 1;
9137+
if (!DrainGenericInstSubtree(parserRight, targetAvail))
91249138
{
9125-
if (FAILED(parserRight.Advance(inner)))
9126-
return false;
9139+
return false;
91279140
}
9141+
91289142
continue;
91299143
}
91309144

91319145
if (resLeft.DataType == DATATYPE_GENERICINST && resRight.DataType == DATATYPE_VAR)
91329146
{
9133-
CLR_RT_SignatureParser::Element inner{};
9134-
if (FAILED(parserLeft.Advance(inner)))
9135-
return false;
9136-
for (int i = 0; i < inner.GenParamCount; i++)
9147+
int targetAvail = iAvailRight - 1;
9148+
9149+
if (!DrainGenericInstSubtree(parserLeft, targetAvail))
91379150
{
9138-
if (FAILED(parserLeft.Advance(inner)))
9139-
return false;
9151+
return false;
91409152
}
9153+
91419154
continue;
91429155
}
91439156

0 commit comments

Comments
 (0)