diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 4ebd5f07..2306f02b 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -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; diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index fc58ee8a..9e6f447f 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -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 diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 2a4b0b26..9ca82a1c 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1818,6 +1818,7 @@ public: BfGenericParamInstance* GetGenericTypeParamInstance(int paramIdx); BfGenericParamInstance* GetGenericParamInstance(BfGenericParamType* type); void GetActiveTypeGenericParamInstances(SizedArray& 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); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 7b86c871..3430d123 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -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(SizedArraymGenericParamFlags; + 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) diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 1d4a3f1a..0714a26d 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -1118,7 +1118,7 @@ public: class BfGenericParamInstance { public: - int mGenericParamFlags; + BfGenericParamFlags mGenericParamFlags; BfType* mExternType; Array mInterfaceConstraints; Array mOperatorConstraints; @@ -1129,7 +1129,7 @@ public: BfGenericParamInstance() { mExternType = NULL; - mGenericParamFlags = 0; + mGenericParamFlags = BfGenericParamFlag_None; mTypeConstraint = NULL; mRefCount = 1; }