瀏覽代碼

Improvements to multi-extension virtual overrides

Brian Fiete 3 年之前
父節點
當前提交
cbc4888853

+ 8 - 0
IDEHelper/Backend/BeIRCodeGen.cpp

@@ -2647,6 +2647,14 @@ void BeIRCodeGen::HandleNextCmd()
 			func->mName += StrFormat("__RENAME%d", curId);
 		}
 		break;
+	case BfIRCmd_Func_SafeRenameFrom:
+		{
+			CMD_PARAM(BeFunction*, func);
+			CMD_PARAM(String, prevName);
+			if (func->mName == prevName)
+				func->mName += StrFormat("__RENAME%d", curId);
+		}
+		break;
 	case BfIRCmd_Func_SetLinkage:
 		{
 			CMD_PARAM(BeFunction*, func);

+ 46 - 6
IDEHelper/Compiler/BfCompiler.cpp

@@ -5827,13 +5827,53 @@ void BfCompiler::PopulateReified()
 
 						if ((declaringMethod->mIsReified) && (declaringMethod->mMethodInstanceGroup->IsImplemented()))
 						{
-							BfMethodInstance* implMethod = vEntry.mImplementingMethod;
-							if ((implMethod != NULL) && ((!implMethod->mMethodInstanceGroup->IsImplemented()) || (!implMethod->mIsReified)))
+							if (vEntry.mImplementingMethod.mKind == BfMethodRefKind_AmbiguousRef)
 							{
-								didWork = true;
-								if (!typeInst->mModule->mIsModuleMutable)
-									typeInst->mModule->StartExtension();
-								typeInst->mModule->GetMethodInstance(implMethod);
+								auto checkTypeInst = typeInst;
+
+								while (checkTypeInst != NULL)
+								{
+									BfMemberSetEntry* memberSetEntry;
+									if (checkTypeInst->mTypeDef->mMethodSet.TryGetWith(String(declaringMethod->mMethodDef->mName), &memberSetEntry))
+									{
+										BfMethodDef* methodDef = (BfMethodDef*)memberSetEntry->mMemberDef;
+										while (methodDef != NULL)
+										{
+											if ((methodDef->mIsOverride) && (methodDef->mParams.mSize == declaringMethod->mMethodDef->mParams.mSize))
+											{
+												auto implMethod = typeInst->mModule->GetRawMethodInstance(typeInst, methodDef);
+												if (typeInst->mModule->CompareMethodSignatures(declaringMethod, implMethod))
+												{
+													if ((implMethod != NULL) && ((!implMethod->mMethodInstanceGroup->IsImplemented()) || (!implMethod->mIsReified)))
+													{
+														didWork = true;
+														if (!typeInst->mModule->mIsModuleMutable)
+															typeInst->mModule->StartExtension();
+														typeInst->mModule->GetMethodInstance(implMethod);
+													}
+												}
+											}
+											
+											methodDef = methodDef->mNextWithSameName;
+										}
+									}
+
+									if (checkTypeInst == declaringMethod->GetOwner())
+										break;
+
+									checkTypeInst = checkTypeInst->mBaseType;
+								}
+							}
+							else
+							{
+								BfMethodInstance* implMethod = vEntry.mImplementingMethod;
+								if ((implMethod != NULL) && ((!implMethod->mMethodInstanceGroup->IsImplemented()) || (!implMethod->mIsReified)))
+								{
+									didWork = true;
+									if (!typeInst->mModule->mIsModuleMutable)
+										typeInst->mModule->StartExtension();
+									typeInst->mModule->GetMethodInstance(implMethod);
+								}
 							}
 						}
 					}

+ 2 - 2
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -2928,7 +2928,7 @@ void BfMethodMatcher::TryDevirtualizeCall(BfTypedValue target, BfTypedValue* ori
 
 						bool isBetter;
 						bool isWorse;
-						mModule->CompareDeclTypes(iface.mDeclaringType, bestIFaceEntry->mDeclaringType, isBetter, isWorse);						
+						mModule->CompareDeclTypes(NULL, iface.mDeclaringType, bestIFaceEntry->mDeclaringType, isBetter, isWorse);						
 						if (isBetter == isWorse)
 						{
 							// Failed
@@ -18669,7 +18669,7 @@ BfModuleMethodInstance BfExprEvaluator::GetPropertyMethodInstance(BfMethodDef* m
 
 						bool isBetter;
 						bool isWorse;
-						mModule->CompareDeclTypes(iface.mDeclaringType, bestIFaceEntry->mDeclaringType, isBetter, isWorse);						
+						mModule->CompareDeclTypes(NULL, iface.mDeclaringType, bestIFaceEntry->mDeclaringType, isBetter, isWorse);						
 						if (isBetter == isWorse)
 						{
 							// Failed

+ 6 - 0
IDEHelper/Compiler/BfIRBuilder.cpp

@@ -5547,6 +5547,12 @@ void BfIRBuilder::Func_SafeRename(BfIRFunction func)
 	NEW_CMD_INSERTED;
 }
 
+void BfIRBuilder::Func_SafeRenameFrom(BfIRFunction func, const StringImpl& prevName)
+{
+	WriteCmd(BfIRCmd_Func_SafeRenameFrom, func, prevName);
+	NEW_CMD_INSERTED;
+}
+
 void BfIRBuilder::Func_SetLinkage(BfIRFunction func, BfIRLinkageType linkage)
 {
 	WriteCmd(BfIRCmd_Func_SetLinkage, func, (uint8)linkage);

+ 2 - 0
IDEHelper/Compiler/BfIRBuilder.h

@@ -299,6 +299,7 @@ enum BfIRCmd : uint8
 	BfIRCmd_Func_SetParamName,	
 	BfIRCmd_Func_DeleteBody,
 	BfIRCmd_Func_SafeRename,
+	BfIRCmd_Func_SafeRenameFrom,
 	BfIRCmd_Func_SetLinkage,
 
 	BfIRCmd_Comptime_Error,
@@ -1336,6 +1337,7 @@ public:
 	void Func_SetParamName(BfIRFunction func, int argIdx, const StringImpl& name);	
 	void Func_DeleteBody(BfIRFunction func);
 	void Func_SafeRename(BfIRFunction func);
+	void Func_SafeRenameFrom(BfIRFunction func, const StringImpl& prevName);
 	void Func_SetLinkage(BfIRFunction func, BfIRLinkageType linkage);
 	
 	void Comptime_Error(int errorKind);

+ 8 - 0
IDEHelper/Compiler/BfIRCodeGen.cpp

@@ -3997,6 +3997,14 @@ void BfIRCodeGen::HandleNextCmd()
 			func->setName(llvm::Twine((Beefy::String(func->getName().data()) + StrFormat("__RENAME%d", curId)).c_str()));
 		}
 		break;
+	case BfIRCmd_Func_SafeRenameFrom:
+		{
+			CMD_PARAM(llvm::Function*, func);
+			CMD_PARAM(String, prevName);
+			if (String(func->getName().data()) == prevName)
+				func->setName(llvm::Twine((Beefy::String(func->getName().data()) + StrFormat("__RENAME%d", curId)).c_str()));
+		}
+		break;
 	case BfIRCmd_Func_SetLinkage:
 		{
 			CMD_PARAM(llvm::Function*, func);

+ 35 - 9
IDEHelper/Compiler/BfModule.cpp

@@ -6283,7 +6283,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 						isWorse = false;
 					}
 					if (isBetter == isWorse)								
-						CompareDeclTypes(interfaceEntry.mDeclaringType, prevEntry->mDeclaringType, isBetter, isWorse);
+						CompareDeclTypes(checkTypeInst, interfaceEntry.mDeclaringType, prevEntry->mDeclaringType, isBetter, isWorse);
 					if (isBetter == isWorse)
 					{
 						if (matchEntry->mAmbiguousEntries.empty())
@@ -18675,7 +18675,7 @@ void BfModule::CallChainedMethods(BfMethodInstance* methodInstance, bool reverse
 		{
 			bool isBetter;
 			bool isWorse;
-			CompareDeclTypes(lhs->mMethodDef->mDeclaringType, rhs->mMethodDef->mDeclaringType, isBetter, isWorse);
+			CompareDeclTypes(mCurTypeInstance, lhs->mMethodDef->mDeclaringType, rhs->mMethodDef->mDeclaringType, isBetter, isWorse);
 			if (isBetter == isWorse)
 			{
 				return false;
@@ -22975,7 +22975,7 @@ void BfModule::SetupIRFunction(BfMethodInstance* methodInstance, StringImpl& man
 				{
 					BfLogSysM("Function collision from inner override erased prevFunc %p: %d\n", methodInstance, prevFunc.mId);
 					if (!mIsComptimeModule)
-						mBfIRBuilder->Func_SafeRename(prevFunc);
+						mBfIRBuilder->Func_SafeRenameFrom(prevFunc, mangledName);
 				}
 			}
 			else if (methodDef->mIsExtern)
@@ -23000,7 +23000,7 @@ void BfModule::SetupIRFunction(BfMethodInstance* methodInstance, StringImpl& man
 			{
 				BfLogSysM("Function collision erased prevFunc %p: %d\n", methodInstance, prevFunc.mId);
 				if (!mIsComptimeModule)
-					mBfIRBuilder->Func_SafeRename(prevFunc);
+					mBfIRBuilder->Func_SafeRenameFrom(prevFunc, mangledName);
 			}
 		}
 	}
@@ -24387,7 +24387,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
 					{
 						bool isBetter;
 						bool isWorse;
-						CompareDeclTypes(checkMethodInstance->mMethodDef->mDeclaringType, methodInstance->mMethodDef->mDeclaringType, isBetter, isWorse);
+						CompareDeclTypes(typeInstance, checkMethodInstance->mMethodDef->mDeclaringType, methodInstance->mMethodDef->mDeclaringType, isBetter, isWorse);
 						if (isBetter && !isWorse)
 						{
 							methodInstance->mChainType = BfMethodChainType_ChainHead;
@@ -24634,7 +24634,7 @@ void BfModule::UniqueSlotVirtualMethod(BfMethodInstance* methodInstance)
 	}
 }
 
-void BfModule::CompareDeclTypes(BfTypeDef* newDeclType, BfTypeDef* prevDeclType, bool& isBetter, bool& isWorse)
+void BfModule::CompareDeclTypes(BfTypeInstance* typeInst, BfTypeDef* newDeclType, BfTypeDef* prevDeclType, bool& isBetter, bool& isWorse)
 {	
 	if ((!prevDeclType->IsExtension()) && (newDeclType->IsExtension()))
 	{
@@ -24646,7 +24646,33 @@ void BfModule::CompareDeclTypes(BfTypeDef* newDeclType, BfTypeDef* prevDeclType,
 	{
 		isBetter = newDeclType->mProject->ContainsReference(prevDeclType->mProject);
 		isWorse = prevDeclType->mProject->ContainsReference(newDeclType->mProject);				
-	}			
+	}
+
+	if ((isBetter == isWorse) && (typeInst != NULL) && (newDeclType->IsExtension()) && (prevDeclType->IsExtension()))
+	{
+		if ((typeInst->mGenericTypeInfo != NULL) && (typeInst->mGenericTypeInfo->mGenericExtensionInfo != NULL))
+		{
+			isBetter = false;
+			isWorse = false;
+
+			auto newConstraints = typeInst->GetGenericParamsVector(newDeclType);
+			auto prevConstraints = typeInst->GetGenericParamsVector(prevDeclType);
+
+			for (int genericIdx = 0; genericIdx < (int)newConstraints->size(); genericIdx++)
+			{
+				auto newConstraint = (*newConstraints)[genericIdx];
+				auto prevConstraint = (*prevConstraints)[genericIdx];
+
+				bool newIsSubset = AreConstraintsSubset(newConstraint, prevConstraint);
+				bool prevIsSubset = AreConstraintsSubset(prevConstraint, newConstraint);
+
+				if ((prevIsSubset) && (!newIsSubset))
+					isBetter = true;
+				if ((!prevIsSubset) && (newIsSubset))
+					isWorse = true;
+			}
+		}
+	}
 }
 
 bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityContext* ambiguityContext)
@@ -25028,7 +25054,7 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
 						{
 							bool isBetter = false;
 							bool isWorse = false;
-							CompareDeclTypes(methodInstance->mMethodDef->mDeclaringType, methodOverriden->mMethodDef->mDeclaringType, isBetter, isWorse);
+							CompareDeclTypes(typeInstance, methodInstance->mMethodDef->mDeclaringType, methodOverriden->mMethodDef->mDeclaringType, isBetter, isWorse);
 							if (isBetter == isWorse)
 							{
 								// We have to resolve later per-project
@@ -25250,7 +25276,7 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
 					isBetter = (methodInstance->mMethodInfoEx != NULL) && (methodInstance->mMethodInfoEx->mExplicitInterface != NULL);
 					isWorse = (prevMethod->mMethodInfoEx != NULL) && (prevMethod->mMethodInfoEx->mExplicitInterface != NULL);
 					if (isBetter == isWorse)
-						CompareDeclTypes(methodInstance->mMethodDef->mDeclaringType, prevMethod->mMethodDef->mDeclaringType, isBetter, isWorse);
+						CompareDeclTypes(typeInstance, methodInstance->mMethodDef->mDeclaringType, prevMethod->mMethodDef->mDeclaringType, isBetter, isWorse);
 					if (isBetter == isWorse)
 					{
 						if (ambiguityContext != NULL)

+ 1 - 1
IDEHelper/Compiler/BfModule.h

@@ -2027,7 +2027,7 @@ public:
 	bool StrictCompareMethodSignatures(BfMethodInstance* methodA, BfMethodInstance* methodB); // Compares return types and static
 	bool IsCompatibleInterfaceMethod(BfMethodInstance* methodA, BfMethodInstance* methodB);
 	void UniqueSlotVirtualMethod(BfMethodInstance* methodInstance);	
-	void CompareDeclTypes(BfTypeDef* newDeclType, BfTypeDef* prevDeclType, bool& isBetter, bool& isWorse);
+	void CompareDeclTypes(BfTypeInstance* typeInst, BfTypeDef* newDeclType, BfTypeDef* prevDeclType, bool& isBetter, bool& isWorse);
 	bool SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityContext* ambiguityContext = NULL);	
 	void CheckOverridenMethod(BfMethodInstance* methodInstance, BfMethodInstance* methodOverriden);
 	bool SlotInterfaceMethod(BfMethodInstance* methodInstance);	

+ 1 - 1
IDEHelper/Compiler/BfModuleTypeUtils.cpp

@@ -6786,7 +6786,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
 											bool isWorse = TypeIsSubTypeOf(bestInterface, checkIFaceInst);
 											if (isBetter == isWorse)
 											{
-												CompareDeclTypes(checkIFaceMethodInst->mMethodDef->mDeclaringType, bestMethodInst->mMethodDef->mDeclaringType, isBetter, isWorse);
+												CompareDeclTypes(NULL, checkIFaceMethodInst->mMethodDef->mDeclaringType, bestMethodInst->mMethodDef->mDeclaringType, isBetter, isWorse);
 											}
 											if ((isBetter) && (!isWorse))
 											{