2
0
Эх сурвалжийг харах

Fix cyclic type checking bug

gingerBill 7 жил өмнө
parent
commit
9df3a94d33
2 өөрчлөгдсөн 42 нэмэгдсэн , 42 устгасан
  1. 1 1
      core/fmt.odin
  2. 41 41
      src/types.cpp

+ 1 - 1
core/fmt.odin

@@ -781,7 +781,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 				if hash do write_string(fi.buf, ",\n");
 			}
 
-			if hash do for in 0..fi.indent do write_byte(fi.buf, '\t');
+			if hash do for in 0..indent do write_byte(fi.buf, '\t');
 			write_byte(fi.buf, '}');
 
 		case:

+ 41 - 41
src/types.cpp

@@ -1731,7 +1731,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
 
 
 struct TypePath {
-	Array<Type *> path; // Entity_TypeName;
+	Array<Entity *> path; // Entity_TypeName;
 	bool failure;
 };
 
@@ -1748,38 +1748,37 @@ void type_path_print_illegal_cycle(TypePath *tp, isize start_index) {
 	GB_ASSERT(tp != nullptr);
 
 	GB_ASSERT(start_index < tp->path.count);
-	Type *t = tp->path[start_index];
-	GB_ASSERT(t != nullptr);
-
-	GB_ASSERT_MSG(is_type_named(t), "%s", type_to_string(t));
-	Entity *e = t->Named.type_name;
-	error(e->token, "Illegal declaration cycle of `%.*s`", LIT(t->Named.name));
+	Entity *e = tp->path[start_index];
+	GB_ASSERT(e != nullptr);
+	error(e->token, "Illegal declaration cycle of `%.*s`", LIT(e->token.string));
 	// NOTE(bill): Print cycle, if it's deep enough
 	for (isize j = start_index; j < tp->path.count; j++) {
-		Type *t = tp->path[j];
-		GB_ASSERT_MSG(is_type_named(t), "%s", type_to_string(t));
-		Entity *e = t->Named.type_name;
-		error(e->token, "\t%.*s refers to", LIT(t->Named.name));
+		Entity *e = tp->path[j];
+		error(e->token, "\t%.*s refers to", LIT(e->token.string));
 	}
 	// NOTE(bill): This will only print if the path count > 1
-	error(e->token, "\t%.*s", LIT(t->Named.name));
+	error(e->token, "\t%.*s", LIT(e->token.string));
 	tp->failure = true;
-	t->failure = true;
+	e->type->failure = true;
+	base_type(e->type)->failure = true;
 }
 
-TypePath *type_path_push(TypePath *tp, Type *t) {
+bool type_path_push(TypePath *tp, Type *t) {
 	GB_ASSERT(tp != nullptr);
+	if (t->kind != Type_Named) {
+		return false;
+	}
+	Entity *e = t->Named.type_name;
 
 	for (isize i = 0; i < tp->path.count; i++) {
-		if (tp->path[i] == t) {
+		Entity *p = tp->path[i];
+		if (p == e) {
 			type_path_print_illegal_cycle(tp, i);
 		}
 	}
 
-	if (!tp->failure && is_type_named(t)) {
-		array_add(&tp->path, t);
-	}
-	return tp;
+	array_add(&tp->path, e);
+	return true;
 }
 
 void type_path_pop(TypePath *tp) {
@@ -1830,6 +1829,7 @@ i64 type_align_of(gbAllocator allocator, Type *t) {
 
 
 i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
+	GB_ASSERT(path != nullptr);
 	if (t->failure) {
 		return FAILURE_ALIGNMENT;
 	}
@@ -1853,35 +1853,35 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
 
 	case Type_Array: {
 		Type *elem = t->Array.elem;
-		type_path_push(path, elem);
+		bool pop = type_path_push(path, elem);
 		if (path->failure) {
 			return FAILURE_ALIGNMENT;
 		}
 		i64 align = type_align_of_internal(allocator, t->Array.elem, path);
-		type_path_pop(path);
+		if (pop) type_path_pop(path);
 		return align;
 	}
-
-	case Type_DynamicArray:
-		// data, count, capacity, allocator
-		return build_context.word_size;
-
-	case Type_Slice:
-		return build_context.word_size;
-
 	case Type_Vector: {
 		Type *elem = t->Vector.elem;
-		type_path_push(path, elem);
+		bool pop = type_path_push(path, elem);
 		if (path->failure) {
 			return FAILURE_ALIGNMENT;
 		}
 		i64 size = type_size_of_internal(allocator, t->Vector.elem, path);
-		type_path_pop(path);
+		if (pop) type_path_pop(path);
 		i64 count = gb_max(prev_pow2(t->Vector.count), 1);
 		i64 total = size * count;
 		return gb_clamp(total, 1, build_context.max_align);
 	} break;
 
+	case Type_DynamicArray:
+		// data, count, capacity, allocator
+		return build_context.word_size;
+
+	case Type_Slice:
+		return build_context.word_size;
+
+
 	case Type_Tuple: {
 		i64 max = 1;
 		for_array(i, t->Tuple.variables) {
@@ -1911,12 +1911,12 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
 		i64 max = union_tag_size(t);
 		for_array(i, t->Union.variants) {
 			Type *variant = t->Union.variants[i];
-			type_path_push(path, variant);
+			bool pop = type_path_push(path, variant);
 			if (path->failure) {
 				return FAILURE_ALIGNMENT;
 			}
 			i64 align = type_align_of_internal(allocator, variant, path);
-			type_path_pop(path);
+			if (pop) type_path_pop(path);
 			if (max < align) {
 				max = align;
 			}
@@ -1932,12 +1932,12 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
 			i64 max = 1;
 			for_array(i, t->Struct.fields) {
 				Type *field_type = t->Struct.fields[i]->type;
-				type_path_push(path, field_type);
+				bool pop = type_path_push(path, field_type);
 				if (path->failure) {
 					return FAILURE_ALIGNMENT;
 				}
 				i64 align = type_align_of_internal(allocator, field_type, path);
-				type_path_pop(path);
+				if (pop) type_path_pop(path);
 				if (max < align) {
 					max = align;
 				}
@@ -1948,10 +1948,10 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
 			// NOTE(bill): Check the fields to check for cyclic definitions
 			for_array(i, t->Struct.fields) {
 				Type *field_type = t->Struct.fields[i]->type;
-				type_path_push(path, field_type);
+				bool pop = type_path_push(path, field_type);
 				if (path->failure) return FAILURE_ALIGNMENT;
 				i64 align = type_align_of_internal(allocator, field_type, path);
-				type_path_pop(path);
+				if (pop) type_path_pop(path);
 				if (max < align) {
 					max = align;
 				}
@@ -2033,12 +2033,12 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
 
 	switch (t->kind) {
 	case Type_Named: {
-		type_path_push(path, t);
+		bool pop = type_path_push(path, t);
 		if (path->failure) {
 			return FAILURE_ALIGNMENT;
 		}
 		i64 size = type_size_of_internal(allocator, t->Named.base, path);
-		type_path_pop(path);
+		if (pop) type_path_pop(path);
 		return size;
 	} break;
 
@@ -2080,12 +2080,12 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
 		if (count == 0) {
 			return 0;
 		}
-		type_path_push(path, t->Vector.elem);
+		bool pop = type_path_push(path, t->Vector.elem);
 		if (path->failure) {
 			return FAILURE_SIZE;
 		}
 		bit_size = 8*type_size_of_internal(allocator, t->Vector.elem, path);
-		type_path_pop(path);
+		if (pop) type_path_pop(path);
 		if (is_type_boolean(t->Vector.elem)) {
 			bit_size = 1; // NOTE(bill): LLVM can store booleans as 1 bit because a boolean _is_ an `i1`
 			              // Silly LLVM spec