mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-09 03:52:19 +02:00
Fixed dynamic cast from class/interface constraint
This commit is contained in:
parent
a67a964142
commit
16a4b36b17
2 changed files with 29 additions and 12 deletions
|
@ -9510,6 +9510,8 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
|
||||||
autoComplete->CheckTypeRef(dynCastExpr->mTypeRef, false, true);
|
autoComplete->CheckTypeRef(dynCastExpr->mTypeRef, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto origTargetType = targetType;
|
||||||
|
|
||||||
if (!targetValue)
|
if (!targetValue)
|
||||||
return;
|
return;
|
||||||
if (!targetType)
|
if (!targetType)
|
||||||
|
@ -9547,24 +9549,23 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
|
||||||
auto genericParamType = (BfGenericParamType*) targetType;
|
auto genericParamType = (BfGenericParamType*) targetType;
|
||||||
auto genericParam = mModule->GetGenericParamInstance(genericParamType);
|
auto genericParam = mModule->GetGenericParamInstance(genericParamType);
|
||||||
auto typeConstraint = genericParam->mTypeConstraint;
|
auto typeConstraint = genericParam->mTypeConstraint;
|
||||||
if ((typeConstraint == NULL) && (genericParam->mGenericParamFlags & BfGenericParamFlag_Class))
|
if ((typeConstraint == NULL) && (genericParam->mGenericParamFlags & (BfGenericParamFlag_Class | BfGenericParamFlag_Interface)))
|
||||||
typeConstraint = mModule->mContext->mBfObjectType;
|
typeConstraint = mModule->mContext->mBfObjectType;
|
||||||
|
|
||||||
if ((typeConstraint == NULL) || (!typeConstraint->IsObject()))
|
if ((typeConstraint == NULL) || (!typeConstraint->IsObject()))
|
||||||
{
|
{
|
||||||
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' constraint",
|
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);
|
genericParam->GetGenericParamDef()->mName.c_str()), dynCastExpr->mTypeRef);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
targetType = typeConstraint;
|
targetType = typeConstraint;
|
||||||
targetValue = mModule->GetDefaultTypedValue(targetType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!targetType->IsObjectOrInterface()) && (!targetType->IsNullable()))
|
if ((!targetType->IsObjectOrInterface()) && (!targetType->IsNullable()))
|
||||||
{
|
{
|
||||||
mModule->Fail(StrFormat("The as operator must be used with a reference type or nullable type ('%s' is a non-nullable value type)",
|
mModule->Fail(StrFormat("The as operator must be used with a reference type or nullable type ('%s' is a non-nullable value type)",
|
||||||
mModule->TypeToString(targetType).c_str()), dynCastExpr->mTypeRef);
|
mModule->TypeToString(origTargetType).c_str()), dynCastExpr->mTypeRef);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9582,23 +9583,29 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
|
||||||
mResult = mModule->GetDefaultTypedValue(targetType);
|
mResult = mModule->GetDefaultTypedValue(targetType);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//targetType = typeConstraint;
|
|
||||||
targetValue = mModule->GetDefaultTypedValue(typeConstraint);
|
targetValue = mModule->GetDefaultTypedValue(typeConstraint);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto boolType = mModule->GetPrimitiveType(BfTypeCode_Boolean);
|
auto boolType = mModule->GetPrimitiveType(BfTypeCode_Boolean);
|
||||||
|
|
||||||
|
auto _CheckResult = [&]()
|
||||||
|
{
|
||||||
|
if ((mResult) && (origTargetType->IsGenericParam()))
|
||||||
|
mResult = mModule->GetDefaultTypedValue(origTargetType);
|
||||||
|
};
|
||||||
|
|
||||||
if ((targetValue.mType->IsNullable()) && (targetType->IsInterface()))
|
if ((targetValue.mType->IsNullable()) && (targetType->IsInterface()))
|
||||||
{
|
{
|
||||||
mResult = mModule->Cast(dynCastExpr, targetValue, targetType, BfCastFlags_SilentFail);
|
mResult = mModule->Cast(dynCastExpr, targetValue, targetType, BfCastFlags_SilentFail);
|
||||||
if (!mResult)
|
if (!mResult)
|
||||||
{
|
{
|
||||||
mModule->Warn(0, StrFormat("Conversion from '%s' to '%s' will always be null",
|
mModule->Warn(0, StrFormat("Conversion from '%s' to '%s' will always be null",
|
||||||
mModule->TypeToString(targetValue.mType).c_str(), mModule->TypeToString(targetType).c_str()), dynCastExpr->mAsToken);
|
mModule->TypeToString(targetValue.mType).c_str(), mModule->TypeToString(origTargetType).c_str()), dynCastExpr->mAsToken);
|
||||||
mResult = BfTypedValue(mModule->GetDefaultValue(targetType), targetType);
|
mResult = BfTypedValue(mModule->GetDefaultValue(origTargetType), origTargetType);
|
||||||
}
|
}
|
||||||
return;
|
_CheckResult();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetValue.mType->IsValueTypeOrValueTypePtr())
|
if (targetValue.mType->IsValueTypeOrValueTypePtr())
|
||||||
|
@ -9624,6 +9631,7 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
|
||||||
hasValueAddr = mModule->mBfIRBuilder->CreateInBoundsGEP(allocaInst, 0, 0); // value
|
hasValueAddr = mModule->mBfIRBuilder->CreateInBoundsGEP(allocaInst, 0, 0); // value
|
||||||
mModule->mBfIRBuilder->CreateStore(targetValue.mValue, hasValueAddr);
|
mModule->mBfIRBuilder->CreateStore(targetValue.mValue, hasValueAddr);
|
||||||
mResult = BfTypedValue(allocaInst, targetType, true);
|
mResult = BfTypedValue(allocaInst, targetType, true);
|
||||||
|
_CheckResult();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9643,6 +9651,7 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mResult = BfTypedValue(mModule->GetDefaultValue(targetType), targetType);
|
mResult = BfTypedValue(mModule->GetDefaultValue(targetType), targetType);
|
||||||
|
_CheckResult();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9689,7 +9698,7 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
|
||||||
|
|
||||||
mModule->AddBasicBlock(endBB);
|
mModule->AddBasicBlock(endBB);
|
||||||
mResult = BfTypedValue(allocaInst, targetType, true);
|
mResult = BfTypedValue(allocaInst, targetType, true);
|
||||||
|
_CheckResult();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9721,6 +9730,7 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
|
||||||
|
|
||||||
auto castedValue = mModule->mBfIRBuilder->CreateBitCast(targetValue.mValue, mModule->mBfIRBuilder->MapType(targetTypeInstance));
|
auto castedValue = mModule->mBfIRBuilder->CreateBitCast(targetValue.mValue, mModule->mBfIRBuilder->MapType(targetTypeInstance));
|
||||||
mResult = BfTypedValue(castedValue, targetTypeInstance);
|
mResult = BfTypedValue(castedValue, targetTypeInstance);
|
||||||
|
_CheckResult();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if ((!targetType->IsInterface()) && (!mModule->TypeIsSubTypeOf(targetTypeInstance, srcTypeInstance)))
|
else if ((!targetType->IsInterface()) && (!mModule->TypeIsSubTypeOf(targetTypeInstance, srcTypeInstance)))
|
||||||
|
@ -9732,6 +9742,7 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
|
||||||
if (autoComplete != NULL)
|
if (autoComplete != NULL)
|
||||||
{
|
{
|
||||||
mResult = mModule->GetDefaultTypedValue(targetType);
|
mResult = mModule->GetDefaultTypedValue(targetType);
|
||||||
|
_CheckResult();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9755,6 +9766,7 @@ void BfExprEvaluator::Visit(BfDynamicCastExpression* dynCastExpr)
|
||||||
|
|
||||||
mModule->AddBasicBlock(endBB);
|
mModule->AddBasicBlock(endBB);
|
||||||
mResult = BfTypedValue(irb->CreateLoad(targetVal), targetType);
|
mResult = BfTypedValue(irb->CreateLoad(targetVal), targetType);
|
||||||
|
_CheckResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfExprEvaluator::Visit(BfCastExpression* castExpr)
|
void BfExprEvaluator::Visit(BfCastExpression* castExpr)
|
||||||
|
|
|
@ -190,6 +190,11 @@ namespace Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void TestCast<T, TI>(T val) where T : class where TI : interface
|
||||||
|
{
|
||||||
|
TI iface = val as TI;
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public static void TestBasics()
|
public static void TestBasics()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue