Procházet zdrojové kódy

Fix for generic constraints checking with mixins

Brian Fiete před 5 roky
rodič
revize
1e7bd7d43f

+ 25 - 0
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -13286,6 +13286,31 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
 		return;
 		return;
 	auto methodInstance = moduleMethodInstance.mMethodInstance;
 	auto methodInstance = moduleMethodInstance.mMethodInstance;
 
 
+	for (int checkGenericIdx = 0; checkGenericIdx < (int)methodMatcher.mBestMethodGenericArguments.size(); checkGenericIdx++)
+	{
+		auto& genericParams = methodInstance->mMethodInfoEx->mGenericParams;
+		auto genericArg = methodMatcher.mBestMethodGenericArguments[checkGenericIdx];
+		if (genericArg->IsVar())
+			continue;
+
+		BfAstNode* paramSrc;
+		if (methodMatcher.mBestMethodGenericArgumentSrcs.size() == 0)		
+			paramSrc = targetSrc;		
+		else
+			paramSrc = methodMatcher.mArguments[methodMatcher.mBestMethodGenericArgumentSrcs[checkGenericIdx]].mExpression;
+
+		// Note: don't pass methodMatcher.mBestMethodGenericArguments into here, this method is already specialized
+		BfError* error = NULL;
+		if (!mModule->CheckGenericConstraints(BfGenericParamSource(methodInstance), genericArg, paramSrc, genericParams[checkGenericIdx], NULL, &error))
+		{			
+			if (methodInstance->mMethodDef->mMethodDeclaration != NULL)
+			{
+				if (error != NULL)
+					mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance->mMethodDef->GetRefNode());
+			}
+		}
+	}
+
 	// Check circular ref based on methodInstance
 	// Check circular ref based on methodInstance
  	{
  	{
  		bool hasCircularRef = false;
  		bool hasCircularRef = false;

+ 52 - 0
IDEHelper/Compiler/BfModule.cpp

@@ -6836,6 +6836,52 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
 			return false;
 			return false;
 		}
 		}
 	}
 	}
+	
+	if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Delete) != 0)
+	{
+		bool canDelete = false;
+		if (checkArgType->IsPointer())		
+			canDelete = true;		
+		else if (checkArgType->IsObjectOrInterface())
+			canDelete = true;
+
+		if (!canDelete)
+		{
+			if (!ignoreErrors)
+				*errorOut = Fail(StrFormat("The type '%s' must be a deletable type in order to use it as parameter '%s' for '%s'",
+					_TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
+			return false;
+		}
+	}
+
+	if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_New) != 0)
+	{
+		bool canAlloc = false;
+		if (auto checkTypeInst = checkArgType->ToTypeInstance())
+		{
+			if (checkTypeInst->IsObjectOrStruct())
+			{
+				auto ctorClear = GetRawMethodByName(checkTypeInst, "__BfCtor", 0);
+				if (ctorClear->mMethodDef->mProtection == BfProtection_Public)
+					canAlloc = true;
+				else if ((ctorClear->mMethodDef->mProtection == BfProtection_Protected) && (mCurTypeInstance != NULL))
+					canAlloc = TypeIsSubTypeOf(mCurTypeInstance, checkTypeInst, false);
+			}
+		}
+		else
+		{
+			// Any primitive types and stuff can be allocated
+			canAlloc = true;
+		}
+		
+		if (!canAlloc)
+		{
+			if (!ignoreErrors)
+				*errorOut = Fail(StrFormat("The type '%s' must have an accessible default constructor in order to use it as parameter '%s' for '%s'",
+					_TypeToString(origCheckArgType).c_str(), genericParamInst->GetName().c_str(), GenericParamSourceToString(genericParamSource).c_str()), checkArgTypeRef);
+			return false;
+		}
+	}
 
 
 	if ((genericParamInst->mInterfaceConstraints.IsEmpty()) && (genericParamInst->mOperatorConstraints.IsEmpty()) && (genericParamInst->mTypeConstraint == NULL))
 	if ((genericParamInst->mInterfaceConstraints.IsEmpty()) && (genericParamInst->mOperatorConstraints.IsEmpty()) && (genericParamInst->mTypeConstraint == NULL))
 		return true;
 		return true;
@@ -12101,6 +12147,12 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
 	SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(declareModule->mCurTypeInstance, typeInst);
 	SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(declareModule->mCurTypeInstance, typeInst);
 	SetAndRestoreValue<BfFilePosition> prevFilePos(declareModule->mCurFilePosition);
 	SetAndRestoreValue<BfFilePosition> prevFilePos(declareModule->mCurFilePosition);
 
 
+	if ((methodDef->mMethodType == BfMethodType_Mixin) && (methodDef->mGenericParams.size() != 0) && (!isUnspecializedPass))
+	{
+		// For mixins we only process the unspecialized version
+		addToWorkList = false;
+	}
+
 	declareModule->DoMethodDeclaration(methodDef->GetMethodDeclaration(), false, addToWorkList);
 	declareModule->DoMethodDeclaration(methodDef->GetMethodDeclaration(), false, addToWorkList);
 	
 	
 	if (processNow)
 	if (processNow)