1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 19:48:20 +02:00

Fixed CRTP - deferred validating base class generic constraints

This commit is contained in:
Brian Fiete 2020-05-25 00:13:15 -07:00
parent 37ac89765f
commit b597b444ab
2 changed files with 58 additions and 54 deletions

View file

@ -13245,7 +13245,7 @@ void BfModule::EmitDefaultReturn()
} }
void BfModule::AssertErrorState() void BfModule::AssertErrorState()
{ {
if (mIgnoreErrors) if (mIgnoreErrors)
return; return;
if (mHadBuildError) if (mHadBuildError)
@ -13285,6 +13285,10 @@ void BfModule::AssertErrorState()
if ((mCurMethodState != NULL) && (mCurMethodState->mMixinState != NULL) && (mCurMethodState->mMixinState->mMixinMethodInstance->mMethodDef->mDeclaringType->mSource->mParsingFailed)) if ((mCurMethodState != NULL) && (mCurMethodState->mMixinState != NULL) && (mCurMethodState->mMixinState->mMixinMethodInstance->mMethodDef->mDeclaringType->mSource->mParsingFailed))
return; return;
} }
if (mCompiler->IsAutocomplete())
return;
BF_ASSERT(mCompiler->mPassInstance->HasFailed()); BF_ASSERT(mCompiler->mPassInstance->HasFailed());
} }

View file

@ -1864,6 +1864,13 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (baseType != NULL) if (baseType != NULL)
defaultBaseTypeInst = baseType->ToTypeInstance(); defaultBaseTypeInst = baseType->ToTypeInstance();
struct _DeferredValidate
{
BfTypeReference* mTypeRef;
BfGenericTypeInstance* mGenericType;
};
Array<_DeferredValidate> deferredTypeValidateList;
BfTypeReference* baseTypeRef = NULL; BfTypeReference* baseTypeRef = NULL;
if ((typeDef->mIsDelegate) && (!typeInstance->IsClosure())) if ((typeDef->mIsDelegate) && (!typeInstance->IsClosure()))
{ {
@ -1886,21 +1893,34 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
baseType = ResolveTypeDef(mCompiler->mFunctionTypeDef)->ToTypeInstance(); baseType = ResolveTypeDef(mCompiler->mFunctionTypeDef)->ToTypeInstance();
} }
else else
{ {
for (auto checkTypeRef : typeDef->mBaseTypes) for (auto checkTypeRef : typeDef->mBaseTypes)
{ {
SetAndRestoreValue<BfTypeReference*> prevTypeRef(mContext->mCurTypeState->mCurBaseTypeRef, checkTypeRef);
auto declTypeDef = typeDef; auto declTypeDef = typeDef;
if (typeDef->mIsCombinedPartial) if (typeDef->mIsCombinedPartial)
declTypeDef = typeDef->mPartials.front(); declTypeDef = typeDef->mPartials.front();
SetAndRestoreValue<BfTypeDef*> prevTypeDef(mContext->mCurTypeState->mCurTypeDef, declTypeDef); SetAndRestoreValue<BfTypeDef*> prevTypeDef(mContext->mCurTypeState->mCurTypeDef, declTypeDef);
SetAndRestoreValue<BfTypeDefineState> prevDefineState(typeInstance->mDefineState, BfTypeDefineState_ResolvingBaseType); SetAndRestoreValue<BfTypeReference*> prevTypeRef(mContext->mCurTypeState->mCurBaseTypeRef, checkTypeRef);
SetAndRestoreValue<BfTypeDefineState> prevDefineState(typeInstance->mDefineState, BfTypeDefineState_ResolvingBaseType);
bool populateBase = !typeInstance->mTypeFailed; bool populateBase = !typeInstance->mTypeFailed;
auto checkType = ResolveTypeRef(checkTypeRef, populateBase ? BfPopulateType_Data : BfPopulateType_Declaration); auto checkType = ResolveTypeRef(checkTypeRef, populateBase ? BfPopulateType_Data : BfPopulateType_Declaration);
if (checkType != NULL)
if (typeInstance->mDefineState >= BfTypeDefineState_Defined)
{ {
prevDefineState.CancelRestore();
return true;
}
if (checkType != NULL)
{
if (auto genericTypeInst = checkType->ToGenericTypeInstance())
{
// Specialized type variations don't need to validate their constraints
if (!typeInstance->IsUnspecializedTypeVariation())
deferredTypeValidateList.Add({ checkTypeRef, genericTypeInst });
}
auto checkTypeInst = checkType->ToTypeInstance(); auto checkTypeInst = checkType->ToTypeInstance();
bool canDeriveFrom = checkTypeInst != NULL; bool canDeriveFrom = checkTypeInst != NULL;
if ((typeInstance->IsStruct()) || (typeInstance->IsTypedPrimitive()) || (typeInstance->IsBoxed())) if ((typeInstance->IsStruct()) || (typeInstance->IsTypedPrimitive()) || (typeInstance->IsBoxed()))
@ -1976,7 +1996,7 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
AssertErrorState(); AssertErrorState();
// Why did we go around setting mTypeFailed on all these things? // Why did we go around setting mTypeFailed on all these things?
//typeInstance->mTypeFailed = true; //typeInstance->mTypeFailed = true;
} }
} }
for (auto partialTypeDef : typeDef->mPartials) for (auto partialTypeDef : typeDef->mPartials)
@ -2167,6 +2187,12 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
BF_ASSERT(!typeInstance->mNeedsMethodProcessing); BF_ASSERT(!typeInstance->mNeedsMethodProcessing);
typeInstance->mDefineState = BfTypeDefineState_HasInterfaces; typeInstance->mDefineState = BfTypeDefineState_HasInterfaces;
for (auto& validateEntry : deferredTypeValidateList)
{
ValidateGenericConstraints(validateEntry.mTypeRef, validateEntry.mGenericType, false);
}
if (populateType <= BfPopulateType_Interfaces) if (populateType <= BfPopulateType_Interfaces)
return true; return true;
@ -5727,27 +5753,28 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
if (wantGeneric) if (wantGeneric)
{ {
Array<BfType*> genericArgs; Array<BfType*> genericArgs;
for (auto genericArg : unspecializedGenericDelegateType->mTypeGenericArguments) for (int genericArgIdx = 0; genericArgIdx < (int)unspecializedGenericDelegateType->mTypeGenericArguments.size(); genericArgIdx++)
{ {
BfType* resolvedArg = NULL; BfType* resolvedArg = unspecializedGenericDelegateType->mTypeGenericArguments[genericArgIdx];
if (genericArg->IsUnspecializedType()) if (resolvedArg->IsUnspecializedType())
{ {
auto resolvedArg = ResolveGenericType(genericArg, typeGenericArguments, methodGenericArguments, allowFail); resolvedArg = ResolveGenericType(resolvedArg, typeGenericArguments, methodGenericArguments, allowFail);
if (resolvedArg == NULL) if (resolvedArg == NULL)
return NULL; return NULL;
} }
else genericArgs.push_back(resolvedArg);
genericArgs.push_back(genericArg);
} }
auto dlgType = mContext->mGenericDelegateTypePool.Get(); auto dlgType = mContext->mGenericDelegateTypePool.Get();
dlgType->mIsUnspecialized = false; dlgType->mIsUnspecialized = false;
dlgType->mIsUnspecializedVariation = false; dlgType->mIsUnspecializedVariation = false;
dlgType->mTypeGenericArguments = genericArgs; dlgType->mTypeGenericArguments = genericArgs;
for (auto typeGenericArg : genericArgs) for (int genericArgIdx = 0; genericArgIdx < (int)unspecializedGenericDelegateType->mTypeGenericArguments.size(); genericArgIdx++)
{ {
auto typeGenericArg = genericArgs[genericArgIdx];
if ((typeGenericArg->IsGenericParam()) || (typeGenericArg->IsUnspecializedType())) if ((typeGenericArg->IsGenericParam()) || (typeGenericArg->IsUnspecializedType()))
dlgType->mIsUnspecialized = true; dlgType->mIsUnspecialized = true;
dlgType->mGenericParams.push_back(unspecializedGenericDelegateType->mGenericParams[genericArgIdx]->AddRef());
} }
CheckUnspecializedGenericType(dlgType, BfPopulateType_Identity); CheckUnspecializedGenericType(dlgType, BfPopulateType_Identity);
delegateType = dlgType; delegateType = dlgType;
@ -5842,7 +5869,13 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
if (resolvedType != delegateType) if (resolvedType != delegateType)
{ {
if (delegateType->IsGenericTypeInstance()) if (delegateType->IsGenericTypeInstance())
mContext->mGenericDelegateTypePool.GiveBack((BfGenericDelegateType*)delegateType); {
auto dlgType = (BfGenericDelegateType*)delegateType;
for (auto genericParam : dlgType->mGenericParams)
genericParam->Release();
dlgType->mGenericParams.Clear();
mContext->mGenericDelegateTypePool.GiveBack(dlgType);
}
else else
mContext->mDelegateTypePool.GiveBack((BfDelegateType*)delegateType); mContext->mDelegateTypePool.GiveBack((BfDelegateType*)delegateType);
} }
@ -6175,10 +6208,11 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
hadError = !populateModule->PopulateType(resolvedTypeRef, populateType); hadError = !populateModule->PopulateType(resolvedTypeRef, populateType);
if ((genericTypeInstance != NULL) && (genericTypeInstance != mCurTypeInstance) && (populateType > BfPopulateType_Identity)) if ((genericTypeInstance != NULL) && (genericTypeInstance != mCurTypeInstance) && (populateType > BfPopulateType_Identity))
{ {
if (((genericTypeInstance->mHadValidateErrors) || (!genericTypeInstance->mValidatedGenericConstraints) || (genericTypeInstance->mIsUnspecializedVariation)) && if (((genericTypeInstance->mHadValidateErrors) || (!genericTypeInstance->mValidatedGenericConstraints) || (genericTypeInstance->mIsUnspecializedVariation)) &&
((mCurMethodInstance == NULL) || (!mCurMethodInstance->mIsUnspecializedVariation)) && ((mCurMethodInstance == NULL) || (!mCurMethodInstance->mIsUnspecializedVariation)) &&
((mCurTypeInstance == NULL) || (!mCurTypeInstance->IsUnspecializedTypeVariation()))) ((mCurTypeInstance == NULL) || (!mCurTypeInstance->IsUnspecializedTypeVariation())) &&
((mContext->mCurTypeState == NULL) || (mContext->mCurTypeState->mCurBaseTypeRef == NULL))) // We validate constraints for base types later
ValidateGenericConstraints(typeRef, genericTypeInstance, false); ValidateGenericConstraints(typeRef, genericTypeInstance, false);
} }
@ -6420,35 +6454,7 @@ BfTypeDef* BfModule::FindTypeDef(const BfAtomComposite& findName, int numGeneric
BfTypeLookupEntry* typeLookupEntryPtr = NULL; BfTypeLookupEntry* typeLookupEntryPtr = NULL;
BfTypeLookupResult* resultPtr = NULL; BfTypeLookupResult* resultPtr = NULL;
if (typeInstance->mLookupResults.TryAdd(typeLookupEntry, &typeLookupEntryPtr, &resultPtr)) if (typeInstance->mLookupResults.TryAdd(typeLookupEntry, &typeLookupEntryPtr, &resultPtr))
{ {
if (!typeInstance->IsTypeAlias())
{
BF_ASSERT(useTypeDef->mTypeCode != BfTypeCode_TypeAlias);
}
#ifdef _DEBUG
if (typeInstance->mTypeId == 2727)
{
NOP;
}
if ((typeInstance->IsTypeAlias()) || (useTypeDef->mTypeCode == BfTypeCode_TypeAlias))
{
if (useTypeDef != typeInstance->mTypeDef)
{
NOP;
}
// if (useTypeDef->mName != typeInstance->mTypeDef->mName)
// {
// if ((mCurMethodInstance == NULL) || (!mCurMethodInstance->mIsForeignMethodDef) ||
// (useTypeDef->mName != mCurMethodInstance->mMethodInfoEx->mForeignType->mTypeDef->mName))
// {
// BF_DBG_FATAL("Name mismatch");
// }
// }
}
#endif
typeLookupEntryPtr->mAtomUpdateIdx = typeLookupEntry.mName.GetAtomUpdateIdx(); typeLookupEntryPtr->mAtomUpdateIdx = typeLookupEntry.mName.GetAtomUpdateIdx();
// FindTypeDefRaw may re-enter when finding base types, so we need to expect that resultPtr can change // FindTypeDefRaw may re-enter when finding base types, so we need to expect that resultPtr can change
@ -7446,12 +7452,6 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
} }
} }
if (typeRef->ToString() == "ClassA<double>.AliasA3")
{
NOP;
}
BfResolvedTypeSet::LookupContext lookupCtx; BfResolvedTypeSet::LookupContext lookupCtx;
lookupCtx.mRootTypeRef = typeRef; lookupCtx.mRootTypeRef = typeRef;
lookupCtx.mRootTypeDef = typeDef; lookupCtx.mRootTypeDef = typeDef;