diff --git a/IDEHelper/Compiler/BfAutoComplete.cpp b/IDEHelper/Compiler/BfAutoComplete.cpp index 5aa9641b..e6168b79 100644 --- a/IDEHelper/Compiler/BfAutoComplete.cpp +++ b/IDEHelper/Compiler/BfAutoComplete.cpp @@ -1794,18 +1794,9 @@ void BfAutoComplete::CheckInvocation(BfAstNode* invocationNode, BfTokenNode* ope if (doCapture) { mIsCapturingMethodMatchInfo = true; - if (mMethodMatchInfo == NULL) - mMethodMatchInfo = new MethodMatchInfo(); - else - { - if (wasCapturingMethodMatchInfo) - { - // We're actually in an inner invocation now - delete mMethodMatchInfo; - mMethodMatchInfo = new MethodMatchInfo(); - mMethodMatchInfo->mSrcPositions.Clear(); - } - } + + delete mMethodMatchInfo; + mMethodMatchInfo = new MethodMatchInfo(); mMethodMatchInfo->mInvocationSrcIdx = target->GetSrcStart(); mMethodMatchInfo->mCurMethodInstance = mModule->mCurMethodInstance; diff --git a/IDEHelper/Compiler/BfAutoComplete.h b/IDEHelper/Compiler/BfAutoComplete.h index 2f98cd6e..3dd5fcca 100644 --- a/IDEHelper/Compiler/BfAutoComplete.h +++ b/IDEHelper/Compiler/BfAutoComplete.h @@ -140,8 +140,8 @@ public: BfMethodInstance* mCurMethodInstance; Array mInstanceList; int mInvocationSrcIdx; - int mBestIdx; - int mPrevBestIdx; + int mBestIdx; + int mPrevBestIdx; bool mHadExactMatch; int mMostParamsMatched; Array mSrcPositions; // start, commas, end @@ -152,8 +152,8 @@ public: mInvocationSrcIdx = -1; mCurTypeInstance = NULL; mCurMethodInstance = NULL; - mBestIdx = 0; - mPrevBestIdx = -1; + mBestIdx = 0; + mPrevBestIdx = -1; mHadExactMatch = false; mMostParamsMatched = 0; } diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 49fbddca..2af61df8 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -833,7 +833,7 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp RETURN_RESULTS; } -BfTypedValue BfMethodMatcher::ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType) +BfTypedValue BfMethodMatcher::ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType, BfTypeVector* genericArgumentsSubstitute) { BfTypedValue argTypedValue = resolvedArg.mTypedValue; if ((resolvedArg.mArgFlags & BfArgFlag_DelegateBindAttempt) != 0) @@ -909,9 +909,8 @@ BfTypedValue BfMethodMatcher::ResolveArgTypedValue(BfResolvedArg& resolvedArg, B if ((resolvedArg.mExpectedType != checkType) || (resolvedArg.mExpectedType == NULL)) // Did our last check match for this type? { SetAndRestoreValue prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true); - SetAndRestoreValue prevIgnoreError(mModule->mIgnoreErrors, true); - //SetAndRestoreValue prevNoBind(mModule->mCurMethodState->mNoBind, true); - + SetAndRestoreValue prevIgnoreError(mModule->mIgnoreErrors, true); + bool prevNoBind = false; if (mModule->mCurMethodState != NULL) { @@ -921,12 +920,28 @@ BfTypedValue BfMethodMatcher::ResolveArgTypedValue(BfResolvedArg& resolvedArg, B auto prevBlock = mModule->mBfIRBuilder->GetInsertBlock(); - BfExprEvaluator exprEvaluator(mModule); - exprEvaluator.mExpectingType = checkType; - exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_AllowIntUnknown); + + BfExprEvaluator exprEvaluator(mModule); + exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_AllowIntUnknown | BfEvalExprFlags_NoAutoComplete); if ((resolvedArg.mArgFlags & BfArgFlag_ParamsExpr) != 0) exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_AllowParamsExpr); - exprEvaluator.Evaluate(resolvedArg.mExpression); + + auto expectType = checkType; + if (expectType != NULL) + { + if (expectType->IsRef()) + { + auto refType = (BfRefType*)expectType; + expectType = refType->mElementType; + } + + if (genericArgumentsSubstitute != NULL) + expectType = mModule->ResolveGenericType(expectType, *genericArgumentsSubstitute, true); + } + + exprEvaluator.mExpectingType = expectType; + + exprEvaluator.Evaluate(resolvedArg.mExpression); argTypedValue = exprEvaluator.GetResult(); if (mModule->mCurMethodState != NULL) @@ -1046,6 +1061,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che BfTypeVector* genericArgumentsSubstitute = NULL; int argIdx = 0; + int argMatchCount = 0; bool needInferGenericParams = (checkMethod->mGenericParams.size() != 0) && (!mHadExplicitGenericArguments); int paramIdx = 0; @@ -1140,7 +1156,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che if (wantType->IsUnspecializedType()) { - BfTypedValue argTypedValue = ResolveArgTypedValue(mArguments[argIdx], checkType); + BfTypedValue argTypedValue = ResolveArgTypedValue(mArguments[argIdx], checkType, genericArgumentsSubstitute); if (!argTypedValue.IsUntypedValue()) { auto type = argTypedValue.mType; @@ -1209,7 +1225,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che if (paramIdx >= (int) mArguments.size()) break; // No params - BfTypedValue argTypedValue = ResolveArgTypedValue(mArguments[argIdx], NULL); + BfTypedValue argTypedValue = ResolveArgTypedValue(mArguments[argIdx], NULL, genericArgumentsSubstitute); if (!argTypedValue) goto NoMatch; @@ -1224,7 +1240,8 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che if ((argTypedValue.IsUntypedValue()) || (mModule->CanImplicitlyCast(argTypedValue, paramsArrayType))) { argIdx++; - paramIdx++; + argMatchCount++; + paramIdx++; break; } @@ -1238,12 +1255,13 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che while (argIdx < (int)mArguments.size()) { - argTypedValue = ResolveArgTypedValue(mArguments[argIdx], paramsElementType); + argTypedValue = ResolveArgTypedValue(mArguments[argIdx], paramsElementType, genericArgumentsSubstitute); if (!argTypedValue.HasType()) goto NoMatch; if (!mModule->CanImplicitlyCast(argTypedValue, paramsElementType)) goto NoMatch; argIdx++; + argMatchCount++; } } else @@ -1283,7 +1301,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che // We had a 'params' expression but this method didn't have a params slot in this parameter goto NoMatch; } - BfTypedValue argTypedValue = ResolveArgTypedValue(mArguments[argIdx], wantType); + BfTypedValue argTypedValue = ResolveArgTypedValue(mArguments[argIdx], wantType, genericArgumentsSubstitute); if (!argTypedValue.IsUntypedValue()) { @@ -1297,6 +1315,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che paramIdx++; argIdx++; + argMatchCount++; if ((autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo)) { @@ -1430,21 +1449,30 @@ NoMatch: if ((prevParamDiff >= 0) && ((paramDiff < 0) || (prevParamDiff < paramDiff))) return false; - // We search from the most specific type, so don't prefer a less specific type - if ((paramDiff == prevParamDiff) && (mBestMethodTypeInstance != typeInstance)) - return false; + if (paramDiff == prevParamDiff) + { + if (argMatchCount < mBackupArgMatchCount) + return false; + else if (argMatchCount == mBackupArgMatchCount) + { + // We search from the most specific type, so don't prefer a less specific type + if (mBestMethodTypeInstance != typeInstance) + return false; + } + } } if ((autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo)) { auto methodMatchInfo = autoComplete->mMethodMatchInfo; if ((methodMatchInfo->mPrevBestIdx == -1) && (!methodMatchInfo->mHadExactMatch)) - { - methodMatchInfo->mBestIdx = (int)methodMatchInfo->mInstanceList.size() - 1; + { + methodMatchInfo->mBestIdx = (int)methodMatchInfo->mInstanceList.size() - 1; } } mBackupMethodDef = checkMethod; + mBackupArgMatchCount = argMatchCount; // Lie temporarily to store at least one candidate (but mBestMethodDef is still NULL) hadMatch = true; } @@ -1950,6 +1978,8 @@ BfAutoComplete* BfExprEvaluator::GetAutoComplete() { if (mModule->mCompiler->mResolvePassData == NULL) return NULL; + if ((mBfEvalExprFlags & BfEvalExprFlags_NoAutoComplete) != 0) + return NULL; // For local methods- only process autocomplete on capture phase if ((mModule->mCurMethodState != NULL) && (mModule->mCurMethodState->mClosureState != NULL) && (!mModule->mCurMethodState->mClosureState->mCapturing)) @@ -7826,9 +7856,17 @@ void BfExprEvaluator::Visit(BfDefaultExpression* defaultExpr) type = mModule->ResolveTypeRef(defaultExpr->mTypeRef); if (type == NULL) return; + + BfDefaultValueKind defaultKind = BfDefaultValueKind_Const; + if (type->IsRef()) + { + mModule->Fail(StrFormat("There is no default value for type '%s'", mModule->TypeToString(type).c_str()), defaultExpr); + defaultKind = BfDefaultValueKind_Addr; + } + mModule->ValidateAllocation(type, defaultExpr->mTypeRef); mModule->AddDependency(type, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference); - mResult = mModule->GetDefaultTypedValue(type); + mResult = mModule->GetDefaultTypedValue(type, true, defaultKind); } void BfExprEvaluator::Visit(BfUninitializedExpression* uninitialziedExpr) diff --git a/IDEHelper/Compiler/BfExprEvaluator.h b/IDEHelper/Compiler/BfExprEvaluator.h index 947c0ca6..38167728 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.h +++ b/IDEHelper/Compiler/BfExprEvaluator.h @@ -142,6 +142,7 @@ public: BfType* mSelfType; // Only when matching interfaces when 'Self' needs to refer back to the implementing type BfMethodDef* mBackupMethodDef; + int mBackupArgMatchCount; BfMethodDef* mBestMethodDef; BfTypeInstance* mBestMethodTypeInstance; BfModuleMethodInstance mBestMethodInstance; @@ -152,7 +153,7 @@ public: Array mAmbiguousEntries; public: - BfTypedValue ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType); + BfTypedValue ResolveArgTypedValue(BfResolvedArg& resolvedArg, BfType* checkType, BfTypeVector* genericArgumentsSubstitute); bool InferGenericArgument(BfMethodInstance* methodInstance, BfType* argType, BfType* wantType, BfIRValue argValue); void CompareMethods(BfMethodInstance* prevMethodInstance, BfTypeVector* prevGenericArgumentsSubstitute, BfMethodInstance* newMethodInstance, BfTypeVector* genericArgumentsSubstitute, diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index e2ee2497..99f07380 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -64,7 +64,8 @@ enum BfEvalExprFlags BfEvalExprFlags_AllowRefExpr = 0x800, BfEvalExprFlags_AllowOutExpr = 0x1000, BfEvalExprFlags_FieldInitializer = 0x2000, - BfEvalExprFlags_VariableDeclaration = 0x4000 + BfEvalExprFlags_VariableDeclaration = 0x4000, + BfEvalExprFlags_NoAutoComplete = 0x8000 }; enum BfCastFlags @@ -1339,8 +1340,7 @@ public: bool mIsModuleMutable; // Set to false after writing module to disk, can be set back to true after doing extension module bool mWroteToLib; bool mHadBuildError; - bool mHadBuildWarning; - bool mHadVarUsage; + bool mHadBuildWarning; bool mIgnoreErrors; bool mIgnoreWarnings; bool mSetIllegalSrcPosition; @@ -1362,8 +1362,7 @@ public: bool CheckProtection(BfProtection protection, bool allowProtected, bool allowPrivate); void GetAccessAllowed(BfTypeInstance* checkType, bool& allowProtected, bool& allowPrivate); bool CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* memberOwner, BfProtection memberProtection, BfTypeInstance* lookupStartType); - void SetElementType(BfAstNode* astNode, BfSourceElementType elementType); - void SetHadVarUsage(); + void SetElementType(BfAstNode* astNode, BfSourceElementType elementType); BfError* Fail(const StringImpl& error, BfAstNode* refNode = NULL, bool isPersistent = false); BfError* FailAfter(const StringImpl& error, BfAstNode* refNode); BfError* Warn(int warningNum, const StringImpl& warning, BfAstNode* refNode = NULL, bool isPersistent = false);