authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-07 17:56:01-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-07 17:56:01-04:00
log7611ed3484ad810fe10d3c303a04d66bfa0bd6fd
treedc0b432b5abc0b0cb46e917f2fa30ae99e4ba515
parent5eb78ba1772b54af1ecfb1cd28cb0f1c46dab9b3

allow implicit cast from `[N]T` to `&const []const T`

closes #296

3 files changed, 63 insertions(+), 18 deletions(-)

src/ir.cpp+44-4
...@@ -5751,6 +5751,10 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc...@@ -5751,6 +5751,10 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
5751 return false;5751 return false;
5752}5752}
57535753
5754static bool is_slice(TypeTableEntry *type) {
5755 return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice;
5756}
5757
5754enum ImplicitCastMatchResult {5758enum ImplicitCastMatchResult {
5755 ImplicitCastMatchResultNo,5759 ImplicitCastMatchResultNo,
5756 ImplicitCastMatchResultYes,5760 ImplicitCastMatchResultYes,
...@@ -5837,6 +5841,22 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,...@@ -5837,6 +5841,22 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
5837 }5841 }
5838 }5842 }
58395843
5844 // implicit [N]T to &const []const N
5845 if (expected_type->id == TypeTableEntryIdPointer &&
5846 expected_type->data.pointer.is_const &&
5847 is_slice(expected_type->data.pointer.child_type) &&
5848 actual_type->id == TypeTableEntryIdArray)
5849 {
5850 TypeTableEntry *ptr_type =
5851 expected_type->data.pointer.child_type->data.structure.fields[slice_ptr_index].type_entry;
5852 assert(ptr_type->id == TypeTableEntryIdPointer);
5853 if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
5854 types_match_const_cast_only(ptr_type->data.pointer.child_type, actual_type->data.array.child_type))
5855 {
5856 return ImplicitCastMatchResultYes;
5857 }
5858 }
5859
5840 // implicit number literal to typed number5860 // implicit number literal to typed number
5841 // implicit number literal to &const integer5861 // implicit number literal to &const integer
5842 if (actual_type->id == TypeTableEntryIdNumLitFloat ||5862 if (actual_type->id == TypeTableEntryIdNumLitFloat ||
...@@ -5883,10 +5903,6 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,...@@ -5883,10 +5903,6 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
5883 return ImplicitCastMatchResultNo;5903 return ImplicitCastMatchResultNo;
5884}5904}
58855905
5886static bool is_slice(TypeTableEntry *type) {
5887 return type->id == TypeTableEntryIdStruct && type->data.structure.is_slice;
5888}
5889
5890static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, IrInstruction **instructions, size_t instruction_count) {5906static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, IrInstruction **instructions, size_t instruction_count) {
5891 assert(instruction_count >= 1);5907 assert(instruction_count >= 1);
5892 IrInstruction *prev_inst = instructions[0];5908 IrInstruction *prev_inst = instructions[0];
...@@ -6860,6 +6876,30 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -6860,6 +6876,30 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
6860 }6876 }
6861 }6877 }
68626878
6879 // explicit cast from [N]T to &const []const N
6880 if (wanted_type->id == TypeTableEntryIdPointer &&
6881 wanted_type->data.pointer.is_const &&
6882 is_slice(wanted_type->data.pointer.child_type) &&
6883 actual_type->id == TypeTableEntryIdArray)
6884 {
6885 TypeTableEntry *ptr_type =
6886 wanted_type->data.pointer.child_type->data.structure.fields[slice_ptr_index].type_entry;
6887 assert(ptr_type->id == TypeTableEntryIdPointer);
6888 if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) &&
6889 types_match_const_cast_only(ptr_type->data.pointer.child_type, actual_type->data.array.child_type))
6890 {
6891 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.pointer.child_type, value);
6892 if (type_is_invalid(cast1->value.type))
6893 return ira->codegen->invalid_instruction;
6894
6895 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
6896 if (type_is_invalid(cast2->value.type))
6897 return ira->codegen->invalid_instruction;
6898
6899 return cast2;
6900 }
6901 }
6902
6863 // explicit cast from []T to []u8 or []u8 to []T6903 // explicit cast from []T to []u8 or []u8 to []T
6864 if (is_slice(wanted_type) && is_slice(actual_type) &&6904 if (is_slice(wanted_type) && is_slice(actual_type) &&
6865 (is_u8(wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type) ||6905 (is_u8(wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type) ||
std/build.zig+14-14
...@@ -119,30 +119,30 @@ pub const Builder = struct {...@@ -119,30 +119,30 @@ pub const Builder = struct {
119 var zig_args = List([]const u8).init(self.allocator);119 var zig_args = List([]const u8).init(self.allocator);
120 defer zig_args.deinit();120 defer zig_args.deinit();
121121
122 %return zig_args.append("build_exe"[0...]); // TODO issue #296122 %return zig_args.append("build_exe");
123 %return zig_args.append(exe.root_src);123 %return zig_args.append(exe.root_src);
124124
125 if (exe.verbose) {125 if (exe.verbose) {
126 %return zig_args.append("--verbose"[0...]); // TODO issue #296126 %return zig_args.append("--verbose");
127 }127 }
128128
129 if (exe.release) {129 if (exe.release) {
130 %return zig_args.append("--release"[0...]); // TODO issue #296130 %return zig_args.append("--release");
131 }131 }
132132
133 %return zig_args.append("--name"[0...]); // TODO issue #296133 %return zig_args.append("--name");
134 %return zig_args.append(exe.name);134 %return zig_args.append(exe.name);
135135
136 switch (exe.target) {136 switch (exe.target) {
137 Target.Native => {},137 Target.Native => {},
138 Target.Cross => |cross_target| {138 Target.Cross => |cross_target| {
139 %return zig_args.append("--target-arch"[0...]); // TODO issue #296139 %return zig_args.append("--target-arch");
140 %return zig_args.append(targetArchName(cross_target.arch));140 %return zig_args.append(targetArchName(cross_target.arch));
141141
142 %return zig_args.append("--target-os"[0...]); // TODO issue #296142 %return zig_args.append("--target-os");
143 %return zig_args.append(targetOsName(cross_target.os));143 %return zig_args.append(targetOsName(cross_target.os));
144144
145 %return zig_args.append("--target-environ"[0...]); // TODO issue #296145 %return zig_args.append("--target-environ");
146 %return zig_args.append(targetEnvironName(cross_target.environ));146 %return zig_args.append(targetEnvironName(cross_target.environ));
147 },147 },
148 }148 }
...@@ -153,11 +153,11 @@ pub const Builder = struct {...@@ -153,11 +153,11 @@ pub const Builder = struct {
153 const tmp_file_name = "linker.ld.tmp"; // TODO issue #298153 const tmp_file_name = "linker.ld.tmp"; // TODO issue #298
154 io.writeFile(tmp_file_name, script, self.allocator)154 io.writeFile(tmp_file_name, script, self.allocator)
155 %% |err| debug.panic("unable to write linker script: {}\n", @errorName(err));155 %% |err| debug.panic("unable to write linker script: {}\n", @errorName(err));
156 %return zig_args.append("--linker-script"[0...]); // TODO issue #296156 %return zig_args.append("--linker-script");
157 %return zig_args.append(tmp_file_name[0...]); // TODO issue #296157 %return zig_args.append(tmp_file_name);
158 },158 },
159 LinkerScript.Path => |path| {159 LinkerScript.Path => |path| {
160 %return zig_args.append("--linker-script"[0...]); // TODO issue #296160 %return zig_args.append("--linker-script");
161 %return zig_args.append(path);161 %return zig_args.append(path);
162 },162 },
163 }163 }
...@@ -166,23 +166,23 @@ pub const Builder = struct {...@@ -166,23 +166,23 @@ pub const Builder = struct {
166 var it = exe.link_libs.iterator();166 var it = exe.link_libs.iterator();
167 while (true) {167 while (true) {
168 const entry = it.next() ?? break;168 const entry = it.next() ?? break;
169 %return zig_args.append("--library"[0...]); // TODO issue #296169 %return zig_args.append("--library");
170 %return zig_args.append(entry.key);170 %return zig_args.append(entry.key);
171 }171 }
172 }172 }
173173
174 for (self.include_paths.toSliceConst()) |include_path| {174 for (self.include_paths.toSliceConst()) |include_path| {
175 %return zig_args.append("-isystem"[0...]); // TODO issue #296175 %return zig_args.append("-isystem");
176 %return zig_args.append(include_path);176 %return zig_args.append(include_path);
177 }177 }
178178
179 for (self.rpaths.toSliceConst()) |rpath| {179 for (self.rpaths.toSliceConst()) |rpath| {
180 %return zig_args.append("-rpath"[0...]); // TODO issue #296180 %return zig_args.append("-rpath");
181 %return zig_args.append(rpath);181 %return zig_args.append(rpath);
182 }182 }
183183
184 for (self.lib_paths.toSliceConst()) |lib_path| {184 for (self.lib_paths.toSliceConst()) |lib_path| {
185 %return zig_args.append("--library-path"[0...]); // TODO issue #296185 %return zig_args.append("--library-path");
186 %return zig_args.append(lib_path);186 %return zig_args.append(lib_path);
187 }187 }
188188
test/cases/cast.zig+5
...@@ -70,3 +70,8 @@ test "integer literal to &const int" {...@@ -70,3 +70,8 @@ test "integer literal to &const int" {
70 const x: &const i32 = 3;70 const x: &const i32 = 3;
71 assert(*x == 3);71 assert(*x == 3);
72}72}
73
74test "string literal to &const []const u8" {
75 const x: &const []const u8 = "hello";
76 assert(mem.eql(u8, *x, "hello"));
77}