Commit 7611ed3484

Andrew Kelley <superjoe30@gmail.com>
2017-04-07 23:56:01
allow implicit cast from `[N]T` to `&const []const T`
closes #296
1 parent 5eb78ba
Changed files (3)
src
std
test
cases
src/ir.cpp
@@ -5751,6 +5751,10 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
     return false;
 }
 
+static bool is_slice(TypeTableEntry *type) {
+    return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice;
+}
+
 enum ImplicitCastMatchResult {
     ImplicitCastMatchResultNo,
     ImplicitCastMatchResultYes,
@@ -5837,6 +5841,22 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
         }
     }
 
+    // implicit [N]T to &const []const N
+    if (expected_type->id == TypeTableEntryIdPointer &&
+        expected_type->data.pointer.is_const &&
+        is_slice(expected_type->data.pointer.child_type) &&
+        actual_type->id == TypeTableEntryIdArray)
+    {
+        TypeTableEntry *ptr_type =
+            expected_type->data.pointer.child_type->data.structure.fields[slice_ptr_index].type_entry;
+        assert(ptr_type->id == TypeTableEntryIdPointer);
+        if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
+                types_match_const_cast_only(ptr_type->data.pointer.child_type, actual_type->data.array.child_type))
+        {
+            return ImplicitCastMatchResultYes;
+        }
+    }
+
     // implicit number literal to typed number
     // implicit number literal to &const integer
     if (actual_type->id == TypeTableEntryIdNumLitFloat ||
@@ -5883,10 +5903,6 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
     return ImplicitCastMatchResultNo;
 }
 
-static bool is_slice(TypeTableEntry *type) {
-    return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice;
-}
-
 static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, IrInstruction **instructions, size_t instruction_count) {
     assert(instruction_count >= 1);
     IrInstruction *prev_inst = instructions[0];
@@ -6860,6 +6876,30 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
         }
     }
 
+    // explicit cast from [N]T to &const []const N
+    if (wanted_type->id == TypeTableEntryIdPointer &&
+        wanted_type->data.pointer.is_const &&
+        is_slice(wanted_type->data.pointer.child_type) &&
+        actual_type->id == TypeTableEntryIdArray)
+    {
+        TypeTableEntry *ptr_type =
+            wanted_type->data.pointer.child_type->data.structure.fields[slice_ptr_index].type_entry;
+        assert(ptr_type->id == TypeTableEntryIdPointer);
+        if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
+                types_match_const_cast_only(ptr_type->data.pointer.child_type, actual_type->data.array.child_type))
+        {
+            IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.pointer.child_type, value);
+            if (type_is_invalid(cast1->value.type))
+                return ira->codegen->invalid_instruction;
+
+            IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
+            if (type_is_invalid(cast2->value.type))
+                return ira->codegen->invalid_instruction;
+
+            return cast2;
+        }
+    }
+
     // explicit cast from []T to []u8 or []u8 to []T
     if (is_slice(wanted_type) && is_slice(actual_type) &&
         (is_u8(wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type) ||
std/build.zig
@@ -119,30 +119,30 @@ pub const Builder = struct {
             var zig_args = List([]const u8).init(self.allocator);
             defer zig_args.deinit();
 
-            %return zig_args.append("build_exe"[0...]); // TODO issue #296
+            %return zig_args.append("build_exe");
             %return zig_args.append(exe.root_src);
 
             if (exe.verbose) {
-                %return zig_args.append("--verbose"[0...]); // TODO issue #296
+                %return zig_args.append("--verbose");
             }
 
             if (exe.release) {
-                %return zig_args.append("--release"[0...]); // TODO issue #296
+                %return zig_args.append("--release");
             }
 
-            %return zig_args.append("--name"[0...]); // TODO issue #296
+            %return zig_args.append("--name");
             %return zig_args.append(exe.name);
 
             switch (exe.target) {
                 Target.Native => {},
                 Target.Cross => |cross_target| {
-                    %return zig_args.append("--target-arch"[0...]); // TODO issue #296
+                    %return zig_args.append("--target-arch");
                     %return zig_args.append(targetArchName(cross_target.arch));
 
-                    %return zig_args.append("--target-os"[0...]); // TODO issue #296
+                    %return zig_args.append("--target-os");
                     %return zig_args.append(targetOsName(cross_target.os));
 
-                    %return zig_args.append("--target-environ"[0...]); // TODO issue #296
+                    %return zig_args.append("--target-environ");
                     %return zig_args.append(targetEnvironName(cross_target.environ));
                 },
             }
@@ -153,11 +153,11 @@ pub const Builder = struct {
                     const tmp_file_name = "linker.ld.tmp"; // TODO issue #298
                     io.writeFile(tmp_file_name, script, self.allocator)
                         %% |err| debug.panic("unable to write linker script: {}\n", @errorName(err));
-                    %return zig_args.append("--linker-script"[0...]); // TODO issue #296
-                    %return zig_args.append(tmp_file_name[0...]); // TODO issue #296
+                    %return zig_args.append("--linker-script");
+                    %return zig_args.append(tmp_file_name);
                 },
                 LinkerScript.Path => |path| {
-                    %return zig_args.append("--linker-script"[0...]); // TODO issue #296
+                    %return zig_args.append("--linker-script");
                     %return zig_args.append(path);
                 },
             }
@@ -166,23 +166,23 @@ pub const Builder = struct {
                 var it = exe.link_libs.iterator();
                 while (true) {
                     const entry = it.next() ?? break;
-                    %return zig_args.append("--library"[0...]); // TODO issue #296
+                    %return zig_args.append("--library");
                     %return zig_args.append(entry.key);
                 }
             }
 
             for (self.include_paths.toSliceConst()) |include_path| {
-                %return zig_args.append("-isystem"[0...]); // TODO issue #296
+                %return zig_args.append("-isystem");
                 %return zig_args.append(include_path);
             }
 
             for (self.rpaths.toSliceConst()) |rpath| {
-                %return zig_args.append("-rpath"[0...]); // TODO issue #296
+                %return zig_args.append("-rpath");
                 %return zig_args.append(rpath);
             }
 
             for (self.lib_paths.toSliceConst()) |lib_path| {
-                %return zig_args.append("--library-path"[0...]); // TODO issue #296
+                %return zig_args.append("--library-path");
                 %return zig_args.append(lib_path);
             }
 
test/cases/cast.zig
@@ -70,3 +70,8 @@ test "integer literal to &const int" {
     const x: &const i32 = 3;
     assert(*x == 3);
 }
+
+test "string literal to &const []const u8" {
+    const x: &const []const u8 = "hello";
+    assert(mem.eql(u8, *x, "hello"));
+}