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

Fixed extern generic constraint and var constraint issues

This commit is contained in:
Brian Fiete 2021-10-31 08:21:30 -07:00
parent dfb16336a2
commit 7a8592268c
5 changed files with 59 additions and 28 deletions

View file

@ -7917,27 +7917,30 @@ BfTypedValue BfExprEvaluator::CheckEnumCreation(BfAstNode* targetSrc, BfTypeInst
bool BfExprEvaluator::CheckGenericCtor(BfGenericParamType* genericParamType, BfResolvedArgs& argValues, BfAstNode* targetSrc)
{
auto genericConstraint = mModule->GetGenericParamInstance(genericParamType);
BfGenericParamFlags genericParamFlags = BfGenericParamFlag_None;
BfType* typeConstraint = NULL;
auto genericParam = mModule->GetMergedGenericParamData((BfGenericParamType*)genericParamType, genericParamFlags, typeConstraint);
bool success = true;
if ((argValues.mArguments != NULL) && (argValues.mArguments->size() != 0))
{
mModule->Fail(StrFormat("Only default parameterless constructors can be called on generic argument '%s'", genericConstraint->GetGenericParamDef()->mName.c_str()), targetSrc);
mModule->Fail(StrFormat("Only default parameterless constructors can be called on generic argument '%s'", genericParam->GetGenericParamDef()->mName.c_str()), targetSrc);
success = false;
}
else if ((genericConstraint->mGenericParamFlags & (BfGenericParamFlag_New | BfGenericParamFlag_Struct)) == 0)
else if ((genericParamFlags & (BfGenericParamFlag_New | BfGenericParamFlag_Struct | BfGenericParamFlag_Var)) == 0)
{
mModule->Fail(StrFormat("Must add 'where %s : new, struct' constraint to generic parameter to instantiate type", genericConstraint->GetGenericParamDef()->mName.c_str()), targetSrc);
mModule->Fail(StrFormat("Must add 'where %s : new, struct' constraint to generic parameter to instantiate type", genericParam->GetGenericParamDef()->mName.c_str()), targetSrc);
success = false;
}
else if ((genericConstraint->mGenericParamFlags & BfGenericParamFlag_New) == 0)
else if ((genericParamFlags & (BfGenericParamFlag_New | BfGenericParamFlag_Var)) == 0)
{
mModule->Fail(StrFormat("Must add 'where %s : new' constraint to generic parameter to instantiate type", genericConstraint->GetGenericParamDef()->mName.c_str()), targetSrc);
mModule->Fail(StrFormat("Must add 'where %s : new' constraint to generic parameter to instantiate type", genericParam->GetGenericParamDef()->mName.c_str()), targetSrc);
success = false;
}
else if ((genericConstraint->mGenericParamFlags & BfGenericParamFlag_Struct) == 0)
else if ((genericParamFlags & (BfGenericParamFlag_Struct | BfGenericParamFlag_Var)) == 0)
{
mModule->Fail(StrFormat("Must add 'where %s : struct' constraint to generic parameter to instantiate type without allocator", genericConstraint->GetGenericParamDef()->mName.c_str()), targetSrc);
mModule->Fail(StrFormat("Must add 'where %s : struct' constraint to generic parameter to instantiate type without allocator", genericParam->GetGenericParamDef()->mName.c_str()), targetSrc);
success = false;
}
@ -14200,16 +14203,19 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
bool isGenericParam = unresolvedTypeRef->IsGenericParam();
if (resolvedTypeRef->IsGenericParam())
{
auto genericParam = mModule->GetGenericParamInstance((BfGenericParamType*)resolvedTypeRef);
if (genericParam->mTypeConstraint == NULL)
BfGenericParamFlags genericParamFlags = BfGenericParamFlag_None;
BfType* typeConstraint = NULL;
auto genericParam = mModule->GetMergedGenericParamData((BfGenericParamType*)resolvedTypeRef, genericParamFlags, typeConstraint);
if (typeConstraint == NULL)
{
if ((genericParam->mGenericParamFlags & BfGenericParamFlag_Var) != 0)
if ((genericParamFlags & BfGenericParamFlag_Var) != 0)
{
// Allow it
}
else
{
if ((genericParam->mGenericParamFlags & BfGenericParamFlag_New) == 0)
if ((genericParamFlags & BfGenericParamFlag_New) == 0)
{
mModule->Fail(StrFormat("Must add 'where %s : new' constraint to generic parameter to instantiate type", genericParam->GetName().c_str()), objCreateExpr->mTypeRef);
}
@ -14220,13 +14226,13 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
}
}
if (((genericParam->mTypeConstraint != NULL) && (genericParam->mTypeConstraint->IsValueType())) ||
((genericParam->mGenericParamFlags & (BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr)) != 0))
if (((typeConstraint != NULL) && (typeConstraint->IsValueType())) ||
((genericParamFlags & (BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr)) != 0))
{
resultType = mModule->CreatePointerType(resolvedTypeRef);
}
else if (((genericParam->mTypeConstraint != NULL) && (!genericParam->mTypeConstraint->IsValueType())) ||
((genericParam->mGenericParamFlags & (BfGenericParamFlag_Class)) != 0))
else if (((typeConstraint != NULL) && (!typeConstraint->IsValueType())) ||
((genericParamFlags & (BfGenericParamFlag_Class)) != 0))
{
// Leave as 'T'
resultType = resolvedTypeRef;

View file

@ -7464,7 +7464,7 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar
if (constraintType->IsVar())
{
// From a `comptype` generic undef resolution. Ignore.
genericParamInstance->mGenericParamFlags |= BfGenericParamFlag_ComptypeExpr;
genericParamInstance->mGenericParamFlags = (BfGenericParamFlags)(genericParamInstance->mGenericParamFlags | BfGenericParamFlag_ComptypeExpr);
genericParamInstance->mComptypeConstraint.Add(constraintTypeRef);
continue;
}
@ -7526,7 +7526,7 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar
if ((startingTypeConstraint != NULL) && (startingTypeConstraint->IsDelegate()))
{
// 'System.Delegate' means that we are expecting an actual delegate instance. Simulate this by wanting a class.
genericParamInstance->mGenericParamFlags |= BfGenericParamFlag_Class;
genericParamInstance->mGenericParamFlags = (BfGenericParamFlags)(genericParamInstance->mGenericParamFlags | BfGenericParamFlag_Class);
}
}
else

View file

@ -1818,6 +1818,7 @@ public:
BfGenericParamInstance* GetGenericTypeParamInstance(int paramIdx);
BfGenericParamInstance* GetGenericParamInstance(BfGenericParamType* type);
void GetActiveTypeGenericParamInstances(SizedArray<BfGenericParamInstance*, 4>& genericParamInstance);
BfGenericParamInstance* GetMergedGenericParamData(BfGenericParamType* type, BfGenericParamFlags& outFlags, BfType*& outTypeConstraint);
BfTypeInstance* GetBaseType(BfTypeInstance* typeInst);
void HandleTypeGenericParamRef(BfAstNode* refNode, BfTypeDef* typeDef, int typeGenericParamIdx);
void HandleMethodGenericParamRef(BfAstNode* refNode, BfTypeDef* typeDef, BfMethodDef* methodDef, int typeGenericParamIdx);

View file

@ -102,7 +102,7 @@ BfGenericExtensionEntry* BfModule::BuildGenericExtensionInfo(BfTypeInstance* gen
auto rootGenericParamInstance = genericTypeInst->mGenericTypeInfo->mGenericParams[paramIdx];
genericParamInstance->mTypeConstraint = rootGenericParamInstance->mTypeConstraint;
genericParamInstance->mInterfaceConstraints = rootGenericParamInstance->mInterfaceConstraints;
genericParamInstance->mGenericParamFlags |= rootGenericParamInstance->mGenericParamFlags;
genericParamInstance->mGenericParamFlags = (BfGenericParamFlags)(genericParamInstance->mGenericParamFlags | rootGenericParamInstance->mGenericParamFlags);
ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType());
}
@ -390,25 +390,25 @@ bool BfModule::AreConstraintsSubset(BfGenericParamInstance* checkInner, BfGeneri
// If the outer had a type flag and the inner has a specific type constraint, then see if those are compatible
auto outerFlags = checkOuter->mGenericParamFlags;
if ((outerFlags & BfGenericParamFlag_Enum) != 0)
outerFlags |= BfGenericParamFlag_Struct;
outerFlags = (BfGenericParamFlags)(outerFlags | BfGenericParamFlag_Struct);
if (checkOuter->mTypeConstraint != NULL)
{
if (checkOuter->mTypeConstraint->IsStruct())
outerFlags |= BfGenericParamFlag_Struct;
outerFlags = (BfGenericParamFlags)(outerFlags | BfGenericParamFlag_Struct);
else if (checkOuter->mTypeConstraint->IsStructOrStructPtr())
outerFlags |= BfGenericParamFlag_StructPtr;
outerFlags = (BfGenericParamFlags)(outerFlags | BfGenericParamFlag_StructPtr);
else if (checkOuter->mTypeConstraint->IsObject())
outerFlags |= BfGenericParamFlag_Class;
outerFlags = (BfGenericParamFlags)(outerFlags | BfGenericParamFlag_Class);
else if (checkOuter->mTypeConstraint->IsEnum())
outerFlags |= BfGenericParamFlag_Enum | BfGenericParamFlag_Struct;
outerFlags = (BfGenericParamFlags)(outerFlags | BfGenericParamFlag_Enum | BfGenericParamFlag_Struct);
else if (checkOuter->mTypeConstraint->IsInterface())
outerFlags |= BfGenericParamFlag_Interface;
outerFlags = (BfGenericParamFlags)(outerFlags | BfGenericParamFlag_Interface);
}
auto innerFlags = checkInner->mGenericParamFlags;
if ((innerFlags & BfGenericParamFlag_Enum) != 0)
innerFlags |= BfGenericParamFlag_Struct;
innerFlags = (BfGenericParamFlags)(innerFlags | BfGenericParamFlag_Struct);
if (((innerFlags | outerFlags) & ~BfGenericParamFlag_Var) != (outerFlags & ~BfGenericParamFlag_Var))
return false;
@ -8057,6 +8057,30 @@ void BfModule::GetActiveTypeGenericParamInstances(SizedArray<BfGenericParamInsta
genericParamInstances.Add(entry);
}
BfGenericParamInstance* BfModule::GetMergedGenericParamData(BfGenericParamType* type, BfGenericParamFlags& outFlags, BfType*& outTypeConstraint)
{
BfGenericParamInstance* genericParam = GetGenericParamInstance(type);
outFlags = genericParam->mGenericParamFlags;
outTypeConstraint = genericParam->mTypeConstraint;
// Check method generic constraints
if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mIsUnspecialized) && (mCurMethodInstance->mMethodInfoEx != NULL))
{
for (int genericParamIdx = (int)mCurMethodInstance->mMethodInfoEx->mMethodGenericArguments.size();
genericParamIdx < mCurMethodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
{
auto genericParam = mCurMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
if (genericParam->mExternType == type)
{
outFlags = (BfGenericParamFlags)(outFlags | genericParam->mGenericParamFlags);
if (genericParam->mTypeConstraint != NULL)
outTypeConstraint = genericParam->mTypeConstraint;
}
}
}
return genericParam;
}
BfGenericParamInstance* BfModule::GetGenericParamInstance(BfGenericParamType* type)
{
if (type->mGenericParamKind == BfGenericParamKind_Method)

View file

@ -1118,7 +1118,7 @@ public:
class BfGenericParamInstance
{
public:
int mGenericParamFlags;
BfGenericParamFlags mGenericParamFlags;
BfType* mExternType;
Array<BfTypeInstance*> mInterfaceConstraints;
Array<BfGenericOperatorConstraintInstance> mOperatorConstraints;
@ -1129,7 +1129,7 @@ public:
BfGenericParamInstance()
{
mExternType = NULL;
mGenericParamFlags = 0;
mGenericParamFlags = BfGenericParamFlag_None;
mTypeConstraint = NULL;
mRefCount = 1;
}