mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 19:48:20 +02:00
Circular dependency checking between generic constraints
This commit is contained in:
parent
e307448363
commit
2bbe66cecc
7 changed files with 108 additions and 5 deletions
|
@ -110,6 +110,10 @@ BfGenericExtensionEntry* BfModule::BuildGenericExtensionInfo(BfTypeInstance* gen
|
|||
for (auto genericParam : genericExEntry->mGenericParams)
|
||||
AddDependency(genericParam, mCurTypeInstance);
|
||||
|
||||
ValidateGenericParams(BfGenericParamKind_Type,
|
||||
Span<BfGenericParamInstance*>((BfGenericParamInstance**)genericExEntry->mGenericParams.mVals,
|
||||
genericExEntry->mGenericParams.mSize));
|
||||
|
||||
return genericExEntry;
|
||||
}
|
||||
|
||||
|
@ -153,7 +157,7 @@ bool BfModule::InitGenericParams(BfType* resolvedTypeRef)
|
|||
}
|
||||
|
||||
bool BfModule::FinishGenericParams(BfType* resolvedTypeRef)
|
||||
{
|
||||
{
|
||||
BfTypeState typeState;
|
||||
typeState.mPrevState = mContext->mCurTypeState;
|
||||
typeState.mResolveKind = BfTypeState::ResolveKind_BuildingGenericParams;
|
||||
|
@ -326,6 +330,10 @@ bool BfModule::FinishGenericParams(BfType* resolvedTypeRef)
|
|||
|
||||
for (auto typeRef : deferredResolveTypes)
|
||||
auto constraintType = ResolveTypeRef(typeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_None);
|
||||
|
||||
ValidateGenericParams(BfGenericParamKind_Type,
|
||||
Span<BfGenericParamInstance*>((BfGenericParamInstance**)genericTypeInst->mGenericTypeInfo->mGenericParams.mVals,
|
||||
genericTypeInst->mGenericTypeInfo->mGenericParams.mSize));
|
||||
|
||||
for (auto genericParam : genericTypeInst->mGenericTypeInfo->mGenericParams)
|
||||
AddDependency(genericParam, mCurTypeInstance);
|
||||
|
@ -333,6 +341,58 @@ bool BfModule::FinishGenericParams(BfType* resolvedTypeRef)
|
|||
return true;
|
||||
}
|
||||
|
||||
void BfModule::ValidateGenericParams(BfGenericParamKind genericParamKind, Span<BfGenericParamInstance*> genericParams)
|
||||
{
|
||||
std::function<void(BfType*, Array<BfGenericParamType*>&)> _CheckType = [&](BfType* type, Array<BfGenericParamType*>& foundParams)
|
||||
{
|
||||
if (type == NULL)
|
||||
return;
|
||||
if (!type->IsGenericParam())
|
||||
return;
|
||||
auto genericParamType = (BfGenericParamType*)type;
|
||||
if (genericParamType->mGenericParamKind != genericParamKind)
|
||||
return;
|
||||
|
||||
auto genericParam = genericParams[genericParamType->mGenericParamIdx];
|
||||
if (genericParam->mTypeConstraint == NULL)
|
||||
return;
|
||||
|
||||
if (foundParams.Contains(genericParamType))
|
||||
{
|
||||
String error = "Circular constraint dependency between ";
|
||||
for (int i = 0; i < foundParams.mSize; i++)
|
||||
{
|
||||
auto foundParam = foundParams[i];
|
||||
if (i > 0)
|
||||
error += " and ";
|
||||
error += TypeToString(foundParam, BfTypeNameFlag_ResolveGenericParamNames);
|
||||
|
||||
// Remove errored type constraint
|
||||
genericParams[foundParam->mGenericParamIdx]->mTypeConstraint = NULL;
|
||||
}
|
||||
|
||||
if (foundParams.mSize == 1)
|
||||
error += " and itself";
|
||||
|
||||
Fail(error, genericParams[genericParamType->mGenericParamIdx]->GetRefNode());
|
||||
return;
|
||||
}
|
||||
|
||||
foundParams.Add(genericParamType);
|
||||
_CheckType(genericParam->mTypeConstraint, foundParams);
|
||||
foundParams.pop_back();
|
||||
};
|
||||
|
||||
for (auto genericParam : genericParams)
|
||||
{
|
||||
if (genericParam->mTypeConstraint != NULL)
|
||||
{
|
||||
Array<BfGenericParamType*> foundParams;
|
||||
_CheckType(genericParam->mTypeConstraint, foundParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BfModule::ValidateGenericConstraints(BfAstNode* typeRef, BfTypeInstance* genericTypeInst, bool ignoreErrors)
|
||||
{
|
||||
if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsTypeAlias()) && (mCurTypeInstance->IsGenericTypeInstance()))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue