mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-09 03:52:19 +02:00
Improved extern type constraints
This commit is contained in:
parent
99989d5472
commit
32cd6d8841
8 changed files with 280 additions and 85 deletions
|
@ -18774,6 +18774,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
||||||
BfBinaryOp findBinaryOp = binaryOp;
|
BfBinaryOp findBinaryOp = binaryOp;
|
||||||
|
|
||||||
bool isComparison = (binaryOp >= BfBinaryOp_Equality) && (binaryOp <= BfBinaryOp_LessThanOrEqual);
|
bool isComparison = (binaryOp >= BfBinaryOp_Equality) && (binaryOp <= BfBinaryOp_LessThanOrEqual);
|
||||||
|
BfBinaryOp oppositeBinaryOp = BfGetOppositeBinaryOp(findBinaryOp);
|
||||||
|
|
||||||
for (int pass = 0; pass < 2; pass++)
|
for (int pass = 0; pass < 2; pass++)
|
||||||
{
|
{
|
||||||
|
@ -18802,8 +18803,6 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
||||||
|
|
||||||
bool invertResult = false;
|
bool invertResult = false;
|
||||||
|
|
||||||
BfBinaryOp oppositeBinaryOp = BfGetOppositeBinaryOp(findBinaryOp);
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
auto entry = baseClassWalker.Next();
|
auto entry = baseClassWalker.Next();
|
||||||
|
@ -18930,49 +18929,80 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto _CheckBinaryOp = [&](BfGenericParamInstance* genericParam)
|
||||||
|
{
|
||||||
|
for (auto& opConstraint : genericParam->mOperatorConstraints)
|
||||||
|
{
|
||||||
|
BfType* returnType = genericParam->mExternType;
|
||||||
|
bool works = false;
|
||||||
|
if (opConstraint.mBinaryOp == findBinaryOp)
|
||||||
|
{
|
||||||
|
if ((mModule->CanCast(args[0].mTypedValue, opConstraint.mLeftType)) &&
|
||||||
|
(mModule->CanCast(args[1].mTypedValue, opConstraint.mRightType)))
|
||||||
|
{
|
||||||
|
works = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (opConstraint.mBinaryOp == oppositeBinaryOp)
|
||||||
|
{
|
||||||
|
if ((mModule->CanCast(args[0].mTypedValue, opConstraint.mRightType)) &&
|
||||||
|
(mModule->CanCast(args[1].mTypedValue, opConstraint.mLeftType)))
|
||||||
|
{
|
||||||
|
works = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((isComparison) && (opConstraint.mBinaryOp == BfBinaryOp_Compare))
|
||||||
|
{
|
||||||
|
if ((mModule->CanCast(args[0].mTypedValue, opConstraint.mLeftType)) &&
|
||||||
|
(mModule->CanCast(args[1].mTypedValue, opConstraint.mRightType)))
|
||||||
|
{
|
||||||
|
works = true;
|
||||||
|
}
|
||||||
|
else if ((mModule->CanCast(args[0].mTypedValue, opConstraint.mRightType)) &&
|
||||||
|
(mModule->CanCast(args[1].mTypedValue, opConstraint.mLeftType)))
|
||||||
|
{
|
||||||
|
works = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (works)
|
||||||
|
{
|
||||||
|
returnType = mModule->GetPrimitiveType(BfTypeCode_Boolean);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (works)
|
||||||
|
{
|
||||||
|
BF_ASSERT(genericParam->mExternType != NULL);
|
||||||
|
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), returnType);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
// Check method generic constraints
|
// Check method generic constraints
|
||||||
if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized) && (mModule->mCurMethodInstance->mMethodInfoEx != NULL))
|
if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized) && (mModule->mCurMethodInstance->mMethodInfoEx != NULL))
|
||||||
{
|
{
|
||||||
for (int genericParamIdx = 0; genericParamIdx < mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
|
for (int genericParamIdx = 0; genericParamIdx < mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
|
||||||
{
|
{
|
||||||
auto genericParam = mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
|
auto genericParam = mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
|
||||||
for (auto& opConstraint : genericParam->mOperatorConstraints)
|
if (_CheckBinaryOp(genericParam))
|
||||||
{
|
|
||||||
if (opConstraint.mBinaryOp == findBinaryOp)
|
|
||||||
{
|
|
||||||
if ((mModule->CanCast(args[0].mTypedValue, opConstraint.mLeftType)) &&
|
|
||||||
(mModule->CanCast(args[1].mTypedValue, opConstraint.mRightType)))
|
|
||||||
{
|
|
||||||
BF_ASSERT(genericParam->mExternType != NULL);
|
|
||||||
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check type generic constraints
|
// Check type generic constraints
|
||||||
if ((mModule->mCurTypeInstance->IsGenericTypeInstance()) && (mModule->mCurTypeInstance->IsUnspecializedType()))
|
if ((mModule->mCurTypeInstance->IsGenericTypeInstance()) && (mModule->mCurTypeInstance->IsUnspecializedType()))
|
||||||
{
|
{
|
||||||
auto genericTypeInst = (BfTypeInstance*)mModule->mCurTypeInstance;
|
SizedArray<BfGenericParamInstance*, 4> genericParams;
|
||||||
for (int genericParamIdx = 0; genericParamIdx < genericTypeInst->mGenericTypeInfo->mGenericParams.size(); genericParamIdx++)
|
mModule->GetActiveTypeGenericParamInstances(genericParams);
|
||||||
|
for (auto genericParam : genericParams)
|
||||||
{
|
{
|
||||||
auto genericParam = mModule->GetGenericTypeParamInstance(genericParamIdx);
|
if (_CheckBinaryOp(genericParam))
|
||||||
for (auto& opConstraint : genericParam->mOperatorConstraints)
|
|
||||||
{
|
|
||||||
if (opConstraint.mBinaryOp == findBinaryOp)
|
|
||||||
{
|
|
||||||
if ((mModule->CanCast(args[0].mTypedValue, opConstraint.mLeftType)) &&
|
|
||||||
(mModule->CanCast(args[1].mTypedValue, opConstraint.mRightType)))
|
|
||||||
{
|
|
||||||
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((!foundOp) || (pass == 1))
|
if ((!foundOp) || (pass == 1))
|
||||||
break;
|
break;
|
||||||
|
@ -19129,6 +19159,8 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((binaryOp == BfBinaryOp_Equality) || (binaryOp == BfBinaryOp_StrictEquality) || (binaryOp == BfBinaryOp_InEquality) || (binaryOp == BfBinaryOp_StrictInEquality))
|
||||||
|
{
|
||||||
if (resultType->IsInterface())
|
if (resultType->IsInterface())
|
||||||
{
|
{
|
||||||
// Compare as objects instead
|
// Compare as objects instead
|
||||||
|
@ -19166,6 +19198,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (resultType->IsTypedPrimitive())
|
if (resultType->IsTypedPrimitive())
|
||||||
{
|
{
|
||||||
|
|
|
@ -569,6 +569,11 @@ struct BfIRTypeData
|
||||||
|
|
||||||
TypeKind mKind;
|
TypeKind mKind;
|
||||||
int mId;
|
int mId;
|
||||||
|
|
||||||
|
operator bool()
|
||||||
|
{
|
||||||
|
return (mId != -1);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BfIRType : public BfIRTypeData
|
struct BfIRType : public BfIRTypeData
|
||||||
|
@ -587,11 +592,6 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
BfIRType(const BfIRValue& val) { mKind = TypeKind_Stream; mId = val.mId; }
|
BfIRType(const BfIRValue& val) { mKind = TypeKind_Stream; mId = val.mId; }
|
||||||
|
|
||||||
operator bool()
|
|
||||||
{
|
|
||||||
return (mId != -1);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BfIRBlock : public BfIRValue
|
struct BfIRBlock : public BfIRValue
|
||||||
|
|
|
@ -12773,7 +12773,7 @@ BfLocalVariable* BfModule::GetThisVariable()
|
||||||
|
|
||||||
bool BfModule::IsInGeneric()
|
bool BfModule::IsInGeneric()
|
||||||
{
|
{
|
||||||
return (mCurMethodInstance->GetNumGenericArguments() != 0) || (mCurTypeInstance->IsGenericTypeInstance());
|
return ((mCurMethodInstance != NULL) && (mCurMethodInstance->GetNumGenericArguments() != 0)) || (mCurTypeInstance->IsGenericTypeInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BfModule::InDefinitionSection()
|
bool BfModule::InDefinitionSection()
|
||||||
|
|
|
@ -1681,6 +1681,7 @@ public:
|
||||||
bool IsUnboundGeneric(BfType* type);
|
bool IsUnboundGeneric(BfType* type);
|
||||||
BfGenericParamInstance* GetGenericTypeParamInstance(int paramIdx);
|
BfGenericParamInstance* GetGenericTypeParamInstance(int paramIdx);
|
||||||
BfGenericParamInstance* GetGenericParamInstance(BfGenericParamType* type);
|
BfGenericParamInstance* GetGenericParamInstance(BfGenericParamType* type);
|
||||||
|
void GetActiveTypeGenericParamInstances(SizedArray<BfGenericParamInstance*, 4>& genericParamInstance);
|
||||||
BfTypeInstance* GetBaseType(BfTypeInstance* typeInst);
|
BfTypeInstance* GetBaseType(BfTypeInstance* typeInst);
|
||||||
void HandleTypeGenericParamRef(BfAstNode* refNode, BfTypeDef* typeDef, int typeGenericParamIdx);
|
void HandleTypeGenericParamRef(BfAstNode* refNode, BfTypeDef* typeDef, int typeGenericParamIdx);
|
||||||
void HandleMethodGenericParamRef(BfAstNode* refNode, BfTypeDef* typeDef, BfMethodDef* methodDef, int typeGenericParamIdx);
|
void HandleMethodGenericParamRef(BfAstNode* refNode, BfTypeDef* typeDef, BfMethodDef* methodDef, int typeGenericParamIdx);
|
||||||
|
|
|
@ -77,7 +77,19 @@ BfGenericExtensionEntry* BfModule::BuildGenericExtensionInfo(BfTypeInstance* gen
|
||||||
|
|
||||||
for (int externConstraintIdx = 0; externConstraintIdx < (int)partialTypeDef->mExternalConstraints.size(); externConstraintIdx++)
|
for (int externConstraintIdx = 0; externConstraintIdx < (int)partialTypeDef->mExternalConstraints.size(); externConstraintIdx++)
|
||||||
{
|
{
|
||||||
|
auto& genericConstraint = partialTypeDef->mExternalConstraints[externConstraintIdx];
|
||||||
|
|
||||||
auto genericParamInstance = new BfGenericTypeParamInstance(partialTypeDef, externConstraintIdx + (int)partialTypeDef->mGenericParamDefs.size());
|
auto genericParamInstance = new BfGenericTypeParamInstance(partialTypeDef, externConstraintIdx + (int)partialTypeDef->mGenericParamDefs.size());
|
||||||
|
genericParamInstance->mExternType = ResolveTypeRef(genericConstraint.mTypeRef);
|
||||||
|
|
||||||
|
auto autoComplete = mCompiler->GetAutoComplete();
|
||||||
|
if (autoComplete != NULL)
|
||||||
|
autoComplete->CheckTypeRef(genericConstraint.mTypeRef, false);
|
||||||
|
|
||||||
|
if (genericParamInstance->mExternType == NULL)
|
||||||
|
genericParamInstance->mExternType = GetPrimitiveType(BfTypeCode_Var);
|
||||||
|
|
||||||
|
ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType());
|
||||||
genericExEntry->mGenericParams.push_back(genericParamInstance);
|
genericExEntry->mGenericParams.push_back(genericParamInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,18 +155,34 @@ bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
|
||||||
if (!partialTypeDef->IsExtension())
|
if (!partialTypeDef->IsExtension())
|
||||||
{
|
{
|
||||||
typeState.mCurTypeDef = partialTypeDef;
|
typeState.mCurTypeDef = partialTypeDef;
|
||||||
for (int paramIdx = startDefGenericParamIdx; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.size(); paramIdx++)
|
for (int paramIdx = startDefGenericParamIdx; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mGenericParams.size(); paramIdx++)
|
||||||
{
|
{
|
||||||
auto genericParamDef = typeDef->mGenericParamDefs[paramIdx];
|
|
||||||
auto genericParamInstance = genericTypeInst->mGenericTypeInfo->mGenericParams[paramIdx];
|
auto genericParamInstance = genericTypeInst->mGenericTypeInfo->mGenericParams[paramIdx];
|
||||||
|
auto genericParamDef = genericParamInstance->GetGenericParamDef();
|
||||||
|
|
||||||
|
if (paramIdx < (int)typeDef->mGenericParamDefs.size())
|
||||||
|
{
|
||||||
|
genericParamInstance->mExternType = GetGenericParamType(BfGenericParamKind_Type, paramIdx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto externConstraintDef = genericParamInstance->GetExternConstraintDef();
|
||||||
|
genericParamInstance->mExternType = ResolveTypeRef(externConstraintDef->mTypeRef);
|
||||||
|
if (genericParamInstance->mExternType == NULL)
|
||||||
|
genericParamInstance->mExternType = GetPrimitiveType(BfTypeCode_Var);
|
||||||
|
}
|
||||||
|
|
||||||
ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType());
|
ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType());
|
||||||
|
|
||||||
|
if (genericParamDef != NULL)
|
||||||
|
{
|
||||||
for (auto nameNode : genericParamDef->mNameNodes)
|
for (auto nameNode : genericParamDef->mNameNodes)
|
||||||
{
|
{
|
||||||
HandleTypeGenericParamRef(nameNode, typeDef, paramIdx);
|
HandleTypeGenericParamRef(nameNode, typeDef, paramIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto genericExEntry = BuildGenericExtensionInfo(genericTypeInst, partialTypeDef);
|
auto genericExEntry = BuildGenericExtensionInfo(genericTypeInst, partialTypeDef);
|
||||||
|
@ -170,7 +198,18 @@ bool BfModule::BuildGenericParams(BfType* resolvedTypeRef)
|
||||||
genericParamSource.mCheckAccessibility = false;
|
genericParamSource.mCheckAccessibility = false;
|
||||||
genericParamSource.mTypeInstance = genericTypeInst;
|
genericParamSource.mTypeInstance = genericTypeInst;
|
||||||
BfError* error = NULL;
|
BfError* error = NULL;
|
||||||
if (!CheckGenericConstraints(genericParamSource, genericTypeInst->mGenericTypeInfo->mTypeGenericArguments[paramIdx], NULL, genericParamInstance, NULL, &error))
|
|
||||||
|
BfType* genericArg;
|
||||||
|
if (paramIdx < (int)genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.size())
|
||||||
|
{
|
||||||
|
genericArg = genericTypeInst->mGenericTypeInfo->mTypeGenericArguments[paramIdx];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
genericArg = genericParamInstance->mExternType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((genericArg == NULL) || (!CheckGenericConstraints(genericParamSource, genericArg, NULL, genericParamInstance, NULL, &error)))
|
||||||
{
|
{
|
||||||
genericExEntry->mConstraintsPassed = false;
|
genericExEntry->mConstraintsPassed = false;
|
||||||
}
|
}
|
||||||
|
@ -274,7 +313,7 @@ bool BfModule::ValidateGenericConstraints(BfTypeReference* typeRef, BfTypeInstan
|
||||||
}
|
}
|
||||||
|
|
||||||
BfError* error = NULL;
|
BfError* error = NULL;
|
||||||
if (!CheckGenericConstraints(BfGenericParamSource(genericTypeInst), genericArg, typeRef, genericParamInstance, NULL, &error))
|
if ((genericArg == NULL) || (!CheckGenericConstraints(BfGenericParamSource(genericTypeInst), genericArg, typeRef, genericParamInstance, NULL, &error)))
|
||||||
{
|
{
|
||||||
genericTypeInst->mGenericTypeInfo->mHadValidateErrors = true;
|
genericTypeInst->mGenericTypeInfo->mHadValidateErrors = true;
|
||||||
return false;
|
return false;
|
||||||
|
@ -6511,6 +6550,12 @@ BfGenericParamInstance* BfModule::GetGenericTypeParamInstance(int genericParamId
|
||||||
PopulateType(genericTypeInst, BfPopulateType_Declaration);
|
PopulateType(genericTypeInst, BfPopulateType_Declaration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (genericParamIdx >= (int)genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.size())
|
||||||
|
{
|
||||||
|
// Extern constraints should always be directly used - they don't get extended
|
||||||
|
return genericTypeInst->mGenericTypeInfo->mGenericParams[genericParamIdx];
|
||||||
|
}
|
||||||
|
|
||||||
if (genericTypeInst->mGenericTypeInfo->mGenericExtensionInfo != NULL)
|
if (genericTypeInst->mGenericTypeInfo->mGenericExtensionInfo != NULL)
|
||||||
{
|
{
|
||||||
auto activeTypeDef = GetActiveTypeDef(NULL, true);
|
auto activeTypeDef = GetActiveTypeDef(NULL, true);
|
||||||
|
@ -6539,6 +6584,58 @@ BfGenericParamInstance* BfModule::GetGenericTypeParamInstance(int genericParamId
|
||||||
return genericTypeInst->mGenericTypeInfo->mGenericParams[genericParamIdx];
|
return genericTypeInst->mGenericTypeInfo->mGenericParams[genericParamIdx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfModule::GetActiveTypeGenericParamInstances(SizedArray<BfGenericParamInstance*, 4>& genericParamInstances)
|
||||||
|
{
|
||||||
|
// When we're evaluating a method, make sure the params refer back to that method context
|
||||||
|
auto curTypeInstance = mCurTypeInstance;
|
||||||
|
if (mCurMethodInstance != NULL)
|
||||||
|
curTypeInstance = mCurMethodInstance->mMethodInstanceGroup->mOwner;
|
||||||
|
|
||||||
|
BfTypeInstance* genericTypeInst = curTypeInstance->ToGenericTypeInstance();
|
||||||
|
if ((genericTypeInst->IsIncomplete()) && (genericTypeInst->mGenericTypeInfo->mGenericParams.size() == 0))
|
||||||
|
{
|
||||||
|
// Set this to NULL so we don't recurse infinitely
|
||||||
|
SetAndRestoreValue<BfTypeInstance*> prevTypeInst(mCurTypeInstance, NULL);
|
||||||
|
PopulateType(genericTypeInst, BfPopulateType_Declaration);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (genericTypeInst->mGenericTypeInfo->mGenericExtensionInfo != NULL)
|
||||||
|
{
|
||||||
|
auto activeTypeDef = GetActiveTypeDef(NULL, true);
|
||||||
|
if ((activeTypeDef->mTypeDeclaration != genericTypeInst->mTypeDef->mTypeDeclaration) && (activeTypeDef->IsExtension()))
|
||||||
|
{
|
||||||
|
BfTypeDef* lookupTypeDef = activeTypeDef;
|
||||||
|
while (lookupTypeDef->mNestDepth > genericTypeInst->mTypeDef->mNestDepth)
|
||||||
|
lookupTypeDef = lookupTypeDef->mOuterType;
|
||||||
|
|
||||||
|
BfGenericExtensionEntry* genericExEntry;
|
||||||
|
if (genericTypeInst->mGenericTypeInfo->mGenericExtensionInfo->mExtensionMap.TryGetValue(lookupTypeDef, &genericExEntry))
|
||||||
|
{
|
||||||
|
for (auto entry : genericExEntry->mGenericParams)
|
||||||
|
genericParamInstances.Add(entry);
|
||||||
|
|
||||||
|
auto genericTypeInfo = genericTypeInst->mGenericTypeInfo;
|
||||||
|
|
||||||
|
// Add root extern constraints - they don't get extended
|
||||||
|
for (int genericParamIdx = (int)genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.size(); genericParamIdx < genericTypeInst->mGenericTypeInfo->mGenericParams.size(); genericParamIdx++)
|
||||||
|
genericParamInstances.Add(genericTypeInst->mGenericTypeInfo->mGenericParams[genericParamIdx]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((mCompiler->mResolvePassData == NULL) || (mCompiler->mResolvePassData->mAutoComplete == NULL))
|
||||||
|
{
|
||||||
|
BFMODULE_FATAL(this, "Invalid GetGenericParamInstance with extension");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BF_ASSERT(genericTypeInst != NULL);
|
||||||
|
for (auto entry : genericTypeInst->mGenericTypeInfo->mGenericParams)
|
||||||
|
genericParamInstances.Add(entry);
|
||||||
|
}
|
||||||
|
|
||||||
BfGenericParamInstance* BfModule::GetGenericParamInstance(BfGenericParamType* type)
|
BfGenericParamInstance* BfModule::GetGenericParamInstance(BfGenericParamType* type)
|
||||||
{
|
{
|
||||||
if (type->mGenericParamKind == BfGenericParamKind_Method)
|
if (type->mGenericParamKind == BfGenericParamKind_Method)
|
||||||
|
@ -8939,7 +9036,15 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
||||||
constExprType->mValue = result;
|
constExprType->mValue = result;
|
||||||
|
|
||||||
resolvedEntry->mValue = constExprType;
|
resolvedEntry->mValue = constExprType;
|
||||||
BF_ASSERT(BfResolvedTypeSet::Hash(constExprType, &lookupCtx) == resolvedEntry->mHash);
|
#ifdef _DEBUG
|
||||||
|
if (BfResolvedTypeSet::Hash(constExprType, &lookupCtx) != resolvedEntry->mHash)
|
||||||
|
{
|
||||||
|
int refHash = BfResolvedTypeSet::Hash(typeRef, &lookupCtx);
|
||||||
|
int typeHash = BfResolvedTypeSet::Hash(constExprType, &lookupCtx);
|
||||||
|
BF_ASSERT(refHash == typeHash);
|
||||||
|
}
|
||||||
|
BF_ASSERT(BfResolvedTypeSet::Equals(constExprType, typeRef, &lookupCtx));
|
||||||
|
#endif
|
||||||
|
|
||||||
populateModule->InitType(constExprType, populateType);
|
populateModule->InitType(constExprType, populateType);
|
||||||
return constExprType;
|
return constExprType;
|
||||||
|
@ -9534,6 +9639,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
|
|
||||||
if (allowCast)
|
if (allowCast)
|
||||||
{
|
{
|
||||||
|
PopulateType(toType);
|
||||||
if (toType->IsValuelessType())
|
if (toType->IsValuelessType())
|
||||||
return BfIRValue::sValueless;
|
return BfIRValue::sValueless;
|
||||||
if (ignoreWrites)
|
if (ignoreWrites)
|
||||||
|
@ -10453,21 +10559,21 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
// Check type generic constraints
|
// Check type generic constraints
|
||||||
if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsGenericTypeInstance()) && (mCurTypeInstance->IsUnspecializedType()))
|
if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsGenericTypeInstance()) && (mCurTypeInstance->IsUnspecializedType()))
|
||||||
{
|
{
|
||||||
auto genericTypeInst = (BfTypeInstance*)mCurTypeInstance;
|
SizedArray<BfGenericParamInstance*, 4> genericParams;
|
||||||
for (int genericParamIdx = 0; genericParamIdx < genericTypeInst->mGenericTypeInfo->mGenericParams.size(); genericParamIdx++)
|
GetActiveTypeGenericParamInstances(genericParams);
|
||||||
|
for (auto genericParam : genericParams)
|
||||||
{
|
{
|
||||||
auto genericParam = GetGenericTypeParamInstance(genericParamIdx);
|
|
||||||
for (auto& opConstraint : genericParam->mOperatorConstraints)
|
for (auto& opConstraint : genericParam->mOperatorConstraints)
|
||||||
{
|
{
|
||||||
if ((opConstraint.mCastToken == BfToken_Implicit) ||
|
if ((opConstraint.mCastToken == BfToken_Implicit) ||
|
||||||
((explicitCast) && (opConstraint.mCastToken == BfToken_Explicit)))
|
((explicitCast) && (opConstraint.mCastToken == BfToken_Explicit)))
|
||||||
{
|
{
|
||||||
// If we can convert OUR fromVal to the constraint's fromVal then we may match
|
// If we can convert OUR fromVal to the constraint's fromVal then we may match
|
||||||
if (CanCast(typedVal, opConstraint.mRightType))
|
if (CanCast(typedVal, opConstraint.mRightType, BfCastFlags_NoConversionOperator))
|
||||||
{
|
{
|
||||||
// .. and we can convert the constraint's toType to OUR toType then we're good
|
// .. and we can convert the constraint's toType to OUR toType then we're good
|
||||||
auto opToVal = genericParam->mExternType;
|
auto opToVal = genericParam->mExternType;
|
||||||
if (CanCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType))
|
if (CanCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType, BfCastFlags_NoConversionOperator))
|
||||||
return mBfIRBuilder->GetFakeVal();
|
return mBfIRBuilder->GetFakeVal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2023,10 +2023,21 @@ bool BfTypeInstance::IsTypeMemberIncluded(BfTypeDef* typeDef, BfTypeDef* activeT
|
||||||
|
|
||||||
for (int genericIdx = 0; genericIdx < (int)declConstraints->size(); genericIdx++)
|
for (int genericIdx = 0; genericIdx < (int)declConstraints->size(); genericIdx++)
|
||||||
{
|
{
|
||||||
auto genericType = mGenericTypeInfo->mTypeGenericArguments[genericIdx];
|
|
||||||
|
|
||||||
auto declGenericParam = (*declConstraints)[genericIdx];
|
auto declGenericParam = (*declConstraints)[genericIdx];
|
||||||
if (!module->CheckGenericConstraints(BfGenericParamSource(), genericType, NULL, declGenericParam))
|
|
||||||
|
BfType* genericArg;
|
||||||
|
if (genericIdx < (int)mGenericTypeInfo->mTypeGenericArguments.size())
|
||||||
|
{
|
||||||
|
genericArg = mGenericTypeInfo->mTypeGenericArguments[genericIdx];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
genericArg = declGenericParam->mExternType;
|
||||||
|
}
|
||||||
|
|
||||||
|
//auto genericType = mGenericTypeInfo->mTypeGenericArguments[genericIdx];
|
||||||
|
|
||||||
|
if ((genericArg == NULL) || (!module->CheckGenericConstraints(BfGenericParamSource(), genericArg, NULL, declGenericParam)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
//if (!mModule->AreConstraintsSubset((*declConstraints)[genericIdx], (*activeConstraints)[genericIdx]))
|
//if (!mModule->AreConstraintsSubset((*declConstraints)[genericIdx], (*activeConstraints)[genericIdx]))
|
||||||
|
|
|
@ -2759,8 +2759,8 @@ void BfSystem::AddToCompositePartial(BfPassInstance* passInstance, BfTypeDef* co
|
||||||
typeDef->mTypeDeclaration = partialTypeDef->mTypeDeclaration;
|
typeDef->mTypeDeclaration = partialTypeDef->mTypeDeclaration;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& externConstraint : partialTypeDef->mExternalConstraints)
|
// for (auto& externConstraint : partialTypeDef->mExternalConstraints)
|
||||||
typeDef->mExternalConstraints.Add(externConstraint);
|
// typeDef->mExternalConstraints.Add(externConstraint);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge attributes together
|
// Merge attributes together
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#pragma warning disable 168
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
|
||||||
|
@ -32,6 +34,48 @@ namespace Tests
|
||||||
return Method2<Dictionary<K, V>.Enumerator, (K key, V value)>(param1.GetEnumerator());
|
return Method2<Dictionary<K, V>.Enumerator, (K key, V value)>(param1.GetEnumerator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct StructA
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClassA<T> where float : operator T * T where char8 : operator implicit T
|
||||||
|
{
|
||||||
|
public static float DoMul(T lhs, T rhs)
|
||||||
|
{
|
||||||
|
char8 val = lhs;
|
||||||
|
return lhs * rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ClassA<T> where double : operator T - T where StructA : operator explicit T
|
||||||
|
{
|
||||||
|
public static double DoSub(T lhs, T rhs)
|
||||||
|
{
|
||||||
|
StructA sa = (StructA)lhs;
|
||||||
|
return lhs - rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ClassA<T> where int16 : operator T + T where int8 : operator implicit T
|
||||||
|
{
|
||||||
|
public static double DoAdd(T lhs, T rhs)
|
||||||
|
{
|
||||||
|
int8 val = lhs;
|
||||||
|
double d = lhs * rhs;
|
||||||
|
return lhs + rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Test0<T>(T val)
|
||||||
|
where float : operator T * T where char8 : operator implicit T
|
||||||
|
where int16 : operator T + T where int8 : operator implicit T
|
||||||
|
{
|
||||||
|
ClassA<T> ca = scope .();
|
||||||
|
ClassA<T>.DoMul(val, val);
|
||||||
|
ClassA<T>.DoAdd(val, val);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public static void TestBasics()
|
public static void TestBasics()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue