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

Fix typeof(T).MinValue/MaxValue with generic params

This commit is contained in:
Brian Fiete 2021-02-17 07:08:09 -08:00
parent fe317aba34
commit e626620e48

View file

@ -10107,19 +10107,22 @@ void BfExprEvaluator::Visit(BfTypeOfExpression* typeOfExpr)
bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifierNode* propName)
{
// We ignore errors because we go through the normal Visit(BfTypeOfExpression) if this fails, which will throw the error again
SetAndRestoreValue<bool> prevIgnoreErrors(mModule->mIgnoreErrors, true);
auto typeType = mModule->ResolveTypeDef(mModule->mCompiler->mTypeTypeDef);
BfType* type;
if (auto genericTypeRef = BfNodeDynCast<BfGenericInstanceTypeRef>(typeOfExpr->mTypeRef))
//
{
type = mModule->ResolveTypeRefAllowUnboundGenerics(typeOfExpr->mTypeRef, BfPopulateType_Identity);
}
else
{
type = ResolveTypeRef(typeOfExpr->mTypeRef, BfPopulateType_Identity);
// We ignore errors because we go through the normal Visit(BfTypeOfExpression) if this fails, which will throw the error again
SetAndRestoreValue<bool> prevIgnoreErrors(mModule->mIgnoreErrors, true);
if (auto genericTypeRef = BfNodeDynCast<BfGenericInstanceTypeRef>(typeOfExpr->mTypeRef))
{
SetAndRestoreValue<bool> prevIgnoreErrors(mModule->mIgnoreErrors, true);
type = mModule->ResolveTypeRefAllowUnboundGenerics(typeOfExpr->mTypeRef, BfPopulateType_Identity);
}
else
{
type = ResolveTypeRef(typeOfExpr->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_IgnoreLookupError);
}
}
if (type == NULL)
@ -10209,11 +10212,40 @@ bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifie
else if ((memberName == "MinValue") || (memberName == "MaxValue"))
{
bool isMin = memberName == "MinValue";
BfType* checkType = typeInstance;
BfType* checkType = type;
if (checkType->IsTypedPrimitive())
checkType = checkType->GetUnderlyingType();
if (checkType->IsGenericParam())
{
bool foundMatch = false;
auto genericParamInstance = mModule->GetGenericParamInstance((BfGenericParamType*)checkType);
if ((genericParamInstance->mTypeConstraint != NULL) && (genericParamInstance->mTypeConstraint->IsInstanceOf(mModule->mCompiler->mEnumTypeDef)))
foundMatch = true;
if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized) && (mModule->mCurMethodInstance->mMethodInfoEx != NULL))
{
for (int genericParamIdx = (int)mModule->mCurMethodInstance->mMethodInfoEx->mMethodGenericArguments.size();
genericParamIdx < mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
{
genericParamInstance = mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
if (genericParamInstance->mExternType == type)
{
if ((genericParamInstance->mTypeConstraint != NULL) && (genericParamInstance->mTypeConstraint->IsInstanceOf(mModule->mCompiler->mEnumTypeDef)))
foundMatch = true;
}
}
}
if (foundMatch)
{
mResult = mModule->GetDefaultTypedValue(type, false, Beefy::BfDefaultValueKind_Undef);
return true;
}
}
if (checkType->IsPrimitiveType())
{
auto primType = (BfPrimitiveType*)checkType;
@ -10260,15 +10292,15 @@ bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifie
default: break;
}
}
}
}
if (typeInstance->IsEnum())
if (type->IsEnum())
{
mModule->Fail("'MinValue' cannot be used on enums with payloads", propName);
mModule->Fail(StrFormat("'MinValue' cannot be used on enum with payload '%s'", mModule->TypeToString(type).c_str()), propName);
}
else
{
mModule->Fail(StrFormat("'%s' cannot be used on type '%s'", memberName.c_str(), mModule->TypeToString(typeInstance).c_str()), propName);
mModule->Fail(StrFormat("'%s' cannot be used on type '%s'", memberName.c_str(), mModule->TypeToString(type).c_str()), propName);
}
}
else