Jelajahi Sumber

Fixed some struct* constraint checking

Brian Fiete 3 tahun lalu
induk
melakukan
69a597574d

+ 8 - 7
IDEHelper/Compiler/BfModule.cpp

@@ -7787,9 +7787,16 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
 		}
 	}
 
+	if (checkArgType->IsPointer())
+	{
+		auto ptrType = (BfPointerType*)checkArgType;		
+		checkArgType = ptrType->mElementType;
+	}
+
 	if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_New) != 0)
 	{
 		bool canAlloc = false;
+
 		if (auto checkTypeInst = checkArgType->ToTypeInstance())
 		{
 			if (checkTypeInst->IsObjectOrStruct())
@@ -7857,13 +7864,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
 	}
 
 	if ((genericParamInst->mInterfaceConstraints.IsEmpty()) && (genericParamInst->mOperatorConstraints.IsEmpty()) && (genericParamInst->mTypeConstraint == NULL))
-		return true;
-	
-	if (checkArgType->IsPointer())
-	{
-		auto ptrType = (BfPointerType*)checkArgType;
-		checkArgType = ptrType->mElementType;
-	}
+		return true;		
 
 	if (genericParamInst->mTypeConstraint != NULL)
 	{

+ 4 - 0
IDEHelper/Compiler/BfStmtEvaluator.cpp

@@ -3925,6 +3925,10 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt)
 		{
 			if (genericParamInst->mGenericParamFlags & (BfGenericParamFlag_Delete | BfGenericParamFlag_Var))
 				return;
+			if (genericParamInst->mGenericParamFlags & BfGenericParamFlag_StructPtr)
+				return;
+			if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Struct) && (checkType->IsPointer()))
+				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;

+ 22 - 1
IDEHelper/Tests/src/Generics.bf

@@ -23,6 +23,16 @@ namespace Tests
 {
 	class Generics
 	{
+		struct StructA : IDisposable
+		{
+			int mA = 123;
+
+			public void Dispose()
+			{
+
+			}
+		}
+
 		class ClassA : IDisposable, LibA.IVal
 		{
 			int LibA.IVal.Val
@@ -172,7 +182,7 @@ namespace Tests
 			delete val;
 		}
 
-		public static void Alloc2<T>() where T : new, delete, IDisposable, struct
+		public static void Alloc2<T>() where T : new, IDisposable, struct
 		{
 			alloctype(T) val = new T();
 			T* val2 = val;
@@ -180,6 +190,14 @@ namespace Tests
 			delete val;
 		}
 
+		public static void Alloc3<T>() where T : new, IDisposable, struct*
+		{
+			T val2 = default;
+			if (val2 != null)
+				val2.Dispose();
+			delete val2;
+		}
+
 		public class ClassE
 		{
 		    public static Self Instance = new ClassE() ~ delete _;
@@ -311,6 +329,9 @@ namespace Tests
 		[Test]
 		public static void TestBasics()
 		{
+			Alloc2<StructA>();
+			Alloc3<StructA*>();
+
 			MethodD(scope => MethodC);
 
 			List<Entry> list = scope .();