From 6d06ee3430c296cf02da6ed3f751267eb50d6b1d Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Tue, 19 Jan 2021 10:40:38 -0800 Subject: [PATCH] Fixed constrained property lookups --- IDEHelper/Compiler/BfExprEvaluator.cpp | 40 +++++++++++++++--- IDEHelper/Compiler/BfModule.cpp | 34 +++++++++------ IDEHelper/Tests/src/Interfaces.bf | 57 ++++++++++++++++++++++++++ IDEHelper/Tests/src/Properties.bf | 27 ++++++++++++ 4 files changed, 139 insertions(+), 19 deletions(-) diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 09cc91f6..4efc171d 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -8576,7 +8576,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp prevBindResult.mPrevVal->mCheckedMultipleMethods = true; BfModuleMethodInstance moduleMethodInstance = GetSelectedMethod(targetSrc, curTypeInst, methodDef, methodMatcher); - if (!mModule->CheckUseMethodInstance(moduleMethodInstance.mMethodInstance, targetSrc)) + if ((moduleMethodInstance.mMethodInstance != NULL) && (!mModule->CheckUseMethodInstance(moduleMethodInstance.mMethodInstance, targetSrc))) return BfTypedValue(); if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized)) @@ -16498,7 +16498,8 @@ BfModuleMethodInstance BfExprEvaluator::GetPropertyMethodInstance(BfMethodDef* m if (bestMethodInstance != NULL) { mPropTarget = mOrigPropTarget; - mPropTarget.mType = checkTypeInst; + //mPropTarget.mType = checkTypeInst; + //mPropTarget = mModule->Cast( mOrigPropTarget, checkTypeInst); return mModule->GetMethodInstanceAtIdx(ifaceMethodEntry.mMethodRef.mTypeInstance, ifaceMethodEntry.mMethodRef.mMethodNum); } } @@ -16638,9 +16639,23 @@ BfTypedValue BfExprEvaluator::GetResult(bool clearResult, bool resolveGenericTyp if (!matchedMethod->mIsStatic) { auto owner = methodInstance.mMethodInstance->GetOwner(); - if ((mPropTarget.mValue.IsFake()) && (!mOrigPropTarget.mValue.IsFake())) - { + + bool isTypeMatch = mPropTarget.mType == owner; + if (owner->IsTypedPrimitive()) + isTypeMatch |= mPropTarget.mType == owner->GetUnderlyingType(); + + if ((!isTypeMatch) || + ((mPropTarget.mValue.IsFake()) && (!mOrigPropTarget.mValue.IsFake()))) + { + auto prevPropTarget = mPropTarget; + mPropTarget = mModule->Cast(mPropSrc, mOrigPropTarget, owner); + + if (!mPropTarget) + { + mModule->Fail("Internal property error", mPropSrc); + return BfTypedValue(); + } } if ((mPropGetMethodFlags & BfGetMethodInstanceFlag_DisableObjectAccessChecks) == 0) @@ -17439,6 +17454,11 @@ void BfExprEvaluator::DoTupleAssignment(BfAssignmentExpression* assignExpr) void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool evaluatedLeft, BfTypedValue rightValue, BfTypedValue* outCascadeValue) { + if (assignExpr->ToString() == "state.StateMachine = this") + { + NOP; + } + auto binaryOp = BfAssignOpToBinaryOp(assignExpr->mOp); BfExpression* targetNode = assignExpr->mLeft; @@ -17589,10 +17609,18 @@ void BfExprEvaluator::PerformAssignment(BfAssignmentExpression* assignExpr, bool if (!setMethod->mIsStatic) { auto owner = methodInstance.mMethodInstance->GetOwner(); - if (mPropTarget.mType != owner) + if ((mPropTarget.mType != owner) || + ((mPropTarget.mValue.IsFake()) && (!mOrigPropTarget.mValue.IsFake()))) { - if (mPropDefBypassVirtual) + if ((mPropDefBypassVirtual) || (!mPropTarget.mType->IsInterface())) + { mPropTarget = mModule->Cast(mPropSrc, mOrigPropTarget, owner); + if (!mPropTarget) + { + mModule->Fail("Internal property error", mPropSrc); + return; + } + } } mModule->EmitObjectAccessCheck(mPropTarget); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index cdbcd87c..6587848f 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -12362,7 +12362,7 @@ BfModuleMethodInstance BfModule::ReferenceExternalMethodInstance(BfMethodInstanc inlineMethodRequest->mFromModuleRevision = mRevision; inlineMethodRequest->mMethodInstance = methodInstance; BF_ASSERT(mIsModuleMutable); - + BfLogSysM("mInlineMethodWorkList %p for method %p in module %p in ReferenceExternalMethodInstance\n", inlineMethodRequest, methodInstance, this); } } @@ -13047,7 +13047,7 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM inlineMethodRequest->mFunc = methodInstance->mIRFunction; inlineMethodRequest->mFromModuleRevision = mRevision; inlineMethodRequest->mMethodInstance = methodInstance; - + BfLogSysM("mInlineMethodWorkList %p for method %p in module %p in GetMethodInstance\n", inlineMethodRequest, methodInstance, this); BF_ASSERT(mIsModuleMutable); } @@ -14650,8 +14650,11 @@ void BfModule::CreateReturn(BfIRValue val) mBfIRBuilder->CreateStore(val, mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx())); mBfIRBuilder->CreateRetVoid(); return; - } - + } + + if (mCurMethodInstance->mReturnType->IsVar()) + return; + if (mCurMethodInstance->mReturnType->IsValuelessType()) { mBfIRBuilder->CreateRetVoid(); @@ -14740,7 +14743,11 @@ void BfModule::EmitDefaultReturn() } else { - if (mCurMethodInstance->mReturnType->IsVoid()) + if (mCurMethodInstance->mReturnType->IsVar()) + { + // Ignore + } + else if (mCurMethodInstance->mReturnType->IsVoid()) mBfIRBuilder->CreateRetVoid(); else if ((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() == -1)) mBfIRBuilder->CreateRet(GetDefaultValue(mCurMethodInstance->mReturnType)); @@ -17994,8 +18001,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) // We set mHasBeenProcessed to true immediately -- this helps avoid stack overflow during recursion for things like // self-referencing append allocations in ctor@calcAppend - methodInstance->mHasBeenProcessed = true; - mIncompleteMethodCount--; + methodInstance->mHasBeenProcessed = true; + mIncompleteMethodCount--; BF_ASSERT((mIsSpecialModule) || (mIncompleteMethodCount >= 0)); auto typeDef = methodInstance->mMethodInstanceGroup->mOwner->mTypeDef; @@ -18126,7 +18133,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) } } - BfLogSysM("ProcessMethod %p Unspecialized: %d Module: %p IRFunction: %d Reified: %d\n", methodInstance, mCurTypeInstance->IsUnspecializedType(), this, methodInstance->mIRFunction.mId, methodInstance->mIsReified); + BfLogSysM("ProcessMethod %p Unspecialized: %d Module: %p IRFunction: %d Reified: %d Incomplete:%d\n", methodInstance, mCurTypeInstance->IsUnspecializedType(), this, methodInstance->mIRFunction.mId, methodInstance->mIsReified, mIncompleteMethodCount); if (methodInstance->GetImportCallKind() != BfImportCallKind_None) { @@ -18242,11 +18249,12 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) BF_ASSERT(unspecializedMethodInstance != methodInstance); if (!unspecializedMethodInstance->mHasBeenProcessed) { - // Make sure the unspecialized method is processed so we can take its bindings - + // Make sure the unspecialized method is processed so we can take its bindings // Clear mCurMethodState so we don't think we're in a local method SetAndRestoreValue prevMethodState_Unspec(mCurMethodState, prevMethodState.mPrevVal); - mContext->ProcessMethod(unspecializedMethodInstance); + if (unspecializedMethodInstance->mMethodProcessRequest == NULL) + unspecializedMethodInstance->mDeclModule->mIncompleteMethodCount++; + mContext->ProcessMethod(unspecializedMethodInstance); } methodState.mGenericTypeBindings = &unspecializedMethodInstance->GetMethodInfoEx()->mGenericTypeBindings; } @@ -20726,7 +20734,7 @@ BfModuleMethodInstance BfModule::GetLocalMethodInstance(BfLocalMethod* localMeth closureState.mReturnType = methodInstance->mReturnType; mCompiler->mStats.mMethodsQueued++; mCompiler->UpdateCompletion(); - declareModule->mIncompleteMethodCount++; + declareModule->mIncompleteMethodCount++; mCompiler->mStats.mMethodsProcessed++; if (!methodInstance->mIsReified) mCompiler->mStats.mUnreifiedMethodsProcessed++; @@ -22156,7 +22164,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool auto func = methodInstance->mIRFunction; // if (methodInstance->mIsReified) -// CheckHotMethod(methodInstance, mangledName); +// CheckHotMethod(methodInstance, mangledName); BfLogSysM("DoMethodDeclaration %s Module: %p Type: %p MethodInst: %p Reified: %d Unspecialized: %d IRFunction: %d MethodId:%llx\n", mangledName.c_str(), this, mCurTypeInstance, methodInstance, methodInstance->mIsReified, mCurTypeInstance->IsUnspecializedType(), methodInstance->mIRFunction.mId, methodInstance->mIdHash); diff --git a/IDEHelper/Tests/src/Interfaces.bf b/IDEHelper/Tests/src/Interfaces.bf index bd2c8751..83391849 100644 --- a/IDEHelper/Tests/src/Interfaces.bf +++ b/IDEHelper/Tests/src/Interfaces.bf @@ -183,6 +183,13 @@ namespace Tests IFaceA ifa = cba; Test.Assert(ifa.GetType() == typeof(ClassB)); + ClassF cf = scope .(); + TestIFaceD(cf); + Test.Assert(cf.mA == 999); + ClassG cg = scope .(); + TestIFaceD(cg); + Test.Assert(cg.mA == 999); + GameItem gameItem = scope .(); var hitbox = GetHitbox(gameItem); Test.Assert(hitbox.mArea == .() { x=1, y=2, width=3, height=4 }); @@ -267,6 +274,47 @@ namespace Tests return T.SMethod2(val.GetVal()); } + interface IFaceD + { + int32 Val + { + get; set; + } + } + + class ClassF : IFaceD + { + public int32 mA; + + int32 IFaceD.Val + { + get + { + return mA; + } + + set + { + mA = value; + } + } + } + + class ClassG : ClassF + { + + } + + static void TestIFaceD(T val) where T : IFaceD + { + val.Val = 999; + } + + static int TestIFaceD2(T val) where T : IFaceD + { + return val.Val; + } + [Test] public static void TestDefaults() { @@ -297,6 +345,15 @@ namespace Tests Test.Assert(v == 3234); v = SGet2(ce); Test.Assert(v == 4234); + + ClassF cf = scope .(); + TestIFaceD(cf); + Test.Assert(cf.mA == 999); + Test.Assert(TestIFaceD2(cf) == 999); + ClassG cg = scope .(); + TestIFaceD(cg); + Test.Assert(cg.mA == 999); + Test.Assert(TestIFaceD2(cg) == 999); } } } diff --git a/IDEHelper/Tests/src/Properties.bf b/IDEHelper/Tests/src/Properties.bf index a499b130..c412727e 100644 --- a/IDEHelper/Tests/src/Properties.bf +++ b/IDEHelper/Tests/src/Properties.bf @@ -71,6 +71,8 @@ namespace Tests } } + + class ClassB { public StructA B { get; set; } @@ -90,6 +92,26 @@ namespace Tests public override int IVal2 { get => base.IVal2 + 100; } } + abstract class ClassD + { + public int32 Val { get; set; } + } + + class ClassE : ClassD + { + + } + + static void MethodC(T val) where T : ClassD + { + val.Val = 999; + } + + static int MethodD(T val) where T : ClassD + { + return val.Val; + } + [Test] public static void TestBasics() { @@ -122,6 +144,11 @@ namespace Tests ClassB cb2 = cc; Test.Assert(cb2.IVal == 1); Test.Assert(cb2.IVal2 == 102); + + ClassE ce = scope .(); + MethodC(ce); + Test.Assert(ce.Val == 999); + Test.Assert(MethodD(ce) == 999); } } }