From 195463cb77d12a54d5625e7c479230162f74f352 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Fri, 21 Mar 2025 11:37:26 -0400 Subject: [PATCH] Improved pointer generic constraints --- IDEHelper/Compiler/BfExprEvaluator.cpp | 9 +++++++++ IDEHelper/Compiler/BfModule.cpp | 19 ++++++++++--------- IDEHelper/Tests/src/Generics.bf | 8 ++++++++ 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 36f03481..5c8e9368 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -23498,6 +23498,15 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr, case BfUnaryOp_Dereference: { CheckResultForReading(mResult); + if (mResult.mType->IsGenericParam()) + { + auto genericParamInstance = mModule->GetGenericParamInstance((BfGenericParamType*)mResult.mType); + if ((genericParamInstance->mTypeConstraint != NULL) && (genericParamInstance->mTypeConstraint->IsPointer())) + { + mResult = mModule->GetDefaultTypedValue(genericParamInstance->mTypeConstraint->GetUnderlyingType(), false, BfDefaultValueKind_Addr); + break; + } + } if (!mResult.mType->IsPointer()) { mResult = BfTypedValue(); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 20773b31..161d46e0 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -8859,17 +8859,18 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS } } - if (checkArgType->IsPointer()) - { - auto ptrType = (BfPointerType*)checkArgType; - checkArgType = ptrType->mElementType; - } + auto checkArgElementType = checkArgType; + if (checkArgElementType->IsPointer()) + { + auto ptrType = (BfPointerType*)checkArgElementType; + checkArgElementType = ptrType->mElementType; + } if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_New) != 0) { bool canAlloc = false; - if (auto checkTypeInst = checkArgType->ToTypeInstance()) + if (auto checkTypeInst = checkArgElementType->ToTypeInstance()) { if (checkTypeInst->IsObjectOrStruct()) { @@ -8910,11 +8911,11 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS canAlloc = TypeIsSubTypeOf(mCurTypeInstance, checkTypeInst, false); } } - else if (checkArgType->IsGenericParam()) + else if (checkArgElementType->IsGenericParam()) { canAlloc = (checkGenericParamFlags & (BfGenericParamFlag_New | BfGenericParamFlag_Var)) != 0; } - else if (checkArgType->IsPrimitiveType()) + else if (checkArgElementType->IsPrimitiveType()) { // Any primitive types and stuff can be allocated canAlloc = true; @@ -8975,7 +8976,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS } if (doError) - { + { if ((!ignoreErrors) && (PreFail())) *errorOut = Fail(StrFormat("Const generic argument '%s', declared with '%s', is not compatible with const constraint '%s' for '%s'", genericParamInst->GetName().c_str(), _TypeToString(constExprValueType).c_str(), _TypeToString(genericParamInst->mTypeConstraint).c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef); diff --git a/IDEHelper/Tests/src/Generics.bf b/IDEHelper/Tests/src/Generics.bf index 804a5fc6..0f395b0c 100644 --- a/IDEHelper/Tests/src/Generics.bf +++ b/IDEHelper/Tests/src/Generics.bf @@ -199,6 +199,11 @@ namespace Tests delete val2; } + public static int IntPtrTest(T val) where T : int* + { + return *val; + } + public class ClassE { public static Self Instance = new ClassE() ~ delete _; @@ -513,6 +518,9 @@ namespace Tests var innerC = OuterA.InnerC.this(123); Test.Assert(innerC.mVal == 123); + + int iVal = 123; + Test.Assert(IntPtrTest(&iVal) == 123); } }