From 29446404b6d858ecf7c06238b35131545385a3e2 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Fri, 13 May 2022 09:43:26 -0700 Subject: [PATCH] Better emitted interface conformance, reified WorkList handling fix --- IDEHelper/Compiler/BfCompiler.cpp | 4 +- IDEHelper/Compiler/BfModule.cpp | 4 +- IDEHelper/Compiler/BfModule.h | 5 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 65 ++++++++++++++++-------- IDEHelper/Compiler/BfResolvedTypeUtils.h | 5 +- 5 files changed, 55 insertions(+), 28 deletions(-) diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index d73277eb..bfc0127d 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -6757,7 +6757,7 @@ void BfCompiler::CompileReified() if (typeInst->mIsReified) continue; - mContext->mUnreifiedModule->PopulateType(typeInst, BfPopulateType_Interfaces); + mContext->mUnreifiedModule->PopulateType(typeInst, BfPopulateType_Interfaces_Direct); if (typeInst->mCustomAttributes == NULL) continue; @@ -7257,6 +7257,8 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) } ProcessPurgatory(true); + if (mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude) + DoWorkLoop(); // Mark used modules if ((mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude) && (!mCanceling)) diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 4b859698..892bf15d 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -7786,7 +7786,7 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar { if (bfAutocomplete != NULL) bfAutocomplete->CheckTypeRef(opConstraint->mLeftType, false); - opConstraintInstance.mLeftType = ResolveTypeRef(opConstraint->mLeftType, BfPopulateType_Interfaces); + opConstraintInstance.mLeftType = ResolveTypeRef(opConstraint->mLeftType, BfPopulateType_Interfaces_All); if (opConstraintInstance.mLeftType == NULL) continue; } @@ -7801,7 +7801,7 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar { if (bfAutocomplete != NULL) bfAutocomplete->CheckTypeRef(opConstraint->mRightType, false); - opConstraintInstance.mRightType = ResolveTypeRef(opConstraint->mRightType, BfPopulateType_Interfaces); + opConstraintInstance.mRightType = ResolveTypeRef(opConstraint->mRightType, BfPopulateType_Interfaces_All); if (opConstraintInstance.mRightType == NULL) continue; } diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index b61ec09c..f2380503 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -38,14 +38,15 @@ class CeDbgState; enum BfCeTypeEmitSourceKind : int8; enum BfPopulateType -{ +{ BfPopulateType_TypeDef, BfPopulateType_Identity, BfPopulateType_IdentityNoRemapAlias, BfPopulateType_Declaration, BfPopulateType_BaseType, - BfPopulateType_Interfaces, + BfPopulateType_Interfaces_Direct, BfPopulateType_AllowStaticMethods, + BfPopulateType_Interfaces_All, BfPopulateType_Data, BfPopulateType_DataAndMethods, BfPopulateType_Full = BfPopulateType_DataAndMethods, diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 77bab66f..5e2e7635 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -409,7 +409,7 @@ bool BfModule::ValidateGenericConstraints(BfAstNode* typeRef, BfTypeInstance* ge SetAndRestoreValue prevIgnoreErrors(mIgnoreErrors, mIgnoreErrors || ignoreErrors); genericTypeInst->mGenericTypeInfo->mValidatedGenericConstraints = true; if (!genericTypeInst->mGenericTypeInfo->mFinishedGenericParams) - PopulateType(genericTypeInst, BfPopulateType_Interfaces); + PopulateType(genericTypeInst, BfPopulateType_Interfaces_All); if (genericTypeInst->IsTypeAlias()) { @@ -549,8 +549,8 @@ bool BfModule::AreConstraintsSubset(BfGenericParamInstance* checkInner, BfGeneri { if (!checkOuter->mInterfaceConstraintSet->Add(ifaceType)) return; - if (ifaceType->mDefineState < BfTypeDefineState_HasInterfaces) - PopulateType(ifaceType); + if (ifaceType->mDefineState < BfTypeDefineState_HasInterfaces_Direct) + PopulateType(ifaceType, Beefy::BfPopulateType_Interfaces_Direct); for (auto& ifaceEntry : ifaceType->mInterfaces) _AddInterface(ifaceEntry.mInterfaceType); }; @@ -1188,7 +1188,7 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType { canFastReify = true; for (auto ownedTypes : typeModule->mOwnedTypeInstances) - if (ownedTypes->mDefineState > BfTypeDefineState_HasInterfaces) + if (ownedTypes->mDefineState > BfTypeDefineState_HasInterfaces_Direct) canFastReify = false; } @@ -3450,9 +3450,21 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy if ((populateType >= BfPopulateType_Identity) && (populateType <= BfPopulateType_IdentityNoRemapAlias)) return; - if ((populateType <= BfPopulateType_AllowStaticMethods) && (typeInstance->mDefineState >= BfTypeDefineState_HasInterfaces)) + if ((populateType <= BfPopulateType_AllowStaticMethods) && (typeInstance->mDefineState >= BfTypeDefineState_HasInterfaces_Direct)) return; + // During CE init we need to avoid interface checking loops, so we only allow show direct interface declarations + if ((populateType == BfPopulateType_Interfaces_All) && (typeInstance->mDefineState >= Beefy::BfTypeDefineState_CETypeInit)) + { + if ((typeInstance->mDefineState == Beefy::BfTypeDefineState_CEPostTypeInit) && (typeInstance->mCeTypeInfo != NULL) && + (!typeInstance->mCeTypeInfo->mPendingInterfaces.IsEmpty())) + { + // We have finished CETypeInit and we have pending interfaces we need to apply + } + else + return; + } + if (!mCompiler->EnsureCeUnpaused(resolvedTypeRef)) { // We need to avoid comptime reentry when the ceDebugger is paused @@ -4230,7 +4242,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy } if ((mCompiler->mOptions.mAllowHotSwapping) && - (typeInstance->mDefineState < BfTypeDefineState_HasInterfaces) && + (typeInstance->mDefineState < BfTypeDefineState_HasInterfaces_Direct) && (typeInstance->mDefineState != BfTypeDefineState_ResolvingBaseType)) { if (typeInstance->mHotTypeData == NULL) @@ -4268,8 +4280,8 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy } BF_ASSERT(!typeInstance->mNeedsMethodProcessing); - if (typeInstance->mDefineState < BfTypeDefineState_HasInterfaces) - typeInstance->mDefineState = BfTypeDefineState_HasInterfaces; + if (typeInstance->mDefineState < BfTypeDefineState_HasInterfaces_Direct) + typeInstance->mDefineState = BfTypeDefineState_HasInterfaces_Direct; for (auto& validateEntry : deferredTypeValidateList) { @@ -4841,6 +4853,10 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy } } + // Type now has interfaces added from CEInit + if (typeInstance->mDefineState < BfTypeDefineState_HasInterfaces_All) + typeInstance->mDefineState = BfTypeDefineState_HasInterfaces_All; + if (_CheckTypeDone()) return; @@ -11527,7 +11543,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula BfTypeReference* elementTypeRef = nullableTypeRef->mElementType; auto typeDef = mCompiler->mNullableTypeDef; - auto elementType = ResolveTypeRef(elementTypeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowGenericParamConstValue); + auto elementType = ResolveTypeRef(elementTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_AllowGenericParamConstValue); if ((elementType == NULL) || (elementType->IsVar())) { mContext->mResolvedTypes.RemoveEntry(resolvedEntry); @@ -11561,7 +11577,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula else if (auto pointerTypeRef = BfNodeDynCast(typeRef)) { BfPointerType* pointerType = new BfPointerType(); - auto elementType = ResolveTypeRef(pointerTypeRef->mElementType, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowGenericParamConstValue); + auto elementType = ResolveTypeRef(pointerTypeRef->mElementType, BfPopulateType_Identity, BfResolveTypeRefFlag_AllowGenericParamConstValue); if ((elementType == NULL) || (elementType->IsVar())) { delete pointerType; @@ -11592,7 +11608,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula refType->mRefKind = BfRefType::RefKind_Out; else if (refTypeRef->mRefToken->GetToken() == BfToken_Mut) refType->mRefKind = BfRefType::RefKind_Mut; - auto elementType = ResolveTypeRef(refTypeRef->mElementType, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowGenericParamConstValue); + auto elementType = ResolveTypeRef(refTypeRef->mElementType, BfPopulateType_Identity, BfResolveTypeRefFlag_AllowGenericParamConstValue); if ((elementType == NULL) || (elementType->IsVar())) { delete refType; @@ -14289,7 +14305,7 @@ bool BfModule::TypeIsSubTypeOf(BfTypeInstance* srcType, BfTypeInstance* wantType if (srcType == wantType) return true; - if (srcType->mDefineState < BfTypeDefineState_HasInterfaces) + if (srcType->mDefineState < BfTypeDefineState_HasInterfaces_Direct) { if (srcType->mDefineState == BfTypeDefineState_ResolvingBaseType) { @@ -14306,12 +14322,15 @@ bool BfModule::TypeIsSubTypeOf(BfTypeInstance* srcType, BfTypeInstance* wantType // Type is incomplete. We don't do the IsIncomplete check here because of re-entry // While handling 'var' resolution, we don't want to force a PopulateType reentry - // but we do have enough information for TypeIsSubTypeOf - PopulateType(srcType, BfPopulateType_Interfaces); + // but we do have enough information for TypeIsSubTypeOf + PopulateType(srcType, BfPopulateType_Interfaces_Direct); } if (wantType->IsInterface()) { + if (wantType->mDefineState < BfTypeDefineState_HasInterfaces_All) + PopulateType(srcType, BfPopulateType_Interfaces_All); + BfTypeDef* checkActiveTypeDef = NULL; bool checkAccessibility = true; if (IsInSpecializedSection()) @@ -14352,9 +14371,10 @@ bool BfModule::TypeIsSubTypeOf(BfTypeInstance* srcType, BfTypeInstance* wantType } } checkType = checkType->GetImplBaseType(); - if ((checkType != NULL) && (checkType->mDefineState < BfTypeDefineState_HasInterfaces)) - { - PopulateType(checkType, BfPopulateType_Interfaces); + if ((checkType != NULL) && (checkType->mDefineState < BfTypeDefineState_CETypeInit)) + { + // We check BfTypeDefineState_CETypeInit so we don't cause a populate loop during interface checking during CETypeInit + PopulateType(checkType, BfPopulateType_Interfaces_All); } } @@ -14383,7 +14403,7 @@ bool BfModule::TypeIsSubTypeOf(BfTypeInstance* srcType, BfTypeDef* wantType) if (srcType->IsInstanceOf(wantType)) return true; - if (srcType->mDefineState < BfTypeDefineState_HasInterfaces) + if (srcType->mDefineState < BfTypeDefineState_HasInterfaces_Direct) { if (srcType->mDefineState == BfTypeDefineState_ResolvingBaseType) { @@ -14401,11 +14421,14 @@ bool BfModule::TypeIsSubTypeOf(BfTypeInstance* srcType, BfTypeDef* wantType) // Type is incomplete. We don't do the IsIncomplete check here because of re-entry // While handling 'var' resolution, we don't want to force a PopulateType reentry // but we do have enough information for TypeIsSubTypeOf - PopulateType(srcType, BfPopulateType_Interfaces); + PopulateType(srcType, BfPopulateType_Interfaces_Direct); } if (wantType->mTypeCode == BfTypeCode_Interface) { + if (srcType->mDefineState < BfTypeDefineState_HasInterfaces_All) + PopulateType(srcType, BfPopulateType_Interfaces_All); + BfTypeDef* checkActiveTypeDef = NULL; auto checkType = srcType; @@ -14417,9 +14440,9 @@ bool BfModule::TypeIsSubTypeOf(BfTypeInstance* srcType, BfTypeDef* wantType) return true; } checkType = checkType->GetImplBaseType(); - if ((checkType != NULL) && (checkType->mDefineState < BfTypeDefineState_HasInterfaces)) + if ((checkType != NULL) && (checkType->mDefineState < BfTypeDefineState_HasInterfaces_All)) { - PopulateType(checkType, BfPopulateType_Interfaces); + PopulateType(checkType, BfPopulateType_Interfaces_All); } } diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index b94ccfcd..9e65c9cf 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -456,9 +456,10 @@ enum BfTypeDefineState : uint8 BfTypeDefineState_Declaring, BfTypeDefineState_Declared, BfTypeDefineState_ResolvingBaseType, - BfTypeDefineState_HasInterfaces, + BfTypeDefineState_HasInterfaces_Direct, BfTypeDefineState_CETypeInit, BfTypeDefineState_CEPostTypeInit, + BfTypeDefineState_HasInterfaces_All, BfTypeDefineState_Defined, BfTypeDefineState_CEAfterFields, BfTypeDefineState_DefinedAndMethodsSlotting, @@ -2122,7 +2123,7 @@ public: bool IsAlwaysInclude(); bool HasBeenInstantiated() { return mHasBeenInstantiated || ((mAlwaysIncludeFlags & BfAlwaysIncludeFlag_AssumeInstantiated) != 0); } bool IncludeAllMethods() { return ((mAlwaysIncludeFlags & BfAlwaysIncludeFlag_IncludeAllMethods) != 0); } - bool DefineStateAllowsStaticMethods() { return mDefineState >= BfTypeDefineState_HasInterfaces; } + bool DefineStateAllowsStaticMethods() { return mDefineState >= BfTypeDefineState_HasInterfaces_Direct; } virtual void ReportMemory(MemReporter* memReporter) override; };