1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-14 14:24:10 +02:00

Expanded var poisoning for generics

This commit is contained in:
Brian Fiete 2020-06-01 07:32:40 -07:00
parent fa3914e674
commit d8f741e779
3 changed files with 144 additions and 40 deletions

View file

@ -156,6 +156,7 @@ void BfMethodMatcher::Init(/*SizedArrayImpl<BfResolvedArg>& arguments, */BfSized
mActiveTypeDef = NULL; mActiveTypeDef = NULL;
mBestMethodDef = NULL; mBestMethodDef = NULL;
mBackupMethodDef = NULL; mBackupMethodDef = NULL;
mBestRawMethodInstance = NULL;
mBestMethodTypeInstance = NULL; mBestMethodTypeInstance = NULL;
mExplicitInterfaceCheck = NULL; mExplicitInterfaceCheck = NULL;
mSelfType = NULL; mSelfType = NULL;
@ -169,6 +170,7 @@ void BfMethodMatcher::Init(/*SizedArrayImpl<BfResolvedArg>& arguments, */BfSized
mAllowNonStatic = true; mAllowNonStatic = true;
mSkipImplicitParams = false; mSkipImplicitParams = false;
mAllowImplicitThis = false; mAllowImplicitThis = false;
mHadVarConflictingReturnType = false;
mMethodCheckCount = 0; mMethodCheckCount = 0;
mInferGenericProgressIdx = 0; mInferGenericProgressIdx = 0;
mCheckedKind = BfCheckedKind_NotSet; mCheckedKind = BfCheckedKind_NotSet;
@ -178,7 +180,15 @@ void BfMethodMatcher::Init(/*SizedArrayImpl<BfResolvedArg>& arguments, */BfSized
{ {
auto bfType = arg.mTypedValue.mType; auto bfType = arg.mTypedValue.mType;
if (bfType != NULL) if (bfType != NULL)
{
mHasVarArguments |= bfType->IsVar(); mHasVarArguments |= bfType->IsVar();
if (bfType->IsGenericParam())
{
auto genericParamInstance = mModule->GetGenericParamInstance((BfGenericParamType*)bfType);
if ((genericParamInstance->mGenericParamFlags & BfGenericParamFlag_Var) != 0)
mHasVarArguments = true;
}
}
} }
if (methodGenericArguments != NULL) if (methodGenericArguments != NULL)
@ -186,8 +196,6 @@ void BfMethodMatcher::Init(/*SizedArrayImpl<BfResolvedArg>& arguments, */BfSized
for (BfTypeReference* genericArg : *methodGenericArguments) for (BfTypeReference* genericArg : *methodGenericArguments)
{ {
auto genericArgType = mModule->ResolveTypeRef(genericArg); auto genericArgType = mModule->ResolveTypeRef(genericArg);
// if (genericArgType == NULL)
// return;
mExplicitMethodGenericArguments.push_back(genericArgType); mExplicitMethodGenericArguments.push_back(genericArgType);
} }
mHadExplicitGenericArguments = true; mHadExplicitGenericArguments = true;
@ -213,9 +221,7 @@ bool BfMethodMatcher::IsMemberAccessible(BfTypeInstance* typeInst, BfTypeDef* de
bool BfMethodMatcher::InferGenericArgument(BfMethodInstance* methodInstance, BfType* argType, BfType* wantType, BfIRValue argValue, HashSet<BfType*>& checkedTypeSet) bool BfMethodMatcher::InferGenericArgument(BfMethodInstance* methodInstance, BfType* argType, BfType* wantType, BfIRValue argValue, HashSet<BfType*>& checkedTypeSet)
{ {
if (argType == NULL) if (argType == NULL)
return false; return false;
if (argType->IsVar())
return false;
if (!wantType->IsUnspecializedType()) if (!wantType->IsUnspecializedType())
return true; return true;
@ -235,9 +241,7 @@ bool BfMethodMatcher::InferGenericArgument(BfMethodInstance* methodInstance, BfT
BfType* methodGenericTypeConstraint = NULL; BfType* methodGenericTypeConstraint = NULL;
auto _SetGeneric = [&]() auto _SetGeneric = [&]()
{ {
BF_ASSERT((argType == NULL) || (!argType->IsVar()));
if (argType != NULL) if (argType != NULL)
{ {
// Disallow illegal types // Disallow illegal types
@ -300,6 +304,12 @@ bool BfMethodMatcher::InferGenericArgument(BfMethodInstance* methodInstance, BfT
mPrevArgValues[wantGenericParam->mGenericParamIdx] = argValue; mPrevArgValues[wantGenericParam->mGenericParamIdx] = argValue;
}; };
if (argType->IsVar())
{
_SetGeneric();
return true;
}
if (wantGenericParam->mGenericParamKind == BfGenericParamKind_Method) if (wantGenericParam->mGenericParamKind == BfGenericParamKind_Method)
{ {
auto genericParamInst = methodInstance->mMethodInfoEx->mGenericParams[wantGenericParam->mGenericParamIdx]; auto genericParamInst = methodInstance->mMethodInfoEx->mGenericParams[wantGenericParam->mGenericParamIdx];
@ -381,8 +391,33 @@ bool BfMethodMatcher::InferGenericArgument(BfMethodInstance* methodInstance, BfT
if ((wantType->IsGenericTypeInstance()) && (wantType->IsUnspecializedTypeVariation())) if ((wantType->IsGenericTypeInstance()) && (wantType->IsUnspecializedTypeVariation()))
{ {
auto wantGenericType = (BfGenericTypeInstance*)wantType; auto wantGenericType = (BfGenericTypeInstance*)wantType;
if (argType->IsGenericParam())
{
auto genericParam = mModule->GetGenericParamInstance((BfGenericParamType*)argType);
if ((genericParam->mGenericParamFlags & BfGenericParamFlag_Var) != 0)
{
InferGenericArgument(methodInstance, mModule->GetPrimitiveType(BfTypeCode_Var), wantType, BfIRValue(), checkedTypeSet);
return true;
}
if ((genericParam->mTypeConstraint != NULL) && (genericParam->mTypeConstraint->IsGenericTypeInstance()))
InferGenericArgument(methodInstance, genericParam->mTypeConstraint, wantType, BfIRValue(), checkedTypeSet);
}
if (argType->IsVar())
{
for (int genericArgIdx = 0; genericArgIdx < (int)wantGenericType->mTypeGenericArguments.size(); genericArgIdx++)
{
BfType* wantGenericArgument = wantGenericType->mTypeGenericArguments[genericArgIdx];
if (!wantGenericArgument->IsUnspecializedType())
continue;
InferGenericArgument(methodInstance, mModule->GetPrimitiveType(BfTypeCode_Var), wantGenericArgument, BfIRValue(), checkedTypeSet);
}
return true;
}
if (!argType->IsGenericTypeInstance()) if (!argType->IsGenericTypeInstance())
return true; return true;
auto argGenericType = (BfGenericTypeInstance*)argType; auto argGenericType = (BfGenericTypeInstance*)argType;
if (argGenericType->mTypeDef != wantGenericType->mTypeDef) if (argGenericType->mTypeDef != wantGenericType->mTypeDef)
return true; return true;
@ -1555,7 +1590,12 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
// And if neither better nor worse then they are equally good, which is not allowed either // And if neither better nor worse then they are equally good, which is not allowed either
if (((!isBetter) && (!isWorse)) || ((isBetter) && (isWorse))) if (((!isBetter) && (!isWorse)) || ((isBetter) && (isWorse)))
{ {
if (!mHasVarArguments) if (mHasVarArguments)
{
if (prevMethodInstance->mReturnType != prevMethodInstance->mReturnType)
mHadVarConflictingReturnType = true;
}
else
{ {
BfAmbiguousEntry ambiguousEntry; BfAmbiguousEntry ambiguousEntry;
ambiguousEntry.mMethodInstance = methodInstance; ambiguousEntry.mMethodInstance = methodInstance;
@ -1588,6 +1628,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
mAmbiguousEntries.Clear(); mAmbiguousEntries.Clear();
hadMatch = true; hadMatch = true;
mBestMethodDef = checkMethod; mBestMethodDef = checkMethod;
mBestRawMethodInstance = methodInstance;
for (auto& arg : mArguments) for (auto& arg : mArguments)
arg.mBestBoundType = arg.mTypedValue.mType; arg.mBestBoundType = arg.mTypedValue.mType;
@ -1646,10 +1687,10 @@ NoMatch:
if (genericArgumentsSubstitute != NULL) if (genericArgumentsSubstitute != NULL)
{ {
mBestMethodGenericArguments = *genericArgumentsSubstitute; mBestMethodGenericArguments = *genericArgumentsSubstitute;
#ifdef _DEBUG // #ifdef _DEBUG
for (auto arg : mBestMethodGenericArguments) // for (auto arg : mBestMethodGenericArguments)
BF_ASSERT((arg == NULL) || (!arg->IsVar())); // BF_ASSERT((arg == NULL) || (!arg->IsVar()));
#endif // #endif
} }
else else
mBestMethodGenericArguments.clear(); mBestMethodGenericArguments.clear();
@ -2087,6 +2128,17 @@ void BfMethodMatcher::TryDevirtualizeCall(BfTypedValue target, BfTypedValue* ori
} }
} }
bool BfMethodMatcher::HasVarGenerics()
{
for (auto genericArg : mBestMethodGenericArguments)
if (genericArg->IsVar())
return true;
for (auto genericArg : mExplicitMethodGenericArguments)
if (genericArg->IsVar())
return true;
return false;
}
void BfMethodMatcher::CheckOuterTypeStaticMethods(BfTypeInstance* typeInstance, bool isFailurePass) void BfMethodMatcher::CheckOuterTypeStaticMethods(BfTypeInstance* typeInstance, bool isFailurePass)
{ {
bool allowPrivate = true; bool allowPrivate = true;
@ -7050,20 +7102,29 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
mModule->Fail(StrFormat("Method '%s' does not exist", methodName.c_str()), targetSrc); mModule->Fail(StrFormat("Method '%s' does not exist", methodName.c_str()), targetSrc);
return BfTypedValue(); return BfTypedValue();
} }
if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized))
{
for (auto& arg : methodMatcher.mBestMethodGenericArguments)
{
if ((arg != NULL) && (arg->IsVar()))
return mModule->GetDefaultTypedValue(mModule->GetPrimitiveType(BfTypeCode_Var));
}
}
if ((prevBindResult.mPrevVal != NULL) && (methodMatcher.mMethodCheckCount > 1)) if ((prevBindResult.mPrevVal != NULL) && (methodMatcher.mMethodCheckCount > 1))
prevBindResult.mPrevVal->mCheckedMultipleMethods = true; prevBindResult.mPrevVal->mCheckedMultipleMethods = true;
BfModuleMethodInstance moduleMethodInstance = GetSelectedMethod(targetSrc, curTypeInst, methodDef, methodMatcher); BfModuleMethodInstance moduleMethodInstance = GetSelectedMethod(targetSrc, curTypeInst, methodDef, methodMatcher);
if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized))
{
if (methodMatcher.mHasVarArguments)
{
BfType* retType = mModule->GetPrimitiveType(BfTypeCode_Var);
if ((!methodMatcher.mHadVarConflictingReturnType) && (methodMatcher.mBestRawMethodInstance != NULL) && (!methodMatcher.mBestRawMethodInstance->mReturnType->IsUnspecializedTypeVariation()))
{
if ((!methodMatcher.mBestRawMethodInstance->mReturnType->IsGenericParam()) ||
(((BfGenericParamType*)methodMatcher.mBestRawMethodInstance->mReturnType)->mGenericParamKind != BfGenericParamKind_Method))
retType = methodMatcher.mBestRawMethodInstance->mReturnType;
}
return mModule->GetDefaultTypedValue(retType);
}
}
if ((bypassVirtual) && (!target.mValue) && (target.mType->IsInterface())) if ((bypassVirtual) && (!target.mValue) && (target.mType->IsInterface()))
{ {
target = mModule->GetThis(); target = mModule->GetThis();
@ -12361,6 +12422,8 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc,
BfMethodInstance* unspecializedMethod = NULL; BfMethodInstance* unspecializedMethod = NULL;
bool hasVarGenerics = false;
for (int checkGenericIdx = 0; checkGenericIdx < (int)methodMatcher.mBestMethodGenericArguments.size(); checkGenericIdx++) for (int checkGenericIdx = 0; checkGenericIdx < (int)methodMatcher.mBestMethodGenericArguments.size(); checkGenericIdx++)
{ {
BfMethodInstance* outerMethodInstance = NULL; BfMethodInstance* outerMethodInstance = NULL;
@ -12440,6 +12503,12 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc,
} }
else else
{ {
if (genericArg->IsVar())
{
BF_ASSERT(methodMatcher.mHasVarArguments);
hasVarGenerics = true;
}
if (genericArg->IsIntUnknown()) if (genericArg->IsIntUnknown())
genericArg = mModule->GetPrimitiveType(BfTypeCode_IntPtr); genericArg = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
@ -12448,7 +12517,7 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc,
hasDifferentResolvedTypes = true; hasDifferentResolvedTypes = true;
resolvedGenericArguments.push_back(resolvedGenericArg); resolvedGenericArguments.push_back(resolvedGenericArg);
} }
} }
BfTypeInstance* foreignType = NULL; BfTypeInstance* foreignType = NULL;
BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None; BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None;
@ -12479,6 +12548,9 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc,
} }
} }
if (hasVarGenerics)
return BfModuleMethodInstance();
BfModuleMethodInstance methodInstance; BfModuleMethodInstance methodInstance;
if (methodMatcher.mBestMethodInstance) if (methodMatcher.mBestMethodInstance)
{ {
@ -12598,21 +12670,24 @@ void BfExprEvaluator::CheckLocalMethods(BfAstNode* targetSrc, BfTypeInstance* ty
if ((mModule->mCurMethodState != NULL) && (mModule->mCurMethodState->mClosureState != NULL) && (mModule->mCurMethodState->mClosureState->mCapturing)) if ((mModule->mCurMethodState != NULL) && (mModule->mCurMethodState->mClosureState != NULL) && (mModule->mCurMethodState->mClosureState->mCapturing))
{ {
BfModuleMethodInstance moduleMethodInstance = GetSelectedMethod(targetSrc, typeInstance, matchedLocalMethod->mMethodDef, methodMatcher); BfModuleMethodInstance moduleMethodInstance = GetSelectedMethod(targetSrc, typeInstance, matchedLocalMethod->mMethodDef, methodMatcher);
auto methodInstance = moduleMethodInstance.mMethodInstance; if (moduleMethodInstance)
if ((methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mClosureInstanceInfo->mCaptureClosureState != NULL))
{ {
// The called method is calling us from its mLocalMethodRefs set. Stretch our mCaptureStartAccessId back to incorporate its auto methodInstance = moduleMethodInstance.mMethodInstance;
// captures as well
if (methodInstance->mMethodInfoEx->mClosureInstanceInfo->mCaptureClosureState->mCaptureStartAccessId < mModule->mCurMethodState->mClosureState->mCaptureStartAccessId) if ((methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mClosureInstanceInfo->mCaptureClosureState != NULL))
mModule->mCurMethodState->mClosureState->mCaptureStartAccessId = methodInstance->mMethodInfoEx->mClosureInstanceInfo->mCaptureClosureState->mCaptureStartAccessId;
}
else
{
if (methodInstance->mDisallowCalling) // We need to process the captures from this guy
{ {
if (mModule->mCurMethodState->mClosureState->mLocalMethodRefSet.Add(methodInstance)) // The called method is calling us from its mLocalMethodRefs set. Stretch our mCaptureStartAccessId back to incorporate its
mModule->mCurMethodState->mClosureState->mLocalMethodRefs.Add(methodInstance); // captures as well
if (methodInstance->mMethodInfoEx->mClosureInstanceInfo->mCaptureClosureState->mCaptureStartAccessId < mModule->mCurMethodState->mClosureState->mCaptureStartAccessId)
mModule->mCurMethodState->mClosureState->mCaptureStartAccessId = methodInstance->mMethodInfoEx->mClosureInstanceInfo->mCaptureClosureState->mCaptureStartAccessId;
}
else
{
if (methodInstance->mDisallowCalling) // We need to process the captures from this guy
{
if (mModule->mCurMethodState->mClosureState->mLocalMethodRefSet.Add(methodInstance))
mModule->mCurMethodState->mClosureState->mLocalMethodRefs.Add(methodInstance);
}
} }
} }
} }

View file

@ -127,12 +127,13 @@ public:
BfMethodType mMethodType; BfMethodType mMethodType;
BfCheckedKind mCheckedKind; BfCheckedKind mCheckedKind;
bool mHadExplicitGenericArguments; bool mHadExplicitGenericArguments;
bool mHasVarArguments; bool mHasVarArguments;
bool mHadVarConflictingReturnType;
bool mBypassVirtual; bool mBypassVirtual;
bool mAllowImplicitThis; bool mAllowImplicitThis;
bool mAllowStatic; bool mAllowStatic;
bool mAllowNonStatic; bool mAllowNonStatic;
bool mSkipImplicitParams; bool mSkipImplicitParams;
int mMethodCheckCount; int mMethodCheckCount;
int mInferGenericProgressIdx; int mInferGenericProgressIdx;
BfType* mExplicitInterfaceCheck; BfType* mExplicitInterfaceCheck;
@ -146,6 +147,7 @@ public:
int mBackupArgMatchCount; int mBackupArgMatchCount;
BfMethodDef* mBestMethodDef; BfMethodDef* mBestMethodDef;
BfTypeInstance* mBestMethodTypeInstance; BfTypeInstance* mBestMethodTypeInstance;
BfMethodInstance* mBestRawMethodInstance;
BfModuleMethodInstance mBestMethodInstance; BfModuleMethodInstance mBestMethodInstance;
SizedArray<int, 4> mBestMethodGenericArgumentSrcs; SizedArray<int, 4> mBestMethodGenericArgumentSrcs;
BfTypeVector mBestMethodGenericArguments; BfTypeVector mBestMethodGenericArguments;
@ -173,6 +175,8 @@ public:
bool WantsCheckMethod(BfProtectionCheckFlags& flags, BfTypeInstance* startTypeInstance, BfTypeInstance* checkTypeInstance, BfMethodDef* methodDef); bool WantsCheckMethod(BfProtectionCheckFlags& flags, BfTypeInstance* startTypeInstance, BfTypeInstance* checkTypeInstance, BfMethodDef* methodDef);
bool CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInstance* typeInstance, BfMethodDef* checkMethod, bool isFailurePass); bool CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInstance* typeInstance, BfMethodDef* checkMethod, bool isFailurePass);
void TryDevirtualizeCall(BfTypedValue target, BfTypedValue* origTarget = NULL, BfTypedValue* staticResult = NULL); void TryDevirtualizeCall(BfTypedValue target, BfTypedValue* origTarget = NULL, BfTypedValue* staticResult = NULL);
bool HasVarGenerics();
bool IsVarCall(BfType*& outReturnType);
}; };

View file

@ -472,6 +472,11 @@ bool BfModule::InitType(BfType* resolvedTypeRef, BfPopulateType populateType)
{ {
auto genericTypeInstance = (BfGenericTypeInstance*)resolvedTypeRef; auto genericTypeInstance = (BfGenericTypeInstance*)resolvedTypeRef;
#ifdef _DEBUG
for (auto genericArg : genericTypeInstance->mTypeGenericArguments)
BF_ASSERT(!genericArg->IsVar());
#endif
// Do it here so the location we attempted to specialize this type will throw the failure if there is one // Do it here so the location we attempted to specialize this type will throw the failure if there is one
if (!BuildGenericParams(resolvedTypeRef)) if (!BuildGenericParams(resolvedTypeRef))
return false; return false;
@ -5680,6 +5685,8 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
auto elementType = ResolveGenericType(arrayType->mElementType, typeGenericArguments, methodGenericArguments, allowFail); auto elementType = ResolveGenericType(arrayType->mElementType, typeGenericArguments, methodGenericArguments, allowFail);
if (elementType == NULL) if (elementType == NULL)
return NULL; return NULL;
if (elementType->IsVar())
return elementType;
auto sizeType = ResolveGenericType(arrayType->mElementCountSource, typeGenericArguments, methodGenericArguments, allowFail); auto sizeType = ResolveGenericType(arrayType->mElementCountSource, typeGenericArguments, methodGenericArguments, allowFail);
if (sizeType == NULL) if (sizeType == NULL)
return NULL; return NULL;
@ -5696,6 +5703,8 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
auto elementType = ResolveGenericType(arrayType->mElementType, typeGenericArguments, methodGenericArguments, allowFail); auto elementType = ResolveGenericType(arrayType->mElementType, typeGenericArguments, methodGenericArguments, allowFail);
if (elementType == NULL) if (elementType == NULL)
return NULL; return NULL;
if (elementType->IsVar())
return elementType;
return CreateSizedArrayType(elementType, (int)arrayType->mElementCount); return CreateSizedArrayType(elementType, (int)arrayType->mElementCount);
} }
@ -5705,6 +5714,8 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
auto elementType = ResolveGenericType(refType->GetUnderlyingType(), typeGenericArguments, methodGenericArguments, allowFail); auto elementType = ResolveGenericType(refType->GetUnderlyingType(), typeGenericArguments, methodGenericArguments, allowFail);
if (elementType == NULL) if (elementType == NULL)
return NULL; return NULL;
if (elementType->IsVar())
return elementType;
return CreateRefType(elementType, refType->mRefKind); return CreateRefType(elementType, refType->mRefKind);
} }
@ -5714,6 +5725,8 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
auto elementType = ResolveGenericType(ptrType->GetUnderlyingType(), typeGenericArguments, methodGenericArguments, allowFail); auto elementType = ResolveGenericType(ptrType->GetUnderlyingType(), typeGenericArguments, methodGenericArguments, allowFail);
if (elementType == NULL) if (elementType == NULL)
return NULL; return NULL;
if (elementType->IsVar())
return elementType;
return CreatePointerType(elementType); return CreatePointerType(elementType);
} }
@ -5723,6 +5736,8 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
auto elementType = ResolveGenericType(arrayType->GetUnderlyingType(), typeGenericArguments, methodGenericArguments, allowFail); auto elementType = ResolveGenericType(arrayType->GetUnderlyingType(), typeGenericArguments, methodGenericArguments, allowFail);
if (elementType == NULL) if (elementType == NULL)
return NULL; return NULL;
if (elementType->IsVar())
return elementType;
return CreateArrayType(elementType, arrayType->mDimensions); return CreateArrayType(elementType, arrayType->mDimensions);
} }
@ -5741,6 +5756,8 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
auto newGenericArg = ResolveGenericType(origGenericArg, typeGenericArguments, methodGenericArguments, allowFail); auto newGenericArg = ResolveGenericType(origGenericArg, typeGenericArguments, methodGenericArguments, allowFail);
if (newGenericArg == NULL) if (newGenericArg == NULL)
return NULL; return NULL;
if (newGenericArg->IsVar())
return newGenericArg;
if (newGenericArg != origGenericArg) if (newGenericArg != origGenericArg)
hadChange = true; hadChange = true;
genericArgs.push_back(newGenericArg); genericArgs.push_back(newGenericArg);
@ -5773,6 +5790,8 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
auto returnType = ResolveGenericType(unspecializedDelegateInfo->mReturnType, typeGenericArguments, methodGenericArguments, allowFail); auto returnType = ResolveGenericType(unspecializedDelegateInfo->mReturnType, typeGenericArguments, methodGenericArguments, allowFail);
if (returnType == NULL) if (returnType == NULL)
return NULL; return NULL;
if (returnType->IsVar())
return returnType;
_CheckType(returnType); _CheckType(returnType);
if (returnType->IsGenericParam()) if (returnType->IsGenericParam())
hasTypeGenerics |= ((BfGenericParamType*)returnType)->mGenericParamKind == BfGenericParamKind_Type; hasTypeGenerics |= ((BfGenericParamType*)returnType)->mGenericParamKind == BfGenericParamKind_Type;
@ -5782,6 +5801,8 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
auto paramType = ResolveGenericType(param, typeGenericArguments, methodGenericArguments, allowFail); auto paramType = ResolveGenericType(param, typeGenericArguments, methodGenericArguments, allowFail);
if (paramType == NULL) if (paramType == NULL)
return NULL; return NULL;
if (paramType->IsVar())
return paramType;
paramTypes.Add(paramType); paramTypes.Add(paramType);
_CheckType(paramType); _CheckType(paramType);
} }
@ -5803,6 +5824,8 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
resolvedArg = ResolveGenericType(resolvedArg, typeGenericArguments, methodGenericArguments, allowFail); resolvedArg = ResolveGenericType(resolvedArg, typeGenericArguments, methodGenericArguments, allowFail);
if (resolvedArg == NULL) if (resolvedArg == NULL)
return NULL; return NULL;
if (resolvedArg->IsVar())
return resolvedArg;
} }
genericArgs.push_back(resolvedArg); genericArgs.push_back(resolvedArg);
} }
@ -5938,6 +5961,8 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
auto resolvedArg = ResolveGenericType(genericArg, typeGenericArguments, methodGenericArguments, allowFail); auto resolvedArg = ResolveGenericType(genericArg, typeGenericArguments, methodGenericArguments, allowFail);
if (resolvedArg == NULL) if (resolvedArg == NULL)
return NULL; return NULL;
if (resolvedArg->IsVar())
return resolvedArg;
genericArgs.push_back(resolvedArg); genericArgs.push_back(resolvedArg);
} }
else else