mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Partial recursive generic fixes, deferred constraint type validation
This commit is contained in:
parent
3681b521b5
commit
eb86c717f0
9 changed files with 162 additions and 53 deletions
|
@ -398,6 +398,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
|
|||
mDbgRawAllocDataTypeDef = NULL;
|
||||
mDeferredCallTypeDef = NULL;
|
||||
mDelegateTypeDef = NULL;
|
||||
mFunctionTypeDef = NULL;
|
||||
mActionTypeDef = NULL;
|
||||
mEnumTypeDef = NULL;
|
||||
mFriendAttributeTypeDef = NULL;
|
||||
|
@ -405,8 +406,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
|
|||
mConstEvalAttributeTypeDef = NULL;
|
||||
mNoExtensionAttributeTypeDef = NULL;
|
||||
mCheckedAttributeTypeDef = NULL;
|
||||
mUncheckedAttributeTypeDef = NULL;
|
||||
mFunctionTypeDef = NULL;
|
||||
mUncheckedAttributeTypeDef = NULL;
|
||||
mGCTypeDef = NULL;
|
||||
mGenericIEnumerableTypeDef = NULL;
|
||||
mGenericIEnumeratorTypeDef = NULL;
|
||||
|
@ -6665,6 +6665,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
|
|||
mDbgRawAllocDataTypeDef = _GetRequiredType("System.DbgRawAllocData");
|
||||
mDeferredCallTypeDef = _GetRequiredType("System.DeferredCall");
|
||||
mDelegateTypeDef = _GetRequiredType("System.Delegate");
|
||||
mFunctionTypeDef = _GetRequiredType("System.Function");
|
||||
mActionTypeDef = _GetRequiredType("System.Action");
|
||||
mEnumTypeDef = _GetRequiredType("System.Enum");
|
||||
mFriendAttributeTypeDef = _GetRequiredType("System.FriendAttribute");
|
||||
|
@ -6673,8 +6674,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
|
|||
mNoExtensionAttributeTypeDef = _GetRequiredType("System.NoExtensionAttribute");
|
||||
mCheckedAttributeTypeDef = _GetRequiredType("System.CheckedAttribute");
|
||||
mUncheckedAttributeTypeDef = _GetRequiredType("System.UncheckedAttribute");
|
||||
mResultTypeDef = _GetRequiredType("System.Result", 1);
|
||||
mFunctionTypeDef = _GetRequiredType("System.Function");
|
||||
mResultTypeDef = _GetRequiredType("System.Result", 1);
|
||||
mGCTypeDef = _GetRequiredType("System.GC");
|
||||
mGenericIEnumerableTypeDef = _GetRequiredType("System.Collections.IEnumerable", 1);
|
||||
mGenericIEnumeratorTypeDef = _GetRequiredType("System.Collections.IEnumerator", 1);
|
||||
|
|
|
@ -353,14 +353,14 @@ public:
|
|||
BfTypeDef* mDbgRawAllocDataTypeDef;
|
||||
BfTypeDef* mDeferredCallTypeDef;
|
||||
BfTypeDef* mDelegateTypeDef;
|
||||
BfTypeDef* mFunctionTypeDef;
|
||||
BfTypeDef* mActionTypeDef;
|
||||
BfTypeDef* mEnumTypeDef;
|
||||
BfTypeDef* mStringTypeDef;
|
||||
BfTypeDef* mStringViewTypeDef;
|
||||
BfTypeDef* mTypeTypeDef;
|
||||
BfTypeDef* mValueTypeTypeDef;
|
||||
BfTypeDef* mResultTypeDef;
|
||||
BfTypeDef* mFunctionTypeDef;
|
||||
BfTypeDef* mResultTypeDef;
|
||||
BfTypeDef* mGCTypeDef;
|
||||
BfTypeDef* mGenericIEnumerableTypeDef;
|
||||
BfTypeDef* mGenericIEnumeratorTypeDef;
|
||||
|
|
|
@ -3425,10 +3425,11 @@ void BfModule::AddDependency(BfType* usedType, BfType* userType, BfDependencyMap
|
|||
BfModule* usedModule;
|
||||
if (usedType->IsFunction())
|
||||
{
|
||||
auto typeInst = usedType->ToTypeInstance();
|
||||
if (typeInst->mBaseType == NULL)
|
||||
PopulateType(typeInst);
|
||||
usedModule = typeInst->mBaseType->GetModule();
|
||||
if (mCompiler->mFunctionTypeDef != NULL)
|
||||
{
|
||||
auto functionType = ResolveTypeDef(mCompiler->mFunctionTypeDef)->ToTypeInstance();
|
||||
usedModule = functionType->GetModule();
|
||||
}
|
||||
}
|
||||
else
|
||||
usedModule = usedType->GetModule();
|
||||
|
@ -7217,7 +7218,7 @@ BfIRFunction BfModule::GetBuiltInFunc(BfBuiltInFuncType funcTypeId)
|
|||
return mBuiltInFuncs[(int)funcTypeId];
|
||||
}
|
||||
|
||||
void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericParamInstance, bool isUnspecialized)
|
||||
void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericParamInstance, bool isUnspecialized, Array<BfTypeReference*>* deferredResolveTypes)
|
||||
{
|
||||
BfGenericParamDef* genericParamDef = genericParamInstance->GetGenericParamDef();
|
||||
BfExternalConstraintDef* externConstraintDef = genericParamInstance->GetExternConstraintDef();
|
||||
|
@ -7323,14 +7324,23 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar
|
|||
if (bfAutocomplete != NULL)
|
||||
bfAutocomplete->CheckTypeRef(constraintTypeRef, true);
|
||||
//TODO: Constraints may refer to other generic params (of either type or method)
|
||||
// TO allow resolution, perhaps move this generic param initalization into GetMethodInstance (passing a genericPass bool)
|
||||
// TO allow resolution, perhaps move this generic param initialization into GetMethodInstance (passing a genericPass bool)
|
||||
|
||||
BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_AllowGenericMethodParamConstValue;
|
||||
if (isUnspecialized)
|
||||
resolveFlags = (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_DisallowComptime);
|
||||
auto constraintType = ResolveTypeRef(constraintTypeRef, BfPopulateType_Declaration, resolveFlags);
|
||||
// We we have a deferredResolveTypes then we defer the generic validation, because we may have a case like
|
||||
// `where T : Dictionay<TElem, int> and TElem : IHashable` and we don't want to throw the error on `T` before we build `TElem`
|
||||
auto constraintType = ResolveTypeRef(constraintTypeRef, (deferredResolveTypes != NULL) ? BfPopulateType_Identity : BfPopulateType_Declaration, resolveFlags);
|
||||
if (constraintType != NULL)
|
||||
{
|
||||
{
|
||||
if (deferredResolveTypes != NULL)
|
||||
{
|
||||
PopulateType(constraintType, BfPopulateType_Declaration);
|
||||
if (constraintType->IsUnspecializedTypeVariation())
|
||||
deferredResolveTypes->Add(constraintTypeRef);
|
||||
}
|
||||
|
||||
if ((constraintDef->mGenericParamFlags & BfGenericParamFlag_Const) != 0)
|
||||
{
|
||||
bool isValidTypeCode = false;
|
||||
|
@ -7511,11 +7521,11 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
|||
origCheckArgType = origCheckArgType->GetUnderlyingType();
|
||||
|
||||
bool argMayBeReferenceType = false;
|
||||
|
||||
|
||||
int checkGenericParamFlags = 0;
|
||||
if (checkArgType->IsGenericParam())
|
||||
{
|
||||
auto checkGenericParamInst = GetGenericParamInstance((BfGenericParamType*)checkArgType);
|
||||
BfGenericParamInstance* checkGenericParamInst = GetGenericParamInstance((BfGenericParamType*)checkArgType);
|
||||
checkGenericParamFlags = checkGenericParamInst->mGenericParamFlags;
|
||||
if (checkGenericParamInst->mTypeConstraint != NULL)
|
||||
checkArgType = checkGenericParamInst->mTypeConstraint;
|
||||
|
@ -7849,7 +7859,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
|||
if (TypeIsSubTypeOf(wrappedStructType, typeConstraintInst))
|
||||
implementsInterface = true;
|
||||
}
|
||||
|
||||
|
||||
if (!implementsInterface)
|
||||
{
|
||||
if ((!ignoreErrors) && (PreFail()))
|
||||
|
@ -21616,6 +21626,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
{
|
||||
BfTypeInstance* unspecializedTypeInstance = NULL;
|
||||
|
||||
Array<BfTypeReference*> deferredResolveTypes;
|
||||
for (int genericParamIdx = 0; genericParamIdx < (int)methodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
|
||||
{
|
||||
auto genericParam = methodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
|
||||
|
@ -21639,8 +21650,8 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
else
|
||||
genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var);
|
||||
}
|
||||
|
||||
ResolveGenericParamConstraints(genericParam, methodInstance->mIsUnspecialized);
|
||||
|
||||
ResolveGenericParamConstraints(genericParam, methodInstance->mIsUnspecialized, &deferredResolveTypes);
|
||||
|
||||
if (genericParamIdx < (int)methodDef->mGenericParams.size())
|
||||
{
|
||||
|
@ -21654,6 +21665,8 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
}
|
||||
}
|
||||
}
|
||||
for (auto typeRef : deferredResolveTypes)
|
||||
auto constraintType = ResolveTypeRef(typeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_None);
|
||||
|
||||
for (auto genericParam : methodInstance->mMethodInfoEx->mGenericParams)
|
||||
{
|
||||
|
|
|
@ -1778,7 +1778,7 @@ public:
|
|||
bool TypeEquals(BfTypedValue& val, BfType* type);
|
||||
BfTypeDef* ResolveGenericInstanceDef(BfGenericInstanceTypeRef* genericTypeRef, BfType** outType = NULL, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None);
|
||||
BfType* ResolveType(BfType* lookupType, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None);
|
||||
void ResolveGenericParamConstraints(BfGenericParamInstance* genericParamInstance, bool isUnspecialized);
|
||||
void ResolveGenericParamConstraints(BfGenericParamInstance* genericParamInstance, bool isUnspecialized, Array<BfTypeReference*>* deferredResolveTypes = NULL);
|
||||
String GenericParamSourceToString(const BfGenericParamSource& genericParamSource);
|
||||
bool CheckGenericConstraints(const BfGenericParamSource& genericParamSource, BfType* checkArgType, BfAstNode* checkArgTypeRef, BfGenericParamInstance* genericParamInst, BfTypeVector* methodGenericArgs = NULL, BfError** errorOut = NULL);
|
||||
BfIRValue AllocLocalVariable(BfType* type, const StringImpl& name, bool doLifetimeEnd = true);
|
||||
|
|
|
@ -164,7 +164,8 @@ bool BfModule::FinishGenericParams(BfType* resolvedTypeRef)
|
|||
typeState.mResolveKind = BfTypeState::ResolveKind_BuildingGenericParams;
|
||||
typeState.mTypeInstance = resolvedTypeRef->ToTypeInstance();
|
||||
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
||||
|
||||
Array<BfTypeReference*> deferredResolveTypes;
|
||||
|
||||
BF_ASSERT(mCurMethodInstance == NULL);
|
||||
|
||||
auto genericTypeInst = resolvedTypeRef->ToGenericTypeInstance();
|
||||
|
@ -210,7 +211,7 @@ bool BfModule::FinishGenericParams(BfType* resolvedTypeRef)
|
|||
genericParamInstance->mExternType = GetPrimitiveType(BfTypeCode_Var);
|
||||
}
|
||||
|
||||
ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType());
|
||||
ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType(), &deferredResolveTypes);
|
||||
|
||||
if (genericParamDef != NULL)
|
||||
{
|
||||
|
@ -283,7 +284,7 @@ bool BfModule::FinishGenericParams(BfType* resolvedTypeRef)
|
|||
genericParamInstance->mExternType = GetPrimitiveType(BfTypeCode_Var);
|
||||
}
|
||||
|
||||
ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType());
|
||||
ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType(), &deferredResolveTypes);
|
||||
auto genericParamDef = genericParamInstance->GetGenericParamDef();
|
||||
if (genericParamDef != NULL)
|
||||
{
|
||||
|
@ -295,6 +296,9 @@ bool BfModule::FinishGenericParams(BfType* resolvedTypeRef)
|
|||
}
|
||||
}
|
||||
|
||||
for (auto typeRef : deferredResolveTypes)
|
||||
auto constraintType = ResolveTypeRef(typeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_None);
|
||||
|
||||
for (auto genericParam : genericTypeInst->mGenericTypeInfo->mGenericParams)
|
||||
{
|
||||
for (auto constraintTypeInst : genericParam->mInterfaceConstraints)
|
||||
|
@ -339,6 +343,13 @@ bool BfModule::ValidateGenericConstraints(BfTypeReference* typeRef, BfTypeInstan
|
|||
return true;
|
||||
}
|
||||
|
||||
for (auto typeArg : genericTypeInst->mGenericTypeInfo->mTypeGenericArguments)
|
||||
{
|
||||
auto genericArg = typeArg->ToGenericTypeInstance();
|
||||
if (genericArg != NULL)
|
||||
genericTypeInst->mGenericTypeInfo->mMaxGenericDepth = BF_MAX(genericTypeInst->mGenericTypeInfo->mMaxGenericDepth, genericArg->mGenericTypeInfo->mMaxGenericDepth + 1);
|
||||
}
|
||||
|
||||
auto typeDef = genericTypeInst->mTypeDef;
|
||||
for (int paramIdx = 0; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mGenericParams.size(); paramIdx++)
|
||||
{
|
||||
|
@ -4973,7 +4984,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
|
|||
|
||||
//
|
||||
{
|
||||
if (typeInstance->IsSpecializedType())
|
||||
if ((typeInstance->IsSpecializedType()) || (typeInstance->IsUnspecializedTypeVariation()))
|
||||
wantsOnDemandMethods = true;
|
||||
else if ((mCompiler->mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude) &&
|
||||
(!typeInstance->IsUnspecializedTypeVariation()))
|
||||
|
@ -7939,7 +7950,7 @@ bool BfModule::ResolveTypeResult_Validate(BfTypeReference* typeRef, BfType* reso
|
|||
if ((curGenericTypeInstance->mDependencyMap.mMinDependDepth > 32) &&
|
||||
(genericTypeInstance->mDependencyMap.mMinDependDepth > 32))
|
||||
{
|
||||
Fail(StrFormat("Generic type dependency depth exceeded for type '{}'", TypeToString(genericTypeInstance).c_str()), typeRef);
|
||||
Fail(StrFormat("Generic type dependency depth exceeded for type '%s'", TypeToString(genericTypeInstance).c_str()), typeRef);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -9724,7 +9735,14 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
CheckUnspecializedGenericType(genericTypeInst, populateType);
|
||||
resolvedEntry->mValue = genericTypeInst;
|
||||
populateModule->InitType(genericTypeInst, populateType);
|
||||
BF_ASSERT(BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx) == resolvedEntry->mHash);
|
||||
#ifdef _DEBUG
|
||||
if (BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx) != resolvedEntry->mHash)
|
||||
{
|
||||
int refHash = BfResolvedTypeSet::Hash(typeRef, &lookupCtx);
|
||||
int typeHash = BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx);
|
||||
BF_ASSERT(refHash == typeHash);
|
||||
}
|
||||
#endif
|
||||
return ResolveTypeResult(typeRef, genericTypeInst, populateType, resolveFlags);
|
||||
}
|
||||
}
|
||||
|
@ -9978,15 +9996,16 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
auto parentTypeInstance = outerTypeInstance;
|
||||
if (parentTypeInstance->IsTypeAlias())
|
||||
parentTypeInstance = (BfTypeInstance*)GetOuterType(parentTypeInstance)->ToTypeInstance();
|
||||
genericTypeInst->mGenericTypeInfo->mMaxGenericDepth = BF_MAX(genericTypeInst->mGenericTypeInfo->mMaxGenericDepth, parentTypeInstance->mGenericTypeInfo->mMaxGenericDepth);
|
||||
for (int i = 0; i < startDefGenericParamIdx; i++)
|
||||
{
|
||||
genericTypeInst->mGenericTypeInfo->mGenericParams.push_back(parentTypeInstance->mGenericTypeInfo->mGenericParams[i]->AddRef());
|
||||
genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.push_back(parentTypeInstance->mGenericTypeInfo->mTypeGenericArguments[i]);
|
||||
auto typeGenericArg = genericTypeInst->mGenericTypeInfo->mTypeGenericArguments[i];
|
||||
genericTypeInst->mGenericTypeInfo->mIsUnspecialized |= typeGenericArg->IsGenericParam() || typeGenericArg->IsUnspecializedType();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int wantedGenericParams = genericParamCount - startDefGenericParamIdx;
|
||||
int genericArgDiffCount = (int)genericArguments.size() - wantedGenericParams;
|
||||
|
@ -10005,14 +10024,28 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
for (auto genericArgRef : genericArguments)
|
||||
{
|
||||
auto genericArg = genericArgs[genericParamIdx + startDefGenericParamIdx];
|
||||
|
||||
if (auto genericGenericArg = genericArg->ToGenericTypeInstance())
|
||||
{
|
||||
genericTypeInst->mGenericTypeInfo->mMaxGenericDepth = BF_MAX(genericTypeInst->mGenericTypeInfo->mMaxGenericDepth, genericGenericArg->mGenericTypeInfo->mMaxGenericDepth + 1);
|
||||
}
|
||||
|
||||
genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.push_back(genericArg);
|
||||
genericTypeInst->mGenericTypeInfo->mTypeGenericArgumentRefs.push_back(genericArgRef);
|
||||
|
||||
genericParamIdx++;
|
||||
}
|
||||
|
||||
resolvedEntry->mValue = genericTypeInst;
|
||||
if (genericTypeInst->mGenericTypeInfo->mMaxGenericDepth > 64)
|
||||
{
|
||||
Fail("Maximum generic depth exceeded", typeRef);
|
||||
delete genericTypeInst;
|
||||
mContext->mResolvedTypes.RemoveEntry(resolvedEntry);
|
||||
return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags);
|
||||
}
|
||||
|
||||
resolvedEntry->mValue = genericTypeInst;
|
||||
|
||||
CheckUnspecializedGenericType(genericTypeInst, populateType);
|
||||
populateModule->InitType(genericTypeInst, populateType);
|
||||
|
||||
|
@ -10027,6 +10060,8 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
{
|
||||
BF_ASSERT(BfResolvedTypeSet::Equals(genericTypeInst, typeRef, &lookupCtx));
|
||||
}
|
||||
|
||||
BfLogSysM("Generic type %p typeHash: %8X\n", genericTypeInst, resolvedEntry->mHash);
|
||||
#endif
|
||||
|
||||
BF_ASSERT(BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx) == resolvedEntry->mHash);
|
||||
|
@ -10161,7 +10196,14 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
CheckUnspecializedGenericType(genericTypeInst, populateType);
|
||||
|
||||
resolvedEntry->mValue = genericTypeInst;
|
||||
BF_ASSERT(BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx) == resolvedEntry->mHash);
|
||||
#ifdef _DEBUG
|
||||
if (BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx) != resolvedEntry->mHash)
|
||||
{
|
||||
int refHash = BfResolvedTypeSet::Hash(typeRef, &lookupCtx);
|
||||
int typeHash = BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx);
|
||||
BF_ASSERT(refHash == typeHash);
|
||||
}
|
||||
#endif
|
||||
populateModule->InitType(genericTypeInst, populateType);
|
||||
return ResolveTypeResult(typeRef, genericTypeInst, populateType, resolveFlags);
|
||||
}
|
||||
|
|
|
@ -2723,6 +2723,8 @@ BfResolvedTypeSet::~BfResolvedTypeSet()
|
|||
|
||||
}
|
||||
|
||||
#define HASH_MIX(origHashVal, newHashVal) ((((origHashVal) << 5) - (origHashVal)) ^ (newHashVal))
|
||||
|
||||
#define HASH_VAL_PTR 1
|
||||
#define HASH_VAL_BOXED 2
|
||||
#define HASH_VAL_REF 3
|
||||
|
@ -2769,7 +2771,7 @@ BfVariant BfResolvedTypeSet::EvaluateToVariant(LookupContext* ctx, BfExpression*
|
|||
return variant;
|
||||
}
|
||||
|
||||
int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef)
|
||||
int BfResolvedTypeSet::DoHash(BfType* type, LookupContext* ctx, bool allowRef, int hashSeed)
|
||||
{
|
||||
//BP_ZONE("BfResolvedTypeSet::Hash");
|
||||
|
||||
|
@ -2875,8 +2877,8 @@ int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef)
|
|||
else if (type->IsGenericTypeInstance())
|
||||
{
|
||||
BfTypeInstance* genericType = (BfTypeInstance*)type;
|
||||
for (auto genericArg : genericType->mGenericTypeInfo->mTypeGenericArguments)
|
||||
hashVal = ((hashVal ^ (Hash(genericArg, ctx))) << 5) - hashVal;
|
||||
for (auto genericArg : genericType->mGenericTypeInfo->mTypeGenericArguments)
|
||||
hashVal = HASH_MIX(hashVal, Hash(genericArg, ctx, BfHashFlag_None, hashSeed + 1));
|
||||
}
|
||||
return hashVal;
|
||||
}
|
||||
|
@ -2952,21 +2954,29 @@ int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void BfResolvedTypeSet::HashGenericArguments(BfTypeReference* typeRef, LookupContext* ctx, int& hashVal)
|
||||
int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef, int hashSeed)
|
||||
{
|
||||
int hashVal = DoHash(type, ctx, allowRef, hashSeed);
|
||||
if (hashSeed == 0)
|
||||
return hashVal;
|
||||
return HASH_MIX(hashVal, hashSeed);
|
||||
}
|
||||
|
||||
void BfResolvedTypeSet::HashGenericArguments(BfTypeReference* typeRef, LookupContext* ctx, int& hashVal, int hashSeed)
|
||||
{
|
||||
if (auto elementedTypeRef = BfNodeDynCast<BfElementedTypeRef>(typeRef))
|
||||
{
|
||||
HashGenericArguments(elementedTypeRef->mElementType, ctx, hashVal);
|
||||
HashGenericArguments(elementedTypeRef->mElementType, ctx, hashVal, hashSeed);
|
||||
}
|
||||
else if (auto qualifiedTypeRef = BfNodeDynCast<BfQualifiedTypeReference>(typeRef))
|
||||
{
|
||||
HashGenericArguments(qualifiedTypeRef->mLeft, ctx, hashVal);
|
||||
HashGenericArguments(qualifiedTypeRef->mLeft, ctx, hashVal, hashSeed);
|
||||
}
|
||||
|
||||
if (auto genericTypeRef = BfNodeDynCast<BfGenericInstanceTypeRef>(typeRef))
|
||||
{
|
||||
for (auto genericArg : genericTypeRef->mGenericArguments)
|
||||
hashVal = ((hashVal ^ (Hash(genericArg, ctx, BfHashFlag_AllowGenericParamConstValue))) << 5) - hashVal;
|
||||
hashVal = HASH_MIX(hashVal, Hash(genericArg, ctx, BfHashFlag_AllowGenericParamConstValue, hashSeed + 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2978,7 +2988,7 @@ static int HashNode(BfAstNode* node)
|
|||
return (int)Hash64(nameStr, node->GetSrcLength());
|
||||
}
|
||||
|
||||
int BfResolvedTypeSet::DirectHash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags)
|
||||
int BfResolvedTypeSet::DirectHash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags, int hashSeed)
|
||||
{
|
||||
bool isHeadType = typeRef == ctx->mRootTypeRef;
|
||||
|
||||
|
@ -2992,7 +3002,7 @@ int BfResolvedTypeSet::DirectHash(BfTypeReference* typeRef, LookupContext* ctx,
|
|||
ctx->mFailed = true;
|
||||
return 0;
|
||||
}
|
||||
return Hash(resolvedType, ctx);
|
||||
return Hash(resolvedType, ctx, BfHashFlag_None, hashSeed);
|
||||
}
|
||||
|
||||
BfTypeDef* BfResolvedTypeSet::FindRootCommonOuterType(BfTypeDef* outerType, LookupContext* ctx, BfTypeInstance*& outOuterTypeInstance)
|
||||
|
@ -3022,7 +3032,7 @@ BfTypeDef* BfResolvedTypeSet::FindRootCommonOuterType(BfTypeDef* outerType, Look
|
|||
return commonOuterType;
|
||||
}
|
||||
|
||||
int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags)
|
||||
int BfResolvedTypeSet::DoHash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags, int& hashSeed)
|
||||
{
|
||||
if ((typeRef == ctx->mRootTypeRef) && (ctx->mRootTypeDef != NULL) &&
|
||||
((typeRef->IsNamedTypeReference()) || (BfNodeIsA<BfDirectTypeDefReference>(typeRef))))
|
||||
|
@ -3074,8 +3084,8 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
|
|||
auto curGenericTypeInst = (BfTypeInstance*)checkTypeInstance;
|
||||
int numParentGenericParams = (int)commonOuterType->mGenericParamDefs.size();
|
||||
for (int i = 0; i < numParentGenericParams; i++)
|
||||
{
|
||||
hashVal = ((hashVal ^ (Hash(curGenericTypeInst->mGenericTypeInfo->mTypeGenericArguments[i], ctx))) << 5) - hashVal;
|
||||
{
|
||||
hashVal = HASH_MIX(hashVal, Hash(curGenericTypeInst->mGenericTypeInfo->mTypeGenericArguments[i], ctx, BfHashFlag_None, hashSeed + 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3084,7 +3094,9 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
|
|||
|
||||
if (typeRef->IsNamedTypeReference())
|
||||
{
|
||||
return DirectHash(typeRef, ctx, flags);
|
||||
int hashVal = DirectHash(typeRef, ctx, flags, hashSeed);
|
||||
hashSeed = 0;
|
||||
return hashVal;
|
||||
}
|
||||
if (auto genericInstTypeRef = BfNodeDynCastExact<BfGenericInstanceTypeRef>(typeRef))
|
||||
{
|
||||
|
@ -3157,12 +3169,12 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
|
|||
{
|
||||
auto parentTypeInstance = checkTypeInstance;
|
||||
int numParentGenericParams = (int)commonOuterType->mGenericParamDefs.size();
|
||||
for (int i = 0; i < numParentGenericParams; i++)
|
||||
hashVal = ((hashVal ^ (Hash(parentTypeInstance->mGenericTypeInfo->mTypeGenericArguments[i], ctx))) << 5) - hashVal;
|
||||
for (int i = 0; i < numParentGenericParams; i++)
|
||||
hashVal = HASH_MIX(hashVal, Hash(parentTypeInstance->mGenericTypeInfo->mTypeGenericArguments[i], ctx, Beefy::BfResolvedTypeSet::BfHashFlag_None, hashSeed + 1));
|
||||
}
|
||||
}
|
||||
|
||||
HashGenericArguments(genericInstTypeRef, ctx, hashVal);
|
||||
HashGenericArguments(genericInstTypeRef, ctx, hashVal, hashSeed);
|
||||
|
||||
return hashVal;
|
||||
}
|
||||
|
@ -3296,8 +3308,8 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
|
|||
if (ctx->mRootTypeRef == typeRef)
|
||||
ctx->mRootTypeDef = ctx->mModule->mCompiler->mNullableTypeDef;
|
||||
|
||||
int hashVal = ctx->mModule->mCompiler->mNullableTypeDef->mHash;
|
||||
hashVal = ((hashVal ^ (Hash(nullableType->mElementType, ctx))) << 5) - hashVal;
|
||||
int hashVal = ctx->mModule->mCompiler->mNullableTypeDef->mHash;
|
||||
hashVal = HASH_MIX(hashVal, Hash(nullableType->mElementType, ctx, BfHashFlag_None, hashSeed + 1));
|
||||
return hashVal;
|
||||
}
|
||||
else if (auto refType = BfNodeDynCastExact<BfRefTypeRef>(typeRef))
|
||||
|
@ -3510,7 +3522,9 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
|
|||
return 0;
|
||||
}
|
||||
|
||||
return Hash(cachedResolvedType, ctx, flags);
|
||||
int hashVal = Hash(cachedResolvedType, ctx, flags, hashSeed);
|
||||
hashSeed = 0;
|
||||
return hashVal;
|
||||
}
|
||||
else if (auto constExprTypeRef = BfNodeDynCastExact<BfConstExprTypeRef>(typeRef))
|
||||
{
|
||||
|
@ -3546,6 +3560,14 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
|
|||
return 0;
|
||||
}
|
||||
|
||||
int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags, int hashSeed)
|
||||
{
|
||||
int hashVal = DoHash(typeRef, ctx, flags, hashSeed);
|
||||
if (hashSeed == 0)
|
||||
return hashVal;
|
||||
return HASH_MIX(hashVal, hashSeed);
|
||||
}
|
||||
|
||||
// These types can be from different contexts ("foreign" types) so we can't just compare ptrs
|
||||
bool BfResolvedTypeSet::Equals(BfType* lhs, BfType* rhs, LookupContext* ctx)
|
||||
{
|
||||
|
|
|
@ -1774,6 +1774,7 @@ public:
|
|||
bool mInitializedGenericParams;
|
||||
bool mFinishedGenericParams;
|
||||
Array<BfProject*> mProjectsReferenced; // Generic methods that only refer to these projects don't need a specialized extension
|
||||
int32 mMaxGenericDepth;
|
||||
|
||||
public:
|
||||
BfGenericTypeInfo()
|
||||
|
@ -1785,6 +1786,7 @@ public:
|
|||
mValidatedGenericConstraints = false;
|
||||
mInitializedGenericParams = false;
|
||||
mFinishedGenericParams = false;
|
||||
mMaxGenericDepth = -1;
|
||||
}
|
||||
|
||||
~BfGenericTypeInfo();
|
||||
|
@ -2525,10 +2527,12 @@ public:
|
|||
static BfVariant EvaluateToVariant(LookupContext* ctx, BfExpression* expr, BfType*& outType);
|
||||
static bool GenericTypeEquals(BfTypeInstance* lhsGenericType, BfTypeVector* lhsTypeGenericArguments, BfTypeReference* rhs, LookupContext* ctx, int& genericParamOffset);
|
||||
static bool GenericTypeEquals(BfTypeInstance* lhsGenericType, BfTypeVector* typeGenericArguments, BfTypeReference* rhs, BfTypeDef* rhsTypeDef, LookupContext* ctx);
|
||||
static void HashGenericArguments(BfTypeReference* typeRef, LookupContext* ctx, int& hash);
|
||||
static int Hash(BfType* type, LookupContext* ctx, bool allowRef = false);
|
||||
static int DirectHash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags = BfHashFlag_None);
|
||||
static int Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags = BfHashFlag_None);
|
||||
static void HashGenericArguments(BfTypeReference* typeRef, LookupContext* ctx, int& hash, int hashSeed);
|
||||
static int DoHash(BfType* type, LookupContext* ctx, bool allowRef, int hashSeed);
|
||||
static int Hash(BfType* type, LookupContext* ctx, bool allowRef = false, int hashSeed = 0);
|
||||
static int DirectHash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags = BfHashFlag_None, int hashSeed = 0);
|
||||
static int DoHash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags, int& hashSeed);
|
||||
static int Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags = BfHashFlag_None, int hashSeed = 0);
|
||||
static bool Equals(BfType* lhs, BfType* rhs, LookupContext* ctx);
|
||||
static bool Equals(BfType* lhs, BfTypeReference* rhs, LookupContext* ctx);
|
||||
static bool Equals(BfType* lhs, BfTypeReference* rhs, BfTypeDef* rhsTypeDef, LookupContext* ctx);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using System;
|
||||
namespace Tests
|
||||
{
|
||||
class Classes
|
||||
|
@ -22,5 +23,22 @@ namespace Tests
|
|||
{
|
||||
}
|
||||
}
|
||||
|
||||
class ClassA<T0, T1>
|
||||
{
|
||||
//public ClassA<T0, ClassA<T0, T1>> mVal;
|
||||
|
||||
public ClassA<T0, ClassA<T0, T1>> GetRecursive()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
static void TestBasics()
|
||||
{
|
||||
ClassA<int, float> ca = scope .();
|
||||
Test.Assert(typeof(decltype(ca.GetRecursive())) == typeof(ClassA<int, ClassA<int, float>>));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,6 +95,16 @@ namespace Tests
|
|||
}
|
||||
}
|
||||
|
||||
class IFaceA<T0, T1> where T0 : Dictionary<T1, int> where T1 : IHashable
|
||||
{
|
||||
Dictionary<T1, int> mDict;
|
||||
}
|
||||
|
||||
public static void MethodA<T0, T1>() where T0 : Dictionary<T1, int> where T1 : IHashable
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public static void TestBasics()
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue