Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/CLR/Core/CLR_RT_HeapBlock_Array.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//
//
// Copyright (c) .NET Foundation and Contributors
// Portions Copyright (c) Microsoft Corporation. All rights reserved.
// See LICENSE file in the project root for full license information.
Expand Down Expand Up @@ -144,7 +144,18 @@ HRESULT CLR_RT_HeapBlock_Array::CreateInstance(
CLR_RT_ReflectionDef_Index reflex{};
reflex.kind = REFLECTION_TYPE;
reflex.levels = tsInst.levels;
reflex.data.type = tsInst.cachedElementType;

// For generic instantiation TypeSpecs (e.g. Pair<TKey,TValue>), genericTypeDef holds
// the open generic typedef (e.g. Pair<,>). cachedElementType is only set for
// non-generic TypeSpecs resolved via VAR/MVAR, so prefer genericTypeDef when valid.
if (NANOCLR_INDEX_IS_VALID(tsInst.genericTypeDef))
{
reflex.data.type = tsInst.genericTypeDef;
}
else
{
reflex.data.type = tsInst.cachedElementType;
}

NANOCLR_CHECK_HRESULT(ref.SetReflection(reflex));
}
Expand Down
33 changes: 24 additions & 9 deletions src/CLR/Core/Execution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2083,7 +2083,8 @@ static HRESULT ResolveGenericTypeParameter(
HRESULT CLR_RT_ExecutionEngine::InitializeReference(
CLR_RT_HeapBlock &ref,
CLR_RT_SignatureParser &parser,
const CLR_RT_TypeSpec_Instance *genericInstance)
const CLR_RT_TypeSpec_Instance *genericInstance,
bool allowUnresolvedVarFallback)
{
NATIVE_PROFILE_CLR_CORE();
//
Expand Down Expand Up @@ -2117,13 +2118,26 @@ HRESULT CLR_RT_ExecutionEngine::InitializeReference(
{
if (genericInstance == nullptr || !NANOCLR_INDEX_IS_VALID(*genericInstance))
{
NANOCLR_SET_AND_LEAVE(CLR_E_FAIL);
if (allowUnresolvedVarFallback)
{
// VAR cannot be resolved without a closed generic context (e.g. when
// pre-allocating array element structs for an open generic type).
// Treat as an object reference (null) so field initialization proceeds;
// subsequent stfld instructions will overwrite with the correct type.
dt = DATATYPE_OBJECT;
}
else
{
NANOCLR_SET_AND_LEAVE(CLR_E_FAIL);
}
}
else
{
NANOCLR_CHECK_HRESULT(
ResolveGenericTypeParameter(*genericInstance, res.GenericParamPosition, realTypeDef, dt));

NANOCLR_CHECK_HRESULT(
ResolveGenericTypeParameter(*genericInstance, res.GenericParamPosition, realTypeDef, dt));

goto process_datatype;
goto process_datatype;
}
Comment thread
josesimoes marked this conversation as resolved.
}
else if (dt == DATATYPE_MVAR)
{
Expand Down Expand Up @@ -2201,15 +2215,16 @@ HRESULT CLR_RT_ExecutionEngine::InitializeReference(
CLR_RT_HeapBlock &ref,
const CLR_RECORD_FIELDDEF *target,
CLR_RT_Assembly *assm,
const CLR_RT_TypeSpec_Instance *genericInstance)
const CLR_RT_TypeSpec_Instance *genericInstance,
bool allowUnresolvedVarFallback)
{
NATIVE_PROFILE_CLR_CORE();
NANOCLR_HEADER();

CLR_RT_SignatureParser parser{};
parser.Initialize_FieldDef(assm, target);

NANOCLR_SET_AND_LEAVE(InitializeReference(ref, parser, genericInstance));
NANOCLR_SET_AND_LEAVE(InitializeReference(ref, parser, genericInstance, allowUnresolvedVarFallback));

NANOCLR_NOCLEANUP();
}
Expand Down Expand Up @@ -2635,7 +2650,7 @@ HRESULT CLR_RT_ExecutionEngine::NewObject(
const char *fieldName = assm->GetString(target->name);
#endif

NANOCLR_CHECK_HRESULT(InitializeReference(*obj, target, assm, genericInstance));
NANOCLR_CHECK_HRESULT(InitializeReference(*obj, target, assm, genericInstance, true));
}
}

Expand Down
41 changes: 16 additions & 25 deletions src/CLR/Core/TypeSystem.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//
//
// Copyright (c) .NET Foundation and Contributors
// Portions Copyright (c) Microsoft Corporation. All rights reserved.
// See LICENSE file in the project root for full license information.
Expand Down Expand Up @@ -1269,38 +1269,29 @@ bool CLR_RT_TypeDef_Instance::ResolveToken(
{
if (elem.DataType == DATATYPE_GENERICINST)
{
// Advance past the open generic type token.
// After this call elem.Class holds the open generic typedef (e.g. Pair<,>).
// The parser has already consumed the arg-count byte inside Advance,
// so there is no further element to skip. Return the typedef directly
// for NEWARR / STELEM / ISINST / CASTCLASS with a GENERICINST token.
if (FAILED(parser.Advance(elem)))
{
return false;
}

if (elem.DataType == DATATYPE_CLASS || elem.DataType == DATATYPE_VALUETYPE)
if ((elem.DataType == DATATYPE_CLASS || elem.DataType == DATATYPE_VALUETYPE) &&
NANOCLR_INDEX_IS_VALID(elem.Class))
{
// consume the CLASS/VALUETYPE marker
if (FAILED(parser.Advance(elem)))
{
return false;
}
// consume the generic‐definition token itself
if (FAILED(parser.Advance(elem)))
{
return false;
}
// consume the count of generic arguments
if (FAILED(parser.Advance(elem)))
{
return false;
}
data = elem.Class.data;
assembly = g_CLR_RT_TypeSystem.m_assemblies[elem.Class.Assembly() - 1];
target = assembly->GetTypeDef(elem.Class.Type());
#if defined(NANOCLR_INSTANCE_NAMES)
name = assembly->GetString(target->name);
#endif
return true;
}

// walk forward until a VAR (type‐generic) or MVAR (method‐generic) is hit
while (elem.DataType != DATATYPE_VAR && elem.DataType != DATATYPE_MVAR)
{
if (FAILED(parser.Advance(elem)))
{
return false;
}
}
return false;
}

genericPosition = elem.GenericParamPosition;
Expand Down
6 changes: 4 additions & 2 deletions src/CLR/Include/nanoCLR_Runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -4222,12 +4222,14 @@ struct CLR_RT_ExecutionEngine
HRESULT InitializeReference(
CLR_RT_HeapBlock &ref,
CLR_RT_SignatureParser &parser,
const CLR_RT_TypeSpec_Instance *genericInstance = nullptr);
const CLR_RT_TypeSpec_Instance *genericInstance = nullptr,
bool allowUnresolvedVarFallback = false);
HRESULT InitializeReference(
CLR_RT_HeapBlock &ref,
const CLR_RECORD_FIELDDEF *target,
CLR_RT_Assembly *assm,
const CLR_RT_TypeSpec_Instance *genericInstance = nullptr);
const CLR_RT_TypeSpec_Instance *genericInstance = nullptr,
bool allowUnresolvedVarFallback = false);

HRESULT InitializeLocals(CLR_RT_HeapBlock *locals, const CLR_RT_MethodDef_Instance &methodDefInstance);

Expand Down