mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-09 20:12:21 +02:00
Make conversion operators use standard method matcher
This commit is contained in:
parent
15e1986a1c
commit
c7d2d2e9bd
8 changed files with 280 additions and 398 deletions
|
@ -154,7 +154,7 @@ namespace System
|
||||||
//
|
//
|
||||||
public this(int year, int month, int day)
|
public this(int year, int month, int day)
|
||||||
{
|
{
|
||||||
this.dateData = (uint64)DateToTicks(year, month, day);
|
this.dateData = (.)DateToTicks(year, month, day).Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public this(int year, int month, int day, int hour, int minute, int second)
|
public this(int year, int month, int day, int hour, int minute, int second)
|
||||||
|
|
|
@ -18,16 +18,16 @@ namespace System.Reflection
|
||||||
var (objType, dataPtr) = GetTypeAndPointer(obj);
|
var (objType, dataPtr) = GetTypeAndPointer(obj);
|
||||||
switch (objType.[Friend]mTypeCode)
|
switch (objType.[Friend]mTypeCode)
|
||||||
{
|
{
|
||||||
case .Int8: return (.)*(int8*)dataPtr;
|
case .Int8: return *(int8*)dataPtr;
|
||||||
case .Int16: return (.)*(int16*)dataPtr;
|
case .Int16: return *(int16*)dataPtr;
|
||||||
case .Int32: return (.)*(int32*)dataPtr;
|
case .Int32: return *(int32*)dataPtr;
|
||||||
case .Int64: return (.)*(int64*)dataPtr;
|
case .Int64: return *(int64*)dataPtr;
|
||||||
case .UInt8, .Char8: return (.)*(uint8*)dataPtr;
|
case .UInt8, .Char8: return (int64)*(uint8*)dataPtr;
|
||||||
case .UInt16, .Char16: return (.)*(uint16*)dataPtr;
|
case .UInt16, .Char16: return *(uint16*)dataPtr;
|
||||||
case .UInt32, .Char32: return (.)*(uint32*)dataPtr;
|
case .UInt32, .Char32: return *(uint32*)dataPtr;
|
||||||
case .UInt64: return (.)*(uint64*)dataPtr;
|
case .UInt64: return (int64)*(uint64*)dataPtr;
|
||||||
case .Int: return (.)*(int*)dataPtr;
|
case .Int: return (int64)*(int*)dataPtr;
|
||||||
case .UInt: return (.)*(uint*)dataPtr;
|
case .UInt: return (int64)*(uint*)dataPtr;
|
||||||
default: return .Err;
|
default: return .Err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,16 +38,16 @@ namespace System.Reflection
|
||||||
var dataPtr = variant.DataPtr;
|
var dataPtr = variant.DataPtr;
|
||||||
switch (variant.VariantType.[Friend]mTypeCode)
|
switch (variant.VariantType.[Friend]mTypeCode)
|
||||||
{
|
{
|
||||||
case .Int8: return (.)*(int8*)dataPtr;
|
case .Int8: return *(int8*)dataPtr;
|
||||||
case .Int16: return (.)*(int16*)dataPtr;
|
case .Int16: return *(int16*)dataPtr;
|
||||||
case .Int32: return (.)*(int32*)dataPtr;
|
case .Int32: return *(int32*)dataPtr;
|
||||||
case .Int64: return (.)*(int64*)dataPtr;
|
case .Int64: return *(int64*)dataPtr;
|
||||||
case .UInt8, .Char8: return (.)*(uint8*)dataPtr;
|
case .UInt8, .Char8: return *(uint8*)dataPtr;
|
||||||
case .UInt16, .Char16: return (.)*(uint16*)dataPtr;
|
case .UInt16, .Char16: return *(uint16*)dataPtr;
|
||||||
case .UInt32, .Char32: return (.)*(uint32*)dataPtr;
|
case .UInt32, .Char32: return *(uint32*)dataPtr;
|
||||||
case .UInt64: return (.)*(uint64*)dataPtr;
|
case .UInt64: return (int64)*(uint64*)dataPtr;
|
||||||
case .Int: return (.)*(int*)dataPtr;
|
case .Int: return (int64)*(int*)dataPtr;
|
||||||
case .UInt: return (.)*(uint*)dataPtr;
|
case .UInt: return (int64)*(uint*)dataPtr;
|
||||||
default: return .Err;
|
default: return .Err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1341,7 +1341,7 @@ namespace System
|
||||||
|
|
||||||
public Result<void> AppendF(StringView format, params Object[] args)
|
public Result<void> AppendF(StringView format, params Object[] args)
|
||||||
{
|
{
|
||||||
return AppendF(null, format, params args);
|
return AppendF((IFormatProvider)null, format, params args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int IndexOf(StringView subStr, bool ignoreCase = false)
|
public int IndexOf(StringView subStr, bool ignoreCase = false)
|
||||||
|
|
|
@ -168,6 +168,7 @@ void BfMethodMatcher::Init(/*SizedArrayImpl<BfResolvedArg>& arguments, */BfSized
|
||||||
mExplicitInterfaceCheck = NULL;
|
mExplicitInterfaceCheck = NULL;
|
||||||
mSelfType = NULL;
|
mSelfType = NULL;
|
||||||
mMethodType = BfMethodType_Normal;
|
mMethodType = BfMethodType_Normal;
|
||||||
|
mCheckReturnType = NULL;
|
||||||
mHadExplicitGenericArguments = false;
|
mHadExplicitGenericArguments = false;
|
||||||
mHasVarArguments = false;
|
mHasVarArguments = false;
|
||||||
mInterfaceMethodInstance = NULL;
|
mInterfaceMethodInstance = NULL;
|
||||||
|
@ -178,6 +179,7 @@ void BfMethodMatcher::Init(/*SizedArrayImpl<BfResolvedArg>& arguments, */BfSized
|
||||||
mSkipImplicitParams = false;
|
mSkipImplicitParams = false;
|
||||||
mAllowImplicitThis = false;
|
mAllowImplicitThis = false;
|
||||||
mAllowImplicitRef = false;
|
mAllowImplicitRef = false;
|
||||||
|
mAllowImplicitWrap = false;
|
||||||
mHadVarConflictingReturnType = false;
|
mHadVarConflictingReturnType = false;
|
||||||
mAutoFlushAmbiguityErrors = true;
|
mAutoFlushAmbiguityErrors = true;
|
||||||
mMethodCheckCount = 0;
|
mMethodCheckCount = 0;
|
||||||
|
@ -2036,8 +2038,7 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
|
||||||
goto NoMatch;
|
goto NoMatch;
|
||||||
wantType = resolvedType;
|
wantType = resolvedType;
|
||||||
}
|
}
|
||||||
if (wantType->IsSelf())
|
wantType = mModule->ResolveSelfType(wantType, typeInstance);
|
||||||
wantType = typeInstance;
|
|
||||||
|
|
||||||
if ((argIdx >= 0) && ((mArguments[argIdx].mArgFlags & BfArgFlag_ParamsExpr) != 0))
|
if ((argIdx >= 0) && ((mArguments[argIdx].mArgFlags & BfArgFlag_ParamsExpr) != 0))
|
||||||
{
|
{
|
||||||
|
@ -2075,8 +2076,15 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
|
||||||
if ((wantType->IsRef()) && (!argTypedValue.mType->IsRef()) &&
|
if ((wantType->IsRef()) && (!argTypedValue.mType->IsRef()) &&
|
||||||
((mAllowImplicitRef) || (wantType->IsIn())))
|
((mAllowImplicitRef) || (wantType->IsIn())))
|
||||||
wantType = wantType->GetUnderlyingType();
|
wantType = wantType->GetUnderlyingType();
|
||||||
if (!mModule->CanCast(argTypedValue, wantType))
|
if (!mModule->CanCast(argTypedValue, wantType, ((mBfEvalExprFlags & BfEvalExprFlags_FromConversionOp) != 0) ? BfCastFlags_NoConversionOperator : BfCastFlags_None))
|
||||||
goto NoMatch;
|
{
|
||||||
|
if ((mAllowImplicitWrap) && (argTypedValue.mType->IsWrappableType()) && (mModule->GetWrappedStructType(argTypedValue.mType) == wantType))
|
||||||
|
{
|
||||||
|
// Is wrapped type
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto NoMatch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2116,6 +2124,26 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
|
||||||
goto NoMatch;
|
goto NoMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mCheckReturnType != NULL)
|
||||||
|
{
|
||||||
|
auto wantType = mCheckReturnType;
|
||||||
|
if ((genericArgumentsSubstitute != NULL) && (wantType->IsUnspecializedType()))
|
||||||
|
{
|
||||||
|
wantType = typeUnspecMethodInstance->GetParamType(paramIdx);
|
||||||
|
auto resolvedType = mModule->ResolveGenericType(wantType, typeGenericArguments, genericArgumentsSubstitute, false);
|
||||||
|
if (resolvedType == NULL)
|
||||||
|
goto NoMatch;
|
||||||
|
wantType = resolvedType;
|
||||||
|
}
|
||||||
|
wantType = mModule->ResolveSelfType(wantType, typeInstance);
|
||||||
|
|
||||||
|
BfCastFlags castFlags = ((mBfEvalExprFlags & BfEvalExprFlags_FromConversionOp) != 0) ? BfCastFlags_NoConversionOperator : BfCastFlags_None;
|
||||||
|
if ((mBfEvalExprFlags & BfEvalExprFlags_FromConversionOp_Explicit) != 0)
|
||||||
|
castFlags = (BfCastFlags)(castFlags | BfCastFlags_Explicit);
|
||||||
|
if (!mModule->CanCast(mModule->GetFakeTypedValue(methodInstance->mReturnType), wantType, castFlags))
|
||||||
|
goto NoMatch;
|
||||||
|
}
|
||||||
|
|
||||||
if ((genericArgumentsSubstitute != NULL) && (genericArgumentsSubstitute->size() != 0))
|
if ((genericArgumentsSubstitute != NULL) && (genericArgumentsSubstitute->size() != 0))
|
||||||
{
|
{
|
||||||
for (int checkGenericIdx = uniqueGenericStartIdx; checkGenericIdx < (int)genericArgumentsSubstitute->size(); checkGenericIdx++)
|
for (int checkGenericIdx = uniqueGenericStartIdx; checkGenericIdx < (int)genericArgumentsSubstitute->size(); checkGenericIdx++)
|
||||||
|
@ -2272,7 +2300,8 @@ NoMatch:
|
||||||
auto resolveThisParam = mModule->ResolveGenericType(thisParam, NULL, &mCheckMethodGenericArguments);
|
auto resolveThisParam = mModule->ResolveGenericType(thisParam, NULL, &mCheckMethodGenericArguments);
|
||||||
if (resolveThisParam == NULL)
|
if (resolveThisParam == NULL)
|
||||||
return false;
|
return false;
|
||||||
if (!mModule->CanCast(mTarget, resolveThisParam, BfCastFlags_Explicit))
|
if (!mModule->CanCast(mTarget, resolveThisParam,
|
||||||
|
((mBfEvalExprFlags & BfEvalExprFlags_FromConversionOp) != 0) ? (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_NoConversionOperator) : BfCastFlags_Explicit))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6127,11 +6156,11 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BfTypedValue BfExprEvaluator::CreateCall(BfMethodMatcher* methodMatcher, BfTypedValue target)
|
BfTypedValue BfExprEvaluator::CreateCall(BfMethodMatcher* methodMatcher, BfTypedValue target)
|
||||||
{
|
{
|
||||||
auto& moduleMethodInstance = methodMatcher->mBestMethodInstance;
|
auto& moduleMethodInstance = GetSelectedMethod(*methodMatcher);
|
||||||
if (!moduleMethodInstance)
|
|
||||||
moduleMethodInstance = GetSelectedMethod(methodMatcher->mTargetSrc, methodMatcher->mBestMethodTypeInstance, methodMatcher->mBestMethodDef, *methodMatcher);
|
|
||||||
if (moduleMethodInstance.mMethodInstance == NULL)
|
if (moduleMethodInstance.mMethodInstance == NULL)
|
||||||
return BfTypedValue();
|
return BfTypedValue();
|
||||||
if ((target) && (target.mType != moduleMethodInstance.mMethodInstance->GetOwner()))
|
if ((target) && (target.mType != moduleMethodInstance.mMethodInstance->GetOwner()))
|
||||||
|
@ -9462,6 +9491,19 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
||||||
BfModuleMethodInstance moduleMethodInstance = mModule->GetMethodByName(typeInst, "ReturnValueDiscarded", 0, true);
|
BfModuleMethodInstance moduleMethodInstance = mModule->GetMethodByName(typeInst, "ReturnValueDiscarded", 0, true);
|
||||||
if (moduleMethodInstance)
|
if (moduleMethodInstance)
|
||||||
{
|
{
|
||||||
|
bool wasCapturingMethodMatchInfo = false;
|
||||||
|
if (autoComplete != NULL)
|
||||||
|
{
|
||||||
|
wasCapturingMethodMatchInfo = autoComplete->mIsCapturingMethodMatchInfo;
|
||||||
|
autoComplete->mIsCapturingMethodMatchInfo = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
defer
|
||||||
|
(
|
||||||
|
if (autoComplete != NULL)
|
||||||
|
autoComplete->mIsCapturingMethodMatchInfo = wasCapturingMethodMatchInfo;
|
||||||
|
);
|
||||||
|
|
||||||
auto wasGetDefinition = (autoComplete != NULL) && (autoComplete->mIsGetDefinition);
|
auto wasGetDefinition = (autoComplete != NULL) && (autoComplete->mIsGetDefinition);
|
||||||
if (wasGetDefinition)
|
if (wasGetDefinition)
|
||||||
autoComplete->mIsGetDefinition = false;
|
autoComplete->mIsGetDefinition = false;
|
||||||
|
@ -15350,6 +15392,13 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc,
|
||||||
return moduleMethodInstance;
|
return moduleMethodInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfMethodMatcher& methodMatcher)
|
||||||
|
{
|
||||||
|
if (!methodMatcher.mBestMethodInstance)
|
||||||
|
methodMatcher.mBestMethodInstance = GetSelectedMethod(methodMatcher.mTargetSrc, methodMatcher.mBestMethodTypeInstance, methodMatcher.mBestMethodDef, methodMatcher);
|
||||||
|
return methodMatcher.mBestMethodInstance;
|
||||||
|
}
|
||||||
|
|
||||||
void BfExprEvaluator::CheckLocalMethods(BfAstNode* targetSrc, BfTypeInstance* typeInstance, const StringImpl& methodName, BfMethodMatcher& methodMatcher, BfMethodType methodType)
|
void BfExprEvaluator::CheckLocalMethods(BfAstNode* targetSrc, BfTypeInstance* typeInstance, const StringImpl& methodName, BfMethodMatcher& methodMatcher, BfMethodType methodType)
|
||||||
{
|
{
|
||||||
auto _GetNodeId = [&]()
|
auto _GetNodeId = [&]()
|
||||||
|
@ -20173,6 +20222,8 @@ BfTypedValue BfExprEvaluator::PerformUnaryOperation_TryOperator(const BfTypedVal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
methodMatcher.FlushAmbiguityError();
|
||||||
|
|
||||||
if (methodMatcher.mBestMethodDef == NULL)
|
if (methodMatcher.mBestMethodDef == NULL)
|
||||||
{
|
{
|
||||||
// Check method generic constraints
|
// Check method generic constraints
|
||||||
|
|
|
@ -190,6 +190,7 @@ public:
|
||||||
String mMethodName;
|
String mMethodName;
|
||||||
BfMethodInstance* mInterfaceMethodInstance;
|
BfMethodInstance* mInterfaceMethodInstance;
|
||||||
SizedArrayImpl<BfResolvedArg>& mArguments;
|
SizedArrayImpl<BfResolvedArg>& mArguments;
|
||||||
|
BfType* mCheckReturnType;
|
||||||
BfMethodType mMethodType;
|
BfMethodType mMethodType;
|
||||||
BfCheckedKind mCheckedKind;
|
BfCheckedKind mCheckedKind;
|
||||||
bool mHadExplicitGenericArguments;
|
bool mHadExplicitGenericArguments;
|
||||||
|
@ -198,6 +199,7 @@ public:
|
||||||
bool mBypassVirtual;
|
bool mBypassVirtual;
|
||||||
bool mAllowImplicitThis;
|
bool mAllowImplicitThis;
|
||||||
bool mAllowImplicitRef;
|
bool mAllowImplicitRef;
|
||||||
|
bool mAllowImplicitWrap;
|
||||||
bool mAllowStatic;
|
bool mAllowStatic;
|
||||||
bool mAllowNonStatic;
|
bool mAllowNonStatic;
|
||||||
bool mSkipImplicitParams;
|
bool mSkipImplicitParams;
|
||||||
|
@ -462,6 +464,7 @@ public:
|
||||||
BfResolvedArgs& argValue, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments, BfCheckedKind checkedKind = BfCheckedKind_NotSet);
|
BfResolvedArgs& argValue, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments, BfCheckedKind checkedKind = BfCheckedKind_NotSet);
|
||||||
BfTypedValue MakeCallableTarget(BfAstNode* targetSrc, BfTypedValue target);
|
BfTypedValue MakeCallableTarget(BfAstNode* targetSrc, BfTypedValue target);
|
||||||
BfModuleMethodInstance GetSelectedMethod(BfAstNode* targetSrc, BfTypeInstance* curTypeInst, BfMethodDef* methodDef, BfMethodMatcher& methodMatcher, BfType** overrideReturnType = NULL);
|
BfModuleMethodInstance GetSelectedMethod(BfAstNode* targetSrc, BfTypeInstance* curTypeInst, BfMethodDef* methodDef, BfMethodMatcher& methodMatcher, BfType** overrideReturnType = NULL);
|
||||||
|
BfModuleMethodInstance GetSelectedMethod(BfMethodMatcher& methodMatcher);
|
||||||
bool CheckVariableDeclaration(BfAstNode* checkNode, bool requireSimpleIfExpr, bool exprMustBeTrue, bool silentFail);
|
bool CheckVariableDeclaration(BfAstNode* checkNode, bool requireSimpleIfExpr, bool exprMustBeTrue, bool silentFail);
|
||||||
bool HasVariableDeclaration(BfAstNode* checkNode);
|
bool HasVariableDeclaration(BfAstNode* checkNode);
|
||||||
void DoInvocation(BfAstNode* target, BfMethodBoundExpression* methodBoundExpr, const BfSizedArray<BfExpression*>& args, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArgs, BfTypedValue* outCascadeValue = NULL);
|
void DoInvocation(BfAstNode* target, BfMethodBoundExpression* methodBoundExpr, const BfSizedArray<BfExpression*>& args, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArgs, BfTypedValue* outCascadeValue = NULL);
|
||||||
|
|
|
@ -80,6 +80,8 @@ enum BfEvalExprFlags
|
||||||
BfEvalExprFlags_DeclType = 0x1000000,
|
BfEvalExprFlags_DeclType = 0x1000000,
|
||||||
BfEvalExprFlags_AllowBase = 0x2000000,
|
BfEvalExprFlags_AllowBase = 0x2000000,
|
||||||
BfEvalExprFlags_NoCeRebuildFlags = 0x4000000,
|
BfEvalExprFlags_NoCeRebuildFlags = 0x4000000,
|
||||||
|
BfEvalExprFlags_FromConversionOp = 0x8000000,
|
||||||
|
BfEvalExprFlags_FromConversionOp_Explicit = 0x10000000,
|
||||||
|
|
||||||
BfEvalExprFlags_InheritFlags = BfEvalExprFlags_NoAutoComplete | BfEvalExprFlags_Comptime | BfEvalExprFlags_DeclType
|
BfEvalExprFlags_InheritFlags = BfEvalExprFlags_NoAutoComplete | BfEvalExprFlags_Comptime | BfEvalExprFlags_DeclType
|
||||||
};
|
};
|
||||||
|
@ -1836,6 +1838,7 @@ public:
|
||||||
void MarkScopeLeft(BfScopeData* scopeData);
|
void MarkScopeLeft(BfScopeData* scopeData);
|
||||||
BfGenericParamType* GetGenericParamType(BfGenericParamKind paramKind, int paramIdx);
|
BfGenericParamType* GetGenericParamType(BfGenericParamKind paramKind, int paramIdx);
|
||||||
BfType* ResolveGenericType(BfType* unspecializedType, BfTypeVector* typeGenericArguments, BfTypeVector* methodGenericArguments, bool allowFail = false);
|
BfType* ResolveGenericType(BfType* unspecializedType, BfTypeVector* typeGenericArguments, BfTypeVector* methodGenericArguments, bool allowFail = false);
|
||||||
|
BfType* ResolveSelfType(BfType* type, BfTypeInstance* selfType);
|
||||||
bool IsUnboundGeneric(BfType* type);
|
bool IsUnboundGeneric(BfType* type);
|
||||||
BfGenericParamInstance* GetGenericTypeParamInstance(int paramIdx);
|
BfGenericParamInstance* GetGenericTypeParamInstance(int paramIdx);
|
||||||
BfGenericParamInstance* GetGenericParamInstance(BfGenericParamType* type);
|
BfGenericParamInstance* GetGenericParamInstance(BfGenericParamType* type);
|
||||||
|
|
|
@ -434,9 +434,29 @@ bool BfModule::AreConstraintsSubset(BfGenericParamInstance* checkInner, BfGeneri
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& innerIFace : checkInner->mInterfaceConstraints)
|
for (auto innerIFace : checkInner->mInterfaceConstraints)
|
||||||
{
|
{
|
||||||
if (!checkOuter->mInterfaceConstraints.Contains(innerIFace))
|
if (checkOuter->mInterfaceConstraints.IsEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (checkOuter->mInterfaceConstraintSet == NULL)
|
||||||
|
{
|
||||||
|
std::function<void(BfTypeInstance*)> _AddInterface = [&](BfTypeInstance* ifaceType)
|
||||||
|
{
|
||||||
|
if (!checkOuter->mInterfaceConstraintSet->Add(ifaceType))
|
||||||
|
return;
|
||||||
|
if (ifaceType->mDefineState < BfTypeDefineState_HasInterfaces)
|
||||||
|
PopulateType(ifaceType);
|
||||||
|
for (auto& ifaceEntry : ifaceType->mInterfaces)
|
||||||
|
_AddInterface(ifaceEntry.mInterfaceType);
|
||||||
|
};
|
||||||
|
|
||||||
|
checkOuter->mInterfaceConstraintSet = new HashSet<BfTypeInstance*>();
|
||||||
|
for (auto outerIFace : checkOuter->mInterfaceConstraints)
|
||||||
|
_AddInterface(outerIFace);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!checkOuter->mInterfaceConstraintSet->Contains(innerIFace))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2590,12 +2610,6 @@ void BfModule::DoPopulateType_TypeAlias(BfTypeInstance* typeAlias)
|
||||||
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL);
|
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL);
|
||||||
SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, NULL);
|
SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, NULL);
|
||||||
|
|
||||||
if (typeAlias->mDefineState < BfTypeDefineState_Declaring)
|
|
||||||
{
|
|
||||||
typeAlias->mDefineState = BfTypeDefineState_Declaring;
|
|
||||||
DoPopulateType_InitSearches(typeAlias);
|
|
||||||
}
|
|
||||||
|
|
||||||
BF_ASSERT(mCurMethodInstance == NULL);
|
BF_ASSERT(mCurMethodInstance == NULL);
|
||||||
auto typeDef = typeAlias->mTypeDef;
|
auto typeDef = typeAlias->mTypeDef;
|
||||||
auto typeAliasDecl = (BfTypeAliasDeclaration*)typeDef->mTypeDeclaration;
|
auto typeAliasDecl = (BfTypeAliasDeclaration*)typeDef->mTypeDeclaration;
|
||||||
|
@ -2607,11 +2621,19 @@ void BfModule::DoPopulateType_TypeAlias(BfTypeInstance* typeAlias)
|
||||||
if ((typeAlias->mGenericTypeInfo != NULL) && (!typeAlias->mGenericTypeInfo->mFinishedGenericParams))
|
if ((typeAlias->mGenericTypeInfo != NULL) && (!typeAlias->mGenericTypeInfo->mFinishedGenericParams))
|
||||||
FinishGenericParams(typeAlias);
|
FinishGenericParams(typeAlias);
|
||||||
|
|
||||||
typeAlias->mDefineState = BfTypeDefineState_ResolvingBaseType;
|
|
||||||
BfTypeState typeState(mCurTypeInstance, mContext->mCurTypeState);
|
BfTypeState typeState(mCurTypeInstance, mContext->mCurTypeState);
|
||||||
typeState.mPopulateType = BfPopulateType_Data;
|
typeState.mPopulateType = BfPopulateType_Data;
|
||||||
typeState.mCurBaseTypeRef = typeAliasDecl->mAliasToType;
|
typeState.mCurBaseTypeRef = typeAliasDecl->mAliasToType;
|
||||||
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
|
||||||
|
|
||||||
|
if (typeAlias->mDefineState < BfTypeDefineState_Declaring)
|
||||||
|
{
|
||||||
|
typeAlias->mDefineState = BfTypeDefineState_Declaring;
|
||||||
|
DoPopulateType_InitSearches(typeAlias);
|
||||||
|
}
|
||||||
|
|
||||||
|
typeAlias->mDefineState = BfTypeDefineState_ResolvingBaseType;
|
||||||
|
|
||||||
if (!CheckCircularDataError())
|
if (!CheckCircularDataError())
|
||||||
{
|
{
|
||||||
if (typeAliasDecl->mAliasToType != NULL)
|
if (typeAliasDecl->mAliasToType != NULL)
|
||||||
|
@ -2826,6 +2848,9 @@ void BfModule::DoPopulateType_FinishEnum(BfTypeInstance* typeInstance, bool unde
|
||||||
else
|
else
|
||||||
typeCode = BfTypeCode_Int64;
|
typeCode = BfTypeCode_Int64;
|
||||||
|
|
||||||
|
if (typeInstance->mIsCRepr)
|
||||||
|
typeCode = BfTypeCode_Int32;
|
||||||
|
|
||||||
if (typeCode != BfTypeCode_Int64)
|
if (typeCode != BfTypeCode_Int64)
|
||||||
{
|
{
|
||||||
for (auto& fieldInstanceRef : typeInstance->mFieldInstances)
|
for (auto& fieldInstanceRef : typeInstance->mFieldInstances)
|
||||||
|
@ -8171,6 +8196,14 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
|
||||||
return unspecializedType;
|
return unspecializedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BfType* BfModule::ResolveSelfType(BfType* type, BfTypeInstance* selfType)
|
||||||
|
{
|
||||||
|
if (!type->IsUnspecializedTypeVariation())
|
||||||
|
return type;
|
||||||
|
SetAndRestoreValue<BfTypeInstance*> prevCurTypeInst(mCurTypeInstance, selfType);
|
||||||
|
return ResolveGenericType(type, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
BfType* BfModule::ResolveType(BfType* lookupType, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags)
|
BfType* BfModule::ResolveType(BfType* lookupType, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags)
|
||||||
{
|
{
|
||||||
BfResolvedTypeSet::LookupContext lookupCtx;
|
BfResolvedTypeSet::LookupContext lookupCtx;
|
||||||
|
@ -12540,378 +12573,167 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check user-defined operators
|
// Check user-defined operators
|
||||||
if ((castFlags & BfCastFlags_NoConversionOperator) == 0)
|
if (((castFlags & BfCastFlags_NoConversionOperator) == 0) && (toType != mContext->mBfObjectType))
|
||||||
{
|
{
|
||||||
auto fromType = typedVal.mType;
|
BfType* walkFromType = typedVal.mType;
|
||||||
auto fromTypeInstance = typedVal.mType->ToTypeInstance();
|
if (walkFromType->IsWrappableType())
|
||||||
auto toTypeInstance = toType->ToTypeInstance();
|
walkFromType = GetWrappedStructType(walkFromType);
|
||||||
|
BfType* walkToType = toType;
|
||||||
|
if (walkToType->IsWrappableType())
|
||||||
|
walkToType = GetWrappedStructType(walkToType);
|
||||||
|
|
||||||
auto liftedFromType = ((fromTypeInstance != NULL) && fromTypeInstance->IsNullable()) ? fromTypeInstance->GetUnderlyingType() : NULL;
|
SizedArray<BfResolvedArg, 1> args;
|
||||||
auto liftedToType = ((toTypeInstance != NULL) && toTypeInstance->IsNullable()) ? toTypeInstance->GetUnderlyingType() : NULL;
|
BfResolvedArg resolvedArg;
|
||||||
|
resolvedArg.mTypedValue = typedVal;
|
||||||
|
args.push_back(resolvedArg);
|
||||||
|
BfMethodMatcher methodMatcher(srcNode, this, "", args, NULL);
|
||||||
|
methodMatcher.mCheckReturnType = toType;
|
||||||
|
methodMatcher.mBfEvalExprFlags = (BfEvalExprFlags)(BfEvalExprFlags_NoAutoComplete | BfEvalExprFlags_FromConversionOp);
|
||||||
|
if ((castFlags & BfCastFlags_Explicit) != 0)
|
||||||
|
methodMatcher.mBfEvalExprFlags = (BfEvalExprFlags)(methodMatcher.mBfEvalExprFlags | BfEvalExprFlags_FromConversionOp_Explicit);
|
||||||
|
methodMatcher.mAllowImplicitRef = true;
|
||||||
|
methodMatcher.mAllowImplicitWrap = true;
|
||||||
|
BfBaseClassWalker baseClassWalker(walkFromType, walkToType, this);
|
||||||
|
|
||||||
int bestFromDist = INT_MAX;
|
bool isConstraintCheck = false;// ((opFlags& BfUnaryOpFlag_IsConstraintCheck) != 0);
|
||||||
BfType* bestFromType = NULL;
|
|
||||||
int bestNegFromDist = INT_MAX;
|
|
||||||
BfType* bestNegFromType = NULL;
|
|
||||||
|
|
||||||
int bestToDist = INT_MAX;
|
BfType* operatorConstraintReturnType = NULL;
|
||||||
BfType* bestToType = NULL;
|
BfType* bestSelfType = NULL;
|
||||||
int bestNegToDist = INT_MAX;
|
while (true)
|
||||||
BfType* bestNegToType = NULL;
|
|
||||||
bool isAmbiguousCast = false;
|
|
||||||
|
|
||||||
BfIRValue conversionResult;
|
|
||||||
BfMethodInstance* opMethodInstance = NULL;
|
|
||||||
BfType* opMethodSrcType = NULL;
|
|
||||||
BfOperatorInfo* constraintOperatorInfo = NULL;
|
|
||||||
|
|
||||||
// Normal, lifted, execute
|
|
||||||
for (int pass = 0; pass < 3; pass++)
|
|
||||||
{
|
{
|
||||||
auto checkToType = toType;
|
auto entry = baseClassWalker.Next();
|
||||||
auto checkFromType = fromType;
|
auto checkType = entry.mTypeInstance;
|
||||||
|
if (checkType == NULL)
|
||||||
if (pass == 1)
|
break;
|
||||||
|
for (auto operatorDef : checkType->mTypeDef->mOperators)
|
||||||
{
|
{
|
||||||
if ((bestFromType != NULL) && (bestToType != NULL))
|
if (operatorDef->mOperatorDeclaration->mIsConvOperator)
|
||||||
continue;
|
|
||||||
|
|
||||||
if (liftedFromType != NULL)
|
|
||||||
checkFromType = liftedFromType;
|
|
||||||
if (liftedToType != NULL)
|
|
||||||
checkToType = liftedToType;
|
|
||||||
}
|
|
||||||
else if (pass == 2)
|
|
||||||
{
|
|
||||||
if ((bestFromType == NULL) || (bestToType == NULL))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
BfType* searchFromType = checkFromType;
|
|
||||||
if (searchFromType->IsSizedArray())
|
|
||||||
searchFromType = GetWrappedStructType(checkFromType);
|
|
||||||
|
|
||||||
bool isConstraintCheck = ((castFlags & BfCastFlags_IsConstraintCheck) != 0);
|
|
||||||
BfBaseClassWalker baseClassWalker(searchFromType, toType, this);
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
auto entry = baseClassWalker.Next();
|
|
||||||
auto checkInstance = entry.mTypeInstance;
|
|
||||||
if (checkInstance == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
for (auto operatorDef : checkInstance->mTypeDef->mOperators)
|
|
||||||
{
|
{
|
||||||
if (operatorDef->mOperatorDeclaration->mIsConvOperator)
|
if ((!explicitCast) && (operatorDef->mOperatorDeclaration->mExplicitToken != NULL) &&
|
||||||
|
(operatorDef->mOperatorDeclaration->mExplicitToken->GetToken() == BfToken_Explicit))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!methodMatcher.IsMemberAccessible(checkType, operatorDef->mDeclaringType))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int prevArgSize = (int)args.mSize;
|
||||||
|
if (!operatorDef->mIsStatic)
|
||||||
{
|
{
|
||||||
if ((!explicitCast) && (operatorDef->mOperatorDeclaration->mExplicitToken != NULL) &&
|
// Try without arg
|
||||||
(operatorDef->mOperatorDeclaration->mExplicitToken->GetToken() == BfToken_Explicit))
|
args.mSize = 0;
|
||||||
continue;
|
}
|
||||||
|
|
||||||
BfType* methodFromType = NULL;
|
if (methodMatcher.CheckMethod(NULL, checkType, operatorDef, false))
|
||||||
BfType* methodToType = NULL;
|
methodMatcher.mSelfType = entry.mSrcType;
|
||||||
|
|
||||||
if (isConstraintCheck)
|
args.mSize = prevArgSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
methodMatcher.FlushAmbiguityError();
|
||||||
|
|
||||||
|
if (methodMatcher.mBestMethodDef == NULL)
|
||||||
|
{
|
||||||
|
// Check method generic constraints
|
||||||
|
if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mIsUnspecialized) && (mCurMethodInstance->mMethodInfoEx != NULL))
|
||||||
|
{
|
||||||
|
for (int genericParamIdx = 0; genericParamIdx < mCurMethodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
|
||||||
|
{
|
||||||
|
auto genericParam = mCurMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
|
||||||
|
for (auto& opConstraint : genericParam->mOperatorConstraints)
|
||||||
|
{
|
||||||
|
if ((opConstraint.mCastToken == BfToken_Implicit) ||
|
||||||
|
((explicitCast) && (opConstraint.mCastToken == BfToken_Explicit)))
|
||||||
{
|
{
|
||||||
auto operatorInfo = GetOperatorInfo(checkInstance, operatorDef);
|
// If we can convert OUR fromVal to the constraint's fromVal then we may match
|
||||||
methodFromType = operatorInfo->mLHSType;
|
if (CanCast(typedVal, opConstraint.mRightType, BfCastFlags_NoConversionOperator))
|
||||||
methodToType = operatorInfo->mReturnType;
|
|
||||||
if ((methodFromType == NULL) || (methodToType == NULL))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto methodInst = GetRawMethodInstanceAtIdx(checkInstance, operatorDef->mIdx);
|
|
||||||
if (methodInst == NULL)
|
|
||||||
continue;
|
|
||||||
if (methodInst->GetParamCount() != 1)
|
|
||||||
{
|
{
|
||||||
AssertErrorState();
|
// .. and we can convert the constraint's toType to OUR toType then we're good
|
||||||
continue;
|
auto opToVal = genericParam->mExternType;
|
||||||
}
|
if (CanCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType, BfCastFlags_NoConversionOperator))
|
||||||
|
return mBfIRBuilder->GetFakeVal();
|
||||||
methodFromType = methodInst->GetParamType(0);
|
|
||||||
methodToType = methodInst->mReturnType;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (methodFromType->IsRef())
|
|
||||||
methodFromType = methodFromType->GetUnderlyingType();
|
|
||||||
|
|
||||||
if (methodFromType->IsSelf())
|
|
||||||
methodFromType = entry.mSrcType;
|
|
||||||
if (methodToType->IsSelf())
|
|
||||||
methodToType = entry.mSrcType;
|
|
||||||
|
|
||||||
// Selection pass
|
|
||||||
if (pass < 2)
|
|
||||||
{
|
|
||||||
auto methodCheckFromType = methodFromType;
|
|
||||||
auto methodCheckToType = methodToType;
|
|
||||||
if (pass == 1)
|
|
||||||
{
|
|
||||||
// Only check inner type on lifted types when we aren't checking conversions within lifted class
|
|
||||||
// This avoid some infinite conversions
|
|
||||||
if ((methodCheckFromType->IsNullable()) && (!checkInstance->IsNullable()))
|
|
||||||
methodCheckFromType = methodCheckFromType->GetUnderlyingType();
|
|
||||||
if ((methodCheckToType->IsNullable()) && (!checkInstance->IsNullable()))
|
|
||||||
methodCheckToType = methodCheckToType->GetUnderlyingType();
|
|
||||||
}
|
|
||||||
|
|
||||||
int fromDist = GetTypeDistance(methodCheckFromType, checkFromType);
|
|
||||||
if ((fromDist == INT_MAX) && (searchFromType != checkFromType))
|
|
||||||
{
|
|
||||||
fromDist = GetTypeDistance(methodCheckFromType, searchFromType);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fromDist < 0)
|
|
||||||
{
|
|
||||||
// Allow us to cast a constant int to a smaller type if it satisfies the cast operator
|
|
||||||
if ((typedVal.mValue.IsConst()) && (CanCast(typedVal, methodCheckFromType, BfCastFlags_NoConversionOperator)))
|
|
||||||
{
|
|
||||||
fromDist = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int toDist = GetTypeDistance(methodCheckToType, checkToType);
|
|
||||||
|
|
||||||
if ((fromDist == INT_MAX) || (toDist == INT_MAX))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (((fromDist >= 0) && (toDist >= 0)) || (explicitCast))
|
|
||||||
{
|
|
||||||
if ((fromDist >= 0) && (fromDist < bestFromDist))
|
|
||||||
{
|
|
||||||
bestFromDist = fromDist;
|
|
||||||
bestFromType = methodFromType;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((toDist >= 0) && (toDist < bestToDist))
|
|
||||||
{
|
|
||||||
bestToDist = toDist;
|
|
||||||
bestToType = methodToType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (explicitCast)
|
|
||||||
{
|
|
||||||
fromDist = abs(fromDist);
|
|
||||||
toDist = abs(toDist);
|
|
||||||
|
|
||||||
if ((fromDist >= 0) && (fromDist < bestNegFromDist))
|
|
||||||
{
|
|
||||||
bestNegFromDist = fromDist;
|
|
||||||
bestNegFromType = methodFromType;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((toDist >= 0) && (toDist < bestNegToDist))
|
|
||||||
{
|
|
||||||
bestNegToDist = toDist;
|
|
||||||
bestNegToType = methodToType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pass == 2) // Execution Pass
|
|
||||||
{
|
|
||||||
if ((methodFromType == bestFromType) && (methodToType == bestToType))
|
|
||||||
{
|
|
||||||
if (isConstraintCheck)
|
|
||||||
{
|
|
||||||
auto operatorInfo = GetOperatorInfo(checkInstance, operatorDef);
|
|
||||||
constraintOperatorInfo = operatorInfo;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Get in native module so our module doesn't get a reference to it - we may not end up calling it at all!
|
|
||||||
BfMethodInstance* methodInstance = GetRawMethodInstanceAtIdx(checkInstance, operatorDef->mIdx);
|
|
||||||
|
|
||||||
if (opMethodInstance != NULL)
|
|
||||||
{
|
|
||||||
int prevGenericCount = GetGenericParamAndReturnCount(opMethodInstance);
|
|
||||||
int newGenericCount = GetGenericParamAndReturnCount(methodInstance);
|
|
||||||
if (newGenericCount > prevGenericCount)
|
|
||||||
{
|
|
||||||
// Prefer generic match
|
|
||||||
opMethodInstance = methodInstance;
|
|
||||||
opMethodSrcType = entry.mSrcType;
|
|
||||||
}
|
|
||||||
else if (newGenericCount < prevGenericCount)
|
|
||||||
{
|
|
||||||
// Previous was a generic match
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isAmbiguousCast = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
opMethodInstance = methodInstance;
|
|
||||||
opMethodSrcType = entry.mSrcType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAmbiguousCast)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if ((opMethodInstance != NULL) || (constraintOperatorInfo != NULL))
|
|
||||||
{
|
|
||||||
if (mayBeBox)
|
|
||||||
{
|
|
||||||
if (!ignoreErrors)
|
|
||||||
{
|
|
||||||
if (Fail("Ambiguous cast, may be conversion operator or may be boxing request", srcNode) != NULL)
|
|
||||||
mCompiler->mPassInstance->MoreInfo("See conversion operator", opMethodInstance->mMethodDef->GetRefNode());
|
|
||||||
}
|
|
||||||
else if (!silentFail)
|
|
||||||
SetFail();
|
|
||||||
}
|
|
||||||
|
|
||||||
BfType* returnType;
|
|
||||||
if (isConstraintCheck)
|
|
||||||
{
|
|
||||||
returnType = constraintOperatorInfo->mReturnType;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
returnType = opMethodInstance->mReturnType;
|
|
||||||
BfMethodInstance* methodInstance = GetRawMethodInstance(opMethodInstance->GetOwner(), opMethodInstance->mMethodDef);
|
|
||||||
auto methodDeclaration = methodInstance->mMethodDef->GetMethodDeclaration();
|
|
||||||
if (methodDeclaration->mBody == NULL)
|
|
||||||
{
|
|
||||||
// Handle the typedPrim<->underlying part implicitly
|
|
||||||
if (fromType->IsTypedPrimitive())
|
|
||||||
{
|
|
||||||
auto convTypedValue = BfTypedValue(typedVal.mValue, fromType->GetUnderlyingType());
|
|
||||||
return CastToValue(srcNode, convTypedValue, toType, (BfCastFlags)(castFlags & ~BfCastFlags_Explicit), NULL);
|
|
||||||
}
|
|
||||||
else if (toType->IsTypedPrimitive())
|
|
||||||
{
|
|
||||||
auto castedVal = CastToValue(srcNode, typedVal, toType->GetUnderlyingType(), (BfCastFlags)(castFlags & ~BfCastFlags_Explicit), NULL);
|
|
||||||
return castedVal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actually perform conversion
|
|
||||||
BfExprEvaluator exprEvaluator(this);
|
|
||||||
BfTypedValue castedFromValue;
|
|
||||||
if ((typedVal.mType->IsSizedArray()) && (bestFromType->IsInstanceOf(mCompiler->mSizedArrayTypeDef)))
|
|
||||||
{
|
|
||||||
castedFromValue = MakeAddressable(typedVal);
|
|
||||||
if (!bestFromType->IsValuelessType())
|
|
||||||
castedFromValue.mValue = mBfIRBuilder->CreateBitCast(castedFromValue.mValue, mBfIRBuilder->MapTypeInstPtr(bestFromType->ToTypeInstance()));
|
|
||||||
castedFromValue.mType = bestFromType;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
castedFromValue = Cast(srcNode, typedVal, bestFromType, castFlags);
|
|
||||||
if (!castedFromValue)
|
|
||||||
return BfIRValue();
|
|
||||||
|
|
||||||
BfTypedValue operatorOut;
|
|
||||||
if (ignoreWrites)
|
|
||||||
{
|
|
||||||
if (opMethodInstance != NULL)
|
|
||||||
exprEvaluator.PerformCallChecks(opMethodInstance, srcNode);
|
|
||||||
|
|
||||||
if (returnType == toType)
|
|
||||||
return mBfIRBuilder->GetFakeVal();
|
|
||||||
operatorOut = GetDefaultTypedValue(returnType, false, BfDefaultValueKind_Addr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BfModuleMethodInstance moduleMethodInstance = GetMethodInstance(opMethodInstance->GetOwner(), opMethodInstance->mMethodDef, BfTypeVector());
|
|
||||||
exprEvaluator.PerformCallChecks(moduleMethodInstance.mMethodInstance, srcNode);
|
|
||||||
|
|
||||||
if (moduleMethodInstance.mMethodInstance->GetParamType(0)->IsRef())
|
|
||||||
castedFromValue = ToRef(castedFromValue);
|
|
||||||
|
|
||||||
SizedArray<BfIRValue, 1> args;
|
|
||||||
exprEvaluator.PushArg(castedFromValue, args);
|
|
||||||
operatorOut = exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, IsSkippingExtraResolveChecks() ? BfIRValue() : moduleMethodInstance.mFunc, false, args);
|
|
||||||
if ((operatorOut.mType != NULL) && (operatorOut.mType->IsSelf()))
|
|
||||||
{
|
|
||||||
BF_ASSERT(IsInGeneric());
|
|
||||||
operatorOut = GetDefaultTypedValue(opMethodSrcType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return CastToValue(srcNode, operatorOut, toType, castFlags, resultFlags);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bestFromType == NULL)
|
// Check type generic constraints
|
||||||
bestFromType = bestNegFromType;
|
if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsGenericTypeInstance()) && (mCurTypeInstance->IsUnspecializedType()))
|
||||||
if (bestToType == NULL)
|
|
||||||
bestToType = bestNegToType;
|
|
||||||
}
|
|
||||||
|
|
||||||
isAmbiguousCast |= ((bestFromType != NULL) && (bestToType != NULL));
|
|
||||||
if (isAmbiguousCast)
|
|
||||||
{
|
|
||||||
if (!ignoreErrors)
|
|
||||||
{
|
{
|
||||||
const char* errStr = "Ambiguous conversion operators for casting from '%s' to '%s'";
|
SizedArray<BfGenericParamInstance*, 4> genericParams;
|
||||||
Fail(StrFormat(errStr, TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
|
GetActiveTypeGenericParamInstances(genericParams);
|
||||||
}
|
for (auto genericParam : genericParams)
|
||||||
else if (!silentFail)
|
|
||||||
SetFail();
|
|
||||||
return BfIRValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check method generic constraints
|
|
||||||
if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mIsUnspecialized) && (mCurMethodInstance->mMethodInfoEx != NULL))
|
|
||||||
{
|
|
||||||
for (int genericParamIdx = 0; genericParamIdx < mCurMethodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
|
|
||||||
{
|
|
||||||
auto genericParam = mCurMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
|
|
||||||
for (auto& opConstraint : genericParam->mOperatorConstraints)
|
|
||||||
{
|
{
|
||||||
if ((opConstraint.mCastToken == BfToken_Implicit) ||
|
for (auto& opConstraint : genericParam->mOperatorConstraints)
|
||||||
((explicitCast) && (opConstraint.mCastToken == BfToken_Explicit)))
|
|
||||||
{
|
{
|
||||||
// If we can convert OUR fromVal to the constraint's fromVal then we may match
|
if ((opConstraint.mCastToken == BfToken_Implicit) ||
|
||||||
if (CanCast(typedVal, opConstraint.mRightType, BfCastFlags_NoConversionOperator))
|
((explicitCast) && (opConstraint.mCastToken == BfToken_Explicit)))
|
||||||
{
|
{
|
||||||
// .. and we can convert the constraint's toType to OUR toType then we're good
|
// If we can convert OUR fromVal to the constraint's fromVal then we may match
|
||||||
auto opToVal = genericParam->mExternType;
|
if (CanCast(typedVal, opConstraint.mRightType, BfCastFlags_NoConversionOperator))
|
||||||
if (CanCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType, BfCastFlags_NoConversionOperator))
|
{
|
||||||
return mBfIRBuilder->GetFakeVal();
|
// .. and we can convert the constraint's toType to OUR toType then we're good
|
||||||
|
auto opToVal = genericParam->mExternType;
|
||||||
|
if (CanCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType, BfCastFlags_NoConversionOperator))
|
||||||
|
return mBfIRBuilder->GetFakeVal();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Check type generic constraints
|
|
||||||
if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsGenericTypeInstance()) && (mCurTypeInstance->IsUnspecializedType()))
|
|
||||||
{
|
{
|
||||||
SizedArray<BfGenericParamInstance*, 4> genericParams;
|
BfTypedValue result;
|
||||||
GetActiveTypeGenericParamInstances(genericParams);
|
BfExprEvaluator exprEvaluator(this);
|
||||||
for (auto genericParam : genericParams)
|
exprEvaluator.mBfEvalExprFlags = BfEvalExprFlags_FromConversionOp;
|
||||||
|
|
||||||
|
auto moduleMethodInstance = exprEvaluator.GetSelectedMethod(methodMatcher);
|
||||||
|
if (moduleMethodInstance.mMethodInstance != NULL)
|
||||||
{
|
{
|
||||||
for (auto& opConstraint : genericParam->mOperatorConstraints)
|
auto paramType = moduleMethodInstance.mMethodInstance->GetParamType(0);
|
||||||
|
auto wantType = paramType;
|
||||||
|
if (wantType->IsRef())
|
||||||
|
wantType = wantType->GetUnderlyingType();
|
||||||
|
auto typedVal = methodMatcher.mArguments[0].mTypedValue;
|
||||||
|
if (wantType != typedVal.mType)
|
||||||
{
|
{
|
||||||
if ((opConstraint.mCastToken == BfToken_Implicit) ||
|
if ((typedVal.mType->IsWrappableType()) && (wantType == GetWrappedStructType(typedVal.mType)))
|
||||||
((explicitCast) && (opConstraint.mCastToken == BfToken_Explicit)))
|
|
||||||
{
|
{
|
||||||
// If we can convert OUR fromVal to the constraint's fromVal then we may match
|
typedVal = MakeAddressable(typedVal);
|
||||||
if (CanCast(typedVal, opConstraint.mRightType, BfCastFlags_NoConversionOperator))
|
methodMatcher.mArguments[0].mTypedValue = BfTypedValue(mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapTypeInstPtr(wantType->ToTypeInstance())),
|
||||||
|
paramType, paramType->IsRef() ? BfTypedValueKind_Value : BfTypedValueKind_Addr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
methodMatcher.mArguments[0].mTypedValue = Cast(srcNode, typedVal, wantType, BfCastFlags_Explicit);
|
||||||
|
if (paramType->IsRef())
|
||||||
{
|
{
|
||||||
// .. and we can convert the constraint's toType to OUR toType then we're good
|
typedVal = MakeAddressable(typedVal);
|
||||||
auto opToVal = genericParam->mExternType;
|
typedVal.mKind = BfTypedValueKind_Addr;
|
||||||
if (CanCast(BfTypedValue(BfIRValue::sValueless, opToVal), toType, BfCastFlags_NoConversionOperator))
|
|
||||||
return mBfIRBuilder->GetFakeVal();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result = exprEvaluator.CreateCall(&methodMatcher, BfTypedValue());
|
||||||
|
if (resultFlags != NULL)
|
||||||
|
{
|
||||||
|
if (result.IsAddr())
|
||||||
|
*resultFlags = (BfCastResultFlags)(*resultFlags | BfCastResultFlags_IsAddr);
|
||||||
|
if (result.mKind == BfTypedValueKind_TempAddr)
|
||||||
|
*resultFlags = (BfCastResultFlags)(*resultFlags | BfCastResultFlags_IsTemp);
|
||||||
|
}
|
||||||
|
else if (result.IsAddr())
|
||||||
|
result = LoadValue(result);
|
||||||
|
|
||||||
|
if (result.mType != toType)
|
||||||
|
return CastToValue(srcNode, result, toType, BfCastFlags_Explicit, resultFlags);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
return result.mValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1141,6 +1141,7 @@ public:
|
||||||
BfGenericParamFlags mGenericParamFlags;
|
BfGenericParamFlags mGenericParamFlags;
|
||||||
BfType* mExternType;
|
BfType* mExternType;
|
||||||
Array<BfTypeInstance*> mInterfaceConstraints;
|
Array<BfTypeInstance*> mInterfaceConstraints;
|
||||||
|
HashSet<BfTypeInstance*>* mInterfaceConstraintSet;
|
||||||
Array<BfGenericOperatorConstraintInstance> mOperatorConstraints;
|
Array<BfGenericOperatorConstraintInstance> mOperatorConstraints;
|
||||||
Array<BfTypeReference*> mComptypeConstraint;
|
Array<BfTypeReference*> mComptypeConstraint;
|
||||||
BfType* mTypeConstraint;
|
BfType* mTypeConstraint;
|
||||||
|
@ -1151,6 +1152,7 @@ public:
|
||||||
mExternType = NULL;
|
mExternType = NULL;
|
||||||
mGenericParamFlags = BfGenericParamFlag_None;
|
mGenericParamFlags = BfGenericParamFlag_None;
|
||||||
mTypeConstraint = NULL;
|
mTypeConstraint = NULL;
|
||||||
|
mInterfaceConstraintSet = NULL;
|
||||||
mRefCount = 1;
|
mRefCount = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1162,6 +1164,7 @@ public:
|
||||||
|
|
||||||
virtual ~BfGenericParamInstance()
|
virtual ~BfGenericParamInstance()
|
||||||
{
|
{
|
||||||
|
delete mInterfaceConstraintSet;
|
||||||
}
|
}
|
||||||
virtual BfConstraintDef* GetConstraintDef() = 0;
|
virtual BfConstraintDef* GetConstraintDef() = 0;
|
||||||
virtual BfGenericParamDef* GetGenericParamDef() = 0;
|
virtual BfGenericParamDef* GetGenericParamDef() = 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue