1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 03:28:20 +02:00

Made implicit tuple cast check names, fixed explicit tuple cast

This commit is contained in:
Brian Fiete 2020-01-24 10:36:22 -08:00
parent 1f77412536
commit fd64aa64d9
12 changed files with 92 additions and 87 deletions

View file

@ -2119,7 +2119,7 @@ namespace System
return false;
}
public (char32 c, int8 len) GetChar32(int idx)
public (char32 c, int8 length) GetChar32(int idx)
{
Debug.Assert((uint)idx < (uint)mLength);
char8* ptr = Ptr;
@ -2131,7 +2131,7 @@ namespace System
return UTF8.Decode(ptr + idx, mLength - idx);
}
public (char32 c, int idx, int8 len) GetChar32WithBacktrack(int idx)
public (char32 c, int idx, int8 length) GetChar32WithBacktrack(int idx)
{
Debug.Assert((uint)idx < (uint)mLength);
char8* ptr = Ptr;

View file

@ -44,7 +44,7 @@ namespace System.Text
return UTF8.sTrailingBytesForUTF8[firstChar] + 1;
}
public static (char32 c, int8 cSize) Decode(char8* buf, int bufSize)
public static (char32 c, int8 length) Decode(char8* buf, int bufSize)
{
char32 c = *buf;
int8 trailingBytes = UTF8.sTrailingBytesForUTF8[c];

View file

@ -721,7 +721,7 @@ void BfAutoComplete::AddSelfResultTypeMembers(BfTypeInstance* typeInst, BfTypeIn
if ((fieldDef->mIsStatic) && (CheckProtection(fieldDef->mProtection, allowProtected, allowPrivate)))
{
if (!mModule->CanImplicitlyCast(BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), fieldInst.mResolvedType), selfType))
if (!mModule->CanCast(BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), fieldInst.mResolvedType), selfType))
continue;
if ((!typeInst->IsTypeMemberIncluded(fieldDef->mDeclaringType, activeTypeDef, mModule)) ||
@ -772,7 +772,7 @@ void BfAutoComplete::AddSelfResultTypeMembers(BfTypeInstance* typeInst, BfTypeIn
continue;
if (methodInstance->mReturnType->IsUnspecializedType())
continue;
if (!mModule->CanImplicitlyCast(BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), methodInstance->mReturnType), selfType))
if (!mModule->CanCast(BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), methodInstance->mReturnType), selfType))
continue;
if (canUseMethod)

View file

@ -240,7 +240,7 @@ bool BfConstResolver::PrepareMethodArguments(BfAstNode* targetSrc, BfMethodMatch
{
if (!arguments[argIdx].mTypedValue.mValue)
return false;
if (mModule->CanImplicitlyCast(arguments[argIdx].mTypedValue, wantType))
if (mModule->CanCast(arguments[argIdx].mTypedValue, wantType))
isDirectPass = true;
}

View file

@ -316,14 +316,14 @@ bool BfMethodMatcher::InferGenericArgument(BfMethodInstance* methodInstance, BfT
if ((prevGenericMethodArg->IsIntUnknown()) && (!argType->IsIntUnknown()))
{
// Old int fits into new argType, that's good
if (mModule->CanImplicitlyCast(BfTypedValue(prevArgValue, prevGenericMethodArg), argType))
if (mModule->CanCast(BfTypedValue(prevArgValue, prevGenericMethodArg), argType))
{
_SetGeneric();
return true;
}
// Doesn't fit, upgrade type to 'int'
argType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
if (mModule->CanImplicitlyCast(BfTypedValue(prevArgValue, prevGenericMethodArg), argType))
if (mModule->CanCast(BfTypedValue(prevArgValue, prevGenericMethodArg), argType))
{
_SetGeneric();
return true;
@ -333,7 +333,7 @@ bool BfMethodMatcher::InferGenericArgument(BfMethodInstance* methodInstance, BfT
if (argType->IsIntUnknown())
{
// New int fits into previous arg type, that's good
if (mModule->CanImplicitlyCast(BfTypedValue(argValue, argType), prevGenericMethodArg))
if (mModule->CanCast(BfTypedValue(argValue, argType), prevGenericMethodArg))
return true;
// Doesn't fit, upgrade type to 'int'
argType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
@ -341,12 +341,12 @@ bool BfMethodMatcher::InferGenericArgument(BfMethodInstance* methodInstance, BfT
else
{
// Prev is already best
if (mModule->CanImplicitlyCast(mModule->GetFakeTypedValue(argType), prevGenericMethodArg))
if (mModule->CanCast(mModule->GetFakeTypedValue(argType), prevGenericMethodArg))
return true;
}
// New best?
if (mModule->CanImplicitlyCast(mModule->GetFakeTypedValue(prevGenericMethodArg), argType))
if (mModule->CanCast(mModule->GetFakeTypedValue(prevGenericMethodArg), argType))
{
_SetGeneric();
return true;
@ -556,8 +556,8 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
isWorse = true;
else
{
bool canCastFromCurToPrev = mModule->CanImplicitlyCast(mModule->GetFakeTypedValue(paramType), prevParamType);
bool canCastFromPrevToCur = mModule->CanImplicitlyCast(mModule->GetFakeTypedValue(prevParamType), paramType);
bool canCastFromCurToPrev = mModule->CanCast(mModule->GetFakeTypedValue(paramType), prevParamType);
bool canCastFromPrevToCur = mModule->CanCast(mModule->GetFakeTypedValue(prevParamType), paramType);
if ((canCastFromCurToPrev) && (!canCastFromPrevToCur))
isBetter = true;
@ -604,9 +604,9 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
}
else
{
if (mModule->CanImplicitlyCast(mModule->GetFakeTypedValue(paramType), prevParamType))
if (mModule->CanCast(mModule->GetFakeTypedValue(paramType), prevParamType))
isBetter = true;
if (mModule->CanImplicitlyCast(mModule->GetFakeTypedValue(prevParamType), paramType))
if (mModule->CanCast(mModule->GetFakeTypedValue(prevParamType), paramType))
isWorse = true;
}*/
}
@ -1330,7 +1330,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
if ((mArguments[argIdx].mArgFlags & BfArgFlag_ParamsExpr) != 0)
{
// Direct-pass params
if ((argTypedValue.IsUntypedValue()) || (mModule->CanImplicitlyCast(argTypedValue, paramsArrayType)))
if ((argTypedValue.IsUntypedValue()) || (mModule->CanCast(argTypedValue, paramsArrayType)))
{
argIdx++;
argMatchCount++;
@ -1351,7 +1351,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
argTypedValue = ResolveArgTypedValue(mArguments[argIdx], paramsElementType, genericArgumentsSubstitute);
if (!argTypedValue.HasType())
goto NoMatch;
if (!mModule->CanImplicitlyCast(argTypedValue, paramsElementType))
if (!mModule->CanCast(argTypedValue, paramsElementType))
goto NoMatch;
argIdx++;
argMatchCount++;
@ -1402,7 +1402,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* typeInstance, BfMethodDef* che
{
goto NoMatch;
}
else if (!mModule->CanImplicitlyCast(argTypedValue, wantType))
else if (!mModule->CanCast(argTypedValue, wantType))
goto NoMatch;
}
@ -5046,7 +5046,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
if (argIdx < (int)argValues.size())
{
auto argValue = argValues[argIdx].mTypedValue;
if ((argValue.IsParams()) /*&& (mModule->CanImplicitlyCast(argValue, wantType))*/)
if ((argValue.IsParams()) /*&& (mModule->CanCast(argValue, wantType))*/)
isDirectPass = true;
}
@ -14367,11 +14367,11 @@ void BfExprEvaluator::Visit(BfConditionalExpression* condExpr)
if ((ignoredValue) && (ignoredValue.mType != actualValue.mType))
{
// Cast to more specific 'ignored' type if applicable
if (mModule->CanImplicitlyCast(actualValue, ignoredValue.mType))
if (mModule->CanCast(actualValue, ignoredValue.mType))
{
actualValue = mModule->Cast(actualExpr, actualValue, ignoredValue.mType);
}
else if (!mModule->CanImplicitlyCast(ignoredValue, actualValue.mType))
else if (!mModule->CanCast(ignoredValue, actualValue.mType))
{
mModule->Fail(StrFormat("Type of conditional expression cannot be determined because there is no implicit conversion between '%s' and '%s'",
mModule->TypeToString(actualValue.mType).c_str(), mModule->TypeToString(ignoredValue.mType).c_str()), condExpr);
@ -16377,7 +16377,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
{
if (opConstraint.mUnaryOp == findOp)
{
if (mModule->CanImplicitlyCast(args[0].mTypedValue, opConstraint.mRightType))
if (mModule->CanCast(args[0].mTypedValue, opConstraint.mRightType))
{
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
return;
@ -16398,7 +16398,7 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
{
if (opConstraint.mUnaryOp == findOp)
{
if (mModule->CanImplicitlyCast(args[0].mTypedValue, opConstraint.mRightType))
if (mModule->CanCast(args[0].mTypedValue, opConstraint.mRightType))
{
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
return;
@ -17246,7 +17246,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
// If one of these is a constant that can be converted into a smaller type, then do that
if (rightValue.mValue.IsConst())
{
if (mModule->CanImplicitlyCast(rightValue, leftValue.mType))
if (mModule->CanCast(rightValue, leftValue.mType))
{
resultType = leftValue.mType;
handled = true;
@ -17258,7 +17258,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
{
if (leftValue.mValue.IsConst())
{
if (mModule->CanImplicitlyCast(leftValue, rightValue.mType))
if (mModule->CanCast(leftValue, rightValue.mType))
{
resultType = rightValue.mType;
handled = true;
@ -17325,7 +17325,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
// This case fixes cases like "c == 0" where "0" is technically an int but can be reduced
if ((binaryOp == BfBinaryOp_Equality) || (binaryOp == BfBinaryOp_InEquality))
{
if ((resultType != otherType) && (resultTypedValue->mValue.IsConst()) && (mModule->CanImplicitlyCast(*resultTypedValue, otherType)))
if ((resultType != otherType) && (resultTypedValue->mValue.IsConst()) && (mModule->CanCast(*resultTypedValue, otherType)))
{
std::swap(resultTypedValue, otherTypedValue);
std::swap(resultTypeSrc, otherTypeSrc);
@ -17582,8 +17582,8 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
{
if (opConstraint.mBinaryOp == findBinaryOp)
{
if ((mModule->CanImplicitlyCast(args[0].mTypedValue, opConstraint.mLeftType)) &&
(mModule->CanImplicitlyCast(args[1].mTypedValue, opConstraint.mRightType)))
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);
@ -17605,8 +17605,8 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
{
if (opConstraint.mBinaryOp == findBinaryOp)
{
if ((mModule->CanImplicitlyCast(args[0].mTypedValue, opConstraint.mLeftType)) &&
(mModule->CanImplicitlyCast(args[1].mTypedValue, opConstraint.mRightType)))
if ((mModule->CanCast(args[0].mTypedValue, opConstraint.mLeftType)) &&
(mModule->CanCast(args[1].mTypedValue, opConstraint.mRightType)))
{
mResult = BfTypedValue(mModule->mBfIRBuilder->GetFakeVal(), genericParam->mExternType);
return;
@ -17891,9 +17891,9 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
// We only do this for tuples, because we would allow an implicit struct
// truncation if we allow it for all structs, which would result in only
// the base class's fields being compared
if (mModule->CanImplicitlyCast(rightValue, leftValue.mType))
if (mModule->CanCast(rightValue, leftValue.mType))
rightValue = mModule->Cast(opToken, rightValue, leftValue.mType, BfCastFlags_Explicit);
else if (mModule->CanImplicitlyCast(leftValue, rightValue.mType))
else if (mModule->CanCast(leftValue, rightValue.mType))
leftValue = mModule->Cast(opToken, leftValue, rightValue.mType, BfCastFlags_Explicit);
}
@ -17990,7 +17990,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
}
else if ((!resultType->IsSigned()) && (otherType->IsSigned()))
{
if (mModule->CanImplicitlyCast(*otherTypedValue, resultType))
if (mModule->CanCast(*otherTypedValue, resultType))
{
// If we can convert the 'other' value implicitly then it's a convertible literal, leave as uint
}

View file

@ -6627,7 +6627,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
constraintMatched = true;
}
else if (CanImplicitlyCast(GetFakeTypedValue(checkArgType), convCheckConstraint))
else if (CanCast(GetFakeTypedValue(checkArgType), convCheckConstraint))
{
constraintMatched = true;
}
@ -6654,7 +6654,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
if (!constraintMatched)
{
BfType* wrappedStructType = GetWrappedStructType(origCheckArgType, false);
if (CanImplicitlyCast(GetFakeTypedValue(wrappedStructType), convCheckConstraint))
if (CanCast(GetFakeTypedValue(wrappedStructType), convCheckConstraint))
constraintMatched = true;
}
}
@ -6694,11 +6694,11 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
bool implementsInterface = false;
if (origCheckArgType != checkArgType)
{
implementsInterface = CanImplicitlyCast(BfTypedValue(BfIRValue::sValueless, origCheckArgType), convCheckConstraint);
implementsInterface = CanCast(BfTypedValue(BfIRValue::sValueless, origCheckArgType), convCheckConstraint);
}
if (!implementsInterface)
implementsInterface = CanImplicitlyCast(BfTypedValue(BfIRValue::sValueless, checkArgType), convCheckConstraint);
implementsInterface = CanCast(BfTypedValue(BfIRValue::sValueless, checkArgType), convCheckConstraint);
if ((!implementsInterface) && (origCheckArgType->IsWrappableType()))
{
@ -6762,7 +6762,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
}
if ((!exprEvaluator.mResult) ||
(!CanImplicitlyCast(exprEvaluator.mResult, origCheckArgType)))
(!CanCast(exprEvaluator.mResult, origCheckArgType)))
{
if (!ignoreErrors)
*errorOut = Fail(StrFormat("Generic argument '%s', declared to be '%s' for '%s', must result from binary operation '%s %s %s'", genericParamInst->GetName().c_str(),
@ -6781,7 +6781,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
if (checkOpConstraint.mCastToken == BfToken_Implicit)
{
if (!CanImplicitlyCast(rightValue, origCheckArgType, BfCastFlags_SilentFail))
if (!CanCast(rightValue, origCheckArgType, BfCastFlags_SilentFail))
failedOpName = "implicit conversion from '";
}
else
@ -6801,7 +6801,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
exprEvaluator.PerformUnaryOperation(NULL, checkOpConstraint.mUnaryOp, NULL);
if ((!exprEvaluator.mResult) ||
(!CanImplicitlyCast(exprEvaluator.mResult, origCheckArgType)))
(!CanCast(exprEvaluator.mResult, origCheckArgType)))
{
failedOpName += "unary operation '";
failedOpName += BfGetOpName(checkOpConstraint.mUnaryOp);
@ -19260,7 +19260,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
{
defaultValue = castedDefaultValue; // Good!
}
else if (!CanImplicitlyCast(defaultValue, resolvedParamType))
else if (!CanCast(defaultValue, resolvedParamType))
{
// We only care that we get a constant value that can be implicitly casted at the callsite- even if that requires
// a conversion operator.

View file

@ -1482,7 +1482,7 @@ public:
BfDeferredCallEntry* AddDeferredCall(const BfModuleMethodInstance& moduleMethodInstance, SizedArrayImpl<BfIRValue>& llvmArgs, BfScopeData* scope, BfAstNode* srcNode = NULL, bool bypassVirtual = false, bool doNullCheck = false);
void EmitDeferredCall(BfDeferredCallEntry& deferredCallEntry);
void EmitDeferredCallProcessor(SLIList<BfDeferredCallEntry*>& callEntries, BfIRValue callTail);
bool CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags = BfCastFlags_None);
bool CanCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags = BfCastFlags_None);
bool AreSplatsCompatible(BfType* fromType, BfType* toType, bool* outNeedsMemberCasting);
BfTypedValue BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfType* toType /*Can be System.Object or interface*/, const BfAllocTarget& allocTarget, bool callDtor = true);
BfIRValue CastToFunction(BfAstNode* srcNode, BfMethodInstance* methodInstance, BfType* toType, BfCastFlags castFlags = BfCastFlags_None);

View file

@ -3954,7 +3954,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
// Concrete
if (matchedMethod->mReturnType->IsInterface())
hadMatch = false;
else if (!CanImplicitlyCast(GetFakeTypedValue(matchedMethod->mReturnType), iReturnType))
else if (!CanCast(GetFakeTypedValue(matchedMethod->mReturnType), iReturnType))
hadMatch = false;
}
@ -4655,7 +4655,7 @@ void BfModule::FixIntUnknown(BfTypedValue& lhs, BfTypedValue& rhs)
{
if ((lhs.mType != NULL) && (lhs.mType->IsIntUnknown()) && (rhs.mType != NULL) && (rhs.mType->IsInteger()))
{
if (CanImplicitlyCast(lhs, rhs.mType))
if (CanCast(lhs, rhs.mType))
{
lhs = Cast(NULL, lhs, rhs.mType, BfCastFlags_SilentFail);
if (!lhs)
@ -4666,7 +4666,7 @@ void BfModule::FixIntUnknown(BfTypedValue& lhs, BfTypedValue& rhs)
if ((rhs.mType != NULL) && (rhs.mType->IsIntUnknown()) && (lhs.mType != NULL) && (lhs.mType->IsInteger()))
{
if (CanImplicitlyCast(rhs, lhs.mType))
if (CanCast(rhs, lhs.mType))
{
rhs = Cast(NULL, rhs, lhs.mType, BfCastFlags_SilentFail);
if (!rhs)
@ -6409,7 +6409,7 @@ BfTypedValue BfModule::TryLookupGenericConstVaue(BfIdentifierNode* identifierNod
if ((genericTypeConstraint != NULL) && (expectingType != NULL))
{
if (!CanImplicitlyCast(BfTypedValue(mBfIRBuilder->GetFakeVal(), genericTypeConstraint), expectingType))
if (!CanCast(BfTypedValue(mBfIRBuilder->GetFakeVal(), genericTypeConstraint), expectingType))
{
Fail(StrFormat("Generic constraint '%s' is not convertible to 'int'", TypeToString(genericTypeConstraint).c_str()), identifierNode);
}
@ -7780,9 +7780,9 @@ BfType* BfModule::ResolveTypeRef(BfAstNode* astNode, const BfSizedArray<BfTypeRe
}
// This flow should mirror CastToValue
bool BfModule::CanImplicitlyCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags)
bool BfModule::CanCast(BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags)
{
BP_ZONE("BfModule::CanImplicitlyCast");
BP_ZONE("BfModule::CanCast");
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
return CastToValue(NULL, typedVal, toType, (BfCastFlags)(castFlags | BfCastFlags_SilentFail));
@ -8837,7 +8837,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
if (fromDist < 0)
{
// Allow us to cast a constant int to a smaller type if it satisfies the cast operator
if ((typedVal.mValue.IsConst()) && (CanImplicitlyCast(typedVal, methodCheckFromType, BfCastFlags_NoConversionOperator)))
if ((typedVal.mValue.IsConst()) && (CanCast(typedVal, methodCheckFromType, BfCastFlags_NoConversionOperator)))
{
fromDist = 0;
}
@ -9003,11 +9003,11 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
((explicitCast) && (opConstraint.mCastToken == BfToken_Explicit)))
{
// If we can convert OUR fromVal to the constraint's fromVal then we may match
if (CanImplicitlyCast(typedVal, opConstraint.mRightType))
if (CanCast(typedVal, opConstraint.mRightType))
{
// .. and we can convert the constraint's toType to OUR toType then we're good
auto opToVal = genericParam->mExternType;
if (CanImplicitlyCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType))
if (CanCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType))
return mBfIRBuilder->GetFakeVal();
}
}
@ -9028,11 +9028,11 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
((explicitCast) && (opConstraint.mCastToken == BfToken_Explicit)))
{
// If we can convert OUR fromVal to the constraint's fromVal then we may match
if (CanImplicitlyCast(typedVal, opConstraint.mRightType))
if (CanCast(typedVal, opConstraint.mRightType))
{
// .. and we can convert the constraint's toType to OUR toType then we're good
auto opToVal = genericParam->mExternType;
if (CanImplicitlyCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType))
if (CanCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType))
return mBfIRBuilder->GetFakeVal();
}
}
@ -9232,7 +9232,8 @@ BfTypedValue BfModule::Cast(BfAstNode* srcNode, const BfTypedValue& typedVal, Bf
if (!toFieldDef->IsUnnamedTupleField())
{
if ((!fromFieldDef->IsUnnamedTupleField()) &&
if ((!explicitCast) &&
(!fromFieldDef->IsUnnamedTupleField()) &&
(fromFieldDef->mName != toFieldDef->mName))
isCompatible = false;
fieldNames.push_back(toFieldDef->mName);
@ -9247,10 +9248,14 @@ BfTypedValue BfModule::Cast(BfAstNode* srcNode, const BfTypedValue& typedVal, Bf
if (fromFieldInst->mResolvedType != toFieldInst->mResolvedType)
isExactTypeMatch = false;
BfCastFlags tryCastFlags = BfCastFlags_SilentFail;
if (explicitCast)
tryCastFlags = (BfCastFlags)(tryCastFlags | BfCastFlags_Explicit);
// The unused-token '?' comes out as 'void', so we allow that to match here. We may want to wrap that with a different fake type
// so we can give normal implicit-cast-to-void errors
if ((fromFieldInst->mResolvedType != toFieldInst->mResolvedType) && (!toFieldInst->mResolvedType->IsVoid()) &&
(!CanImplicitlyCast(GetFakeTypedValue(fromFieldInst->mResolvedType), toFieldInst->mResolvedType)))
(!CanCast(GetFakeTypedValue(fromFieldInst->mResolvedType), toFieldInst->mResolvedType, tryCastFlags)))
isCompatible = false;
fieldTypes.push_back(toFieldInst->mResolvedType);
}
@ -9260,25 +9265,25 @@ BfTypedValue BfModule::Cast(BfAstNode* srcNode, const BfTypedValue& typedVal, Bf
AddDependency(tupleType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
mBfIRBuilder->PopulateType(tupleType);
if (isExactTypeMatch)
{
if (typedVal.mKind == BfTypedValueKind_TempAddr)
{
return BfTypedValue(mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapTypeInstPtr(tupleType)), tupleType, BfTypedValueKind_TempAddr);
}
else if (typedVal.IsAddr())
{
return BfTypedValue(mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapTypeInstPtr(tupleType)), tupleType, BfTypedValueKind_ReadOnlyAddr);
}
BfIRValue curTupleValue = CreateAlloca(tupleType);
auto loadedVal = LoadValue(typedVal);
mBfIRBuilder->CreateStore(loadedVal.mValue, mBfIRBuilder->CreateBitCast(curTupleValue, mBfIRBuilder->MapTypeInstPtr(fromTupleType)));
return BfTypedValue(curTupleValue, tupleType, BfTypedValueKind_TempAddr);
}
if (isCompatible)
{
{
if (isExactTypeMatch)
{
if (typedVal.mKind == BfTypedValueKind_TempAddr)
{
return BfTypedValue(mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapTypeInstPtr(tupleType)), tupleType, BfTypedValueKind_TempAddr);
}
else if (typedVal.IsAddr())
{
return BfTypedValue(mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapTypeInstPtr(tupleType)), tupleType, BfTypedValueKind_ReadOnlyAddr);
}
BfIRValue curTupleValue = CreateAlloca(tupleType);
auto loadedVal = LoadValue(typedVal);
mBfIRBuilder->CreateStore(loadedVal.mValue, mBfIRBuilder->CreateBitCast(curTupleValue, mBfIRBuilder->MapTypeInstPtr(fromTupleType)));
return BfTypedValue(curTupleValue, tupleType, BfTypedValueKind_TempAddr);
}
BfIRValue curTupleValue = CreateAlloca(tupleType);
for (int fieldIdx = 0; fieldIdx < (int)fromTupleType->mFieldInstances.size(); fieldIdx++)
{

View file

@ -2451,7 +2451,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
/*BF_ASSERT(typedVal.mType->IsGenericParam());
auto genericParamInstance = ctx->mModule->GetGenericParamInstance((BfGenericParamType*)typedVal.mType);
if ((genericParamInstance->mTypeConstraint == NULL) ||
(!ctx->mModule->CanImplicitlyCast(BfTypedValue(ctx->mModule->mBfIRBuilder->GetFakeVal(), genericParamInstance->mTypeConstraint),
(!ctx->mModule->CanCast(BfTypedValue(ctx->mModule->mBfIRBuilder->GetFakeVal(), genericParamInstance->mTypeConstraint),
ctx->mModule->GetPrimitiveType(BfTypeCode_IntPtr))))
{
ctx->mModule->Fail(StrFormat("Generic constraint '%s' is not convertible to 'int'", ctx->mModule->TypeToString(typedVal.mType).c_str()), sizeExpr);

View file

@ -1018,7 +1018,7 @@ void BfModule::TryInitVar(BfAstNode* checkNode, BfLocalVariable* localVar, BfTyp
BfTypeInstance* srcTypeInstance = initValue.mType->ToTypeInstance();
BfTypeInstance* varTypeInstance = varType->ToTypeInstance();
if (CanImplicitlyCast(initValue, varType))
if (CanCast(initValue, varType))
{
if ((!varType->IsPointer()) && (!varType->IsObjectOrInterface()))
{
@ -1044,7 +1044,7 @@ void BfModule::TryInitVar(BfAstNode* checkNode, BfLocalVariable* localVar, BfTyp
// // Class downcast
// isDynamicCast = true;
// }
// else if ((!CanImplicitlyCast(GetFakeTypedValue(varType), initType)) && (!initType->IsGenericParam()))
// else if ((!CanCast(GetFakeTypedValue(varType), initType)) && (!initType->IsGenericParam()))
// {
// if (!IsInSpecializedSection())
// {

View file

@ -65,11 +65,11 @@ DwMethodMatcher::DwMethodMatcher(BfAstNode* targetSrc, DbgExprEvaluator* exprEva
}
// Prev is already best
if (mModule->CanImplicitlyCast(DbgTypedValue(NULL, argType), prevGenericMethodArg))
if (mModule->CanCast(DbgTypedValue(NULL, argType), prevGenericMethodArg))
return true;
// New best?
if (mModule->CanImplicitlyCast(DbgTypedValue(NULL, prevGenericMethodArg), argType))
if (mModule->CanCast(DbgTypedValue(NULL, prevGenericMethodArg), argType))
{
mCheckMethodGenericArguments[wantGenericParam->mGenericParamIdx] = argType;
return true;
@ -198,9 +198,9 @@ void DwMethodMatcher::CompareMethods(DbgSubprogram* prevMethodInstance, DwTypeVe
}
else
{
if (mExprEvaluator->CanImplicitlyCast(DbgTypedValue::GetValueless(paramType), prevParamType))
if (mExprEvaluator->CanCast(DbgTypedValue::GetValueless(paramType), prevParamType))
isBetter = true;
if (mExprEvaluator->CanImplicitlyCast(DbgTypedValue::GetValueless(prevParamType), paramType))
if (mExprEvaluator->CanCast(DbgTypedValue::GetValueless(prevParamType), paramType))
isWorse = true;
}
}
@ -387,7 +387,7 @@ bool DwMethodMatcher::CheckMethod(DbgType* typeInstance, DbgSubprogram* checkMet
// Check to see if we're directly passing the params type (like an int[])
auto paramsArrayType = methodInstance->mParamTypes[paramIdx];
if (mModule->CanImplicitlyCast(mArguments[argIdx], paramsArrayType))
if (mModule->CanCast(mArguments[argIdx], paramsArrayType))
{
argIdx++;
paramIdx++;
@ -402,7 +402,7 @@ bool DwMethodMatcher::CheckMethod(DbgType* typeInstance, DbgSubprogram* checkMet
{
if (!mArguments[argIdx])
goto NoMatch;
if (!mModule->CanImplicitlyCast(mArguments[argIdx], paramsElementType))
if (!mModule->CanCast(mArguments[argIdx], paramsElementType))
goto NoMatch;
argIdx++;
}
@ -428,7 +428,7 @@ bool DwMethodMatcher::CheckMethod(DbgType* typeInstance, DbgSubprogram* checkMet
goto NoMatch;
if (!mExprEvaluator->CanImplicitlyCast(mArguments[argIdx], wantType))
if (!mExprEvaluator->CanCast(mArguments[argIdx], wantType))
goto NoMatch;
paramIdx++;
@ -1510,7 +1510,7 @@ bool DbgExprEvaluator::CheckHasValue(DbgTypedValue typedValue, BfAstNode* refNod
}
//TODO: Expand this
bool DbgExprEvaluator::CanImplicitlyCast(DbgTypedValue typedVal, DbgType* toType)
bool DbgExprEvaluator::CanCast(DbgTypedValue typedVal, DbgType* toType, BfCastFlags castFlags)
{
DbgType* fromType = typedVal.mType;
@ -6003,7 +6003,7 @@ void DbgExprEvaluator::PerformBinaryOperation(ASTREF(BfExpression*)& leftExpress
}
else if ((!resultType->IsSigned()) && (otherType->IsSigned()))
{
/*if (CanImplicitlyCast(*otherTypedValue, resultType))
/*if (CanCast(*otherTypedValue, resultType))
{
// If we can convert the 'other' value implicitly then it's a convertible literal, leave as uint
}
@ -6864,7 +6864,7 @@ DbgTypedValue DbgExprEvaluator::CreateCall(BfAstNode* targetSrc, DbgTypedValue t
{
if (argValues[argIdx].mValue == NULL)
return DbgTypedValue();
if (mModule->CanImplicitlyCast(argValues[argIdx], wantType))
if (mModule->CanCast(argValues[argIdx], wantType))
isDirectPass = true;
}

View file

@ -362,7 +362,7 @@ public:
String TypeToString(DbgType* type);
bool CheckHasValue(DbgTypedValue typedValue, BfAstNode* refNode);
bool CanImplicitlyCast(DbgTypedValue typedVal, DbgType* toType);
bool CanCast(DbgTypedValue typedVal, DbgType* toType, BfCastFlags castFlags = BfCastFlags_None);
DbgTypedValue Cast(BfAstNode* srcNode, const DbgTypedValue& val, DbgType* toType, bool explicitCast = false, bool silentFail = false);
bool HasField(DbgType* type, const StringImpl& fieldName);
DbgTypedValue DoLookupField(BfAstNode* targetSrc, DbgTypedValue target, DbgType* curCheckType, const StringImpl& fieldName, CPUStackFrame* stackFrame, bool allowImplicitThis);