From 1e44392da8dc0697f5d3389c8b619391776a758b Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Wed, 15 Jan 2025 11:25:51 -0800 Subject: [PATCH] Better handling of extern generic constraints --- IDEHelper/Compiler/BfModule.cpp | 14 +++++++++ IDEHelper/Compiler/BfModule.h | 2 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 36 +++++++++++++++++++++--- IDEHelper/Tests/src/Generics2.bf | 28 ++++++++++++++++++ 4 files changed, 75 insertions(+), 5 deletions(-) diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index f1cd86b1..faf36589 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -8566,6 +8566,20 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS if (checkArgType->IsObjectOrInterface()) argIsReferenceType = true; + if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mIsUnspecialized) && (mCurMethodInstance->mMethodInfoEx != NULL)) + { + for (int genericParamIdx = (int)mCurMethodInstance->mMethodInfoEx->mMethodGenericArguments.size(); + genericParamIdx < mCurMethodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++) + { + auto genericParamInst = mCurMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx]; + + if (genericParamInst->mExternType == checkArgType) + { + checkGenericParamFlags |= genericParamInst->mGenericParamFlags; + } + } + } + BfTypeInstance* typeConstraintInst = NULL; if (genericParamInst->mTypeConstraint != NULL) typeConstraintInst = genericParamInst->mTypeConstraint->ToTypeInstance(); diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 934ae992..aff341f4 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1959,7 +1959,7 @@ public: BfGenericParamInstance* GetGenericTypeParamInstance(int paramIdx); BfGenericParamInstance* GetGenericParamInstance(BfGenericParamType* type, bool checkMixinBind = false, BfFailHandleKind failHandleKind = BfFailHandleKind_Normal); void GetActiveTypeGenericParamInstances(SizedArray& genericParamInstance); - BfGenericParamInstance* GetMergedGenericParamData(BfGenericParamType* type, BfGenericParamFlags& outFlags, BfType*& outTypeConstraint); + BfGenericParamInstance* GetMergedGenericParamData(BfType* 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 871e8b28..984a88be 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -9621,11 +9621,39 @@ void BfModule::GetActiveTypeGenericParamInstances(SizedArraymGenericParamFlags; - outTypeConstraint = genericParam->mTypeConstraint; + BfGenericParamType* genericParamType = NULL; + if (type->IsGenericParam()) + genericParamType = (BfGenericParamType*)type; + + BfGenericParamInstance* genericParam = NULL; + if (genericParamType != NULL) + { + genericParam = GetGenericParamInstance(genericParamType); + outFlags = (BfGenericParamFlags)(outFlags | genericParam->mGenericParamFlags); + if (genericParam->mTypeConstraint != NULL) + outTypeConstraint = genericParam->mTypeConstraint; + } + else + { + outFlags = BfGenericParamFlag_None; + outTypeConstraint = NULL; + + if ((mCurTypeInstance != NULL) && (mCurTypeInstance->mGenericTypeInfo != NULL)) + { + for (int genericIdx = mCurTypeInstance->mTypeDef->mGenericParamDefs.mSize; genericIdx < mCurTypeInstance->mGenericTypeInfo->mGenericParams.mSize; genericIdx++) + { + auto genericParam = mCurTypeInstance->mGenericTypeInfo->mGenericParams[genericIdx]; + if (genericParam->mExternType == type) + { + outFlags = (BfGenericParamFlags)(outFlags | genericParam->mGenericParamFlags); + if (genericParam->mTypeConstraint != NULL) + outTypeConstraint = genericParam->mTypeConstraint; + } + } + } + } // Check method generic constraints if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mIsUnspecialized) && (mCurMethodInstance->mMethodInfoEx != NULL)) diff --git a/IDEHelper/Tests/src/Generics2.bf b/IDEHelper/Tests/src/Generics2.bf index 93eb8ee9..ea68d7df 100644 --- a/IDEHelper/Tests/src/Generics2.bf +++ b/IDEHelper/Tests/src/Generics2.bf @@ -1,3 +1,5 @@ +#pragma warning disable 168 + using System; using System.Collections; @@ -21,6 +23,32 @@ namespace Tests } } + interface IZop + { + void Zop(); + } + + interface IZag + { + void Zag(); + } + + class ClassC where T : IDisposable + { + public void MethodA(T val) where T : IZop, delete, new + { + val.Zop(); + MethodB(val); + delete val; + } + + public void MethodB(T val) where T : IZop, delete, new + { + alloctype(T) z = new T(); + delete val; + } + } + struct TestFunc { private int mId;