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

Fixed some issues with new/delete generic constraints

This commit is contained in:
Brian Fiete 2020-02-20 11:57:25 -08:00
parent a781f29c31
commit c2c2c24ac8
9 changed files with 99 additions and 26 deletions

View file

@ -273,7 +273,7 @@ namespace System.Collections.Generic
protected void Free(T* val) protected void Free(T* val)
{ {
delete val; delete (void*)val;
} }
/*protected T[] Alloc(int size) /*protected T[] Alloc(int size)
{ {

View file

@ -458,7 +458,7 @@ namespace System
if (result == .Ok) if (result == .Ok)
return .Ok(Span<T>(vals, inOutSize)); return .Ok(Span<T>(vals, inOutSize));
delete vals; delete (void*)vals;
trySize = inOutSize; trySize = inOutSize;
} }
} }

View file

@ -260,7 +260,7 @@ namespace System.Collections.Generic
protected void Free(T* val) protected void Free(T* val)
{ {
delete val; delete (void*)val;
} }
/*protected T[] Alloc(int size) /*protected T[] Alloc(int size)
{ {

View file

@ -407,7 +407,7 @@ namespace System
if (result == .Ok) if (result == .Ok)
return .Ok(Span<T>(vals, inOutSize)); return .Ok(Span<T>(vals, inOutSize));
delete vals; delete (void*)vals;
trySize = inOutSize; trySize = inOutSize;
} }
} }

View file

@ -6001,6 +6001,30 @@ BfTypedValue BfExprEvaluator::CheckEnumCreation(BfAstNode* targetSrc, BfTypeInst
return BfTypedValue(); return BfTypedValue();
} }
bool BfExprEvaluator::CheckGenericCtor(BfGenericParamType* genericParamType, BfResolvedArgs& argValues, BfAstNode* targetSrc)
{
auto genericConstraint = mModule->GetGenericParamInstance(genericParamType);
bool success = true;
if ((genericConstraint->mGenericParamFlags & BfGenericParamFlag_New) == 0)
{
mModule->Fail(StrFormat("Must add 'where %s : new' constraint to generic parameter to instantiate type", genericConstraint->GetGenericParamDef()->mName.c_str()), targetSrc);
success = false;
}
if ((genericConstraint->mGenericParamFlags & BfGenericParamFlag_Struct) == 0)
{
mModule->Fail(StrFormat("Must add 'where %s : struct' constraint to generic parameter to instantiate type without allocator", genericConstraint->GetGenericParamDef()->mName.c_str()), targetSrc);
success = false;
}
if ((argValues.mArguments != NULL) && (argValues.mArguments->size() != 0))
{
mModule->Fail(StrFormat("Only default parameterless constructors can be called on generic argument '%s'", genericConstraint->GetGenericParamDef()->mName.c_str()), targetSrc);
success = false;
}
return success;
}
BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExpression* methodBoundExpr, BfTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& methodName, BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExpression* methodBoundExpr, BfTypedValue target, bool allowImplicitThis, bool bypassVirtual, const StringImpl& methodName,
BfResolvedArgs& argValues, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments, BfCheckedKind checkedKind) BfResolvedArgs& argValues, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments, BfCheckedKind checkedKind)
{ {
@ -6669,7 +6693,15 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
} }
if (refType != NULL) if (refType != NULL)
{
resolvedTypeInstance = refType->ToTypeInstance(); resolvedTypeInstance = refType->ToTypeInstance();
if (refType->IsGenericParam())
{
CheckGenericCtor((BfGenericParamType*)refType, argValues, targetSrc);
return mModule->GetDefaultTypedValue(refType);
}
}
} }
} }
@ -10873,7 +10905,7 @@ void BfExprEvaluator::Visit(BfObjectCreateExpression* objCreateExpr)
{ {
//mModule->SetElementType(objCreateExpr->mTypeRef, BfSourceElementType_TypeRef); //mModule->SetElementType(objCreateExpr->mTypeRef, BfSourceElementType_TypeRef);
if (mExpectingType->IsObject()) if ((mExpectingType->IsObject()) || (mExpectingType->IsGenericParam()))
{ {
unresolvedTypeRef = mExpectingType; unresolvedTypeRef = mExpectingType;
@ -11441,7 +11473,7 @@ void BfExprEvaluator::Visit(BfObjectCreateExpression* objCreateExpr)
auto genericConstraint = mModule->GetGenericParamInstance((BfGenericParamType*)resolvedTypeRef); auto genericConstraint = mModule->GetGenericParamInstance((BfGenericParamType*)resolvedTypeRef);
if (genericConstraint->mTypeConstraint == NULL) if (genericConstraint->mTypeConstraint == NULL)
{ {
if ((genericConstraint->mGenericParamFlags & (BfGenericParamFlag_New | BfGenericParamFlag_Struct)) == 0) if ((genericConstraint->mGenericParamFlags & BfGenericParamFlag_New) == 0)
{ {
mModule->Fail(StrFormat("Must add 'where %s : new' constraint to generic parameter to instantiate type", genericConstraint->GetGenericParamDef()->mName.c_str()), objCreateExpr->mTypeRef); mModule->Fail(StrFormat("Must add 'where %s : new' constraint to generic parameter to instantiate type", genericConstraint->GetGenericParamDef()->mName.c_str()), objCreateExpr->mTypeRef);
} }
@ -13151,6 +13183,23 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
} }
} }
} }
else if (mExpectingType->IsGenericParam())
{
if (mModule->mParentNodeEntry != NULL)
{
if (auto invocationExpr = BfNodeDynCast<BfInvocationExpression>(mModule->mParentNodeEntry->mNode))
{
BfResolvedArgs argValues(invocationExpr->mOpenParen, &invocationExpr->mArguments, &invocationExpr->mCommas, invocationExpr->mCloseParen);
BfResolveArgFlags resolveArgsFlags = BfResolveArgFlag_None;
ResolveArgValues(argValues, resolveArgsFlags);
CheckGenericCtor((BfGenericParamType*)mExpectingType, argValues, invocationExpr->mTarget);
mResult = mModule->GetDefaultTypedValue(mExpectingType);
return;
}
}
}
else else
{ {
gaveUnqualifiedDotError = true; gaveUnqualifiedDotError = true;

View file

@ -337,6 +337,7 @@ public:
void MarkResultAssigned(); void MarkResultAssigned();
void MakeResultAsValue(); void MakeResultAsValue();
bool CheckModifyResult(BfTypedValue typeValue, BfAstNode* refNode, const char* modifyType, bool onlyNeedsMut = false); bool CheckModifyResult(BfTypedValue typeValue, BfAstNode* refNode, const char* modifyType, bool onlyNeedsMut = false);
bool CheckGenericCtor(BfGenericParamType* genericParamType, BfResolvedArgs& argValues, BfAstNode* targetSrc);
BfTypedValue LookupField(BfAstNode* targetSrc, BfTypedValue target, const StringImpl& fieldName, BfLookupFieldFlags flags = BfLookupFieldFlag_None); BfTypedValue LookupField(BfAstNode* targetSrc, BfTypedValue target, const StringImpl& fieldName, BfLookupFieldFlags flags = BfLookupFieldFlag_None);
void CheckObjectCreateTypeRef(BfType* expectingType, BfAstNode* afterNode); void CheckObjectCreateTypeRef(BfType* expectingType, BfAstNode* afterNode);
void LookupQualifiedName(BfQualifiedNameNode* nameNode, bool ignoreInitialError = false, bool* hadError = NULL); void LookupQualifiedName(BfQualifiedNameNode* nameNode, bool ignoreInitialError = false, bool* hadError = NULL);

View file

@ -6536,22 +6536,22 @@ BfTypedValue BfModule::TryLookupGenericConstVaue(BfIdentifierNode* identifierNod
return BfTypedValue(mBfIRBuilder->GetFakeVal(), genericTypeConstraint); return BfTypedValue(mBfIRBuilder->GetFakeVal(), genericTypeConstraint);
} }
if ((genericParamDef->mGenericParamFlags & BfGenericParamFlag_Const) == 0) if ((genericParamDef->mGenericParamFlags & BfGenericParamFlag_Const) != 0)
Fail("Only const generic parameters can be used a value", identifierNode);
if ((genericTypeConstraint != NULL) && (expectingType != NULL))
{ {
if (!CanCast(BfTypedValue(mBfIRBuilder->GetFakeVal(), genericTypeConstraint), expectingType)) if ((genericTypeConstraint != NULL) && (expectingType != NULL))
{ {
Fail(StrFormat("Generic constraint '%s' is not convertible to 'int'", TypeToString(genericTypeConstraint).c_str()), identifierNode); if (!CanCast(BfTypedValue(mBfIRBuilder->GetFakeVal(), genericTypeConstraint), expectingType))
{
Fail(StrFormat("Generic constraint '%s' is not convertible to 'int'", TypeToString(genericTypeConstraint).c_str()), identifierNode);
}
} }
BfTypedValue result;
result.mType = genericParamResult;
result.mKind = BfTypedValueKind_GenericConstValue;
return result;
} }
BfTypedValue result;
result.mType = genericParamResult;
result.mKind = BfTypedValueKind_GenericConstValue;
return result;
} }
} }
} }

View file

@ -9064,6 +9064,8 @@ BfGenericConstraintsDeclaration* BfReducer::CreateGenericConstraintsDeclaration(
case BfToken_Struct: case BfToken_Struct:
case BfToken_Const: case BfToken_Const:
case BfToken_Var: case BfToken_Var:
case BfToken_New:
case BfToken_Delete:
addToConstraint = true; addToConstraint = true;
break; break;
case BfToken_Operator: case BfToken_Operator:

View file

@ -3636,14 +3636,35 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt)
if (!val) if (!val)
return; return;
auto checkType = val.mType;
BfGenericParamType* genericType = NULL;
if (val.mType->IsGenericParam()) if (val.mType->IsGenericParam())
genericType = (BfGenericParamType*)val.mType;
if ((val.mType->IsPointer()) && (val.mType->GetUnderlyingType()->IsGenericParam()))
genericType = (BfGenericParamType*)val.mType->GetUnderlyingType();
auto checkType = val.mType;
if (genericType != NULL)
{ {
auto genericParamInst = GetGenericParamInstance((BfGenericParamType*)checkType); auto genericParamInst = GetGenericParamInstance(genericType);
if (genericParamInst->mTypeConstraint != NULL) if (genericParamInst->mTypeConstraint != NULL)
checkType = genericParamInst->mTypeConstraint; checkType = genericParamInst->mTypeConstraint;
if (genericParamInst->mGenericParamFlags & (BfGenericParamFlag_Delete | BfGenericParamFlag_Var)) bool canAlwaysDelete = checkType->IsDelegate() || checkType->IsFunction() || checkType->IsArray();
if (auto checkTypeInst = checkType->ToTypeInstance())
{
if ((checkTypeInst->mTypeDef == mCompiler->mDelegateTypeDef) ||
(checkTypeInst->mTypeDef == mCompiler->mFunctionTypeDef))
canAlwaysDelete = true;
}
if (!canAlwaysDelete)
{
if (genericParamInst->mGenericParamFlags & (BfGenericParamFlag_Delete | BfGenericParamFlag_Var))
return;
Fail(StrFormat("Must add 'where %s : delete' constraint to generic parameter to delete generic type '%s'",
genericParamInst->GetGenericParamDef()->mName.c_str(), TypeToString(val.mType).c_str()), deleteStmt->mExpression);
return; return;
}
} }
if (checkType->IsVar()) if (checkType->IsVar())