mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-09 20:12:21 +02:00
Fixed bugs with type extensions
This commit is contained in:
parent
55f3bdfa54
commit
38a650fc2e
5 changed files with 81 additions and 15 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,6 +794,36 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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_BETTER_OR_WORSE(newMethodDef->mCheckedKind == mCheckedKind, prevMethodDef->mCheckedKind == mCheckedKind);
|
||||||
|
|
||||||
RETURN_RESULTS;
|
RETURN_RESULTS;
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -3942,7 +3950,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
|
||||||
{
|
{
|
||||||
*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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
return GetCombinedPartial(checkType);
|
||||||
do
|
|
||||||
{
|
|
||||||
BF_ASSERT(checkType->mIsPartial);
|
|
||||||
checkType = *itr;
|
|
||||||
itr.MoveToNextHashMatch();
|
|
||||||
}
|
|
||||||
while (!checkType->mIsCombinedPartial);
|
|
||||||
return checkType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int BfSystem::GetGenericParamIdx(const Array<BfGenericParamDef*>& genericParams, const StringImpl& name)
|
int BfSystem::GetGenericParamIdx(const Array<BfGenericParamDef*>& genericParams, const StringImpl& name)
|
||||||
|
|
|
@ -1301,8 +1301,10 @@ public:
|
||||||
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);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue