From bec6f1d007e19a7b5179ceda39e4c650a96acd07 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Fri, 24 Jul 2020 05:20:50 -0700 Subject: [PATCH] Properly checking extern method constraints, fixed dtor body scopes --- IDEHelper/Compiler/BfExprEvaluator.cpp | 70 ++++++++++++++++---------- IDEHelper/Compiler/BfModule.cpp | 30 +++++++---- IDEHelper/Tests/src/Extensions.bf | 2 +- IDEHelper/Tests/src/Operators.bf | 2 +- 4 files changed, 67 insertions(+), 37 deletions(-) diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 3aaf8a36..3791a2d7 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -4989,7 +4989,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV BfTypedValue BfExprEvaluator::CreateCall(BfMethodMatcher* methodMatcher, BfTypedValue target) { - auto moduleMethodInstance = mModule->GetMethodInstance(methodMatcher->mBestMethodTypeInstance, methodMatcher->mBestMethodDef, methodMatcher->mBestMethodGenericArguments); + auto moduleMethodInstance = GetSelectedMethod(methodMatcher->mTargetSrc, methodMatcher->mBestMethodTypeInstance, methodMatcher->mBestMethodDef, *methodMatcher); if (moduleMethodInstance.mMethodInstance == NULL) return BfTypedValue(); if ((target) && (target.mType != moduleMethodInstance.mMethodInstance->GetOwner())) @@ -12933,39 +12933,57 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc, if (methodDef->IsEmptyPartial()) return methodInstance; - - for (int checkGenericIdx = 0; checkGenericIdx < (int)methodMatcher.mBestMethodGenericArguments.size(); checkGenericIdx++) + + if (methodInstance.mMethodInstance->mMethodInfoEx != NULL) { - auto& genericParams = methodInstance.mMethodInstance->mMethodInfoEx->mGenericParams; - auto genericArg = methodMatcher.mBestMethodGenericArguments[checkGenericIdx]; - if (genericArg->IsVar()) - continue; - - BfAstNode* paramSrc; - if (methodMatcher.mBestMethodGenericArgumentSrcs.size() == 0) + for (int checkGenericIdx = 0; checkGenericIdx < (int)methodInstance.mMethodInstance->mMethodInfoEx->mGenericParams.size(); checkGenericIdx++) { - paramSrc = targetSrc; - } - else - paramSrc = methodMatcher.mArguments[methodMatcher.mBestMethodGenericArgumentSrcs[checkGenericIdx]].mExpression; - - // Note: don't pass methodMatcher.mBestMethodGenericArguments into here, this method is already specialized - BfError* error = NULL; - if (!mModule->CheckGenericConstraints(BfGenericParamSource(methodInstance.mMethodInstance), genericArg, paramSrc, genericParams[checkGenericIdx], NULL, - failed ? NULL : &error)) - { - if (methodInstance.mMethodInstance->IsSpecializedGenericMethod()) + auto genericParams = methodInstance.mMethodInstance->mMethodInfoEx->mGenericParams[checkGenericIdx]; + BfTypeVector* checkMethodGenericArgs = NULL; + BfType* genericArg = NULL; + + if (checkGenericIdx < (int)methodMatcher.mBestMethodGenericArguments.size()) { - // We mark this as failed to make sure we don't try to process a method that doesn't even follow the constraints - methodInstance.mMethodInstance->mFailedConstraints = true; + genericArg = methodMatcher.mBestMethodGenericArguments[checkGenericIdx]; } - if (methodInstance.mMethodInstance->mMethodDef->mMethodDeclaration != NULL) + else { - if (error != NULL) - mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance.mMethodInstance->mMethodDef->GetRefNode()); + checkMethodGenericArgs = &methodMatcher.mBestMethodGenericArguments; + genericArg = genericParams->mExternType; + genericArg = mModule->ResolveGenericType(genericArg, NULL, checkMethodGenericArgs); + } + + if (genericArg->IsVar()) + continue; + + BfAstNode* paramSrc; + if (checkGenericIdx >= methodMatcher.mBestMethodGenericArgumentSrcs.size()) + { + paramSrc = targetSrc; + } + else + paramSrc = methodMatcher.mArguments[methodMatcher.mBestMethodGenericArgumentSrcs[checkGenericIdx]].mExpression; + + // Note: don't pass methodMatcher.mBestMethodGenericArguments into here, this method is already specialized + BfError* error = NULL; + if (!mModule->CheckGenericConstraints(BfGenericParamSource(methodInstance.mMethodInstance), genericArg, paramSrc, genericParams, checkMethodGenericArgs, + failed ? NULL : &error)) + { + if (methodInstance.mMethodInstance->IsSpecializedGenericMethod()) + { + // We mark this as failed to make sure we don't try to process a method that doesn't even follow the constraints + methodInstance.mMethodInstance->mFailedConstraints = true; + } + if (methodInstance.mMethodInstance->mMethodDef->mMethodDeclaration != NULL) + { + if (error != NULL) + mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance.mMethodInstance->mMethodDef->GetRefNode()); + } } } } + else + BF_ASSERT(methodMatcher.mBestMethodGenericArguments.IsEmpty()); return methodInstance; } diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 47349192..fb4e216a 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -7276,10 +7276,18 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS (!CanCast(exprEvaluator.mResult, origCheckArgType))) { if (!ignoreErrors) - *errorOut = Fail(StrFormat("Generic argument '%s', declared to be '%s' for '%s', must result from binary operation '%s %s %s'", genericParamInst->GetName().c_str(), - TypeToString(origCheckArgType).c_str(), GenericParamSourceToString(genericParamSource).c_str(), - TypeToString(leftType).c_str(), BfGetOpName(checkOpConstraint.mBinaryOp), TypeToString(rightType).c_str() - ), checkArgTypeRef); + { + if (genericParamInst->mExternType != NULL) + *errorOut = Fail(StrFormat("Binary operation for '%s' must result in '%s' from binary operation '%s %s %s'", + GenericParamSourceToString(genericParamSource).c_str(), TypeToString(origCheckArgType).c_str(), + TypeToString(leftType).c_str(), BfGetOpName(checkOpConstraint.mBinaryOp), TypeToString(rightType).c_str() + ), checkArgTypeRef); + else + *errorOut = Fail(StrFormat("Generic argument '%s', declared to be '%s' for '%s', must result from binary operation '%s %s %s'", genericParamInst->GetName().c_str(), + TypeToString(origCheckArgType).c_str(), GenericParamSourceToString(genericParamSource).c_str(), + TypeToString(leftType).c_str(), BfGetOpName(checkOpConstraint.mBinaryOp), TypeToString(rightType).c_str() + ), checkArgTypeRef); + } return false; } @@ -12297,10 +12305,14 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM } // Generic constraints - for (int genericParamIdx = 0; genericParamIdx < (int)methodDef->mGenericParams.size(); genericParamIdx++) + if (!methodDef->mGenericParams.IsEmpty()) { - auto genericParamInstance = new BfGenericMethodParamInstance(methodDef, genericParamIdx); - methodInstance->GetMethodInfoEx()->mGenericParams.push_back(genericParamInstance); + BF_ASSERT(methodInstance->GetMethodInfoEx()->mGenericParams.IsEmpty()); + for (int genericParamIdx = 0; genericParamIdx < (int)methodDef->mGenericParams.size(); genericParamIdx++) + { + auto genericParamInstance = new BfGenericMethodParamInstance(methodDef, genericParamIdx); + methodInstance->GetMethodInfoEx()->mGenericParams.push_back(genericParamInstance); + } } for (int externConstraintIdx = 0; externConstraintIdx < (int)methodDef->mExternalConstraints.size(); externConstraintIdx++) @@ -14244,8 +14256,8 @@ void BfModule::EmitDtorBody() CallChainedMethods(mCurMethodInstance, true); if (auto bodyBlock = BfNodeDynCast(methodDef->mBody)) - { - VisitCodeBlock(bodyBlock); + { + VisitEmbeddedStatement(bodyBlock); if (bodyBlock->mCloseBrace != NULL) { UpdateSrcPos(bodyBlock->mCloseBrace); diff --git a/IDEHelper/Tests/src/Extensions.bf b/IDEHelper/Tests/src/Extensions.bf index e43b5a6a..fefa78b0 100644 --- a/IDEHelper/Tests/src/Extensions.bf +++ b/IDEHelper/Tests/src/Extensions.bf @@ -20,7 +20,7 @@ namespace System.Collections extension Dictionary { - public static bool operator==(Self lhs, Self rhs) where K : IOpEquals where V : IOpEquals + public static bool operator==(Self lhs, Self rhs) { if (lhs.mCount != rhs.mCount) return false; diff --git a/IDEHelper/Tests/src/Operators.bf b/IDEHelper/Tests/src/Operators.bf index cd50e1b2..e10e9569 100644 --- a/IDEHelper/Tests/src/Operators.bf +++ b/IDEHelper/Tests/src/Operators.bf @@ -82,7 +82,7 @@ namespace Tests return -val; } - public T GetInt() where T : Int + public T GetInt() where T : Int32 { return mVal; }