From e6352571c1ca61681d6e363d7d948d7412f3bd23 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Wed, 3 Aug 2022 07:54:35 -0700 Subject: [PATCH] Fixed nullable null coalescing short circuiting --- BeefLibs/corlib/src/Nullable.bf | 25 ------------------------- IDEHelper/Compiler/BfExprEvaluator.cpp | 22 +++++++++++++++++----- IDEHelper/Tests/src/Nullable.bf | 17 +++++++++++++++++ 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/BeefLibs/corlib/src/Nullable.bf b/BeefLibs/corlib/src/Nullable.bf index 6172ee57..6830b790 100644 --- a/BeefLibs/corlib/src/Nullable.bf +++ b/BeefLibs/corlib/src/Nullable.bf @@ -420,31 +420,6 @@ namespace System return Nullable(lhs.mValue | rhs.mValue); } - // - - public static T operator??(Nullable lhs, T rhs) - { - return (lhs.mHasValue) ? lhs.mValue : rhs; - } - - public static TResult? operator??(TOther lhs, Nullable rhs) where TResult : operator TOther ?? T where TResult : struct - { - if (!rhs.mHasValue) return null; - return Nullable(lhs ?? rhs.mValue); - } - - public static TResult? operator??(Nullable lhs, TOther rhs) where TResult : operator T ?? TOther where TResult : struct - { - if (!lhs.mHasValue) return null; - return Nullable(lhs.mValue ?? rhs); - } - - public static TResult? operator??(Nullable lhs, Nullable rhs) where TOther : struct where TResult : operator T ?? TOther where TResult : struct - { - if ((!lhs.mHasValue) || (!rhs.mHasValue)) return null; - return Nullable(lhs.mValue ?? rhs.mValue); - } - // public static TResult? operator<< (TOther lhs, Nullable rhs) where TResult : operator TOther << T where TResult : struct diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index c20dfb82..c11889a0 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -22925,17 +22925,21 @@ void BfExprEvaluator::PerformBinaryOperation(BfExpression* leftExpression, BfExp bool BfExprEvaluator::PerformBinaryOperation_NullCoalesce(BfTokenNode* opToken, BfExpression* leftExpression, BfExpression* rightExpression, BfTypedValue leftValue, BfType* wantType, BfTypedValue* assignTo) { - if ((leftValue) && ((leftValue.mType->IsPointer()) || (leftValue.mType->IsFunction()) || (leftValue.mType->IsObject())) /* || (leftValue.mType->IsNullable())*/) + if ((leftValue) && ((leftValue.mType->IsPointer()) || (leftValue.mType->IsFunction()) || (leftValue.mType->IsObject())) || (leftValue.mType->IsNullable())) { leftValue = mModule->LoadValue(leftValue); + BfType* nullableElementType = NULL; BfIRValue nullableHasValue; + BfTypedValue nullableExtractedLeftValue; if (leftValue.mType->IsNullable()) { - if (wantType == leftValue.mType) - wantType = leftValue.mType->GetUnderlyingType(); - nullableHasValue = mModule->mBfIRBuilder->CreateExtractValue(leftValue.mValue, 1); - leftValue = BfTypedValue(mModule->mBfIRBuilder->CreateExtractValue(leftValue.mValue, 0), leftValue.mType->GetUnderlyingType()); + nullableElementType = leftValue.mType->GetUnderlyingType(); + nullableHasValue = mModule->mBfIRBuilder->CreateExtractValue(leftValue.mValue, nullableElementType->IsValuelessType() ? 1 : 2); // has_value + if (!nullableElementType->IsValuelessType()) + nullableExtractedLeftValue = BfTypedValue(mModule->mBfIRBuilder->CreateExtractValue(leftValue.mValue, 1), nullableElementType); // value + else + nullableExtractedLeftValue = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), nullableElementType); } if (leftValue.mValue.IsConst()) @@ -22984,6 +22988,14 @@ bool BfExprEvaluator::PerformBinaryOperation_NullCoalesce(BfTokenNode* opToken, mModule->AssertErrorState(); return true; } + + if ((assignTo == NULL) && (leftValue.mType->IsNullable()) && (!rightValue.mType->IsNullable())) + { + if (wantType == leftValue.mType) + wantType = nullableElementType; + leftValue = nullableExtractedLeftValue; + } + rightValue = mModule->LoadValue(rightValue); if (assignTo == NULL) diff --git a/IDEHelper/Tests/src/Nullable.bf b/IDEHelper/Tests/src/Nullable.bf index 284302a8..237d0542 100644 --- a/IDEHelper/Tests/src/Nullable.bf +++ b/IDEHelper/Tests/src/Nullable.bf @@ -1,6 +1,7 @@ #pragma warning disable 168 using System; +using System.Collections; namespace Tests { @@ -97,6 +98,22 @@ namespace Tests String str = "Abc"; StringView? svn = str; + + iNull = null; + int? iNull2 = 123; + List l = null; + List l2 = scope .(); + + int a = iNull2 ?? l.Count; + int b = iNull ?? l2.Count; + var c = iNull ?? iNull2; + + Test.Assert(a == 123); + Test.Assert(b == 0); + Test.Assert(typeof(decltype(c)) == typeof(int?)); + + iNull ??= iNull2; + Test.Assert(iNull == 123); } } }