1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Fixed bugs with type extensions

This commit is contained in:
Brian Fiete 2019-09-10 11:27:53 -07:00
parent 55f3bdfa54
commit 38a650fc2e
5 changed files with 81 additions and 15 deletions

View file

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

View file

@ -745,6 +745,18 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
int prevArgIdx = argIdx + prevImplicitParamCount;
_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))
{
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;
}

View file

@ -1502,6 +1502,10 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
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);
if (baseType != NULL)
{
@ -3811,6 +3815,10 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
if (ifaceMethodInst == NULL)
continue;
// Don't even try to match generics
if (!ifaceMethodInst->mMethodDef->mGenericParams.IsEmpty())
continue;
auto iReturnType = ifaceMethodInst->mReturnType;
if (iReturnType->IsSelf())
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;
BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_ForeignMethodDef;
@ -3939,10 +3947,10 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
flags = (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_UnspecializedPass);
auto methodInst = GetMethodInstance(typeInstance, methodDef, BfTypeVector(), flags, ifaceInst);
if (methodInst)
{
{
*matchedMethodRef = methodInst.mMethodInstance;
BfMethodInstance* newMethodInstance = *matchedMethodRef;
BfMethodInstance* newMethodInstance = methodInst.mMethodInstance;
BF_ASSERT(newMethodInstance->mIsForeignMethodDef);
if (newMethodInstance->mMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference)
mOnDemandMethodCount++;
@ -4053,7 +4061,7 @@ void BfModule::AddMethodToWorkList(BfMethodInstance* methodInstance)
return;
BF_ASSERT(mCompiler->mCompileState != BfCompiler::CompileState_VData);
if (methodInstance->mIsReified)
if ((methodInstance->mIsReified) && (!methodInstance->mIsUnspecialized))
{
BF_ASSERT(mCompiler->mCompileState != BfCompiler::CompileState_Unreified);
}

View file

@ -2925,21 +2925,28 @@ void BfSystem::FinishCompositePartial(BfTypeDef* compositeTypeDef)
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)
{
auto checkType = typeDef->mOuterType;
if ((checkType == NULL) || (!checkType->mIsPartial))
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)

View file

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