From fd64aa64d92628c7e53e775e8ce902a002230464 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Fri, 24 Jan 2020 10:36:22 -0800 Subject: [PATCH] Made implicit tuple cast check names, fixed explicit tuple cast --- BeefLibs/corlib/src/String.bf | 4 +- BeefLibs/corlib/src/Text/UTF8.bf | 2 +- IDEHelper/Compiler/BfAutoComplete.cpp | 4 +- IDEHelper/Compiler/BfConstResolver.cpp | 2 +- IDEHelper/Compiler/BfExprEvaluator.cpp | 54 ++++++++--------- IDEHelper/Compiler/BfModule.cpp | 16 +++--- IDEHelper/Compiler/BfModule.h | 2 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 67 ++++++++++++---------- IDEHelper/Compiler/BfResolvedTypeUtils.cpp | 2 +- IDEHelper/Compiler/BfStmtEvaluator.cpp | 4 +- IDEHelper/DbgExprEvaluator.cpp | 20 +++---- IDEHelper/DbgExprEvaluator.h | 2 +- 12 files changed, 92 insertions(+), 87 deletions(-) diff --git a/BeefLibs/corlib/src/String.bf b/BeefLibs/corlib/src/String.bf index 2f68d006..71ae8da5 100644 --- a/BeefLibs/corlib/src/String.bf +++ b/BeefLibs/corlib/src/String.bf @@ -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; diff --git a/BeefLibs/corlib/src/Text/UTF8.bf b/BeefLibs/corlib/src/Text/UTF8.bf index b23b10fd..87fd31e3 100644 --- a/BeefLibs/corlib/src/Text/UTF8.bf +++ b/BeefLibs/corlib/src/Text/UTF8.bf @@ -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]; diff --git a/IDEHelper/Compiler/BfAutoComplete.cpp b/IDEHelper/Compiler/BfAutoComplete.cpp index 2a316ea7..b3a2ec85 100644 --- a/IDEHelper/Compiler/BfAutoComplete.cpp +++ b/IDEHelper/Compiler/BfAutoComplete.cpp @@ -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) diff --git a/IDEHelper/Compiler/BfConstResolver.cpp b/IDEHelper/Compiler/BfConstResolver.cpp index 225a9804..67467965 100644 --- a/IDEHelper/Compiler/BfConstResolver.cpp +++ b/IDEHelper/Compiler/BfConstResolver.cpp @@ -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; } diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 75c9a4ec..cf3b8fa8 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -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 } diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 61160106..4bd4d8f7 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -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. diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index fb4a687f..d2cda888 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1482,7 +1482,7 @@ public: BfDeferredCallEntry* AddDeferredCall(const BfModuleMethodInstance& moduleMethodInstance, SizedArrayImpl& llvmArgs, BfScopeData* scope, BfAstNode* srcNode = NULL, bool bypassVirtual = false, bool doNullCheck = false); void EmitDeferredCall(BfDeferredCallEntry& deferredCallEntry); void EmitDeferredCallProcessor(SLIList& 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); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 287584b9..f7294850 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -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 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++) { diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index 141b66b7..74da798f 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -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); diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index f8687a55..a1d2a935 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -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()) // { diff --git a/IDEHelper/DbgExprEvaluator.cpp b/IDEHelper/DbgExprEvaluator.cpp index 8d3a6f9e..0ad686f4 100644 --- a/IDEHelper/DbgExprEvaluator.cpp +++ b/IDEHelper/DbgExprEvaluator.cpp @@ -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; } diff --git a/IDEHelper/DbgExprEvaluator.h b/IDEHelper/DbgExprEvaluator.h index 3c0bccd1..1c81de2c 100644 --- a/IDEHelper/DbgExprEvaluator.h +++ b/IDEHelper/DbgExprEvaluator.h @@ -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);