mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-09 12:02:21 +02:00
Method selection issues, issues with tuples containing 'var'
This commit is contained in:
parent
03c8d72f33
commit
fc21c66b27
5 changed files with 117 additions and 24 deletions
|
@ -573,6 +573,15 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
|
||||||
BfMethodDef* prevMethodDef = prevMethodInstance->mMethodDef;
|
BfMethodDef* prevMethodDef = prevMethodInstance->mMethodDef;
|
||||||
BfMethodDef* newMethodDef = newMethodInstance->mMethodDef;
|
BfMethodDef* newMethodDef = newMethodInstance->mMethodDef;
|
||||||
|
|
||||||
|
if (prevMethodDef == mBackupMethodDef)
|
||||||
|
{
|
||||||
|
// This can happen for extension methods and such
|
||||||
|
*outNewIsBetter = true;
|
||||||
|
*outNewIsWorse = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (newMethodDef->mExplicitInterface != prevMethodDef->mExplicitInterface)
|
if (newMethodDef->mExplicitInterface != prevMethodDef->mExplicitInterface)
|
||||||
{
|
{
|
||||||
if (mModule->CompareMethodSignatures(newMethodInstance, prevMethodInstance))
|
if (mModule->CompareMethodSignatures(newMethodInstance, prevMethodInstance))
|
||||||
|
@ -688,9 +697,9 @@ void BfMethodMatcher::CompareMethods(BfMethodInstance* prevMethodInstance, BfTyp
|
||||||
{
|
{
|
||||||
// The resolved argument type may actually match for both considered functions. IE:
|
// The resolved argument type may actually match for both considered functions. IE:
|
||||||
// Method(int8 val) and Method(int16 val) called with Method(0) will create arguments that match their param types
|
// Method(int8 val) and Method(int16 val) called with Method(0) will create arguments that match their param types
|
||||||
if ((IsType(arg, paramType)) && ((resolvedArg == NULL) || (prevParamType != resolvedArg->mBestBoundType)))
|
if ((!wasGenericParam) && (IsType(arg, paramType)) && ((resolvedArg == NULL) || (prevParamType != resolvedArg->mBestBoundType)))
|
||||||
isBetter = true;
|
isBetter = true;
|
||||||
else if ((IsType(arg, prevParamType)) && (!IsType(arg, paramType)))
|
else if ((!prevWasGenericParam) && (IsType(arg, prevParamType)) && (!IsType(arg, paramType)))
|
||||||
isWorse = true;
|
isWorse = true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1438,7 +1447,6 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
|
||||||
auto type = argTypedValue.mType;
|
auto type = argTypedValue.mType;
|
||||||
if (!argTypedValue)
|
if (!argTypedValue)
|
||||||
goto NoMatch;
|
goto NoMatch;
|
||||||
//HashSet<BfType*> checkedTypeSet;
|
|
||||||
|
|
||||||
if (type->IsVar())
|
if (type->IsVar())
|
||||||
mHasVarArguments = true;
|
mHasVarArguments = true;
|
||||||
|
@ -7328,10 +7336,17 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
||||||
|
|
||||||
bool isSkipCall = moduleMethodInstance.mMethodInstance->IsSkipCall(bypassVirtual);
|
bool isSkipCall = moduleMethodInstance.mMethodInstance->IsSkipCall(bypassVirtual);
|
||||||
|
|
||||||
|
if ((moduleMethodInstance.mMethodInstance->mIsUnspecializedVariation) && (!mModule->mBfIRBuilder->mIgnoreWrites))
|
||||||
|
{
|
||||||
|
// Invalid methods such as types with a HasVar tuple generic arg will be marked as mIsUnspecializedVariation and shouldn't actually be called
|
||||||
|
FinishDeferredEvals(argValues.mResolvedArgs);
|
||||||
|
return mModule->GetDefaultTypedValue(moduleMethodInstance.mMethodInstance->mReturnType, true, BfDefaultValueKind_Addr);
|
||||||
|
}
|
||||||
|
|
||||||
if (methodDef->IsEmptyPartial())
|
if (methodDef->IsEmptyPartial())
|
||||||
{
|
{
|
||||||
// Ignore call
|
// Ignore call
|
||||||
return mModule->GetDefaultTypedValue(moduleMethodInstance.mMethodInstance->mReturnType);
|
return mModule->GetDefaultTypedValue(moduleMethodInstance.mMethodInstance->mReturnType, true, BfDefaultValueKind_Addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((moduleMethodInstance.mMethodInstance->mMethodDef->mIsStatic) && (moduleMethodInstance.mMethodInstance->GetOwner()->IsInterface()))
|
if ((moduleMethodInstance.mMethodInstance->mMethodDef->mIsStatic) && (moduleMethodInstance.mMethodInstance->GetOwner()->IsInterface()))
|
||||||
|
@ -7356,7 +7371,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
||||||
else
|
else
|
||||||
mModule->Fail(StrFormat("Static interface method '%s' can only be dispatched from a concrete type, consider using this interface as a generic constraint", mModule->MethodToString(moduleMethodInstance.mMethodInstance).c_str()), targetSrc);
|
mModule->Fail(StrFormat("Static interface method '%s' can only be dispatched from a concrete type, consider using this interface as a generic constraint", mModule->MethodToString(moduleMethodInstance.mMethodInstance).c_str()), targetSrc);
|
||||||
FinishDeferredEvals(argValues.mResolvedArgs);
|
FinishDeferredEvals(argValues.mResolvedArgs);
|
||||||
return mModule->GetDefaultTypedValue(moduleMethodInstance.mMethodInstance->mReturnType);
|
return mModule->GetDefaultTypedValue(moduleMethodInstance.mMethodInstance->mReturnType, true, BfDefaultValueKind_Addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15560,7 +15575,7 @@ void BfExprEvaluator::PopulateDeferrredTupleAssignData(BfTupleExpression* tupleE
|
||||||
fieldNames.push_back(requestedName->mNameNode->ToString());
|
fieldNames.push_back(requestedName->mNameNode->ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
BfTypeInstance* tupleType = mModule->CreateTupleType(fieldTypes, fieldNames);
|
BfTypeInstance* tupleType = mModule->CreateTupleType(fieldTypes, fieldNames, true);
|
||||||
deferredTupleAssignData.mTupleType = tupleType;
|
deferredTupleAssignData.mTupleType = tupleType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16583,7 +16598,11 @@ void BfExprEvaluator::Visit(BfTupleExpression* tupleExpr)
|
||||||
typedVal = mModule->LoadValue(typedVal);
|
typedVal = mModule->LoadValue(typedVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typedVal.IsSplat())
|
if (typedVal.mType->IsVar())
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
else if (typedVal.IsSplat())
|
||||||
mModule->AggregateSplatIntoAddr(typedVal, memberVal);
|
mModule->AggregateSplatIntoAddr(typedVal, memberVal);
|
||||||
else
|
else
|
||||||
mModule->mBfIRBuilder->CreateStore(typedVal.mValue, memberVal);
|
mModule->mBfIRBuilder->CreateStore(typedVal.mValue, memberVal);
|
||||||
|
|
|
@ -1630,7 +1630,7 @@ public:
|
||||||
BfPointerType* CreatePointerType(BfTypeReference* typeRef);
|
BfPointerType* CreatePointerType(BfTypeReference* typeRef);
|
||||||
BfConstExprValueType* CreateConstExprValueType(const BfTypedValue& typedValue);
|
BfConstExprValueType* CreateConstExprValueType(const BfTypedValue& typedValue);
|
||||||
BfBoxedType* CreateBoxedType(BfType* resolvedTypeRef);
|
BfBoxedType* CreateBoxedType(BfType* resolvedTypeRef);
|
||||||
BfTypeInstance* CreateTupleType(const BfTypeVector& fieldTypes, const Array<String>& fieldNames);
|
BfTypeInstance* CreateTupleType(const BfTypeVector& fieldTypes, const Array<String>& fieldNames, bool allowVar = false);
|
||||||
BfTypeInstance* SantizeTupleType(BfTypeInstance* tupleType);
|
BfTypeInstance* SantizeTupleType(BfTypeInstance* tupleType);
|
||||||
BfRefType* CreateRefType(BfType* resolvedTypeRef, BfRefType::RefKind refKind = BfRefType::RefKind_Ref);
|
BfRefType* CreateRefType(BfType* resolvedTypeRef, BfRefType::RefKind refKind = BfRefType::RefKind_Ref);
|
||||||
BfModifiedTypeType* CreateModifiedTypeType(BfType* resolvedTypeRef, BfToken modifiedKind);
|
BfModifiedTypeType* CreateModifiedTypeType(BfType* resolvedTypeRef, BfToken modifiedKind);
|
||||||
|
|
|
@ -5295,7 +5295,7 @@ BfBoxedType* BfModule::CreateBoxedType(BfType* resolvedTypeRef)
|
||||||
return (BfBoxedType*)resolvedBoxedType;
|
return (BfBoxedType*)resolvedBoxedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
BfTypeInstance* BfModule::CreateTupleType(const BfTypeVector& fieldTypes, const Array<String>& fieldNames)
|
BfTypeInstance* BfModule::CreateTupleType(const BfTypeVector& fieldTypes, const Array<String>& fieldNames, bool allowVar)
|
||||||
{
|
{
|
||||||
auto baseType = (BfTypeInstance*)ResolveTypeDef(mContext->mCompiler->mValueTypeTypeDef);
|
auto baseType = (BfTypeInstance*)ResolveTypeDef(mContext->mCompiler->mValueTypeTypeDef);
|
||||||
|
|
||||||
|
@ -5315,7 +5315,7 @@ BfTypeInstance* BfModule::CreateTupleType(const BfTypeVector& fieldTypes, const
|
||||||
BfFieldDef* fieldDef = actualTupleType->AddField(fieldName);
|
BfFieldDef* fieldDef = actualTupleType->AddField(fieldName);
|
||||||
|
|
||||||
auto fieldType = fieldTypes[fieldIdx];
|
auto fieldType = fieldTypes[fieldIdx];
|
||||||
if (fieldType->IsUnspecializedType())
|
if ((fieldType->IsUnspecializedType()) || (fieldType->IsVar()))
|
||||||
isUnspecialzied = true;
|
isUnspecialzied = true;
|
||||||
}
|
}
|
||||||
tupleType = actualTupleType;
|
tupleType = actualTupleType;
|
||||||
|
@ -5326,7 +5326,10 @@ BfTypeInstance* BfModule::CreateTupleType(const BfTypeVector& fieldTypes, const
|
||||||
{
|
{
|
||||||
BfFieldInstance* fieldInstance = (BfFieldInstance*)&tupleType->mFieldInstances[fieldIdx];
|
BfFieldInstance* fieldInstance = (BfFieldInstance*)&tupleType->mFieldInstances[fieldIdx];
|
||||||
fieldInstance->mFieldIdx = fieldIdx;
|
fieldInstance->mFieldIdx = fieldIdx;
|
||||||
fieldInstance->SetResolvedType(fieldTypes[fieldIdx]);
|
BfType* fieldType = fieldTypes[fieldIdx];
|
||||||
|
if ((fieldType->IsVar()) && (!allowVar))
|
||||||
|
fieldType = mContext->mBfObjectType;
|
||||||
|
fieldInstance->SetResolvedType(fieldType);
|
||||||
fieldInstance->mOwner = tupleType;
|
fieldInstance->mOwner = tupleType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6079,6 +6082,9 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty
|
||||||
wantGeneric = true;
|
wantGeneric = true;
|
||||||
if (newGenericArg->IsUnspecializedType())
|
if (newGenericArg->IsUnspecializedType())
|
||||||
isUnspecialized = true;
|
isUnspecialized = true;
|
||||||
|
if (newGenericArg->IsVar())
|
||||||
|
wantGeneric = mContext->mBfObjectType;
|
||||||
|
//wantGeneric = true;
|
||||||
|
|
||||||
if (newGenericArg != origGenericArg)
|
if (newGenericArg != origGenericArg)
|
||||||
hadChange = true;
|
hadChange = true;
|
||||||
|
@ -8475,6 +8481,9 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
||||||
wantGeneric = true;
|
wantGeneric = true;
|
||||||
if (type->IsUnspecializedType())
|
if (type->IsUnspecializedType())
|
||||||
isUnspecialized = true;
|
isUnspecialized = true;
|
||||||
|
BF_ASSERT(!type->IsVar());
|
||||||
|
// if (type->IsVar())
|
||||||
|
// isUnspecialized = true;
|
||||||
|
|
||||||
String typeName = TypeToString(type);
|
String typeName = TypeToString(type);
|
||||||
types.push_back(type);
|
types.push_back(type);
|
||||||
|
@ -8536,6 +8545,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
||||||
BfFieldInstance* fieldInstance = &tupleType->mFieldInstances[fieldIdx];
|
BfFieldInstance* fieldInstance = &tupleType->mFieldInstances[fieldIdx];
|
||||||
fieldInstance->mFieldIdx = fieldIdx;
|
fieldInstance->mFieldIdx = fieldIdx;
|
||||||
fieldInstance->SetResolvedType(types[fieldIdx]);
|
fieldInstance->SetResolvedType(types[fieldIdx]);
|
||||||
|
BF_ASSERT(!types[fieldIdx]->IsVar());
|
||||||
fieldInstance->mOwner = tupleType;
|
fieldInstance->mOwner = tupleType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9715,12 +9725,18 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
// Nullable<A> -> Nullable<B>
|
// Nullable<A> -> Nullable<B>
|
||||||
if ((typedVal.mType->IsNullable()) && (toType->IsNullable()))
|
if ((typedVal.mType->IsNullable()) && (toType->IsNullable()))
|
||||||
{
|
{
|
||||||
if (ignoreWrites)
|
|
||||||
return mBfIRBuilder->GetFakeVal();
|
|
||||||
|
|
||||||
auto fromNullableType = (BfTypeInstance*)typedVal.mType;
|
auto fromNullableType = (BfTypeInstance*)typedVal.mType;
|
||||||
auto toNullableType = (BfTypeInstance*)toType;
|
auto toNullableType = (BfTypeInstance*)toType;
|
||||||
|
|
||||||
|
if (ignoreWrites)
|
||||||
|
{
|
||||||
|
auto toVal = CastToValue(srcNode, BfTypedValue(mBfIRBuilder->GetFakeVal(), fromNullableType->mGenericTypeInfo->mTypeGenericArguments[0]),
|
||||||
|
toNullableType->mGenericTypeInfo->mTypeGenericArguments[0], ignoreErrors ? BfCastFlags_SilentFail : BfCastFlags_None);
|
||||||
|
if (!toVal)
|
||||||
|
return BfIRValue();
|
||||||
|
return mBfIRBuilder->GetFakeVal();
|
||||||
|
}
|
||||||
|
|
||||||
BfIRValue srcPtr = typedVal.mValue;
|
BfIRValue srcPtr = typedVal.mValue;
|
||||||
if (!typedVal.IsAddr())
|
if (!typedVal.IsAddr())
|
||||||
{
|
{
|
||||||
|
@ -9757,6 +9773,10 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
{
|
{
|
||||||
auto fromTupleType = (BfTypeInstance*)typedVal.mType;
|
auto fromTupleType = (BfTypeInstance*)typedVal.mType;
|
||||||
auto toTupleType = (BfTypeInstance*)toType;
|
auto toTupleType = (BfTypeInstance*)toType;
|
||||||
|
|
||||||
|
PopulateType(fromTupleType);
|
||||||
|
PopulateType(toTupleType);
|
||||||
|
|
||||||
if (fromTupleType->mFieldInstances.size() == toTupleType->mFieldInstances.size())
|
if (fromTupleType->mFieldInstances.size() == toTupleType->mFieldInstances.size())
|
||||||
{
|
{
|
||||||
typedVal = LoadValue(typedVal);
|
typedVal = LoadValue(typedVal);
|
||||||
|
@ -10096,6 +10116,13 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((typedVal.mValue.IsConst()) && (toType->IsPointer()) && (toType->GetUnderlyingType() == GetPrimitiveType(BfTypeCode_Char8)) && (typedVal.mType->IsInstanceOf(mCompiler->mStringTypeDef)))
|
||||||
|
{
|
||||||
|
int stringId = GetStringPoolIdx(typedVal.mValue, mBfIRBuilder);
|
||||||
|
if (stringId >= 0)
|
||||||
|
return GetStringCharPtr(stringId);
|
||||||
|
}
|
||||||
|
|
||||||
// Check user-defined operators
|
// Check user-defined operators
|
||||||
if ((castFlags & BfCastFlags_NoConversionOperator) == 0)
|
if ((castFlags & BfCastFlags_NoConversionOperator) == 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -798,7 +798,6 @@ public:
|
||||||
bool mIsIntrinsic:1;
|
bool mIsIntrinsic:1;
|
||||||
bool mHasMethodRefType:1;
|
bool mHasMethodRefType:1;
|
||||||
bool mDisallowCalling:1;
|
bool mDisallowCalling:1;
|
||||||
bool mIsGenericMethodInstance:1;
|
|
||||||
BfMethodChainType mChainType;
|
BfMethodChainType mChainType;
|
||||||
BfCallingConvention mCallingConvention;
|
BfCallingConvention mCallingConvention;
|
||||||
BfMethodInstanceGroup* mMethodInstanceGroup;
|
BfMethodInstanceGroup* mMethodInstanceGroup;
|
||||||
|
@ -833,7 +832,6 @@ public:
|
||||||
mIsIntrinsic = false;
|
mIsIntrinsic = false;
|
||||||
mHasMethodRefType = false;
|
mHasMethodRefType = false;
|
||||||
mDisallowCalling = false;
|
mDisallowCalling = false;
|
||||||
mIsGenericMethodInstance = false;
|
|
||||||
mChainType = BfMethodChainType_None;
|
mChainType = BfMethodChainType_None;
|
||||||
mCallingConvention = BfCallingConvention_Unspecified;
|
mCallingConvention = BfCallingConvention_Unspecified;
|
||||||
mMethodInstanceGroup = NULL;
|
mMethodInstanceGroup = NULL;
|
||||||
|
|
|
@ -31,6 +31,46 @@ namespace Tests
|
||||||
int mA;
|
int mA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int MethodA(int8 a)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int MethodA(uint8 a)
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int MethodA(int16 a)
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int MethodA(int32 a)
|
||||||
|
{
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int MethodB<T>(T foo) where T : class, delete
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int MethodB<T>(T foo) where T : struct
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int MethodB<K, V>((K key, V value) foo) where K : var where V : var
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int MethodC<T>(T val) where T : struct
|
||||||
|
{
|
||||||
|
return MethodB(val);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public static void TestBasics()
|
public static void TestBasics()
|
||||||
{
|
{
|
||||||
|
@ -55,6 +95,15 @@ namespace Tests
|
||||||
Test.Assert(LibA.Handler.HandleT(sa) == 4);
|
Test.Assert(LibA.Handler.HandleT(sa) == 4);
|
||||||
Test.Assert(LibA.Handler.HandleT(sal) == 4);
|
Test.Assert(LibA.Handler.HandleT(sal) == 4);
|
||||||
Test.Assert(LibA.Handler.HandleT(las) == 0);
|
Test.Assert(LibA.Handler.HandleT(las) == 0);
|
||||||
|
|
||||||
|
Test.Assert(MethodA(1) == 1);
|
||||||
|
Test.Assert(MethodA(240) == 2);
|
||||||
|
Test.Assert(MethodA(1000) == 3);
|
||||||
|
Test.Assert(MethodA(1000000) == 4);
|
||||||
|
|
||||||
|
Test.Assert(MethodB(11) == 2);
|
||||||
|
Test.Assert(MethodB(("A", "B")) == 3);
|
||||||
|
Test.Assert(MethodC(("A", "B")) == 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue