authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-13 16:25:35-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-13 16:25:35-04:00
log3cbe82746489e467706c9002c0068368bb73e6d5
tree4c2f889a95c30974d2133838b3cfa0bad4e824fc
parentefb064449f4db63c1e841f6f0e434f26fcd487ab
signature Commit is signed but in an unrecognized format.

fix behavior for nested array literals

new compile error for trying to cast runtime array literals to slices

4 files changed, 158 insertions(+), 142 deletions(-)

BRANCH_TODO+6
......@@ -10,3 +10,9 @@ get an empty file compiling successfully (with no panic fn override)
1010
1111uncomment all the behavior tests
1212
13better behavior for implicit casts. for example these introduce an extra allocation/memcpy:
14 var x: [1]i32 = [_]i32{1};
15 var x = ([1]i32)([_]i32{1});
16whereas this one does not:
17 var x = [_]i32{1};
18but all 3 should be semantically identical
src/all_types.hpp+2-2
......@@ -2651,7 +2651,7 @@ struct IrInstructionContainerInitList {
26512651 IrInstruction *elem_type;
26522652 size_t item_count;
26532653 IrInstruction **items;
2654 ResultLoc *result_loc;
2654 IrInstruction *result_loc;
26552655};
26562656
26572657struct IrInstructionContainerInitFieldsField {
......@@ -2667,7 +2667,7 @@ struct IrInstructionContainerInitFields {
26672667 IrInstruction *container_type;
26682668 size_t field_count;
26692669 IrInstructionContainerInitFieldsField *fields;
2670 ResultLoc *result_loc;
2670 IrInstruction *result_loc;
26712671};
26722672
26732673struct IrInstructionUnreachable {
src/ir.cpp+53-43
......@@ -1507,7 +1507,7 @@ static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *sour
15071507}
15081508
15091509static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node,
1510 IrInstruction *container_type, size_t item_count, IrInstruction **items, ResultLoc *result_loc)
1510 IrInstruction *container_type, size_t item_count, IrInstruction **items, IrInstruction *result_loc)
15111511{
15121512 IrInstructionContainerInitList *container_init_list_instruction =
15131513 ir_build_instruction<IrInstructionContainerInitList>(irb, scope, source_node);
......@@ -1520,13 +1520,14 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope,
15201520 for (size_t i = 0; i < item_count; i += 1) {
15211521 ir_ref_instruction(items[i], irb->current_basic_block);
15221522 }
1523 if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block);
15231524
15241525 return &container_init_list_instruction->base;
15251526}
15261527
15271528static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scope, AstNode *source_node,
15281529 IrInstruction *container_type, size_t field_count, IrInstructionContainerInitFieldsField *fields,
1529 ResultLoc *result_loc)
1530 IrInstruction *result_loc)
15301531{
15311532 IrInstructionContainerInitFields *container_init_fields_instruction =
15321533 ir_build_instruction<IrInstructionContainerInitFields>(irb, scope, source_node);
......@@ -1539,6 +1540,7 @@ static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scop
15391540 for (size_t i = 0; i < field_count; i += 1) {
15401541 ir_ref_instruction(fields[i].value, irb->current_basic_block);
15411542 }
1543 if (result_loc != nullptr) ir_ref_instruction(result_loc, irb->current_basic_block);
15421544
15431545 return &container_init_fields_instruction->base;
15441546}
......@@ -5667,14 +5669,10 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
56675669}
56685670
56695671static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval,
5670 ResultLoc *result_loc)
5672 ResultLoc *parent_result_loc)
56715673{
56725674 assert(node->type == NodeTypeContainerInitExpr);
56735675
5674 if (ir_should_inline(irb->exec, scope)) {
5675 result_loc = nullptr;
5676 }
5677
56785676 AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
56795677 ContainerInitKind kind = container_init_expr->kind;
56805678
......@@ -5699,13 +5697,13 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
56995697 }
57005698
57015699 IrInstruction *container_ptr = nullptr;
5702 if (result_loc != nullptr) {
5703 src_assert(result_loc->scope_elide == nullptr, node);
5704 result_loc->scope_elide = create_elide_scope(irb->codegen, node, scope);
5700 if (!ir_should_inline(irb->exec, scope)) {
5701 src_assert(parent_result_loc->scope_elide == nullptr, node);
5702 parent_result_loc->scope_elide = create_elide_scope(irb->codegen, node, scope);
57055703
5706 src_assert(result_loc != nullptr, node);
5707 container_ptr = ir_build_resolve_result(irb, &result_loc->scope_elide->base,
5708 node, result_loc, container_type);
5704 src_assert(parent_result_loc != nullptr, node);
5705 container_ptr = ir_build_resolve_result(irb, &parent_result_loc->scope_elide->base,
5706 node, parent_result_loc, container_type);
57095707 }
57105708
57115709 size_t field_count = container_init_expr->entries.length;
......@@ -5720,14 +5718,14 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
57205718 Scope *val_scope = scope;
57215719 ResultLoc *child_result_loc = nullptr;
57225720 if (container_ptr != nullptr) {
5723 IrInstruction *field_ptr = ir_build_field_ptr(irb, &result_loc->scope_elide->base, expr_node,
5724 container_ptr, name, true);
5721 IrInstruction *field_ptr = ir_build_field_ptr(irb, &parent_result_loc->scope_elide->base,
5722 expr_node, container_ptr, name, true);
57255723 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
57265724 result_loc_inst->base.id = ResultLocIdInstruction;
57275725 result_loc_inst->base.source_instruction = field_ptr;
57285726 ir_ref_instruction(field_ptr, irb->current_basic_block);
57295727 child_result_loc = &result_loc_inst->base;
5730 val_scope = &result_loc->scope_elide->base;
5728 val_scope = &parent_result_loc->scope_elide->base;
57315729 }
57325730
57335731 IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, val_scope, LValNone,
......@@ -5740,9 +5738,9 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
57405738 fields[i].source_node = entry_node;
57415739 }
57425740 IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type,
5743 field_count, fields, result_loc);
5741 field_count, fields, container_ptr);
57445742
5745 return ir_lval_wrap(irb, scope, init_fields, lval, result_loc);
5743 return ir_lval_wrap(irb, scope, init_fields, lval, parent_result_loc);
57465744 }
57475745 case ContainerInitKindArray: {
57485746 size_t item_count = container_init_expr->entries.length;
......@@ -5753,12 +5751,12 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
57535751 }
57545752
57555753 IrInstruction *container_ptr = nullptr;
5756 if (result_loc != nullptr) {
5757 src_assert(result_loc->scope_elide == nullptr, node);
5758 result_loc->scope_elide = create_elide_scope(irb->codegen, node, scope);
5754 if (!ir_should_inline(irb->exec, scope)) {
5755 src_assert(parent_result_loc->scope_elide == nullptr, node);
5756 parent_result_loc->scope_elide = create_elide_scope(irb->codegen, node, scope);
57595757
5760 container_ptr = ir_build_resolve_result(irb, &result_loc->scope_elide->base,
5761 node, result_loc, container_type);
5758 container_ptr = ir_build_resolve_result(irb, &parent_result_loc->scope_elide->base,
5759 node, parent_result_loc, container_type);
57625760 }
57635761
57645762 IrInstruction **values = allocate<IrInstruction *>(item_count);
......@@ -5768,15 +5766,16 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
57685766 ResultLoc *child_result_loc = nullptr;
57695767 Scope *val_scope = scope;
57705768 if (container_ptr != nullptr) {
5771 IrInstruction *elem_index = ir_build_const_usize(irb, &result_loc->scope_elide->base, expr_node, i);
5772 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, &result_loc->scope_elide->base, expr_node,
5773 container_ptr, elem_index, false, PtrLenSingle, true);
5769 IrInstruction *elem_index = ir_build_const_usize(irb, &parent_result_loc->scope_elide->base,
5770 expr_node, i);
5771 IrInstruction *elem_ptr = ir_build_elem_ptr(irb, &parent_result_loc->scope_elide->base,
5772 expr_node, container_ptr, elem_index, false, PtrLenSingle, true);
57745773 ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
57755774 result_loc_inst->base.id = ResultLocIdInstruction;
57765775 result_loc_inst->base.source_instruction = elem_ptr;
57775776 ir_ref_instruction(elem_ptr, irb->current_basic_block);
57785777 child_result_loc = &result_loc_inst->base;
5779 val_scope = &result_loc->scope_elide->base;
5778 val_scope = &parent_result_loc->scope_elide->base;
57805779 }
57815780
57825781 IrInstruction *expr_value = ir_gen_node_extra(irb, expr_node, val_scope, LValNone,
......@@ -5787,8 +5786,8 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
57875786 values[i] = expr_value;
57885787 }
57895788 IrInstruction *init_list = ir_build_container_init_list(irb, scope, node, container_type,
5790 item_count, values, result_loc);
5791 return ir_lval_wrap(irb, scope, init_list, lval, result_loc);
5789 item_count, values, container_ptr);
5790 return ir_lval_wrap(irb, scope, init_list, lval, parent_result_loc);
57925791 }
57935792 }
57945793 zig_unreachable();
......@@ -16900,6 +16899,14 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1690016899 }
1690116900 }
1690216901
16902 if (is_slice(array_type) && elem_ptr_instruction->initializing) {
16903 // we need a pointer to an element inside a slice. but we're initializing an array.
16904 // this means that the slice isn't actually pointing at anything.
16905 ir_add_error(ira, &elem_ptr_instruction->base,
16906 buf_sprintf("runtime-initialized array cannot be casted to slice type '%s'",
16907 buf_ptr(&array_type->name)));
16908 return ira->codegen->invalid_instruction;
16909 }
1690316910 } else {
1690416911 // runtime known element index
1690516912 switch (type_requires_comptime(ira->codegen, return_type)) {
......@@ -18729,7 +18736,8 @@ static IrInstruction *ir_analyze_instruction_ref(IrAnalyze *ira, IrInstructionRe
1872918736}
1873018737
1873118738static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrInstruction *instruction,
18732 ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields)
18739 ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields,
18740 IrInstruction *old_result_loc)
1873318741{
1873418742 Error err;
1873518743 assert(container_type->id == ZigTypeIdUnion);
......@@ -18785,20 +18793,21 @@ static IrInstruction *ir_analyze_container_init_fields_union(IrAnalyze *ira, IrI
1878518793 return result;
1878618794 }
1878718795
18788 // this instruction should not get to codegen
18789 IrInstruction *new_instruction = ir_const(ira, instruction, container_type);
18790 // this is how we signal to EndExpr the value is not comptime known
18791 new_instruction->value.special = ConstValSpecialRuntime;
18792 return new_instruction;
18796 ir_assert(old_result_loc != nullptr, instruction);
18797 IrInstruction *result_loc = old_result_loc->child;
18798 if (type_is_invalid(result_loc->value.type))
18799 return result_loc;
18800 return ir_get_deref(ira, instruction, result_loc, nullptr);
1879318801}
1879418802
1879518803static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruction *instruction,
1879618804 ZigType *container_type, size_t instr_field_count, IrInstructionContainerInitFieldsField *fields,
18797 ResultLoc *result_loc_pass1)
18805 IrInstruction *old_result_loc)
1879818806{
1879918807 Error err;
1880018808 if (container_type->id == ZigTypeIdUnion) {
18801 return ir_analyze_container_init_fields_union(ira, instruction, container_type, instr_field_count, fields);
18809 return ir_analyze_container_init_fields_union(ira, instruction, container_type, instr_field_count,
18810 fields, old_result_loc);
1880218811 }
1880318812 if (container_type->id != ZigTypeIdStruct || is_slice(container_type)) {
1880418813 ir_add_error(ira, instruction,
......@@ -18929,9 +18938,10 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
1892918938 return ira->codegen->invalid_instruction;
1893018939 }
1893118940
18932 IrInstruction *result_loc = ir_resolve_result(ira, instruction, result_loc_pass1,
18933 container_type, nullptr);
18934 if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))
18941
18942 ir_assert(old_result_loc != nullptr, instruction);
18943 IrInstruction *result_loc = old_result_loc->child;
18944 if (type_is_invalid(result_loc->value.type))
1893518945 return result_loc;
1893618946 return ir_get_deref(ira, instruction, result_loc, nullptr);
1893718947}
......@@ -19039,9 +19049,9 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
1903919049 return ira->codegen->invalid_instruction;
1904019050 }
1904119051
19042 IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
19043 fixed_size_array_type, nullptr);
19044 if (type_is_invalid(result_loc->value.type) || instr_is_unreachable(result_loc))
19052 ir_assert(instruction->result_loc != nullptr, &instruction->base);
19053 IrInstruction *result_loc = instruction->result_loc->child;
19054 if (type_is_invalid(result_loc->value.type))
1904519055 return result_loc;
1904619056 return ir_get_deref(ira, &instruction->base, result_loc, nullptr);
1904719057 } else if (container_type->id == ZigTypeIdVoid) {
test/stage1/behavior/array.zig+97-97
......@@ -174,103 +174,103 @@ fn plusOne(x: u32) u32 {
174174
175175test "runtime initialize array elem and then implicit cast to slice" {
176176 var two: i32 = 2;
177 const x: []const i32 = [_]i32{two};
177 const x: []const i32 = [_]i32{two};
178178 expect(x[0] == 2);
179179}
180180
181//test "array literal as argument to function" {
182// const S = struct {
183// fn entry(two: i32) void {
184// foo([_]i32{
185// 1,
186// 2,
187// 3,
188// });
189// foo([_]i32{
190// 1,
191// two,
192// 3,
193// });
194// foo2(true, [_]i32{
195// 1,
196// 2,
197// 3,
198// });
199// foo2(true, [_]i32{
200// 1,
201// two,
202// 3,
203// });
204// }
205// fn foo(x: []const i32) void {
206// expect(x[0] == 1);
207// expect(x[1] == 2);
208// expect(x[2] == 3);
209// }
210// fn foo2(trash: bool, x: []const i32) void {
211// expect(trash);
212// expect(x[0] == 1);
213// expect(x[1] == 2);
214// expect(x[2] == 3);
215// }
216// };
217// S.entry(2);
218// comptime S.entry(2);
219//}
220
221//test "double nested array to const slice cast in array literal" {
222// const S = struct {
223// fn entry(two: i32) void {
224// const cases = [_][]const []const i32{
225// [_][]const i32{[_]i32{1}},
226// [_][]const i32{[_]i32{ 2, 3 }},
227// [_][]const i32{
228// [_]i32{4},
229// [_]i32{ 5, 6, 7 },
230// },
231// };
232// check(cases);
233//
234// const cases2 = [_][]const i32{
235// [_]i32{1},
236// [_]i32{ two, 3 },
237// };
238// expect(cases2.len == 2);
239// expect(cases2[0].len == 1);
240// expect(cases2[0][0] == 1);
241// expect(cases2[1].len == 2);
242// expect(cases2[1][0] == 2);
243// expect(cases2[1][1] == 3);
244//
245// const cases3 = [_][]const []const i32{
246// [_][]const i32{[_]i32{1}},
247// [_][]const i32{[_]i32{ two, 3 }},
248// [_][]const i32{
249// [_]i32{4},
250// [_]i32{ 5, 6, 7 },
251// },
252// };
253// check(cases3);
254// }
255//
256// fn check(cases: []const []const []const i32) void {
257// expect(cases.len == 3);
258// expect(cases[0].len == 1);
259// expect(cases[0][0].len == 1);
260// expect(cases[0][0][0] == 1);
261// expect(cases[1].len == 1);
262// expect(cases[1][0].len == 2);
263// expect(cases[1][0][0] == 2);
264// expect(cases[1][0][1] == 3);
265// expect(cases[2].len == 2);
266// expect(cases[2][0].len == 1);
267// expect(cases[2][0][0] == 4);
268// expect(cases[2][1].len == 3);
269// expect(cases[2][1][0] == 5);
270// expect(cases[2][1][1] == 6);
271// expect(cases[2][1][2] == 7);
272// }
273// };
274// S.entry(2);
275// comptime S.entry(2);
276//}
181test "array literal as argument to function" {
182 const S = struct {
183 fn entry(two: i32) void {
184 foo([_]i32{
185 1,
186 2,
187 3,
188 });
189 foo([_]i32{
190 1,
191 two,
192 3,
193 });
194 foo2(true, [_]i32{
195 1,
196 2,
197 3,
198 });
199 foo2(true, [_]i32{
200 1,
201 two,
202 3,
203 });
204 }
205 fn foo(x: []const i32) void {
206 expect(x[0] == 1);
207 expect(x[1] == 2);
208 expect(x[2] == 3);
209 }
210 fn foo2(trash: bool, x: []const i32) void {
211 expect(trash);
212 expect(x[0] == 1);
213 expect(x[1] == 2);
214 expect(x[2] == 3);
215 }
216 };
217 S.entry(2);
218 comptime S.entry(2);
219}
220
221test "double nested array to const slice cast in array literal" {
222 const S = struct {
223 fn entry(two: i32) void {
224 const cases = [_][]const []const i32{
225 &[_][]const i32{&[_]i32{1}},
226 &[_][]const i32{&[_]i32{ 2, 3 }},
227 &[_][]const i32{
228 &[_]i32{4},
229 &[_]i32{ 5, 6, 7 },
230 },
231 };
232 check(cases);
233
234 const cases2 = [_][]const i32{
235 &[_]i32{1},
236 &[_]i32{ two, 3 },
237 };
238 expect(cases2.len == 2);
239 expect(cases2[0].len == 1);
240 expect(cases2[0][0] == 1);
241 expect(cases2[1].len == 2);
242 expect(cases2[1][0] == 2);
243 expect(cases2[1][1] == 3);
244
245 const cases3 = [_][]const []const i32{
246 &[_][]const i32{&[_]i32{1}},
247 &[_][]const i32{&[_]i32{ two, 3 }},
248 &[_][]const i32{
249 &[_]i32{4},
250 &[_]i32{ 5, 6, 7 },
251 },
252 };
253 check(cases3);
254 }
255
256 fn check(cases: []const []const []const i32) void {
257 expect(cases.len == 3);
258 expect(cases[0].len == 1);
259 expect(cases[0][0].len == 1);
260 expect(cases[0][0][0] == 1);
261 expect(cases[1].len == 1);
262 expect(cases[1][0].len == 2);
263 expect(cases[1][0][0] == 2);
264 expect(cases[1][0][1] == 3);
265 expect(cases[2].len == 2);
266 expect(cases[2][0].len == 1);
267 expect(cases[2][0][0] == 4);
268 expect(cases[2][1].len == 3);
269 expect(cases[2][1][0] == 5);
270 expect(cases[2][1][1] == 6);
271 expect(cases[2][1][2] == 7);
272 }
273 };
274 S.entry(2);
275 comptime S.entry(2);
276}