1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-11 04:52:21 +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) 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); auto typeType = mModule->ResolveTypeDef(mModule->mCompiler->mTypeTypeDef);
BfType* type; BfType* type;
if (auto genericTypeRef = BfNodeDynCast<BfGenericInstanceTypeRef>(typeOfExpr->mTypeRef)) //
{ {
type = mModule->ResolveTypeRefAllowUnboundGenerics(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);
else if (auto genericTypeRef = BfNodeDynCast<BfGenericInstanceTypeRef>(typeOfExpr->mTypeRef))
{ {
type = ResolveTypeRef(typeOfExpr->mTypeRef, BfPopulateType_Identity); 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) if (type == NULL)
@ -10209,11 +10212,40 @@ bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifie
else if ((memberName == "MinValue") || (memberName == "MaxValue")) else if ((memberName == "MinValue") || (memberName == "MaxValue"))
{ {
bool isMin = memberName == "MinValue"; bool isMin = memberName == "MinValue";
BfType* checkType = typeInstance; BfType* checkType = type;
if (checkType->IsTypedPrimitive()) if (checkType->IsTypedPrimitive())
checkType = checkType->GetUnderlyingType(); 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()) if (checkType->IsPrimitiveType())
{ {
auto primType = (BfPrimitiveType*)checkType; auto primType = (BfPrimitiveType*)checkType;
@ -10260,15 +10292,15 @@ bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifie
default: break; 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 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 else