From 03fbc9d468164a7a1f951afad00734de875e479e Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Thu, 4 Jun 2020 11:47:55 -0700 Subject: [PATCH] Fixes for type dependencies and tests for type deletion bug --- IDE/Tests/BugW004/BeefProj.toml | 5 + IDE/Tests/BugW004/BeefSpace.toml | 6 ++ IDE/Tests/BugW004/scripts/Test.txt | 21 +++++ IDE/Tests/BugW004/src/Program.bf | 49 ++++++++++ IDE/src/Compiler/BfCompiler.bf | 8 ++ IDE/src/IDEApp.bf | 5 +- IDE/src/ScriptManager.bf | 11 +++ IDEHelper/Compiler/BfCompiler.cpp | 104 +++++++++++++++++++-- IDEHelper/Compiler/BfContext.cpp | 20 +++- IDEHelper/Compiler/BfContext.h | 1 + IDEHelper/Compiler/BfExprEvaluator.cpp | 27 +++--- IDEHelper/Compiler/BfModule.cpp | 11 +++ IDEHelper/Compiler/BfModule.h | 16 ---- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 43 +++++++-- IDEHelper/Compiler/BfResolvedTypeUtils.cpp | 16 ++-- IDEHelper/Compiler/BfResolvedTypeUtils.h | 21 ++++- 16 files changed, 309 insertions(+), 55 deletions(-) create mode 100644 IDE/Tests/BugW004/BeefProj.toml create mode 100644 IDE/Tests/BugW004/BeefSpace.toml create mode 100644 IDE/Tests/BugW004/scripts/Test.txt create mode 100644 IDE/Tests/BugW004/src/Program.bf diff --git a/IDE/Tests/BugW004/BeefProj.toml b/IDE/Tests/BugW004/BeefProj.toml new file mode 100644 index 00000000..f0c46edc --- /dev/null +++ b/IDE/Tests/BugW004/BeefProj.toml @@ -0,0 +1,5 @@ +FileVersion = 1 + +[Project] +Name = "Bug" +StartupObject = "Bug.Program" diff --git a/IDE/Tests/BugW004/BeefSpace.toml b/IDE/Tests/BugW004/BeefSpace.toml new file mode 100644 index 00000000..c389207f --- /dev/null +++ b/IDE/Tests/BugW004/BeefSpace.toml @@ -0,0 +1,6 @@ +FileVersion = 1 +Projects = {Bug = {Path = "."}} + +[Workspace] +StartupProject = "Bug" + diff --git a/IDE/Tests/BugW004/scripts/Test.txt b/IDE/Tests/BugW004/scripts/Test.txt new file mode 100644 index 00000000..de6e3331 --- /dev/null +++ b/IDE/Tests/BugW004/scripts/Test.txt @@ -0,0 +1,21 @@ +# This tests that types that fail generic tests don't create types referenced in methods +# and also that they get deleted immediately when they are dereferenced. + +ShowFile("src/Program.bf") + +SetExpectError("Generic argument") +Compile() +ExpectError() + +AssertTypeInfo(1, "System.Collections.Dictionary.Enumerator, (int key, float value)>", "Found Reified ValidateErrors") +AssertTypeInfo(1, "System.Collections.Dictionary.Enumerator, (int key, float value)>.Entry", "Found Reified ValidateErrors") + +ToggleCommentAt("Method3_BadCall") +ToggleCommentAt("Method3_GoodCall") + +Compile() + +AssertTypeInfo(0, "System.Collections.Dictionary.Enumerator, (int key, float value)>", "") +AssertTypeInfo(0, "System.Collections.Dictionary.Enumerator, (int key, float value)>.Entry", "") +AssertTypeInfo(0, "System.Collections.Dictionary.Enumerator, (int key, float value)>", "") +AssertTypeInfo(0, "System.Collections.Dictionary.Enumerator, (int key, float value)>.Entry", "") \ No newline at end of file diff --git a/IDE/Tests/BugW004/src/Program.bf b/IDE/Tests/BugW004/src/Program.bf new file mode 100644 index 00000000..3b03e052 --- /dev/null +++ b/IDE/Tests/BugW004/src/Program.bf @@ -0,0 +1,49 @@ +#pragma warning disable 168 + +using System; +using System.Collections; + +namespace Bug +{ + class Program + { + class Dicto : Dictionary + { + + } + + public static bool Method1(IEnumerator param1) + { + return true; + } + + public static bool Method2(TEnumerator param1) where TEnumerator : IEnumerator + { + for (let val in param1) + { + + } + + return true; + } + + public static bool Method3(Dictionary param1) where K : IHashable + { + Method1(param1.GetEnumerator()); + Method1((IEnumerator<(K key, V value)>)param1.GetEnumerator()); + //*Method3_BadCall + return Method3.Enumerator, (K key, V value)>(param1.GetEnumerator()); + /*@*/ + + /*Method3_GoodCall + return Method2.Enumerator, (K key, V value)>(param1.GetEnumerator()); + */ + } + + static void Main() + { + Dicto dicto = scope .(); + Method3(dicto); + } + } +} diff --git a/IDE/src/Compiler/BfCompiler.bf b/IDE/src/Compiler/BfCompiler.bf index 3efbae90..35b7759e 100644 --- a/IDE/src/Compiler/BfCompiler.bf +++ b/IDE/src/Compiler/BfCompiler.bf @@ -99,6 +99,9 @@ namespace IDE.Compiler [CallingConvention(.Stdcall), CLink] static extern char8* BfCompiler_GetTypeDefInfo(void* bfCompiler, char8* typeDefName); + [CallingConvention(.Stdcall), CLink] + static extern char8* BfCompiler_GetTypeInfo(void* bfCompiler, char8* typeName); + [CallingConvention(.Stdcall), CLink] static extern void BfCompiler_SetOptions(void* bfCompiler, void* hotProject, int32 hotIdx, char8* targetTriple, int32 toolsetType, int32 simdSetting, int32 allocStackCount, int32 maxWorkerThreads, @@ -682,6 +685,11 @@ namespace IDE.Compiler outStr.Append(BfCompiler_GetTypeDefInfo(mNativeBfCompiler, typeDefName)); } + public void GetTypeInfo(String typeDefName, String outStr) + { + outStr.Append(BfCompiler_GetTypeInfo(mNativeBfCompiler, typeDefName)); + } + public void ClearBuildCache() { BfCompiler_ClearBuildCache(mNativeBfCompiler); diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index 48c1742c..7122641f 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -4417,7 +4417,8 @@ namespace IDE if (!mInitialized) return; #if !CLI - mLastActivePanel = panel; + if (setFocus) + mLastActivePanel = panel; RecordHistoryLocation(); ShowTab(panel, label, false, setFocus); if (setFocus) @@ -4580,7 +4581,7 @@ namespace IDE [IDECommand] public void ShowOutput() { - ShowPanel(mOutputPanel, "Output"); + ShowPanel(mOutputPanel, "Output", false); } [IDECommand] diff --git a/IDE/src/ScriptManager.bf b/IDE/src/ScriptManager.bf index f8010a4d..46b9719a 100644 --- a/IDE/src/ScriptManager.bf +++ b/IDE/src/ScriptManager.bf @@ -1513,6 +1513,17 @@ namespace IDE } } + [IDECommand] + public void AssertTypeInfo(int compilerId, String typeName, String wantTypeInfo) + { + String typeInfo = scope String(); + var compiler = (compilerId == 0) ? gApp.mBfResolveCompiler : gApp.mBfBuildCompiler; + compiler.GetTypeInfo(typeName, typeInfo); + + if (typeInfo != wantTypeInfo) + mScriptManager.Fail("Assert failed: {0} == {1}", typeInfo, wantTypeInfo); + } + [IDECommand] public void AddWatch(String evalStr) { diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 31e17b4d..e20630db 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -2052,6 +2052,8 @@ void BfCompiler::UpdateDependencyMap(bool deleteUnusued, bool& didWork) if ((mResolvePassData != NULL) && (mResolvePassData->mParser != NULL)) madeFullPass = false; + SetAndRestoreValue prevAssertOnPopulateType(mContext->mAssertOnPopulateType, deleteUnusued && madeFullPass); + if ((deleteUnusued) && (madeFullPass)) { // Work queues should be empty if we're not canceling @@ -2077,7 +2079,12 @@ void BfCompiler::UpdateDependencyMap(bool deleteUnusued, bool& didWork) auto typeInst = type->ToTypeInstance(); if (depType != NULL) - { + { + if ((depType->mTypeId == 2574) && (!mIsResolveOnly) && (deleteUnusued)) + { + NOP; + } + extern BfModule* gLastCreatedModule; for (auto itr = depType->mDependencyMap.begin(); itr != depType->mDependencyMap.end(); ++itr) @@ -2145,12 +2152,9 @@ void BfCompiler::UpdateDependencyMap(bool deleteUnusued, bool& didWork) if ((depTypeInst != NULL) && (typeInst->mLastNonGenericUsedRevision != mRevision) && (isDependentUsage) && ((isDirectReference) || (dependentType->IsUnspecializedType()) || (depTypeInst->mLastNonGenericUsedRevision == mRevision))) - { - //if (deleteUnusued) - { - typeInst->mLastNonGenericUsedRevision = mRevision; - foundNew = true; - } + { + typeInst->mLastNonGenericUsedRevision = mRevision; + foundNew = true; if (!typeInst->HasBeenReferenced()) { @@ -8250,6 +8254,92 @@ BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeDefInfo(BfCompiler* bfCompil return outString.c_str(); } +BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeInfo(BfCompiler* bfCompiler, const char* name) +{ + String& outString = *gTLStrReturn.Get(); + outString = ""; + + String typeName = name; + + auto system = bfCompiler->mSystem; + AutoCrit autoCrit(system->mSystemLock); + + String& autoCompleteResultString = *gTLStrReturn.Get(); + autoCompleteResultString.Clear(); + + BfPassInstance passInstance(bfCompiler->mSystem); + + BfParser parser(bfCompiler->mSystem); + parser.SetSource(typeName.c_str(), (int)typeName.length()); + parser.Parse(&passInstance); + + BfReducer reducer; + reducer.mAlloc = parser.mAlloc; + reducer.mPassInstance = &passInstance; + reducer.mAllowTypeWildcard = true; + + if (parser.mRootNode->mChildArr.mSize == 0) + return false; + + bool attribWasClosed = false; + bool isAttributeRef = false; + auto firstNode = parser.mRootNode->mChildArr[0]; + auto endIdx = parser.mRootNode->mSrcEnd; + reducer.mVisitorPos = BfReducer::BfVisitorPos(parser.mRootNode); + if (auto tokenNode = BfNodeDynCast(firstNode)) + { + if (tokenNode->mToken == BfToken_LBracket) + { + if (auto lastToken = BfNodeDynCast(parser.mRootNode->mChildArr.back())) + { + if (lastToken->mToken == BfToken_RBracket) + { + attribWasClosed = true; + endIdx = lastToken->mSrcStart; + } + } + + isAttributeRef = true; + if (parser.mRootNode->mChildArr.mSize < 2) + return false; + firstNode = parser.mRootNode->mChildArr[1]; + reducer.mVisitorPos.MoveNext(); + } + } + + reducer.mVisitorPos.MoveNext(); + auto typeRef = reducer.CreateTypeRef(firstNode); + if (typeRef == NULL) + return ""; + + BfResolvePassData resolvePass; + SetAndRestoreValue prevIgnoreError(bfCompiler->mContext->mScratchModule->mIgnoreErrors, true); + SetAndRestoreValue prevIgnoreWarnings(bfCompiler->mContext->mScratchModule->mIgnoreWarnings, true); + SetAndRestoreValue prevResolvePass(bfCompiler->mResolvePassData, &resolvePass); + + auto type = bfCompiler->mContext->mScratchModule->ResolveTypeRef(typeRef, BfPopulateType_Data, BfResolveTypeRefFlag_NoCreate); + if (type != NULL) + { + outString += "Found"; + if (auto typeInst = type->ToTypeInstance()) + { + if (typeInst->mIsReified) + outString += " Reified"; + if (typeInst->mHasBeenInstantiated) + outString += " Instantiated"; + if (typeInst->mTypeFailed) + outString += " TypeFailed"; + if (auto genericTypeInst = typeInst->ToGenericTypeInstance()) + { + if (genericTypeInst->mHadValidateErrors) + outString += " ValidateErrors"; + } + } + } + + return outString.c_str(); +} + BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetOutputFileNames(BfCompiler* bfCompiler, BfProject* bfProject, bool* hadOutputChanges) { BF_FATAL("not used ?"); diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index 6265abe7..1c1a184f 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -48,6 +48,7 @@ BfContext::BfContext(BfCompiler* compiler) : mCurTypeState = NULL; mCurConstraintState = NULL; mResolvingVarField = false; + mAssertOnPopulateType = false; for (int i = 0; i < BfTypeCode_Length; i++) { @@ -762,6 +763,8 @@ BfType * BfContext::FindTypeById(int typeId) void BfContext::AddTypeToWorkList(BfType* type) { + BF_ASSERT(!mAssertOnPopulateType); + BF_ASSERT((type->mRebuildFlags & BfTypeRebuildFlag_InTempPool) == 0); if ((type->mRebuildFlags & BfTypeRebuildFlag_AddedToWorkList) == 0) { @@ -1464,8 +1467,8 @@ void BfContext::DeleteType(BfType* type, bool deferDepRebuilds) } } } - } - + } + type->mRebuildFlags = (BfTypeRebuildFlags)((type->mRebuildFlags | BfTypeRebuildFlag_Deleted) & ~BfTypeRebuildFlag_DeleteQueued); SaveDeletingType(type); @@ -1530,6 +1533,19 @@ void BfContext::DeleteType(BfType* type, bool deferDepRebuilds) if ((dependencyEntry.mFlags & ~(BfDependencyMap::DependencyFlag_UnspecializedType | BfDependencyMap::DependencyFlag_WeakReference)) == 0) continue; // Not a cause for rebuilding + if (dependentTypeInst->IsOnDemand()) + { + // Force on-demand dependencies to rebuild themselves + DeleteType(dependentType, deferDepRebuilds); + continue; + } + + if (dType->IsBoxed()) + { + // Allow these to just be implicitly used. This solves some issues with switching between ignoreWrites settings in resolveOnly compilation + continue; + } + if ((deferDepRebuilds) && (dependentTypeInst != NULL)) mFailTypes.Add(dependentTypeInst); else diff --git a/IDEHelper/Compiler/BfContext.h b/IDEHelper/Compiler/BfContext.h index 08efa290..7b9bc332 100644 --- a/IDEHelper/Compiler/BfContext.h +++ b/IDEHelper/Compiler/BfContext.h @@ -317,6 +317,7 @@ public: BfConstraintState* mCurConstraintState; bool mResolvingVarField; int mMappedObjectRevision; + bool mAssertOnPopulateType; BfSystem* mSystem; BfCompiler* mCompiler; diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 7457de39..ceab1e28 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -1369,9 +1369,9 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst if (checkMethod->mMethodType == BfMethodType_Extension) { - argIdx--; - paramOfs++; + argIdx--; } + paramIdx += paramOfs; for ( ; argIdx < (int)mArguments.size(); argIdx++) { @@ -1845,7 +1845,8 @@ bool BfMethodMatcher::IsType(BfTypedValue& typedVal, BfType* type) // This method checks all base classes before checking interfaces. Is that correct? bool BfMethodMatcher::CheckType(BfTypeInstance* typeInstance, BfTypedValue target, bool isFailurePass, bool forceOuterCheck) -{ +{ + BfMethodDef* prevBesstMethodDef = mBestMethodDef; auto curTypeInst = typeInstance; auto curTypeDef = typeInstance->mTypeDef; @@ -2041,7 +2042,7 @@ bool BfMethodMatcher::CheckType(BfTypeInstance* typeInstance, BfTypedValue targe if (mAutoFlushAmbiguityErrors) FlushAmbiguityError(); - return mBestMethodDef != NULL; + return mBestMethodDef != prevBesstMethodDef; } void BfMethodMatcher::TryDevirtualizeCall(BfTypedValue target, BfTypedValue* origTarget, BfTypedValue* staticResult) @@ -7155,9 +7156,8 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp { auto checkTypeInst = mModule->mCurTypeInstance; methodMatcher.mMethodType = BfMethodType_Extension; - methodMatcher.CheckType(checkTypeInst, BfTypedValue(), false, true); - if (methodMatcher.mBestMethodDef != NULL) - { + if (methodMatcher.CheckType(checkTypeInst, BfTypedValue(), false, true)) + { isFailurePass = false; curTypeInst = methodMatcher.mBestMethodTypeInstance; methodDef = methodMatcher.mBestMethodDef; @@ -7178,9 +7178,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp if (globalContainer.mTypeInst == NULL) continue; methodMatcher.mMethodType = wantsExtensionCheck ? BfMethodType_Extension : BfMethodType_Normal; - methodMatcher.CheckType(globalContainer.mTypeInst, BfTypedValue(), false); - - if (methodMatcher.mBestMethodDef != NULL) + if (methodMatcher.CheckType(globalContainer.mTypeInst, BfTypedValue(), false)) { isFailurePass = false; curTypeInst = methodMatcher.mBestMethodTypeInstance; @@ -7202,8 +7200,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp for (auto typeInst : staticSearch->mStaticTypes) { methodMatcher.mMethodType = wantsExtensionCheck ? BfMethodType_Extension : BfMethodType_Normal; - methodMatcher.CheckType(typeInst, BfTypedValue(), false); - if (methodMatcher.mBestMethodDef != NULL) + if (methodMatcher.CheckType(typeInst, BfTypedValue(), false)) { isFailurePass = false; curTypeInst = methodMatcher.mBestMethodTypeInstance; @@ -11995,7 +11992,11 @@ void BfExprEvaluator::Visit(BfObjectCreateExpression* objCreateExpr) } else { - if ((!resolvedTypeRef->IsObjectOrInterface()) && (!resolvedTypeRef->IsGenericParam())) + if (resolvedTypeRef->IsVar()) + { + // Leave as a var + } + else if ((!resolvedTypeRef->IsObjectOrInterface()) && (!resolvedTypeRef->IsGenericParam())) { resultType = mModule->CreatePointerType(resolvedTypeRef); } diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 6d4f02ce..8fe434e7 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -2991,6 +2991,16 @@ void BfModule::AddDependency(BfType* usedType, BfType* userType, BfDependencyMap if (usedType->IsSpecializedByAutoCompleteMethod()) return; +// if (usedType->IsBoxed()) +// { +// NOP; +// auto underlyingType = usedType->GetUnderlyingType()->ToTypeInstance(); +// if ((underlyingType != NULL) && (underlyingType->IsInstanceOf(mCompiler->mSizedArrayTypeDef))) +// { +// BfLogSysM("AddDependency UsedType:%p UserType:%p Method:%p\n", usedType, userType, mCurMethodInstance); +// } +// } + BfType* origUsedType = usedType; bool isDataAccess = ((flags & (BfDependencyMap::DependencyFlag_ReadFields | BfDependencyMap::DependencyFlag_LocalUsage | BfDependencyMap::DependencyFlag_Allocates)) != 0); if (isDataAccess) @@ -18581,6 +18591,7 @@ BfModuleMethodInstance BfModule::GetLocalMethodInstance(BfLocalMethod* localMeth BF_ASSERT(methodInstance->mMethodInfoEx != NULL); methodState.mGenericTypeBindings = &methodInstance->mMethodInfoEx->mGenericTypeBindings; + methodState.mMethodInstance = methodInstance; NewScopeState(); ProcessMethod_SetupParams(methodInstance, NULL, false, NULL); diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 2f61cc25..3a534889 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1268,22 +1268,6 @@ public: String mName; }; -enum BfResolveTypeRefFlags -{ - BfResolveTypeRefFlag_None = 0, - BfResolveTypeRefFlag_NoResolveGenericParam = 1, - BfResolveTypeRefFlag_AllowRef = 2, - BfResolveTypeRefFlag_AllowRefGeneric = 4, - BfResolveTypeRefFlag_IgnoreLookupError = 8, - BfResolveTypeRefFlag_AllowGenericTypeParamConstValue = 0x10, - BfResolveTypeRefFlag_AllowGenericMethodParamConstValue = 0x20, - BfResolveTypeRefFlag_AllowGenericParamConstValue = 0x10 | 0x20, - BfResolveTypeRefFlag_AutoComplete = 0x40, - BfResolveTypeRefFlag_FromIndirectSource = 0x80, // Such as a type alias or a generic parameter - BfResolveTypeRefFlag_Attribute = 0x100, - BfResolveTypeRefFlag_NoReify = 0x200 -}; - enum BfSrcPosFlags { BfSrcPosFlag_None = 0, diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 425ef0b1..92d3a373 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -881,6 +881,11 @@ bool BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType else resolvedTypeRef->mTypeId = mCompiler->mCurTypeId++; + if ((resolvedTypeRef->mTypeId == 2599) && (!mCompiler->mIsResolveOnly)) + { + NOP; + } + while (resolvedTypeRef->mTypeId >= (int)mContext->mTypes.size()) mContext->mTypes.Add(NULL); mContext->mTypes[resolvedTypeRef->mTypeId] = resolvedTypeRef; @@ -3648,6 +3653,13 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) } } + bool isFailedType = mCurTypeInstance->mTypeFailed; + if (auto genericTypeInst = mCurTypeInstance->ToGenericTypeInstance()) + { + if (genericTypeInst->mHadValidateErrors) + isFailedType = true; + } + // Generate all methods. Pass 1 for (auto methodDef : typeDef->mMethods) { @@ -3656,6 +3668,12 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude) continue; + if (isFailedType) + { + // We don't want method decls from failed generic types to clog up our type system + continue; + } + // This should still be set to the default value BF_ASSERT(methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet); @@ -4014,7 +4032,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) mCompiler->mHotState->mHasNewInterfaceTypes = true; } - if ((!typeInstance->IsInterface()) && (!typeInstance->IsUnspecializedTypeVariation()) && (!isBoxed)) + if ((!typeInstance->IsInterface()) && (!typeInstance->IsUnspecializedTypeVariation()) && (!isBoxed) && (!isFailedType)) { if (!typeInstance->mTypeDef->mIsAbstract) { @@ -4542,6 +4560,8 @@ BfUnknownSizedArrayType* BfModule::CreateUnknownSizedArrayType(BfType* resolvedT BfPointerType* BfModule::CreatePointerType(BfType* resolvedType) { + BF_ASSERT(!resolvedType->IsVar()); + auto pointerType = mContext->mPointerTypePool.Get(); pointerType->mContext = mContext; pointerType->mElementType = resolvedType; @@ -6273,16 +6293,20 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy } if (resolvedTypeRef == NULL) - return NULL; + return NULL; - if (resolvedTypeRef->IsTuple()) + if (mCurTypeInstance == NULL) + { + // No deps + } + else if (resolvedTypeRef->IsTuple()) { // Add the fields from the tuple as references since those inner fields types would have been explicitly stated, so we need // to make sure to record the current type instance as a referring type. This mostly matters for symbol renaming. BfTupleType* payloadTupleType = (BfTupleType*)resolvedTypeRef; for (auto& payloadFieldInst : payloadTupleType->mFieldInstances) { - auto payloadFieldType = payloadFieldInst.mResolvedType; + auto payloadFieldType = payloadFieldInst.mResolvedType; AddDependency(payloadFieldType, mCurTypeInstance, BfDependencyMap::DependencyFlag_TypeReference); } } @@ -7408,7 +7432,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula if (leftType == NULL) { BfAutoParentNodeEntry autoParentNodeEntry(this, qualifiedTypeRef); - leftType = ResolveTypeRef(qualifiedTypeRef->mLeft, BfPopulateType_Declaration, BfResolveTypeRefFlag_IgnoreLookupError); // We throw an error below if we can't find the type + leftType = ResolveTypeRef(qualifiedTypeRef->mLeft, BfPopulateType_Identity, (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_IgnoreLookupError)); // We throw an error below if we can't find the type } if (leftType == NULL) @@ -7582,6 +7606,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula } BfResolvedTypeSet::LookupContext lookupCtx; + lookupCtx.mResolveFlags = (BfResolveTypeRefFlags)(resolveFlags & BfResolveTypeRefFlag_NoCreate); lookupCtx.mRootTypeRef = typeRef; lookupCtx.mRootTypeDef = typeDef; lookupCtx.mModule = this; @@ -7599,6 +7624,12 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula return ResolveTypeResult(typeRef, resolvedEntry->mValue, populateType, resolveFlags); } + if ((resolveFlags & BfResolveTypeRefFlag_NoCreate) != 0) + { + mContext->mResolvedTypes.RemoveEntry(resolvedEntry); + return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags); + } + BfModule* populateModule = this; if ((resolveFlags & BfResolveTypeRefFlag_NoReify) != 0) populateModule = mContext->mUnreifiedModule; @@ -9724,7 +9755,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp } // Check type generic constraints - if ((mCurTypeInstance->IsGenericTypeInstance()) && (mCurTypeInstance->IsUnspecializedType())) + if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsGenericTypeInstance()) && (mCurTypeInstance->IsUnspecializedType())) { auto genericTypeInst = (BfGenericTypeInstance*)mCurTypeInstance; for (int genericParamIdx = 0; genericParamIdx < genericTypeInst->mGenericParams.size(); genericParamIdx++) diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index c1ef340b..f0a97b9a 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -2335,7 +2335,7 @@ int BfResolvedTypeSet::DirectHash(BfTypeReference* typeRef, LookupContext* ctx, { bool isHeadType = typeRef == ctx->mRootTypeRef; - BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None; + BfResolveTypeRefFlags resolveFlags = ctx->mResolveFlags; if ((flags & BfHashFlag_AllowGenericParamConstValue) != 0) resolveFlags = (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_AllowGenericParamConstValue); @@ -2410,7 +2410,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash BfTypeVector genericArgs; for (auto genericArgTypeRef : genericInstTypeRef->mGenericArguments) { - auto argType = ctx->mModule->ResolveTypeRef(genericArgTypeRef, BfPopulateType_Identity); + auto argType = ctx->mModule->ResolveTypeRef(genericArgTypeRef, BfPopulateType_Identity, ctx->mResolveFlags); if (argType != NULL) genericArgs.Add(argType); else @@ -2602,7 +2602,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash } else { - ctx->mModule->ResolveTypeRef(typeRef); // To throw an error... + ctx->mModule->ResolveTypeRef(typeRef, BfPopulateType_Identity, ctx->mResolveFlags); // To throw an error... ctx->mFailed = true; return 0; //return Hash(refType->mElementType, ctx); @@ -2635,7 +2635,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash } return Hash(rightType, ctx);*/ - auto resolvedType = ctx->mModule->ResolveTypeRef(typeRef, BfPopulateType_Identity); + auto resolvedType = ctx->mModule->ResolveTypeRef(typeRef, BfPopulateType_Identity, ctx->mResolveFlags); if (resolvedType == NULL) { ctx->mFailed = true; @@ -2663,7 +2663,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash // Only use the HAS_RETTYPE for root-level rettype insertions if (ctx->mRootTypeRef != retTypeTypeRef) { - auto type = ctx->mModule->ResolveTypeRef(retTypeTypeRef); + auto type = ctx->mModule->ResolveTypeRef(retTypeTypeRef, BfPopulateType_Identity, ctx->mResolveFlags); return Hash(type, ctx, flags); } @@ -2750,7 +2750,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash } else if (auto dotTypeRef = BfNodeDynCastExact(typeRef)) { - ctx->mModule->ResolveTypeRef(dotTypeRef); + ctx->mModule->ResolveTypeRef(dotTypeRef, BfPopulateType_Identity, ctx->mResolveFlags); ctx->mFailed = true; return 0; } @@ -3016,7 +3016,7 @@ bool BfResolvedTypeSet::GenericTypeEquals(BfGenericTypeInstance* lhsGenericType, if (lhsGenericType->mTypeDef != ctx->mModule->mContext->mCompiler->mNullableTypeDef) return false; - auto rhsElemType = ctx->mModule->ResolveTypeRef(rhsNullableTypeRef->mElementType, BfPopulateType_Identity); + auto rhsElemType = ctx->mModule->ResolveTypeRef(rhsNullableTypeRef->mElementType, BfPopulateType_Identity, ctx->mResolveFlags); return lhsGenericType->mTypeGenericArguments[0] == rhsElemType; } } @@ -3046,7 +3046,7 @@ bool BfResolvedTypeSet::GenericTypeEquals(BfGenericTypeInstance* lhsGenericType, if (auto rhsQualifiedTypeRef = BfNodeDynCastExact(rhs)) { - auto rhsRightType = ctx->mModule->ResolveTypeRef(rhs, BfPopulateType_Identity); + auto rhsRightType = ctx->mModule->ResolveTypeRef(rhs, BfPopulateType_Identity, ctx->mResolveFlags); return rhsRightType == lhsGenericType; } diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 4eb61ead..d5a6ac08 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -16,6 +16,23 @@ class BfTypeInstance; class BfContext; class BfCustomAttributes; +enum BfResolveTypeRefFlags +{ + BfResolveTypeRefFlag_None = 0, + BfResolveTypeRefFlag_NoResolveGenericParam = 1, + BfResolveTypeRefFlag_AllowRef = 2, + BfResolveTypeRefFlag_AllowRefGeneric = 4, + BfResolveTypeRefFlag_IgnoreLookupError = 8, + BfResolveTypeRefFlag_AllowGenericTypeParamConstValue = 0x10, + BfResolveTypeRefFlag_AllowGenericMethodParamConstValue = 0x20, + BfResolveTypeRefFlag_AllowGenericParamConstValue = 0x10 | 0x20, + BfResolveTypeRefFlag_AutoComplete = 0x40, + BfResolveTypeRefFlag_FromIndirectSource = 0x80, // Such as a type alias or a generic parameter + BfResolveTypeRefFlag_Attribute = 0x100, + BfResolveTypeRefFlag_NoReify = 0x200, + BfResolveTypeRefFlag_NoCreate = 0x400 +}; + enum BfTypeNameFlags : uint16 { BfTypeNameFlags_None = 0, @@ -2348,16 +2365,18 @@ public: BfTypeReference* mRootTypeRef; BfTypeDef* mRootTypeDef; BfType* mResolvedType; + BfResolveTypeRefFlags mResolveFlags; bool mFailed; public: LookupContext() - { + { mRootTypeRef = NULL; mRootTypeDef = NULL; mModule = NULL; mResolvedType = NULL; mFailed = false; + mResolveFlags = BfResolveTypeRefFlag_None; } BfType* ResolveTypeRef(BfTypeReference* typeReference);