2
0
Эх сурвалжийг харах

Added 'visibleProjectSet', changed visibility rules for generics

Brian Fiete 5 жил өмнө
parent
commit
75dd1a4213

+ 30 - 23
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -612,11 +612,6 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
 	bool prevChainSkip = (prevMethodInstance->mChainType == BfMethodChainType_ChainMember) || (prevMethodInstance->mChainType == BfMethodChainType_ChainSkip);
 	RETURN_BETTER_OR_WORSE(!chainSkip, !prevChainSkip);
 
-	// If one of these methods is local to the current extension then choose that one
-	auto activeDef = mModule->GetActiveTypeDef();
-	RETURN_BETTER_OR_WORSE(newMethodDef->mDeclaringType == activeDef, prevMethodDef->mDeclaringType == activeDef);
-	RETURN_BETTER_OR_WORSE(newMethodDef->mDeclaringType->IsExtension(), prevMethodDef->mDeclaringType->IsExtension());
-	
 	if ((!isBetter) && (!isWorse))
 	{
 		bool betterByGenericParam = false;
@@ -948,6 +943,11 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
 	RETURN_BETTER_OR_WORSE(newMethodDef->mCheckedKind == mCheckedKind, prevMethodDef->mCheckedKind == mCheckedKind);
 	RETURN_BETTER_OR_WORSE(newMethodDef->mCommutableKind != BfCommutableKind_Reverse, prevMethodDef->mCommutableKind != BfCommutableKind_Reverse);
 
+	// If one of these methods is local to the current extension then choose that one
+	auto activeDef = mModule->GetActiveTypeDef();
+	RETURN_BETTER_OR_WORSE(newMethodDef->mDeclaringType == activeDef, prevMethodDef->mDeclaringType == activeDef);
+	RETURN_BETTER_OR_WORSE(newMethodDef->mDeclaringType->IsExtension(), prevMethodDef->mDeclaringType->IsExtension());
+
 	RETURN_RESULTS;
 }
 
@@ -1877,7 +1877,12 @@ bool BfMethodMatcher::CheckType(BfTypeInstance* typeInstance, BfTypedValue targe
 	auto curTypeDef = typeInstance->mTypeDef;
 		
 	int checkInterfaceIdx = 0;
-		
+	
+	if (mMethodName == "Handle")
+	{
+		NOP;
+	}
+
 	bool targetIsBase = target.IsBase();
 	bool checkExtensionBase = false;
 	if (targetIsBase)
@@ -1915,6 +1920,7 @@ bool BfMethodMatcher::CheckType(BfTypeInstance* typeInstance, BfTypedValue targe
 		{
 			bool allowExplicitInterface = curTypeInst->IsInterface() && mBypassVirtual;
 			auto activeTypeDef = mModule->GetActiveTypeDef();
+			auto visibleProjectSet = mModule->GetVisibleProjectSet();
 			bool isDelegate = typeInstance->IsDelegate();
 
 			auto checkMethod = nextMethodDef;
@@ -1970,7 +1976,7 @@ bool BfMethodMatcher::CheckType(BfTypeInstance* typeInstance, BfTypedValue targe
 			if (!isDelegate)
 			{				
 				if ((!curTypeInst->IsTypeMemberIncluded(checkMethod->mDeclaringType, activeTypeDef, mModule)) ||
-					(!curTypeInst->IsTypeMemberAccessible(checkMethod->mDeclaringType, activeTypeDef)))
+					(!curTypeInst->IsTypeMemberAccessible(checkMethod->mDeclaringType, visibleProjectSet)))
 					continue;
 			}
 
@@ -5353,9 +5359,11 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
 			if (!target)
 			{
 				FinishDeferredEvals(argValues);
-				mModule->Fail(StrFormat("An instance reference is required to %s the non-static method '%s'",
+				auto error = mModule->Fail(StrFormat("An instance reference is required to %s the non-static method '%s'",
 					(prevBindResult.mPrevVal != NULL) ? "bind" : "invoke",
 					mModule->MethodToString(methodInstance).c_str()), targetSrc);
+				if ((error != NULL) && (methodInstance->mMethodDef->GetRefNode() != NULL))
+					mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance->mMethodDef->GetRefNode());
 				return mModule->GetDefaultTypedValue(returnType);
 			}
 
@@ -6023,6 +6031,7 @@ BfTypedValue BfExprEvaluator::MatchConstructor(BfAstNode* targetSrc, BfMethodBou
 	BfProtectionCheckFlags protectionCheckFlags = BfProtectionCheckFlag_None;
 	
 	auto activeTypeDef = mModule->GetActiveTypeDef();
+	auto visibleProjectSet = mModule->GetVisibleProjectSet();
 	bool isFailurePass = false;
 	for (int pass = 0; pass < 2; pass++)
 	{
@@ -6047,7 +6056,7 @@ BfTypedValue BfExprEvaluator::MatchConstructor(BfAstNode* targetSrc, BfMethodBou
 			if (!mModule->IsInSpecializedSection())
 			{
 				if ((!curTypeInst->IsTypeMemberIncluded(checkMethod->mDeclaringType, activeTypeDef, mModule)) ||
-					(!curTypeInst->IsTypeMemberAccessible(checkMethod->mDeclaringType, activeTypeDef)))
+					(!curTypeInst->IsTypeMemberAccessible(checkMethod->mDeclaringType, visibleProjectSet)))
 					continue;
 			}
 			
@@ -7233,7 +7242,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
 		}		
 	}
 
-	// Look in globals. Always check  for extension methods.
+	// Look in globals. Always check for extension methods.
 	if ((methodDef == NULL) || (wantsExtensionCheck))
 	{
 		if (mModule->mContext->mCurTypeState != NULL)
@@ -7251,10 +7260,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
 				{
 					isFailurePass = false;
 					curTypeInst = methodMatcher.mBestMethodTypeInstance;
-					methodDef = methodMatcher.mBestMethodDef;
-					// Extension check must check all possible extensions, no early bailout
-					if (!wantsExtensionCheck)
-						break;
+					methodDef = methodMatcher.mBestMethodDef;					
 				}
 			}
 		}		
@@ -7273,10 +7279,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
 				{
 					isFailurePass = false;
 					curTypeInst = methodMatcher.mBestMethodTypeInstance;
-					methodDef = methodMatcher.mBestMethodDef;
-					// Extension check must check all possible extensions, no early bailout
-					if (!wantsExtensionCheck)
-						break;
+					methodDef = methodMatcher.mBestMethodDef;					
 				}
 			}
 		}
@@ -13001,7 +13004,7 @@ void BfExprEvaluator::CheckLocalMethods(BfAstNode* targetSrc, BfTypeInstance* ty
  	{
 		 ctxClosureInstanceInfo = mModule->mCurMethodState->mClosureState->mClosureInstanceInfo;
 		 ctxMethodState = mModule->mCurMethodState;
-	 }
+	}
 
 	bool atCtxMethodState = false;
 	auto checkMethodState = mModule->mCurMethodState;
@@ -13324,16 +13327,20 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
 
 		if (!target)
 		{
-			mModule->Fail(StrFormat("An instance reference is required to invoke the non-static mixin '%s'",
+			BfError* error = mModule->Fail(StrFormat("An instance reference is required to invoke the non-static mixin '%s'",
 				mModule->MethodToString(methodInstance).c_str()), targetSrc);
+			if ((error != NULL) && (methodInstance->mMethodDef->GetRefNode() != NULL))
+				mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance->mMethodDef->GetRefNode());
 		}
 	}
 	else
 	{
 		if (target)
 		{
-			mModule->Fail(StrFormat("Mixin '%s' cannot be accessed with an instance reference; qualify it with a type name instead", 
+			BfError* error = mModule->Fail(StrFormat("Mixin '%s' cannot be accessed with an instance reference; qualify it with a type name instead", 
 				mModule->MethodToString(methodInstance).c_str()), targetSrc);
+			if ((error != NULL) && (methodInstance->mMethodDef->GetRefNode() != NULL))
+				mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance->mMethodDef->GetRefNode());
 		}
 	}
 
@@ -13354,14 +13361,14 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
 	if ((int)args.size() < explicitParamCount)
 	{		
 		BfError* error = mModule->Fail(StrFormat("Not enough arguments specified, expected %d more.", explicitParamCount - (int)arguments.size()), targetSrc);
-		if ((error != NULL) && (methodInstance->mMethodDef->mMethodDeclaration != NULL))
+		if ((error != NULL) && (methodInstance->mMethodDef->GetRefNode() != NULL))
 			mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance->mMethodDef->GetRefNode());
 		return;
 	}
 	else if ((int)args.size() > explicitParamCount)
 	{
 		BfError* error = mModule->Fail(StrFormat("Too many arguments specified, expected %d fewer.", (int)arguments.size() - explicitParamCount), targetSrc);
-		if ((error != NULL) && (methodInstance->mMethodDef->mMethodDeclaration != NULL))
+		if ((error != NULL) && (methodInstance->mMethodDef->GetRefNode() != NULL))
 			mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See method declaration"), methodInstance->mMethodDef->GetRefNode());
 		return;
 	}

+ 56 - 0
IDEHelper/Compiler/BfModule.cpp

@@ -2204,6 +2204,62 @@ void BfModule::ValueScopeEnd(BfIRValue valueScopeStart)
 		mBfIRBuilder->CreateValueScopeHardEnd(valueScopeStart);
 }
 
+BfProjectSet* BfModule::GetVisibleProjectSet()
+{
+	if (mCurMethodState == NULL)
+		return NULL;
+	
+	if (mCurMethodState->mVisibleProjectSet.IsEmpty())
+	{
+		HashSet<BfType*> seenTypes;
+
+		std::function<void(BfProject* project)> _AddProject = [&](BfProject* project)
+		{
+			if (mCurMethodState->mVisibleProjectSet.Add(project))
+			{
+				for (auto dep : project->mDependencies)
+					_AddProject(dep);
+			}
+		};
+
+		std::function<void(BfType* type)> _AddType = [&](BfType* type)
+		{
+			auto typeInstance = type->ToTypeInstance();
+			if (typeInstance == NULL)
+				return;
+			_AddProject(typeInstance->mTypeDef->mProject);
+			if (typeInstance->mGenericTypeInfo == NULL)
+				return;
+			for (auto type : typeInstance->mGenericTypeInfo->mTypeGenericArguments)
+			{
+				if (seenTypes.Add(type))				
+					_AddType(type);				
+			}
+		};
+
+		if (mCurTypeInstance != NULL)
+			_AddType(mCurTypeInstance);
+		
+		auto methodState = mCurMethodState;
+		while (methodState != NULL)
+		{
+			if (methodState->mMethodInstance != NULL)
+			{
+				_AddProject(methodState->mMethodInstance->mMethodDef->mDeclaringType->mProject);
+				if (methodState->mMethodInstance->mMethodInfoEx != NULL)
+				{
+					for (auto type : methodState->mMethodInstance->mMethodInfoEx->mMethodGenericArguments)
+						_AddType(type);					
+				}
+			}
+
+			methodState = methodState->mPrevMethodState;			
+		}
+	}
+
+	return &mCurMethodState->mVisibleProjectSet;
+}
+
 BfFileInstance* BfModule::GetFileFromNode(BfAstNode* astNode)
 {
 	auto bfParser = astNode->GetSourceData()->ToParserData();

+ 3 - 1
IDEHelper/Compiler/BfModule.h

@@ -895,6 +895,7 @@ public:
 	Array<BfLambdaInstance*> mDeferredLambdaInstances;
 	Array<BfIRValue> mSplatDecompAddrs;	
 	BfDeferredLocalAssignData* mDeferredLocalAssignData;
+	BfProjectSet mVisibleProjectSet;
 	int mDeferredLoopListCount;
 	int mDeferredLoopListEntryCount;
 	HashSet<int> mSkipObjectAccessChecks; // Indexed by BfIRValue value id
@@ -1468,6 +1469,7 @@ public:
 	void SaveStackState(BfScopeData* scope);
 	BfIRValue ValueScopeStart();
 	void ValueScopeEnd(BfIRValue valueScopeStart);
+	BfProjectSet* GetVisibleProjectSet();
 
 	void AddBasicBlock(BfIRBlock bb, bool activate = true);	
 	void VisitEmbeddedStatement(BfAstNode* stmt, BfExprEvaluator* exprEvaluator = NULL, BfEmbeddedStatementFlags flags = BfEmbeddedStatementFlags_None);
@@ -1682,7 +1684,7 @@ public:
 	BfType* ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTypeRef, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags);
 	void ShowAmbiguousTypeError(BfAstNode* refNode, BfTypeDef* typeDef, BfTypeDef* otherTypeDef);
 	void ShowGenericArgCountError(BfTypeReference* typeRef, int wantedGenericParams);	
-	BfTypeDef* GetActiveTypeDef(BfTypeInstance* typeInstanceOverride = NULL, bool useMixinDecl = false); // useMixinDecl is useful for type lookup, but we don't want the decl project to limit what methods the user can call
+	BfTypeDef* GetActiveTypeDef(BfTypeInstance* typeInstanceOverride = NULL, bool useMixinDecl = false); // useMixinDecl is useful for type lookup, but we don't want the decl project to limit what methods the user can call	
 	BfTypeDef* FindTypeDefRaw(const BfAtomComposite& findName, int numGenericArgs, BfTypeInstance* typeInstance, BfTypeDef* useTypeDef, BfTypeLookupError* error);
 	BfTypeDef* FindTypeDef(const BfAtomComposite& findName, int numGenericArgs = 0, BfTypeInstance* typeInstanceOverride = NULL, BfTypeLookupError* error = NULL);
 	BfTypeDef* FindTypeDef(const StringImpl& typeName, int numGenericArgs = 0, BfTypeInstance* typeInstanceOverride = NULL, BfTypeLookupError* error = NULL);

+ 7 - 0
IDEHelper/Compiler/BfResolvedTypeUtils.cpp

@@ -1698,6 +1698,13 @@ bool BfTypeInstance::IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfProje
 	return curProject->ContainsReference(declaringTypeDef->mProject);
 }
 
+bool BfTypeInstance::IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfProjectSet* visibleProjectSet)
+{
+	if (visibleProjectSet == NULL)
+		return false;
+	return visibleProjectSet->Contains(declaringTypeDef->mProject);
+}
+
 bool BfTypeInstance::WantsGCMarking()
 {
 	if (IsObjectOrInterface()) 

+ 3 - 1
IDEHelper/Compiler/BfResolvedTypeUtils.h

@@ -552,7 +552,8 @@ public:
 	virtual bool HasWrappedRepresentation() { return IsWrappableType(); }
 	virtual bool IsTypeMemberIncluded(BfTypeDef* declaringTypeDef, BfTypeDef* activeTypeDef = NULL, BfModule* module = NULL) { return true; } // May be 'false' only for generic extensions with constraints
 	virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfTypeDef* activeTypeDef) { return true; }
-	virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfProject* curProject) { return true; }	
+	virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfProject* curProject) { return true; }
+	virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfProjectSet* visibleProjectSet) { return true; }
 
 	virtual void ReportMemory(MemReporter* memReporter);
 };
@@ -1836,6 +1837,7 @@ public:
 	virtual bool HasPackingHoles() override { return mHasPackingHoles; }
 	virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfTypeDef* activeTypeDef) override;
 	virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfProject* curProject) override;	
+	virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfProjectSet* visibleProjectSet) override;
 	virtual bool WantsGCMarking() override;
 	virtual bool GetLoweredType(BfTypeUsage typeUsage, BfTypeCode* outTypeCode = NULL, BfTypeCode* outTypeCode2 = NULL) override;
 

+ 1 - 0
IDEHelper/Compiler/BfSystem.h

@@ -44,6 +44,7 @@ class BfProject;
 
 struct BfTypeDefMapFuncs;
 typedef MultiHashSet<BfTypeDef*, BfTypeDefMapFuncs> BfTypeDefMap;
+typedef HashSet<BfProject*> BfProjectSet;
 
 class BfAtom
 {