1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 20:12: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

@ -1980,9 +1980,16 @@ bool BfMethodMatcher::CheckMethod(BfTypeInstance* targetTypeInstance, BfTypeInst
if (methodInstance->GetParamKind(paramIdx) == BfParamKind_Params)
{
paramsParamIdx = paramIdx;
if ((wantType->IsArray()) || (wantType->IsSizedArray()) || (wantType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)))
wantType = wantType->GetUnderlyingType();
if ((mArguments[argIdx].mArgFlags & BfArgFlag_ParamsExpr) != 0)
{
// Match to entire thing
}
else
{
paramsParamIdx = paramIdx;
if ((wantType->IsArray()) || (wantType->IsSizedArray()) || (wantType->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)))
wantType = wantType->GetUnderlyingType();
}
}
if (!genericInferContext.InferGenericArgument(methodInstance, type, wantType, argTypedValue.mValue))
@ -22954,15 +22961,60 @@ void BfExprEvaluator::PerformUnaryOperation_OnResult(BfExpression* unaryOpExpr,
}
else
{
auto origValue = mResult;
auto isValid = false;
auto genericTypeInst = mResult.mType->ToGenericTypeInstance();
if ((genericTypeInst != NULL) && (genericTypeInst->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)))
isValid = true;
else if ((mResult.mType->IsArray()) || (mResult.mType->IsSizedArray()))
isValid = true;
for (int pass = 0; pass < 2; pass++)
{
auto typeInst = mResult.mType->ToTypeInstance();
auto genericTypeInst = mResult.mType->ToGenericTypeInstance();
if ((genericTypeInst != NULL) && (genericTypeInst->IsInstanceOf(mModule->mCompiler->mSpanTypeDef)))
isValid = true;
else if ((mResult.mType->IsArray()) || (mResult.mType->IsSizedArray()))
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)
{
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);
if (memberOwner->mTypeDef->IsGlobalsContainer())
allowPrivate |= curCheckType->mTypeDef->mNamespace.StartsWith(memberOwner->mTypeDef->mNamespace);
allowPrivate |= curCheckType->mTypeDef->mNamespace == memberOwner->mTypeDef->mNamespace;
}
if (allowPrivate)
flags = (BfProtectionCheckFlags)(flags | BfProtectionCheckFlag_AllowPrivate | BfProtectionCheckFlag_CheckedPrivate);

View file

@ -1,4 +1,6 @@
using System;
using System.Collections;
namespace Tests
{
class MethodCalls
@ -205,6 +207,16 @@ namespace Tests
static int sIdx = 0;
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]
public static void TestBasics()
{
@ -273,6 +285,11 @@ namespace Tests
Test.Assert(Named(p3:GetNext(), p2:GetNext(), p1:GetNext()) == 10321);
Test.Assert(Named(p2:GetNext(), p1:GetNext(), p0:GetNext()) == 20654);
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);
}
}
}