mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28: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
|
@ -109,5 +109,24 @@ namespace IDETest
|
||||||
TestPreGen<List<int>>();
|
TestPreGen<List<int>>();
|
||||||
Method7<int>(); //FAIL The type 'int' must be a reference type in order to use it as parameter 'comptype(typeof(T))' for 'IDETest.Generics.Method7<int>()'
|
Method7<int>(); //FAIL The type 'int' must be a reference type in order to use it as parameter 'comptype(typeof(T))' for 'IDETest.Generics.Method7<int>()'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void CircDepMethod<T, T2>() where T : T2 where T2 : T //FAIL
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class CircDep<T> where T : T //FAIL
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace System.Collections
|
||||||
|
{
|
||||||
|
extension List<T> //FAIL
|
||||||
|
where T : T
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -14316,7 +14316,7 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
|
||||||
{
|
{
|
||||||
auto genericParamInstance = new BfGenericMethodParamInstance(methodDef, externConstraintIdx + (int)methodDef->mGenericParams.size());
|
auto genericParamInstance = new BfGenericMethodParamInstance(methodDef, externConstraintIdx + (int)methodDef->mGenericParams.size());
|
||||||
methodInstance->GetMethodInfoEx()->mGenericParams.push_back(genericParamInstance);
|
methodInstance->GetMethodInfoEx()->mGenericParams.push_back(genericParamInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool addToWorkList = !processNow;
|
bool addToWorkList = !processNow;
|
||||||
if (mCompiler->GetAutoComplete() != NULL)
|
if (mCompiler->GetAutoComplete() != NULL)
|
||||||
|
@ -22953,6 +22953,13 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
||||||
for (auto typeRef : deferredResolveTypes)
|
for (auto typeRef : deferredResolveTypes)
|
||||||
auto constraintType = ResolveTypeRef(typeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_None);
|
auto constraintType = ResolveTypeRef(typeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_None);
|
||||||
|
|
||||||
|
if (methodInstance->mMethodInfoEx != NULL)
|
||||||
|
{
|
||||||
|
ValidateGenericParams(BfGenericParamKind_Method,
|
||||||
|
Span<BfGenericParamInstance*>((BfGenericParamInstance**)methodInstance->mMethodInfoEx->mGenericParams.mVals,
|
||||||
|
methodInstance->mMethodInfoEx->mGenericParams.mSize));
|
||||||
|
}
|
||||||
|
|
||||||
for (auto genericParam : methodInstance->mMethodInfoEx->mGenericParams)
|
for (auto genericParam : methodInstance->mMethodInfoEx->mGenericParams)
|
||||||
AddDependency(genericParam, mCurTypeInstance);
|
AddDependency(genericParam, mCurTypeInstance);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "BeefySysLib/util/Hash.h"
|
#include "BeefySysLib/util/Hash.h"
|
||||||
#include "BeefySysLib/util/HashSet.h"
|
#include "BeefySysLib/util/HashSet.h"
|
||||||
#include "BeefySysLib/util/SizedArray.h"
|
#include "BeefySysLib/util/SizedArray.h"
|
||||||
|
#include "BeefySysLib/Span.h"
|
||||||
#include "BfSourceClassifier.h"
|
#include "BfSourceClassifier.h"
|
||||||
#include "BfAst.h"
|
#include "BfAst.h"
|
||||||
#include "BfSystem.h"
|
#include "BfSystem.h"
|
||||||
|
@ -1756,6 +1757,7 @@ public:
|
||||||
BfType* ResolveGenericMethodTypeRef(BfTypeReference* typeRef, BfMethodInstance* methodInstance, BfGenericParamInstance* genericParamInstance, BfTypeVector* methodGenericArgsOverride);
|
BfType* ResolveGenericMethodTypeRef(BfTypeReference* typeRef, BfMethodInstance* methodInstance, BfGenericParamInstance* genericParamInstance, BfTypeVector* methodGenericArgsOverride);
|
||||||
bool AreConstraintsSubset(BfGenericParamInstance* checkInner, BfGenericParamInstance* checkOuter);
|
bool AreConstraintsSubset(BfGenericParamInstance* checkInner, BfGenericParamInstance* checkOuter);
|
||||||
bool CheckConstraintState(BfAstNode* refNode);
|
bool CheckConstraintState(BfAstNode* refNode);
|
||||||
|
void ValidateGenericParams(BfGenericParamKind genericParamKind, Span<BfGenericParamInstance*> genericParams);
|
||||||
bool ShouldAllowMultipleDefinitions(BfTypeInstance* typeInst, BfTypeDef* firstDeclaringTypeDef, BfTypeDef* secondDeclaringTypeDef);
|
bool ShouldAllowMultipleDefinitions(BfTypeInstance* typeInst, BfTypeDef* firstDeclaringTypeDef, BfTypeDef* secondDeclaringTypeDef);
|
||||||
void CheckInjectNewRevision(BfTypeInstance* typeInstance);
|
void CheckInjectNewRevision(BfTypeInstance* typeInstance);
|
||||||
void InitType(BfType* resolvedTypeRef, BfPopulateType populateType);
|
void InitType(BfType* resolvedTypeRef, BfPopulateType populateType);
|
||||||
|
|
|
@ -110,6 +110,10 @@ BfGenericExtensionEntry* BfModule::BuildGenericExtensionInfo(BfTypeInstance* gen
|
||||||
for (auto genericParam : genericExEntry->mGenericParams)
|
for (auto genericParam : genericExEntry->mGenericParams)
|
||||||
AddDependency(genericParam, mCurTypeInstance);
|
AddDependency(genericParam, mCurTypeInstance);
|
||||||
|
|
||||||
|
ValidateGenericParams(BfGenericParamKind_Type,
|
||||||
|
Span<BfGenericParamInstance*>((BfGenericParamInstance**)genericExEntry->mGenericParams.mVals,
|
||||||
|
genericExEntry->mGenericParams.mSize));
|
||||||
|
|
||||||
return genericExEntry;
|
return genericExEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +157,7 @@ bool BfModule::InitGenericParams(BfType* resolvedTypeRef)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BfModule::FinishGenericParams(BfType* resolvedTypeRef)
|
bool BfModule::FinishGenericParams(BfType* resolvedTypeRef)
|
||||||
{
|
{
|
||||||
BfTypeState typeState;
|
BfTypeState typeState;
|
||||||
typeState.mPrevState = mContext->mCurTypeState;
|
typeState.mPrevState = mContext->mCurTypeState;
|
||||||
typeState.mResolveKind = BfTypeState::ResolveKind_BuildingGenericParams;
|
typeState.mResolveKind = BfTypeState::ResolveKind_BuildingGenericParams;
|
||||||
|
@ -326,6 +330,10 @@ bool BfModule::FinishGenericParams(BfType* resolvedTypeRef)
|
||||||
|
|
||||||
for (auto typeRef : deferredResolveTypes)
|
for (auto typeRef : deferredResolveTypes)
|
||||||
auto constraintType = ResolveTypeRef(typeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_None);
|
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)
|
for (auto genericParam : genericTypeInst->mGenericTypeInfo->mGenericParams)
|
||||||
AddDependency(genericParam, mCurTypeInstance);
|
AddDependency(genericParam, mCurTypeInstance);
|
||||||
|
@ -333,6 +341,58 @@ bool BfModule::FinishGenericParams(BfType* resolvedTypeRef)
|
||||||
return true;
|
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)
|
bool BfModule::ValidateGenericConstraints(BfAstNode* typeRef, BfTypeInstance* genericTypeInst, bool ignoreErrors)
|
||||||
{
|
{
|
||||||
if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsTypeAlias()) && (mCurTypeInstance->IsGenericTypeInstance()))
|
if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsTypeAlias()) && (mCurTypeInstance->IsGenericTypeInstance()))
|
||||||
|
|
|
@ -1204,6 +1204,7 @@ public:
|
||||||
virtual BfGenericParamDef* GetGenericParamDef() = 0;
|
virtual BfGenericParamDef* GetGenericParamDef() = 0;
|
||||||
virtual BfExternalConstraintDef* GetExternConstraintDef() = 0;
|
virtual BfExternalConstraintDef* GetExternConstraintDef() = 0;
|
||||||
virtual String GetName() = 0;
|
virtual String GetName() = 0;
|
||||||
|
virtual BfAstNode* GetRefNode() = NULL;
|
||||||
bool IsEnum();
|
bool IsEnum();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1255,6 +1256,13 @@ public:
|
||||||
return mTypeDef->mGenericParamDefs[mGenericIdx]->mName;
|
return mTypeDef->mGenericParamDefs[mGenericIdx]->mName;
|
||||||
return mTypeDef->mExternalConstraints[mGenericIdx - (int)mTypeDef->mGenericParamDefs.size()].mTypeRef->ToString();
|
return mTypeDef->mExternalConstraints[mGenericIdx - (int)mTypeDef->mGenericParamDefs.size()].mTypeRef->ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual BfAstNode* GetRefNode() override
|
||||||
|
{
|
||||||
|
if (mGenericIdx < (int)mTypeDef->mGenericParamDefs.size())
|
||||||
|
return mTypeDef->mGenericParamDefs[mGenericIdx]->mNameNodes[0];
|
||||||
|
return mTypeDef->mExternalConstraints[mGenericIdx - (int)mTypeDef->mGenericParamDefs.size()].mTypeRef;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class BfGenericMethodParamInstance : public BfGenericParamInstance
|
class BfGenericMethodParamInstance : public BfGenericParamInstance
|
||||||
|
@ -1305,6 +1313,13 @@ public:
|
||||||
return mMethodDef->mGenericParams[mGenericIdx]->mName;
|
return mMethodDef->mGenericParams[mGenericIdx]->mName;
|
||||||
return mMethodDef->mExternalConstraints[mGenericIdx - (int)mMethodDef->mGenericParams.size()].mTypeRef->ToString();
|
return mMethodDef->mExternalConstraints[mGenericIdx - (int)mMethodDef->mGenericParams.size()].mTypeRef->ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual BfAstNode* GetRefNode() override
|
||||||
|
{
|
||||||
|
if (mGenericIdx < (int)mMethodDef->mGenericParams.size())
|
||||||
|
return mMethodDef->mGenericParams[mGenericIdx]->mNameNodes[0];
|
||||||
|
return mMethodDef->mExternalConstraints[mGenericIdx - (int)mMethodDef->mGenericParams.size()].mTypeRef;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BF_VALCOMP(val) if (val != 0) return val
|
#define BF_VALCOMP(val) if (val != 0) return val
|
||||||
|
|
|
@ -297,7 +297,7 @@ void DbgHotScanner::ScanRoot(addr_target rootPtr, int memKind)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int expectedStartPage = (rootIdx * PageHeap::PageMap::LEAF_LENGTH) + leafIdx;
|
int expectedStartPage = (rootIdx * PageHeap::PageMap::LEAF_LENGTH) + leafIdx;
|
||||||
Span span;
|
TCFake::Span span;
|
||||||
mDebugger->ReadMemory(spanAddr, sizeof(span), &span);
|
mDebugger->ReadMemory(spanAddr, sizeof(span), &span);
|
||||||
ScanSpan(&span, expectedStartPage, memKind);
|
ScanSpan(&span, expectedStartPage, memKind);
|
||||||
}
|
}
|
||||||
|
@ -326,7 +326,7 @@ void DbgHotScanner::ScanRoot(addr_target rootPtr, int memKind)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int expectedStartPage = ((pageIdx1 * PageHeap::PageMap::INTERIOR_LENGTH) + pageIdx2) * PageHeap::PageMap::LEAF_LENGTH + pageIdx3;
|
int expectedStartPage = ((pageIdx1 * PageHeap::PageMap::INTERIOR_LENGTH) + pageIdx2) * PageHeap::PageMap::LEAF_LENGTH + pageIdx3;
|
||||||
Span span;
|
TCFake::Span span;
|
||||||
mDebugger->ReadMemory(spanAddr, sizeof(span), &span);
|
mDebugger->ReadMemory(spanAddr, sizeof(span), &span);
|
||||||
ScanSpan(&span, expectedStartPage, memKind);
|
ScanSpan(&span, expectedStartPage, memKind);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ NS_BF_DBG_BEGIN
|
||||||
|
|
||||||
namespace TCFake
|
namespace TCFake
|
||||||
{
|
{
|
||||||
struct Span;
|
struct Span;
|
||||||
static const size_t kPageShift = 13;
|
static const size_t kPageShift = 13;
|
||||||
static const size_t kNumClasses = 88;
|
static const size_t kNumClasses = 88;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue