1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 04:22: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) 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; bool success = true;
if ((argValues.mArguments != NULL) && (argValues.mArguments->size() != 0)) 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; 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; 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; 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; success = false;
} }
@ -14200,16 +14203,19 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
bool isGenericParam = unresolvedTypeRef->IsGenericParam(); bool isGenericParam = unresolvedTypeRef->IsGenericParam();
if (resolvedTypeRef->IsGenericParam()) if (resolvedTypeRef->IsGenericParam())
{ {
auto genericParam = mModule->GetGenericParamInstance((BfGenericParamType*)resolvedTypeRef); BfGenericParamFlags genericParamFlags = BfGenericParamFlag_None;
if (genericParam->mTypeConstraint == NULL) 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 // Allow it
} }
else 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); 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())) || if (((typeConstraint != NULL) && (typeConstraint->IsValueType())) ||
((genericParam->mGenericParamFlags & (BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr)) != 0)) ((genericParamFlags & (BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr)) != 0))
{ {
resultType = mModule->CreatePointerType(resolvedTypeRef); resultType = mModule->CreatePointerType(resolvedTypeRef);
} }
else if (((genericParam->mTypeConstraint != NULL) && (!genericParam->mTypeConstraint->IsValueType())) || else if (((typeConstraint != NULL) && (!typeConstraint->IsValueType())) ||
((genericParam->mGenericParamFlags & (BfGenericParamFlag_Class)) != 0)) ((genericParamFlags & (BfGenericParamFlag_Class)) != 0))
{ {
// Leave as 'T' // Leave as 'T'
resultType = resolvedTypeRef; resultType = resolvedTypeRef;

View file

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

View file

@ -1818,6 +1818,7 @@ public:
BfGenericParamInstance* GetGenericTypeParamInstance(int paramIdx); BfGenericParamInstance* GetGenericTypeParamInstance(int paramIdx);
BfGenericParamInstance* GetGenericParamInstance(BfGenericParamType* type); BfGenericParamInstance* GetGenericParamInstance(BfGenericParamType* type);
void GetActiveTypeGenericParamInstances(SizedArray<BfGenericParamInstance*, 4>& genericParamInstance); void GetActiveTypeGenericParamInstances(SizedArray<BfGenericParamInstance*, 4>& genericParamInstance);
BfGenericParamInstance* GetMergedGenericParamData(BfGenericParamType* type, BfGenericParamFlags& outFlags, BfType*& outTypeConstraint);
BfTypeInstance* GetBaseType(BfTypeInstance* typeInst); BfTypeInstance* GetBaseType(BfTypeInstance* typeInst);
void HandleTypeGenericParamRef(BfAstNode* refNode, BfTypeDef* typeDef, int typeGenericParamIdx); void HandleTypeGenericParamRef(BfAstNode* refNode, BfTypeDef* typeDef, int typeGenericParamIdx);
void HandleMethodGenericParamRef(BfAstNode* refNode, BfTypeDef* typeDef, BfMethodDef* methodDef, 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]; auto rootGenericParamInstance = genericTypeInst->mGenericTypeInfo->mGenericParams[paramIdx];
genericParamInstance->mTypeConstraint = rootGenericParamInstance->mTypeConstraint; genericParamInstance->mTypeConstraint = rootGenericParamInstance->mTypeConstraint;
genericParamInstance->mInterfaceConstraints = rootGenericParamInstance->mInterfaceConstraints; genericParamInstance->mInterfaceConstraints = rootGenericParamInstance->mInterfaceConstraints;
genericParamInstance->mGenericParamFlags |= rootGenericParamInstance->mGenericParamFlags; genericParamInstance->mGenericParamFlags = (BfGenericParamFlags)(genericParamInstance->mGenericParamFlags | rootGenericParamInstance->mGenericParamFlags);
ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType()); 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 // 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; auto outerFlags = checkOuter->mGenericParamFlags;
if ((outerFlags & BfGenericParamFlag_Enum) != 0) if ((outerFlags & BfGenericParamFlag_Enum) != 0)
outerFlags |= BfGenericParamFlag_Struct; outerFlags = (BfGenericParamFlags)(outerFlags | BfGenericParamFlag_Struct);
if (checkOuter->mTypeConstraint != NULL) if (checkOuter->mTypeConstraint != NULL)
{ {
if (checkOuter->mTypeConstraint->IsStruct()) if (checkOuter->mTypeConstraint->IsStruct())
outerFlags |= BfGenericParamFlag_Struct; outerFlags = (BfGenericParamFlags)(outerFlags | BfGenericParamFlag_Struct);
else if (checkOuter->mTypeConstraint->IsStructOrStructPtr()) else if (checkOuter->mTypeConstraint->IsStructOrStructPtr())
outerFlags |= BfGenericParamFlag_StructPtr; outerFlags = (BfGenericParamFlags)(outerFlags | BfGenericParamFlag_StructPtr);
else if (checkOuter->mTypeConstraint->IsObject()) else if (checkOuter->mTypeConstraint->IsObject())
outerFlags |= BfGenericParamFlag_Class; outerFlags = (BfGenericParamFlags)(outerFlags | BfGenericParamFlag_Class);
else if (checkOuter->mTypeConstraint->IsEnum()) else if (checkOuter->mTypeConstraint->IsEnum())
outerFlags |= BfGenericParamFlag_Enum | BfGenericParamFlag_Struct; outerFlags = (BfGenericParamFlags)(outerFlags | BfGenericParamFlag_Enum | BfGenericParamFlag_Struct);
else if (checkOuter->mTypeConstraint->IsInterface()) else if (checkOuter->mTypeConstraint->IsInterface())
outerFlags |= BfGenericParamFlag_Interface; outerFlags = (BfGenericParamFlags)(outerFlags | BfGenericParamFlag_Interface);
} }
auto innerFlags = checkInner->mGenericParamFlags; auto innerFlags = checkInner->mGenericParamFlags;
if ((innerFlags & BfGenericParamFlag_Enum) != 0) if ((innerFlags & BfGenericParamFlag_Enum) != 0)
innerFlags |= BfGenericParamFlag_Struct; innerFlags = (BfGenericParamFlags)(innerFlags | BfGenericParamFlag_Struct);
if (((innerFlags | outerFlags) & ~BfGenericParamFlag_Var) != (outerFlags & ~BfGenericParamFlag_Var)) if (((innerFlags | outerFlags) & ~BfGenericParamFlag_Var) != (outerFlags & ~BfGenericParamFlag_Var))
return false; return false;
@ -8057,6 +8057,30 @@ void BfModule::GetActiveTypeGenericParamInstances(SizedArray<BfGenericParamInsta
genericParamInstances.Add(entry); 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) BfGenericParamInstance* BfModule::GetGenericParamInstance(BfGenericParamType* type)
{ {
if (type->mGenericParamKind == BfGenericParamKind_Method) if (type->mGenericParamKind == BfGenericParamKind_Method)

View file

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