Explorar o código

Fixed bugs with type extensions

Brian Fiete %!s(int64=6) %!d(string=hai) anos
pai
achega
38a650fc2e

+ 7 - 0
IDEHelper/Compiler/BfAutoComplete.cpp

@@ -549,6 +549,13 @@ void BfAutoComplete::AddCurrentTypes(BfTypeInstance* typeInst, const StringImpl&
 	auto typeDef = typeInst->mTypeDef;
 	auto typeDef = typeInst->mTypeDef;
 	for (auto nestedTypeDef : typeDef->mNestedTypes)
 	for (auto nestedTypeDef : typeDef->mNestedTypes)
 	{
 	{
+		if (nestedTypeDef->mIsPartial)
+		{
+			nestedTypeDef = mSystem->GetCombinedPartial(nestedTypeDef);
+			if (nestedTypeDef == NULL)
+				continue;
+		}
+
 	 	if (CheckProtection(nestedTypeDef->mProtection, allowProtected, allowPrivate))
 	 	if (CheckProtection(nestedTypeDef->mProtection, allowProtected, allowPrivate))
 	 		AddTypeDef(nestedTypeDef, filter, onlyAttribute);
 	 		AddTypeDef(nestedTypeDef, filter, onlyAttribute);
 	}
 	}

+ 43 - 1
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -745,6 +745,18 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
 		int prevArgIdx = argIdx + prevImplicitParamCount;		
 		int prevArgIdx = argIdx + prevImplicitParamCount;		
 		_CompareParamTypes(newMethodInstance->GetParamType(newArgIdx), prevMethodInstance->GetParamType(prevArgIdx));
 		_CompareParamTypes(newMethodInstance->GetParamType(newArgIdx), prevMethodInstance->GetParamType(prevArgIdx));
 	}	
 	}	
+
+	// Do generic constraint subset test directly to handle cases like "NotDisposed<T>()" vs "NOtDisposed<T>() where T : IDisposable"
+	if ((newMethodInstance->GetNumGenericArguments() > 0) && (newMethodInstance->GetNumGenericArguments() == prevMethodInstance->GetNumGenericArguments()))
+	{
+		for (int genericParamIdx = 0; genericParamIdx < (int)newMethodInstance->GetNumGenericArguments(); genericParamIdx++)
+		{
+			auto newMethodGenericParam = newMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
+			auto prevMethodGenericParam = prevMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
+			SET_BETTER_OR_WORSE(mModule->AreConstraintsSubset(prevMethodGenericParam, newMethodGenericParam), mModule->AreConstraintsSubset(newMethodGenericParam, prevMethodGenericParam));
+		}
+	}
+	
 	if ((isBetter) || (isWorse))
 	if ((isBetter) || (isWorse))
 	{
 	{
 		RETURN_RESULTS;
 		RETURN_RESULTS;
@@ -782,7 +794,37 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
 		}
 		}
 	}
 	}
 
 
-	RETURN_BETTER_OR_WORSE(newMethodDef->mCheckedKind == mCheckedKind, prevMethodDef->mCheckedKind == mCheckedKind);
+	// If we have conditional type extensions that both define an implementation for a method, use the most-specific conditional extension constraints
+	auto owner = newMethodInstance->GetOwner();
+	if ((newMethodDef->mDeclaringType != prevMethodDef->mDeclaringType) && (owner->IsGenericTypeInstance()))
+	{
+		auto genericOwner = (BfGenericTypeInstance*)owner;
+		if (genericOwner->mGenericExtensionInfo != NULL)
+		{			
+			BfGenericExtensionEntry* newGenericExtesionEntry = NULL;
+			BfGenericExtensionEntry* prevGenericExtesionEntry = NULL;
+			if ((genericOwner->mGenericExtensionInfo->mExtensionMap.TryGetValue(newMethodDef->mDeclaringType, &newGenericExtesionEntry)) &&
+				(genericOwner->mGenericExtensionInfo->mExtensionMap.TryGetValue(prevMethodDef->mDeclaringType, &prevGenericExtesionEntry)))
+			{
+				if ((newGenericExtesionEntry->mGenericParams.size() == prevGenericExtesionEntry->mGenericParams.size()))
+				{
+					for (int genericParamIdx = 0; genericParamIdx < (int)newGenericExtesionEntry->mGenericParams.size(); genericParamIdx++)
+					{
+						auto newMethodGenericParam = newGenericExtesionEntry->mGenericParams[genericParamIdx];
+						auto prevMethodGenericParam = prevGenericExtesionEntry->mGenericParams[genericParamIdx];
+						SET_BETTER_OR_WORSE(mModule->AreConstraintsSubset(prevMethodGenericParam, newMethodGenericParam), mModule->AreConstraintsSubset(newMethodGenericParam, prevMethodGenericParam));
+					}
+				}
+
+				if ((isBetter) || (isWorse))
+				{
+					RETURN_RESULTS;
+				}
+			}
+		}
+	}
+
+	RETURN_BETTER_OR_WORSE(newMethodDef->mCheckedKind == mCheckedKind, prevMethodDef->mCheckedKind == mCheckedKind);	
 
 
 	RETURN_RESULTS;
 	RETURN_RESULTS;
 }
 }

+ 12 - 4
IDEHelper/Compiler/BfModuleTypeUtils.cpp

@@ -1502,6 +1502,10 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
 
 
 			for (auto baseTypeRef : typeDef->mBaseTypes)
 			for (auto baseTypeRef : typeDef->mBaseTypes)
 			{
 			{
+				SetAndRestoreValue<BfTypeReference*> prevTypeRef(mContext->mCurTypeState->mCurBaseTypeRef, baseTypeRef);				
+				SetAndRestoreValue<bool> prevIgnoreError(mIgnoreErrors, true);				
+				SetAndRestoreValue<bool> prevSkipTypeProtectionChecks(typeInstance->mSkipTypeProtectionChecks, true);
+
 				auto baseType = ResolveTypeRef(baseTypeRef, BfPopulateType_Declaration);
 				auto baseType = ResolveTypeRef(baseTypeRef, BfPopulateType_Declaration);
 				if (baseType != NULL)
 				if (baseType != NULL)
 				{
 				{
@@ -3811,6 +3815,10 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
 				if (ifaceMethodInst == NULL)
 				if (ifaceMethodInst == NULL)
 					continue;
 					continue;
 
 
+				// Don't even try to match generics
+				if (!ifaceMethodInst->mMethodDef->mGenericParams.IsEmpty())
+					continue;
+
 				auto iReturnType = ifaceMethodInst->mReturnType;
 				auto iReturnType = ifaceMethodInst->mReturnType;
 				if (iReturnType->IsSelf())
 				if (iReturnType->IsSelf())
 					iReturnType = typeInstance;
 					iReturnType = typeInstance;
@@ -3931,7 +3939,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
 							}
 							}
 						}
 						}
 
 
-						if ((bestMethodInst->mMethodDef->HasBody()) && (matchedMethod == NULL))
+						if ((bestMethodInst->mMethodDef->HasBody()) && (bestMethodInst->mMethodDef->mGenericParams.size() == 0) && (matchedMethod == NULL))
 						{
 						{
 							auto methodDef = bestMethodInst->mMethodDef;
 							auto methodDef = bestMethodInst->mMethodDef;
 							BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_ForeignMethodDef;
 							BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_ForeignMethodDef;
@@ -3939,10 +3947,10 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
 								flags = (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_UnspecializedPass);
 								flags = (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_UnspecializedPass);
 							auto methodInst = GetMethodInstance(typeInstance, methodDef, BfTypeVector(), flags, ifaceInst);
 							auto methodInst = GetMethodInstance(typeInstance, methodDef, BfTypeVector(), flags, ifaceInst);
 							if (methodInst)
 							if (methodInst)
-							{																	
+							{
 								*matchedMethodRef = methodInst.mMethodInstance;
 								*matchedMethodRef = methodInst.mMethodInstance;
 
 
-								BfMethodInstance* newMethodInstance = *matchedMethodRef;
+								BfMethodInstance* newMethodInstance = methodInst.mMethodInstance;
 								BF_ASSERT(newMethodInstance->mIsForeignMethodDef);					
 								BF_ASSERT(newMethodInstance->mIsForeignMethodDef);					
 								if (newMethodInstance->mMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference)
 								if (newMethodInstance->mMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference)
 									mOnDemandMethodCount++;
 									mOnDemandMethodCount++;
@@ -4053,7 +4061,7 @@ void BfModule::AddMethodToWorkList(BfMethodInstance* methodInstance)
 		return;
 		return;
 
 
 	BF_ASSERT(mCompiler->mCompileState != BfCompiler::CompileState_VData);
 	BF_ASSERT(mCompiler->mCompileState != BfCompiler::CompileState_VData);
-	if (methodInstance->mIsReified)
+	if ((methodInstance->mIsReified) && (!methodInstance->mIsUnspecialized))
 	{
 	{
 		BF_ASSERT(mCompiler->mCompileState != BfCompiler::CompileState_Unreified);
 		BF_ASSERT(mCompiler->mCompileState != BfCompiler::CompileState_Unreified);
 	}
 	}

+ 16 - 9
IDEHelper/Compiler/BfSystem.cpp

@@ -2925,21 +2925,28 @@ void BfSystem::FinishCompositePartial(BfTypeDef* compositeTypeDef)
 	VerifyTypeDef(nextRevision);
 	VerifyTypeDef(nextRevision);
 }
 }
 
 
+BfTypeDef* BfSystem::GetCombinedPartial(BfTypeDef* typeDef)
+{
+	if ((!typeDef->mIsPartial) || (typeDef->mIsCombinedPartial))
+		return typeDef;
+		
+	auto itr = mTypeDefs.TryGet(typeDef->mFullName);
+	do
+	{
+		BF_ASSERT(typeDef->mIsPartial);
+		typeDef = *itr;
+		itr.MoveToNextHashMatch();
+	} while (!typeDef->mIsCombinedPartial);
+	return typeDef;
+}
+
 BfTypeDef* BfSystem::GetOuterTypeNonPartial(BfTypeDef* typeDef)
 BfTypeDef* BfSystem::GetOuterTypeNonPartial(BfTypeDef* typeDef)
 {
 {
 	auto checkType = typeDef->mOuterType;
 	auto checkType = typeDef->mOuterType;
 	if ((checkType == NULL) || (!checkType->mIsPartial))
 	if ((checkType == NULL) || (!checkType->mIsPartial))
 		return checkType;
 		return checkType;
 
 
-	auto itr = mTypeDefs.TryGet(checkType->mFullName);
-	do 
-	{
-		BF_ASSERT(checkType->mIsPartial);
-		checkType = *itr;
-		itr.MoveToNextHashMatch();
-	} 
-	while (!checkType->mIsCombinedPartial);		
-	return checkType;
+	return GetCombinedPartial(checkType);	
 }
 }
 
 
 int BfSystem::GetGenericParamIdx(const Array<BfGenericParamDef*>& genericParams, const StringImpl& name)
 int BfSystem::GetGenericParamIdx(const Array<BfGenericParamDef*>& genericParams, const StringImpl& name)

+ 3 - 1
IDEHelper/Compiler/BfSystem.h

@@ -1300,8 +1300,10 @@ public:
 	bool ContainsNamespace(const BfAtomComposite& namespaceStr, BfProject* bfProject);	
 	bool ContainsNamespace(const BfAtomComposite& namespaceStr, BfProject* bfProject);	
 	void InjectNewRevision(BfTypeDef* typeDef);
 	void InjectNewRevision(BfTypeDef* typeDef);
 	void AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* compositeTypeDef, BfTypeDef* partialTypeDef);
 	void AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* compositeTypeDef, BfTypeDef* partialTypeDef);
-	void FinishCompositePartial(BfTypeDef* compositeTypeDef);
+	void FinishCompositePartial(BfTypeDef* compositeTypeDef);	
+	BfTypeDef* GetCombinedPartial(BfTypeDef* typeDef);
 	BfTypeDef* GetOuterTypeNonPartial(BfTypeDef* typeDef);
 	BfTypeDef* GetOuterTypeNonPartial(BfTypeDef* typeDef);
+	
 
 
 	int GetGenericParamIdx(const Array<BfGenericParamDef*>& genericParams, const StringImpl& name);
 	int GetGenericParamIdx(const Array<BfGenericParamDef*>& genericParams, const StringImpl& name);
 	int GetGenericParamIdx(const Array<BfGenericParamDef*>& genericParams, BfTypeReference* typeRef);
 	int GetGenericParamIdx(const Array<BfGenericParamDef*>& genericParams, BfTypeReference* typeRef);