diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 8d453cdf..b255a7a4 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -1000,7 +1000,7 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp { auto returnType = newMethodInstance->mReturnType; auto prevReturnType = prevMethodInstance->mReturnType; - + if ((mBfEvalExprFlags & BfEvalExprFlags_FromConversionOp_Explicit) != 0) { // Pick the one that can implicitly cast @@ -2205,7 +2205,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst } returnType = mModule->ResolveSelfType(returnType, typeInstance); - BfCastFlags castFlags = ((mBfEvalExprFlags & BfEvalExprFlags_FromConversionOp) != 0) ? BfCastFlags_NoConversionOperator : BfCastFlags_None; + BfCastFlags castFlags = ((mBfEvalExprFlags & BfEvalExprFlags_FromConversionOp) != 0) ? (BfCastFlags)(BfCastFlags_NoConversionOperator | BfCastFlags_NoInterfaceImpl) : BfCastFlags_None; if ((mBfEvalExprFlags & BfEvalExprFlags_FromConversionOp_Explicit) != 0) castFlags = (BfCastFlags)(castFlags | BfCastFlags_Explicit); if (!mModule->CanCast(mModule->GetFakeTypedValue(returnType), mCheckReturnType, castFlags)) diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 8f3f626a..d064b2f5 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -95,13 +95,14 @@ enum BfCastFlags BfCastFlags_SilentFail = 8, BfCastFlags_NoBox = 0x10, BfCastFlags_NoBoxDtor = 0x20, - BfCastFlags_NoConversionOperator = 0x40, - BfCastFlags_FromCompiler = 0x80, // Not user specified - BfCastFlags_Force = 0x100, - BfCastFlags_PreferAddr = 0x200, - BfCastFlags_WarnOnBox = 0x400, - BfCastFlags_IsCastCheck = 0x800, - BfCastFlags_IsConstraintCheck = 0x1000 + BfCastFlags_NoInterfaceImpl = 0x40, + BfCastFlags_NoConversionOperator = 0x80, + BfCastFlags_FromCompiler = 0x100, // Not user specified + BfCastFlags_Force = 0x200, + BfCastFlags_PreferAddr = 0x400, + BfCastFlags_WarnOnBox = 0x800, + BfCastFlags_IsCastCheck = 0x1000, + BfCastFlags_IsConstraintCheck = 0x2000, }; enum BfCastResultFlags diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index cab289ff..5c160bf7 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -11985,9 +11985,13 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp // ObjectInst|IFace -> object|IFace if ((typedVal.mType->IsObject() || (typedVal.mType->IsInterface())) && ((toType->IsObject() || (toType->IsInterface())))) { - bool allowCast = false; + bool allowCast = false; - if (TypeIsSubTypeOf(fromTypeInstance, toTypeInstance)) + if (((castFlags & BfCastFlags_NoInterfaceImpl) != 0) && (toTypeInstance->IsInterface())) + { + // Don't allow + } + else if (TypeIsSubTypeOf(fromTypeInstance, toTypeInstance)) allowCast = true; else if ((explicitCast) && ((toType->IsInterface()) || (TypeIsSubTypeOf(toTypeInstance, fromTypeInstance)))) @@ -12887,27 +12891,28 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp if (doCall) { - methodMatcher.FlushAmbiguityError(); + if (!silentFail) + methodMatcher.FlushAmbiguityError(); auto wantType = paramType; if (wantType->IsRef()) wantType = wantType->GetUnderlyingType(); - auto typedVal = methodMatcher.mArguments[0].mTypedValue; - if (wantType != typedVal.mType) + auto convTypedVal = methodMatcher.mArguments[0].mTypedValue; + if (wantType != convTypedVal.mType) { - if ((typedVal.mType->IsWrappableType()) && (wantType == GetWrappedStructType(typedVal.mType))) + if ((convTypedVal.mType->IsWrappableType()) && (wantType == GetWrappedStructType(convTypedVal.mType))) { - typedVal = MakeAddressable(typedVal); - methodMatcher.mArguments[0].mTypedValue = BfTypedValue(mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapTypeInstPtr(wantType->ToTypeInstance())), + convTypedVal = MakeAddressable(convTypedVal); + methodMatcher.mArguments[0].mTypedValue = BfTypedValue(mBfIRBuilder->CreateBitCast(convTypedVal.mValue, mBfIRBuilder->MapTypeInstPtr(wantType->ToTypeInstance())), paramType, paramType->IsRef() ? BfTypedValueKind_Value : BfTypedValueKind_Addr); } else { - methodMatcher.mArguments[0].mTypedValue = Cast(srcNode, typedVal, wantType, (BfCastFlags)(castFlags | BfCastFlags_Explicit | BfCastFlags_NoConversionOperator)); + methodMatcher.mArguments[0].mTypedValue = Cast(srcNode, convTypedVal, wantType, (BfCastFlags)(castFlags | BfCastFlags_Explicit | BfCastFlags_NoConversionOperator)); if (paramType->IsRef()) { - typedVal = MakeAddressable(typedVal); - typedVal.mKind = BfTypedValueKind_Addr; + convTypedVal = MakeAddressable(convTypedVal); + convTypedVal.mKind = BfTypedValueKind_Addr; } } }