diff --git a/BeefLibs/corlib/src/Collections/Generic/List.bf b/BeefLibs/corlib/src/Collections/Generic/List.bf index 3451ebee..54fe75eb 100644 --- a/BeefLibs/corlib/src/Collections/Generic/List.bf +++ b/BeefLibs/corlib/src/Collections/Generic/List.bf @@ -273,7 +273,7 @@ namespace System.Collections.Generic protected void Free(T* val) { - delete val; + delete (void*)val; } /*protected T[] Alloc(int size) { diff --git a/BeefLibs/corlib/src/Platform.bf b/BeefLibs/corlib/src/Platform.bf index 794c1de1..8e31db6a 100644 --- a/BeefLibs/corlib/src/Platform.bf +++ b/BeefLibs/corlib/src/Platform.bf @@ -458,7 +458,7 @@ namespace System if (result == .Ok) return .Ok(Span(vals, inOutSize)); - delete vals; + delete (void*)vals; trySize = inOutSize; } } diff --git a/IDE/mintest/minlib/src/System/Collections/Generic/List.bf b/IDE/mintest/minlib/src/System/Collections/Generic/List.bf index 275b861a..e7f057c7 100644 --- a/IDE/mintest/minlib/src/System/Collections/Generic/List.bf +++ b/IDE/mintest/minlib/src/System/Collections/Generic/List.bf @@ -260,7 +260,7 @@ namespace System.Collections.Generic protected void Free(T* val) { - delete val; + delete (void*)val; } /*protected T[] Alloc(int size) { diff --git a/IDE/mintest/minlib/src/System/Platform.bf b/IDE/mintest/minlib/src/System/Platform.bf index ad28f17f..ca40f4d3 100644 --- a/IDE/mintest/minlib/src/System/Platform.bf +++ b/IDE/mintest/minlib/src/System/Platform.bf @@ -407,7 +407,7 @@ namespace System if (result == .Ok) return .Ok(Span(vals, inOutSize)); - delete vals; + delete (void*)vals; trySize = inOutSize; } } diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index c125c182..67377677 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -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* 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); } @@ -13108,7 +13140,7 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m if ((memberRefExpression->mTarget == NULL) && (memberRefExpression->mMemberName == NULL)) { if (mExpectingType != NULL) - { + { if (mExpectingType->IsSizedArray()) { if (mModule->mParentNodeEntry != NULL) @@ -13151,6 +13183,23 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m } } } + else if (mExpectingType->IsGenericParam()) + { + if (mModule->mParentNodeEntry != NULL) + { + if (auto invocationExpr = BfNodeDynCast(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; diff --git a/IDEHelper/Compiler/BfExprEvaluator.h b/IDEHelper/Compiler/BfExprEvaluator.h index f3e29a7a..3cdb4db0 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.h +++ b/IDEHelper/Compiler/BfExprEvaluator.h @@ -337,7 +337,8 @@ public: void MarkResultAssigned(); void MakeResultAsValue(); bool CheckModifyResult(BfTypedValue typeValue, BfAstNode* refNode, const char* modifyType, bool onlyNeedsMut = false); - BfTypedValue LookupField(BfAstNode* targetSrc, BfTypedValue target, const StringImpl& fieldName, BfLookupFieldFlags flags = BfLookupFieldFlag_None); + 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); void LookupQualifiedName(BfAstNode* nameNode, BfIdentifierNode* nameLeft, BfIdentifierNode* nameRight, bool ignoreInitialError, bool* hadError = NULL); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 7de9f4f7..4296cee3 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -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 (!CanCast(BfTypedValue(mBfIRBuilder->GetFakeVal(), genericTypeConstraint), expectingType)) + if ((genericParamDef->mGenericParamFlags & BfGenericParamFlag_Const) != 0) + { + 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; } } } diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index b2fd1791..5e1ebe2f 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -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: diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 3da61b7b..31402be4 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -3636,16 +3636,37 @@ 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)) - return; - } + 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()) { // Mixin or unconstrained generic