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

Improved type constraint checks constrained by other generic params

This commit is contained in:
Brian Fiete 2022-06-11 07:56:43 -07:00
parent 10682e67af
commit 06ceaf617b
3 changed files with 55 additions and 26 deletions

View file

@ -11835,8 +11835,8 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
{
auto targetValue = mModule->CreateValueFromExpression(dynCastExpr->mTarget);
auto targetType = mModule->ResolveTypeRefAllowUnboundGenerics(dynCastExpr->mTypeRef, BfPopulateType_Data, false);
auto autoComplete = GetAutoComplete();
auto autoComplete = GetAutoComplete();
if (autoComplete != NULL)
{
autoComplete->CheckTypeRef(dynCastExpr->mTypeRef, false, true);
@ -11873,25 +11873,32 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
}
mModule->AddDependency(targetType, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
if (targetType->IsGenericParam())
{
wasGenericParamType = true;
//wasGenericParamType = false; // "was", not "is"
auto genericParamType = (BfGenericParamType*) targetType;
auto genericParam = mModule->GetGenericParamInstance(genericParamType);
auto typeConstraint = genericParam->mTypeConstraint;
if ((typeConstraint == NULL) && (genericParam->mGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_Interface)))
typeConstraint = mModule->mContext->mBfObjectType;
if ((typeConstraint == NULL) || (!typeConstraint->IsObject()))
BfGenericParamInstance* origGenericParam = NULL;
int pass = 0;
while ((targetType != NULL) && (targetType->IsGenericParam()))
{
mModule->Fail(StrFormat("The type parameter '%s' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' or 'interface' constraint",
genericParam->GetGenericParamDef()->mName.c_str()), dynCastExpr->mTypeRef);
return;
auto genericParamType = (BfGenericParamType*)targetType;
auto genericParam = mModule->GetGenericParamInstance(genericParamType);
if (pass == 0)
origGenericParam = genericParam;
auto typeConstraint = genericParam->mTypeConstraint;
if ((typeConstraint == NULL) && (genericParam->mGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_Interface)))
typeConstraint = mModule->mContext->mBfObjectType;
targetType = typeConstraint;
if (++pass >= 100) // Sanity - but we should have caught circular error before
break;
}
targetType = typeConstraint;
if ((targetType == NULL) || (!targetType->IsObjectOrInterface()))
{
mModule->Fail(StrFormat("The type parameter '%s' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' or 'interface' constraint",
origGenericParam->GetGenericParamDef()->mName.c_str()), dynCastExpr->mTypeRef);
return;
}
}
if (targetType->IsVar())
@ -11930,7 +11937,7 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
auto _CheckResult = [&]()
{
if ((mResult) && (origTargetType->IsGenericParam()))
mResult = mModule->GetDefaultTypedValue(origTargetType);
mResult = mModule->GetDefaultTypedValue(origTargetType, false, BfDefaultValueKind_Undef);
};
if ((targetValue.mType->IsNullable()) && (targetType->IsInterface()))
@ -12053,7 +12060,7 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
mModule->Fail("Invalid dynamic cast type", dynCastExpr->mTypeRef);
return;
}
BfTypeInstance* srcTypeInstance = targetValue.mType->ToTypeInstance();
BfTypeInstance* targetTypeInstance = targetType->ToTypeInstance();

View file

@ -1197,15 +1197,24 @@ void BfModule::TryInitVar(BfAstNode* checkNode, BfLocalVariable* localVar, BfTyp
bool isDynamicCast = false;
if (varType->IsGenericParam())
{
auto genericParamType = (BfGenericParamType*) varType;
auto genericParam = GetGenericParamInstance(genericParamType);
auto typeConstraint = genericParam->mTypeConstraint;
if ((typeConstraint == NULL) && (genericParam->mGenericParamFlags & BfGenericParamFlag_Class))
typeConstraint = mContext->mBfObjectType;
if (typeConstraint != NULL)
varType = typeConstraint;
initValue = GetDefaultTypedValue(varType);
{
int pass = 0;
while (varType->IsGenericParam())
{
auto genericParamType = (BfGenericParamType*)varType;
auto genericParam = GetGenericParamInstance(genericParamType);
auto typeConstraint = genericParam->mTypeConstraint;
if ((typeConstraint == NULL) && (genericParam->mGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_Interface)))
typeConstraint = mContext->mBfObjectType;
if (typeConstraint != NULL)
varType = typeConstraint;
else
break;
if (++pass >= 100) // Sanity - but we should have caught circular error before
break;
}
initValue = GetDefaultTypedValue(varType, false, BfDefaultValueKind_Undef);
}
BfTypeInstance* srcTypeInstance = initValue.mType->ToTypeInstance();