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:
parent
a781f29c31
commit
c2c2c24ac8
9 changed files with 99 additions and 26 deletions
|
@ -273,7 +273,7 @@ namespace System.Collections.Generic
|
|||
|
||||
protected void Free(T* val)
|
||||
{
|
||||
delete val;
|
||||
delete (void*)val;
|
||||
}
|
||||
/*protected T[] Alloc(int size)
|
||||
{
|
||||
|
|
|
@ -458,7 +458,7 @@ namespace System
|
|||
if (result == .Ok)
|
||||
return .Ok(Span<T>(vals, inOutSize));
|
||||
|
||||
delete vals;
|
||||
delete (void*)vals;
|
||||
trySize = inOutSize;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -260,7 +260,7 @@ namespace System.Collections.Generic
|
|||
|
||||
protected void Free(T* val)
|
||||
{
|
||||
delete val;
|
||||
delete (void*)val;
|
||||
}
|
||||
/*protected T[] Alloc(int size)
|
||||
{
|
||||
|
|
|
@ -407,7 +407,7 @@ namespace System
|
|||
if (result == .Ok)
|
||||
return .Ok(Span<T>(vals, inOutSize));
|
||||
|
||||
delete vals;
|
||||
delete (void*)vals;
|
||||
trySize = inOutSize;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6001,6 +6001,30 @@ BfTypedValue BfExprEvaluator::CheckEnumCreation(BfAstNode* targetSrc, BfTypeInst
|
|||
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,
|
||||
BfResolvedArgs& argValues, BfSizedArray<ASTREF(BfTypeReference*)>* methodGenericArguments, BfCheckedKind checkedKind)
|
||||
{
|
||||
|
@ -6669,7 +6693,15 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
|
|||
}
|
||||
|
||||
if (refType != NULL)
|
||||
{
|
||||
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);
|
||||
|
||||
if (mExpectingType->IsObject())
|
||||
if ((mExpectingType->IsObject()) || (mExpectingType->IsGenericParam()))
|
||||
{
|
||||
unresolvedTypeRef = mExpectingType;
|
||||
|
||||
|
@ -11441,7 +11473,7 @@ void BfExprEvaluator::Visit(BfObjectCreateExpression* objCreateExpr)
|
|||
auto genericConstraint = mModule->GetGenericParamInstance((BfGenericParamType*)resolvedTypeRef);
|
||||
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);
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
gaveUnqualifiedDotError = true;
|
||||
|
|
|
@ -337,6 +337,7 @@ public:
|
|||
void MarkResultAssigned();
|
||||
void MakeResultAsValue();
|
||||
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);
|
||||
void CheckObjectCreateTypeRef(BfType* expectingType, BfAstNode* afterNode);
|
||||
void LookupQualifiedName(BfQualifiedNameNode* nameNode, bool ignoreInitialError = false, bool* hadError = NULL);
|
||||
|
|
|
@ -6536,22 +6536,22 @@ BfTypedValue BfModule::TryLookupGenericConstVaue(BfIdentifierNode* identifierNod
|
|||
return BfTypedValue(mBfIRBuilder->GetFakeVal(), genericTypeConstraint);
|
||||
}
|
||||
|
||||
if ((genericParamDef->mGenericParamFlags & BfGenericParamFlag_Const) == 0)
|
||||
Fail("Only const generic parameters can be used a value", identifierNode);
|
||||
|
||||
if ((genericTypeConstraint != NULL) && (expectingType != NULL))
|
||||
if ((genericParamDef->mGenericParamFlags & BfGenericParamFlag_Const) != 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9064,6 +9064,8 @@ BfGenericConstraintsDeclaration* BfReducer::CreateGenericConstraintsDeclaration(
|
|||
case BfToken_Struct:
|
||||
case BfToken_Const:
|
||||
case BfToken_Var:
|
||||
case BfToken_New:
|
||||
case BfToken_Delete:
|
||||
addToConstraint = true;
|
||||
break;
|
||||
case BfToken_Operator:
|
||||
|
|
|
@ -3636,14 +3636,35 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt)
|
|||
if (!val)
|
||||
return;
|
||||
|
||||
auto checkType = val.mType;
|
||||
|
||||
BfGenericParamType* genericType = NULL;
|
||||
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)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (checkType->IsVar())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue