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

Properly checking extern method constraints, fixed dtor body scopes

This commit is contained in:
Brian Fiete 2020-07-24 05:20:50 -07:00
parent b1f741b1f0
commit bec6f1d007
4 changed files with 67 additions and 37 deletions

View file

@ -4989,7 +4989,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfMethodInstance* methodInstance, BfIRV
BfTypedValue BfExprEvaluator::CreateCall(BfMethodMatcher* methodMatcher, BfTypedValue target) BfTypedValue BfExprEvaluator::CreateCall(BfMethodMatcher* methodMatcher, BfTypedValue target)
{ {
auto moduleMethodInstance = mModule->GetMethodInstance(methodMatcher->mBestMethodTypeInstance, methodMatcher->mBestMethodDef, methodMatcher->mBestMethodGenericArguments); auto moduleMethodInstance = GetSelectedMethod(methodMatcher->mTargetSrc, methodMatcher->mBestMethodTypeInstance, methodMatcher->mBestMethodDef, *methodMatcher);
if (moduleMethodInstance.mMethodInstance == NULL) if (moduleMethodInstance.mMethodInstance == NULL)
return BfTypedValue(); return BfTypedValue();
if ((target) && (target.mType != moduleMethodInstance.mMethodInstance->GetOwner())) if ((target) && (target.mType != moduleMethodInstance.mMethodInstance->GetOwner()))
@ -12934,15 +12934,30 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc,
if (methodDef->IsEmptyPartial()) if (methodDef->IsEmptyPartial())
return methodInstance; return methodInstance;
for (int checkGenericIdx = 0; checkGenericIdx < (int)methodMatcher.mBestMethodGenericArguments.size(); checkGenericIdx++) if (methodInstance.mMethodInstance->mMethodInfoEx != NULL)
{ {
auto& genericParams = methodInstance.mMethodInstance->mMethodInfoEx->mGenericParams; for (int checkGenericIdx = 0; checkGenericIdx < (int)methodInstance.mMethodInstance->mMethodInfoEx->mGenericParams.size(); checkGenericIdx++)
auto genericArg = methodMatcher.mBestMethodGenericArguments[checkGenericIdx]; {
auto genericParams = methodInstance.mMethodInstance->mMethodInfoEx->mGenericParams[checkGenericIdx];
BfTypeVector* checkMethodGenericArgs = NULL;
BfType* genericArg = NULL;
if (checkGenericIdx < (int)methodMatcher.mBestMethodGenericArguments.size())
{
genericArg = methodMatcher.mBestMethodGenericArguments[checkGenericIdx];
}
else
{
checkMethodGenericArgs = &methodMatcher.mBestMethodGenericArguments;
genericArg = genericParams->mExternType;
genericArg = mModule->ResolveGenericType(genericArg, NULL, checkMethodGenericArgs);
}
if (genericArg->IsVar()) if (genericArg->IsVar())
continue; continue;
BfAstNode* paramSrc; BfAstNode* paramSrc;
if (methodMatcher.mBestMethodGenericArgumentSrcs.size() == 0) if (checkGenericIdx >= methodMatcher.mBestMethodGenericArgumentSrcs.size())
{ {
paramSrc = targetSrc; paramSrc = targetSrc;
} }
@ -12951,7 +12966,7 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc,
// Note: don't pass methodMatcher.mBestMethodGenericArguments into here, this method is already specialized // Note: don't pass methodMatcher.mBestMethodGenericArguments into here, this method is already specialized
BfError* error = NULL; BfError* error = NULL;
if (!mModule->CheckGenericConstraints(BfGenericParamSource(methodInstance.mMethodInstance), genericArg, paramSrc, genericParams[checkGenericIdx], NULL, if (!mModule->CheckGenericConstraints(BfGenericParamSource(methodInstance.mMethodInstance), genericArg, paramSrc, genericParams, checkMethodGenericArgs,
failed ? NULL : &error)) failed ? NULL : &error))
{ {
if (methodInstance.mMethodInstance->IsSpecializedGenericMethod()) if (methodInstance.mMethodInstance->IsSpecializedGenericMethod())
@ -12966,6 +12981,9 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc,
} }
} }
} }
}
else
BF_ASSERT(methodMatcher.mBestMethodGenericArguments.IsEmpty());
return methodInstance; return methodInstance;
} }

View file

@ -7276,10 +7276,18 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
(!CanCast(exprEvaluator.mResult, origCheckArgType))) (!CanCast(exprEvaluator.mResult, origCheckArgType)))
{ {
if (!ignoreErrors) if (!ignoreErrors)
{
if (genericParamInst->mExternType != NULL)
*errorOut = Fail(StrFormat("Binary operation for '%s' must result in '%s' from binary operation '%s %s %s'",
GenericParamSourceToString(genericParamSource).c_str(), TypeToString(origCheckArgType).c_str(),
TypeToString(leftType).c_str(), BfGetOpName(checkOpConstraint.mBinaryOp), TypeToString(rightType).c_str()
), checkArgTypeRef);
else
*errorOut = Fail(StrFormat("Generic argument '%s', declared to be '%s' for '%s', must result from binary operation '%s %s %s'", genericParamInst->GetName().c_str(), *errorOut = Fail(StrFormat("Generic argument '%s', declared to be '%s' for '%s', must result from binary operation '%s %s %s'", genericParamInst->GetName().c_str(),
TypeToString(origCheckArgType).c_str(), GenericParamSourceToString(genericParamSource).c_str(), TypeToString(origCheckArgType).c_str(), GenericParamSourceToString(genericParamSource).c_str(),
TypeToString(leftType).c_str(), BfGetOpName(checkOpConstraint.mBinaryOp), TypeToString(rightType).c_str() TypeToString(leftType).c_str(), BfGetOpName(checkOpConstraint.mBinaryOp), TypeToString(rightType).c_str()
), checkArgTypeRef); ), checkArgTypeRef);
}
return false; return false;
} }
@ -12297,11 +12305,15 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
} }
// Generic constraints // Generic constraints
if (!methodDef->mGenericParams.IsEmpty())
{
BF_ASSERT(methodInstance->GetMethodInfoEx()->mGenericParams.IsEmpty());
for (int genericParamIdx = 0; genericParamIdx < (int)methodDef->mGenericParams.size(); genericParamIdx++) for (int genericParamIdx = 0; genericParamIdx < (int)methodDef->mGenericParams.size(); genericParamIdx++)
{ {
auto genericParamInstance = new BfGenericMethodParamInstance(methodDef, genericParamIdx); auto genericParamInstance = new BfGenericMethodParamInstance(methodDef, genericParamIdx);
methodInstance->GetMethodInfoEx()->mGenericParams.push_back(genericParamInstance); methodInstance->GetMethodInfoEx()->mGenericParams.push_back(genericParamInstance);
} }
}
for (int externConstraintIdx = 0; externConstraintIdx < (int)methodDef->mExternalConstraints.size(); externConstraintIdx++) for (int externConstraintIdx = 0; externConstraintIdx < (int)methodDef->mExternalConstraints.size(); externConstraintIdx++)
{ {
@ -14245,7 +14257,7 @@ void BfModule::EmitDtorBody()
if (auto bodyBlock = BfNodeDynCast<BfBlock>(methodDef->mBody)) if (auto bodyBlock = BfNodeDynCast<BfBlock>(methodDef->mBody))
{ {
VisitCodeBlock(bodyBlock); VisitEmbeddedStatement(bodyBlock);
if (bodyBlock->mCloseBrace != NULL) if (bodyBlock->mCloseBrace != NULL)
{ {
UpdateSrcPos(bodyBlock->mCloseBrace); UpdateSrcPos(bodyBlock->mCloseBrace);

View file

@ -20,7 +20,7 @@ namespace System.Collections
extension Dictionary<K, V> extension Dictionary<K, V>
{ {
public static bool operator==(Self lhs, Self rhs) where K : IOpEquals where V : IOpEquals public static bool operator==(Self lhs, Self rhs)
{ {
if (lhs.mCount != rhs.mCount) if (lhs.mCount != rhs.mCount)
return false; return false;

View file

@ -82,7 +82,7 @@ namespace Tests
return -val; return -val;
} }
public T GetInt() where T : Int public T GetInt() where T : Int32
{ {
return mVal; return mVal;
} }