From 683da0e4ecd336f9a74098d49d5748bdc1ed2f70 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 25 Sep 2016 13:39:46 -0400 Subject: [PATCH] ability to have struct to have a field which is slice of itself closes #197 --- src/analyze.cpp | 11 +++-- .../cases/struct_contains_slice_of_itself.zig | 43 +++++++++++++++++++ test/self_hosted.zig | 1 + 3 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 test/cases/struct_contains_slice_of_itself.zig diff --git a/src/analyze.cpp b/src/analyze.cpp index b3cf10737c..09eb823e9d 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1589,6 +1589,9 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE TypeTableEntry *field_type = type_struct_field->type_entry; + assert(field_type->type_ref); + assert(struct_type->type_ref); + assert(struct_type->data.structure.complete); uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, field_type->type_ref); uint64_t debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref, @@ -4065,7 +4068,8 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, { AstNode *size_node = node->data.array_type.size; - TypeTableEntry *child_type = analyze_type_expr(g, import, context, node->data.array_type.child_type); + TypeTableEntry *child_type = analyze_type_expr_pointer_only(g, import, context, + node->data.array_type.child_type, true); if (child_type->id == TypeTableEntryIdUnreachable) { add_node_error(g, node, buf_create_from_str("array of unreachable not allowed")); @@ -4075,6 +4079,7 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, } if (size_node) { + child_type = analyze_type_expr(g, import, context, node->data.array_type.child_type); TypeTableEntry *size_type = analyze_expression(g, import, context, g->builtin_types.entry_usize, size_node); if (size_type->id == TypeTableEntryIdInvalid) { @@ -4101,8 +4106,8 @@ static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, return g->builtin_types.entry_invalid; } } else { - return resolve_expr_const_val_as_type(g, node, - get_slice_type(g, child_type, node->data.array_type.is_const), false); + TypeTableEntry *slice_type = get_slice_type(g, child_type, node->data.array_type.is_const); + return resolve_expr_const_val_as_type(g, node, slice_type, false); } } diff --git a/test/cases/struct_contains_slice_of_itself.zig b/test/cases/struct_contains_slice_of_itself.zig new file mode 100644 index 0000000000..24b5c92116 --- /dev/null +++ b/test/cases/struct_contains_slice_of_itself.zig @@ -0,0 +1,43 @@ +const assert = @import("std").debug.assert; + +struct Node { + payload: i32, + children: []Node, +} + +#attribute("test") +fn structContainsSliceOfItself() { + var nodes = []Node { + Node { + .payload = 1, + .children = []Node{}, + }, + Node { + .payload = 2, + .children = []Node{}, + }, + Node { + .payload = 3, + .children = []Node{ + Node { + .payload = 31, + .children = []Node{}, + }, + Node { + .payload = 32, + .children = []Node{}, + }, + }, + }, + }; + const root = Node { + .payload = 1234, + .children = nodes[0...], + }; + assert(root.payload == 1234); + assert(root.children[0].payload == 1); + assert(root.children[1].payload == 2); + assert(root.children[2].payload == 3); + assert(root.children[2].children[0].payload == 31); + assert(root.children[2].children[1].payload == 32); +} diff --git a/test/self_hosted.zig b/test/self_hosted.zig index 80920758a4..62be85c64f 100644 --- a/test/self_hosted.zig +++ b/test/self_hosted.zig @@ -14,6 +14,7 @@ const test_const_slice_child = @import("cases/const_slice_child.zig"); const test_switch_prong_implicit_cast = @import("cases/switch_prong_implicit_cast.zig"); const test_switch_prong_err_enum = @import("cases/switch_prong_err_enum.zig"); const test_enum_with_members = @import("cases/enum_with_members.zig"); +const test_struct_contains_slice_of_itself = @import("cases/struct_contains_slice_of_itself.zig"); // normal comment /// this is a documentation comment