Commit 43e7ac8418

Andrew Kelley <superjoe30@gmail.com>
2017-04-30 18:21:24
add peer type resolution `[]T` and `[0]T`
closes #349 also fix slicing const array to be []const T instead of []T
1 parent 29defd7
src/ir.cpp
@@ -6218,16 +6218,18 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_nod
             convert_to_const_slice = true;
             continue;
         } else if (cur_type->id == TypeTableEntryIdArray && is_slice(prev_type) &&
-                prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const &&
-                types_match_const_cast_only(prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
-                    cur_type->data.array.child_type))
+            (prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||
+            cur_type->data.array.len == 0) &&
+            types_match_const_cast_only(prev_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
+                cur_type->data.array.child_type))
         {
             convert_to_const_slice = false;
             continue;
         } else if (prev_type->id == TypeTableEntryIdArray && is_slice(cur_type) &&
-                cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const &&
-                types_match_const_cast_only(cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
-                    prev_type->data.array.child_type))
+            (cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const ||
+            prev_type->data.array.len == 0) &&
+            types_match_const_cast_only(cur_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type,
+            prev_type->data.array.child_type))
         {
             prev_inst = cur_inst;
             convert_to_const_slice = false;
@@ -6796,8 +6798,9 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
         ConstExprValue *val = ir_resolve_const(ira, value, UndefBad);
         if (!val)
             return ira->codegen->invalid_instruction;
+        bool final_is_const = (value->value.type->id == TypeTableEntryIdMetaType) ? is_const : true;
         return ir_get_const_ptr(ira, source_instruction, val, value->value.type,
-                ConstPtrMutComptimeConst, is_const, is_volatile);
+                ConstPtrMutComptimeConst, final_is_const, is_volatile);
     }
 
     TypeTableEntry *ptr_type = get_pointer_to_type_extra(ira->codegen, value->value.type, is_const, is_volatile, 0, 0);
@@ -6806,6 +6809,7 @@ static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instructi
     IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope,
             source_instruction->source_node, value, is_const, is_volatile);
     new_instruction->value.type = ptr_type;
+    new_instruction->value.data.rh_ptr = RuntimeHintPtrStack;
     fn_entry->alloca_list.append(new_instruction);
     return new_instruction;
 }
test/cases/cast.zig
@@ -173,3 +173,25 @@ fn testCastZeroArrayToErrSliceMut() {
 fn gimmeErrOrSlice() -> %[]u8 {
     return []u8{};
 }
+
+test "peer type resolution: [0]u8, []const u8, and %[]u8" {
+    {
+        var data = "hi";
+        const slice = data[0...];
+        assert((%%peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
+        assert((%%peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
+    }
+    comptime {
+        var data = "hi";
+        const slice = data[0...];
+        assert((%%peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
+        assert((%%peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
+    }
+}
+fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) -> %[]u8 {
+    if (a) {
+        return []u8{};
+    }
+
+    return slice[0...1];
+}
test/cases/misc.zig
@@ -486,3 +486,11 @@ test "volatileLoadAndStore" {
     *ptr += 1;
     assert(*ptr == 1235);
 }
+
+test "slice string literal has type []const u8" {
+    comptime {
+        assert(@typeOf("aoeu"[0...]) == []const u8);
+        const array = []i32{1, 2, 3, 4};
+        assert(@typeOf(array[0...]) == []const i32);
+    }
+}
test/cases/struct_contains_slice_of_itself.zig
@@ -5,7 +5,17 @@ const Node = struct {
     children: []Node,
 };
 
-test "structContainsSliceOfItself" {
+test "struct contains slice of itself" {
+    var other_nodes = []Node{
+        Node {
+            .payload = 31,
+            .children = []Node{},
+        },
+        Node {
+            .payload = 32,
+            .children = []Node{},
+        },
+    };
     var nodes = []Node {
         Node {
             .payload = 1,
@@ -17,16 +27,7 @@ test "structContainsSliceOfItself" {
         },
         Node {
             .payload = 3,
-            .children = ([]Node{
-                Node {
-                    .payload = 31,
-                    .children = []Node{},
-                },
-                Node {
-                    .payload = 32,
-                    .children = []Node{},
-                },
-            })[0...],
+            .children = other_nodes[0...],
         },
     };
     const root = Node {