1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 04:22:20 +02:00

Added 'visibleProjectSet', changed visibility rules for generics

This commit is contained in:
Brian Fiete 2020-07-01 12:06:28 -07:00
parent 6021518343
commit 75dd1a4213
6 changed files with 100 additions and 25 deletions

View file

@ -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;
}

View file

@ -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();

View file

@ -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);

View file

@ -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())

View file

@ -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;

View file

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