1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 12:02:21 +02:00

params operator implicit cast, params generic inference fix

This commit is contained in:
Brian Fiete 2024-11-04 06:06:46 -05:00
parent 4885871785
commit 64d646e130
3 changed files with 81 additions and 12 deletions

View file

@ -1979,11 +1979,18 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
mHasVarArguments = true; mHasVarArguments = true;
if (methodInstance->GetParamKind(paramIdx) == BfParamKind_Params) if (methodInstance->GetParamKind(paramIdx) == BfParamKind_Params)
{
if ((mArguments[argIdx].mArgFlags & BfArgFlag_ParamsExpr) != 0)
{
// Match to entire thing
}
else
{ {
paramsParamIdx = paramIdx; paramsParamIdx = paramIdx;
if ((wantType->IsArray()) || (wantType->IsSizedArray()) || (wantType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef))) if ((wantType->IsArray()) || (wantType->IsSizedArray()) || (wantType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)))
wantType = wantType->GetUnderlyingType(); wantType = wantType->GetUnderlyingType();
} }
}
if (!genericInferContext.InferGenericArgument(methodInstance, type, wantType, argTypedValue.mValue)) if (!genericInferContext.InferGenericArgument(methodInstance, type, wantType, argTypedValue.mValue))
return ResultKind_Failed; return ResultKind_Failed;
@ -22954,15 +22961,60 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
} }
else else
{ {
auto origValue = mResult;
auto isValid = false; auto isValid = false;
for (int pass = 0; pass < 2; pass++)
{
auto typeInst = mResult.mType->ToTypeInstance();
auto genericTypeInst = mResult.mType->ToGenericTypeInstance(); auto genericTypeInst = mResult.mType->ToGenericTypeInstance();
if ((genericTypeInst != NULL) && (genericTypeInst->IsInstanceOf(mModule->mCompiler->mSpanTypeDef))) if ((genericTypeInst != NULL) && (genericTypeInst->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)))
isValid = true; isValid = true;
else if ((mResult.mType->IsArray()) || (mResult.mType->IsSizedArray())) else if ((mResult.mType->IsArray()) || (mResult.mType->IsSizedArray()))
isValid = true; isValid = true;
else if ((typeInst != NULL) && (pass == 0))
{
BfBaseClassWalker baseClassWalker(typeInst, NULL, mModule);
BfType* bestCastType = NULL;
while (true)
{
auto entry = baseClassWalker.Next();
auto checkType = entry.mTypeInstance;
if (checkType == NULL)
break;
for (auto operatorDef : checkType->mTypeDef->mOperators)
{
if (operatorDef->mOperatorDeclaration->mIsConvOperator)
{
if (operatorDef->IsExplicit())
continue;
auto methodInstance = mModule->GetRawMethodInstanceAtIdx(typeInst, operatorDef->mIdx);
auto checkType = methodInstance->mReturnType;
if (checkType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef))
bestCastType = checkType;
else if ((checkType->IsArray()) || (checkType->IsSizedArray()))
bestCastType = checkType;
}
}
}
if (bestCastType == NULL)
break;
auto castTypedValue = mModule->Cast(opToken, mResult, bestCastType, BfCastFlags_SilentFail);
if (!castTypedValue)
break;
mResult = castTypedValue;
}
else
break;
}
if (!isValid) if (!isValid)
{ {
mModule->Fail(StrFormat("A 'params' expression cannot be used on type '%s'", mModule->TypeToString(mResult.mType).c_str()), opToken); mModule->Fail(StrFormat("A 'params' expression cannot be used on type '%s'", mModule->TypeToString(origValue.mType).c_str()), opToken);
} }
} }
} }

View file

@ -2862,7 +2862,7 @@ bool BfModule::CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* me
{ {
allowPrivate |= IsInnerType(curCheckType->mTypeDef, memberOwner->mTypeDef); allowPrivate |= IsInnerType(curCheckType->mTypeDef, memberOwner->mTypeDef);
if (memberOwner->mTypeDef->IsGlobalsContainer()) if (memberOwner->mTypeDef->IsGlobalsContainer())
allowPrivate |= curCheckType->mTypeDef->mNamespace.StartsWith(memberOwner->mTypeDef->mNamespace); allowPrivate |= curCheckType->mTypeDef->mNamespace == memberOwner->mTypeDef->mNamespace;
} }
if (allowPrivate) if (allowPrivate)
flags = (BfProtectionCheckFlags)(flags | BfProtectionCheckFlag_AllowPrivate | BfProtectionCheckFlag_CheckedPrivate); flags = (BfProtectionCheckFlags)(flags | BfProtectionCheckFlag_AllowPrivate | BfProtectionCheckFlag_CheckedPrivate);

View file

@ -1,4 +1,6 @@
using System; using System;
using System.Collections;
namespace Tests namespace Tests
{ {
class MethodCalls class MethodCalls
@ -205,6 +207,16 @@ namespace Tests
static int sIdx = 0; static int sIdx = 0;
static int GetNext() => ++sIdx; static int GetNext() => ++sIdx;
public static float ParamsTest(params Span<float> span)
{
return span[0];
}
public static T ParamsTest2<T>(params Span<T> span)
{
return span[0];
}
[Test] [Test]
public static void TestBasics() public static void TestBasics()
{ {
@ -273,6 +285,11 @@ namespace Tests
Test.Assert(Named(p3:GetNext(), p2:GetNext(), p1:GetNext()) == 10321); Test.Assert(Named(p3:GetNext(), p2:GetNext(), p1:GetNext()) == 10321);
Test.Assert(Named(p2:GetNext(), p1:GetNext(), p0:GetNext()) == 20654); Test.Assert(Named(p2:GetNext(), p1:GetNext(), p0:GetNext()) == 20654);
Test.Assert(Named(p1:9) == 30193); Test.Assert(Named(p1:9) == 30193);
List<float> fList = scope .();
fList.Add(1.2f);
Test.Assert(ParamsTest(params fList) == 1.2f);
Test.Assert(ParamsTest2(params fList) == 1.2f);
} }
} }
} }