authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-11-29 20:40:57+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2023-11-30 13:15:40+02:00
log39a966b0a496b683d0ac0d1b04dc851caa655a23
treea53abaa7edc89af1a4d44e2a4853ed29ace10e9b
parent1e42a3de89e8a4e78b76d8fc5192bbacf842c02b

Sema: improve error location for array cat/mul


3 files changed, 130 insertions(+), 42 deletions(-)

src/Module.zig+38
...@@ -1608,6 +1608,33 @@ pub const SrcLoc = struct {...@@ -1608,6 +1608,33 @@ pub const SrcLoc = struct {
1608 const node_datas = tree.nodes.items(.data);1608 const node_datas = tree.nodes.items(.data);
1609 return nodeToSpan(tree, node_datas[node].rhs);1609 return nodeToSpan(tree, node_datas[node].rhs);
1610 },1610 },
1611 .array_cat_lhs, .array_cat_rhs => |cat| {
1612 const tree = try src_loc.file_scope.getTree(gpa);
1613 const node = src_loc.declRelativeToNodeIndex(cat.array_cat_offset);
1614 const node_datas = tree.nodes.items(.data);
1615 const arr_node = if (src_loc.lazy == .array_cat_lhs)
1616 node_datas[node].lhs
1617 else
1618 node_datas[node].rhs;
1619
1620 const node_tags = tree.nodes.items(.tag);
1621 var buf: [2]Ast.Node.Index = undefined;
1622 switch (node_tags[arr_node]) {
1623 .array_init_one,
1624 .array_init_one_comma,
1625 .array_init_dot_two,
1626 .array_init_dot_two_comma,
1627 .array_init_dot,
1628 .array_init_dot_comma,
1629 .array_init,
1630 .array_init_comma,
1631 => {
1632 const full = tree.fullArrayInit(&buf, arr_node).?.ast.elements;
1633 return nodeToSpan(tree, full[cat.elem_index]);
1634 },
1635 else => return nodeToSpan(tree, arr_node),
1636 }
1637 },
16111638
1612 .node_offset_switch_operand => |node_off| {1639 .node_offset_switch_operand => |node_off| {
1613 const tree = try src_loc.file_scope.getTree(gpa);1640 const tree = try src_loc.file_scope.getTree(gpa);
...@@ -2297,6 +2324,15 @@ pub const LazySrcLoc = union(enum) {...@@ -2297,6 +2324,15 @@ pub const LazySrcLoc = union(enum) {
2297 /// The index of the parameter the source location points to.2324 /// The index of the parameter the source location points to.
2298 param_index: u32,2325 param_index: u32,
2299 },2326 },
2327 array_cat_lhs: ArrayCat,
2328 array_cat_rhs: ArrayCat,
2329
2330 const ArrayCat = struct {
2331 /// Points to the array concat AST node.
2332 array_cat_offset: i32,
2333 /// The index of the element the source location points to.
2334 elem_index: u32,
2335 };
23002336
2301 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;2337 pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
23022338
...@@ -2387,6 +2423,8 @@ pub const LazySrcLoc = union(enum) {...@@ -2387,6 +2423,8 @@ pub const LazySrcLoc = union(enum) {
2387 .node_offset_store_operand,2423 .node_offset_store_operand,
2388 .for_input,2424 .for_input,
2389 .for_capture_from_input,2425 .for_capture_from_input,
2426 .array_cat_lhs,
2427 .array_cat_rhs,
2390 => .{2428 => .{
2391 .file_scope = decl.getFileScope(mod),2429 .file_scope = decl.getFileScope(mod),
2392 .parent_decl_node = decl.src_node,2430 .parent_decl_node = decl.src_node,
src/Sema.zig+75-42
...@@ -13565,8 +13565,6 @@ fn analyzeTupleCat(...@@ -13565,8 +13565,6 @@ fn analyzeTupleCat(
13565 const lhs_ty = sema.typeOf(lhs);13565 const lhs_ty = sema.typeOf(lhs);
13566 const rhs_ty = sema.typeOf(rhs);13566 const rhs_ty = sema.typeOf(rhs);
13567 const src = LazySrcLoc.nodeOffset(src_node);13567 const src = LazySrcLoc.nodeOffset(src_node);
13568 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node };
13569 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };
1357013568
13571 const lhs_len = lhs_ty.structFieldCount(mod);13569 const lhs_len = lhs_ty.structFieldCount(mod);
13572 const rhs_len = rhs_ty.structFieldCount(mod);13570 const rhs_len = rhs_ty.structFieldCount(mod);
...@@ -13581,7 +13579,7 @@ fn analyzeTupleCat(...@@ -13581,7 +13579,7 @@ fn analyzeTupleCat(
13581 if (rhs_len == 0) {13579 if (rhs_len == 0) {
13582 return lhs;13580 return lhs;
13583 }13581 }
13584 const final_len = try sema.usizeCast(block, rhs_src, dest_fields);13582 const final_len = try sema.usizeCast(block, src, dest_fields);
1358513583
13586 const types = try sema.arena.alloc(InternPool.Index, final_len);13584 const types = try sema.arena.alloc(InternPool.Index, final_len);
13587 const values = try sema.arena.alloc(InternPool.Index, final_len);13585 const values = try sema.arena.alloc(InternPool.Index, final_len);
...@@ -13593,7 +13591,10 @@ fn analyzeTupleCat(...@@ -13593,7 +13591,10 @@ fn analyzeTupleCat(
13593 types[i] = lhs_ty.structFieldType(i, mod).toIntern();13591 types[i] = lhs_ty.structFieldType(i, mod).toIntern();
13594 const default_val = lhs_ty.structFieldDefaultValue(i, mod);13592 const default_val = lhs_ty.structFieldDefaultValue(i, mod);
13595 values[i] = default_val.toIntern();13593 values[i] = default_val.toIntern();
13596 const operand_src = lhs_src; // TODO better source location13594 const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{
13595 .array_cat_offset = src_node,
13596 .elem_index = i,
13597 } };
13597 if (default_val.toIntern() == .unreachable_value) {13598 if (default_val.toIntern() == .unreachable_value) {
13598 runtime_src = operand_src;13599 runtime_src = operand_src;
13599 values[i] = .none;13600 values[i] = .none;
...@@ -13604,7 +13605,10 @@ fn analyzeTupleCat(...@@ -13604,7 +13605,10 @@ fn analyzeTupleCat(
13604 types[i + lhs_len] = rhs_ty.structFieldType(i, mod).toIntern();13605 types[i + lhs_len] = rhs_ty.structFieldType(i, mod).toIntern();
13605 const default_val = rhs_ty.structFieldDefaultValue(i, mod);13606 const default_val = rhs_ty.structFieldDefaultValue(i, mod);
13606 values[i + lhs_len] = default_val.toIntern();13607 values[i + lhs_len] = default_val.toIntern();
13607 const operand_src = rhs_src; // TODO better source location13608 const operand_src: LazySrcLoc = .{ .array_cat_rhs = .{
13609 .array_cat_offset = src_node,
13610 .elem_index = i,
13611 } };
13608 if (default_val.toIntern() == .unreachable_value) {13612 if (default_val.toIntern() == .unreachable_value) {
13609 runtime_src = operand_src;13613 runtime_src = operand_src;
13610 values[i + lhs_len] = .none;13614 values[i + lhs_len] = .none;
...@@ -13632,12 +13636,18 @@ fn analyzeTupleCat(...@@ -13632,12 +13636,18 @@ fn analyzeTupleCat(
13632 const element_refs = try sema.arena.alloc(Air.Inst.Ref, final_len);13636 const element_refs = try sema.arena.alloc(Air.Inst.Ref, final_len);
13633 var i: u32 = 0;13637 var i: u32 = 0;
13634 while (i < lhs_len) : (i += 1) {13638 while (i < lhs_len) : (i += 1) {
13635 const operand_src = lhs_src; // TODO better source location13639 const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{
13640 .array_cat_offset = src_node,
13641 .elem_index = i,
13642 } };
13636 element_refs[i] = try sema.tupleFieldValByIndex(block, operand_src, lhs, i, lhs_ty);13643 element_refs[i] = try sema.tupleFieldValByIndex(block, operand_src, lhs, i, lhs_ty);
13637 }13644 }
13638 i = 0;13645 i = 0;
13639 while (i < rhs_len) : (i += 1) {13646 while (i < rhs_len) : (i += 1) {
13640 const operand_src = rhs_src; // TODO better source location13647 const operand_src: LazySrcLoc = .{ .array_cat_rhs = .{
13648 .array_cat_offset = src_node,
13649 .elem_index = i,
13650 } };
13641 element_refs[i + lhs_len] =13651 element_refs[i + lhs_len] =
13642 try sema.tupleFieldValByIndex(block, operand_src, rhs, i, rhs_ty);13652 try sema.tupleFieldValByIndex(block, operand_src, rhs, i, rhs_ty);
13643 }13653 }
...@@ -13700,12 +13710,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13700,12 +13710,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13700 const rhs_sent = Air.internedToRef(rhs_sent_val.toIntern());13710 const rhs_sent = Air.internedToRef(rhs_sent_val.toIntern());
13701 const lhs_sent_casted = try sema.coerce(block, resolved_elem_ty, lhs_sent, lhs_src);13711 const lhs_sent_casted = try sema.coerce(block, resolved_elem_ty, lhs_sent, lhs_src);
13702 const rhs_sent_casted = try sema.coerce(block, resolved_elem_ty, rhs_sent, rhs_src);13712 const rhs_sent_casted = try sema.coerce(block, resolved_elem_ty, rhs_sent, rhs_src);
13703 const lhs_sent_casted_val = try sema.resolveConstDefinedValue(block, lhs_src, lhs_sent_casted, .{13713 const lhs_sent_casted_val = (try sema.resolveDefinedValue(block, lhs_src, lhs_sent_casted)).?;
13704 .needed_comptime_reason = "array sentinel value must be comptime-known",13714 const rhs_sent_casted_val = (try sema.resolveDefinedValue(block, rhs_src, rhs_sent_casted)).?;
13705 });
13706 const rhs_sent_casted_val = try sema.resolveConstDefinedValue(block, rhs_src, rhs_sent_casted, .{
13707 .needed_comptime_reason = "array sentinel value must be comptime-known",
13708 });
13709 if (try sema.valuesEqual(lhs_sent_casted_val, rhs_sent_casted_val, resolved_elem_ty)) {13715 if (try sema.valuesEqual(lhs_sent_casted_val, rhs_sent_casted_val, resolved_elem_ty)) {
13710 break :s lhs_sent_casted_val;13716 break :s lhs_sent_casted_val;
13711 } else {13717 } else {
...@@ -13713,18 +13719,14 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13713,18 +13719,14 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13713 }13719 }
13714 } else {13720 } else {
13715 const lhs_sent_casted = try sema.coerce(block, resolved_elem_ty, lhs_sent, lhs_src);13721 const lhs_sent_casted = try sema.coerce(block, resolved_elem_ty, lhs_sent, lhs_src);
13716 const lhs_sent_casted_val = try sema.resolveConstDefinedValue(block, lhs_src, lhs_sent_casted, .{13722 const lhs_sent_casted_val = (try sema.resolveDefinedValue(block, lhs_src, lhs_sent_casted)).?;
13717 .needed_comptime_reason = "array sentinel value must be comptime-known",
13718 });
13719 break :s lhs_sent_casted_val;13723 break :s lhs_sent_casted_val;
13720 }13724 }
13721 } else {13725 } else {
13722 if (rhs_info.sentinel) |rhs_sent_val| {13726 if (rhs_info.sentinel) |rhs_sent_val| {
13723 const rhs_sent = Air.internedToRef(rhs_sent_val.toIntern());13727 const rhs_sent = Air.internedToRef(rhs_sent_val.toIntern());
13724 const rhs_sent_casted = try sema.coerce(block, resolved_elem_ty, rhs_sent, rhs_src);13728 const rhs_sent_casted = try sema.coerce(block, resolved_elem_ty, rhs_sent, rhs_src);
13725 const rhs_sent_casted_val = try sema.resolveConstDefinedValue(block, rhs_src, rhs_sent_casted, .{13729 const rhs_sent_casted_val = (try sema.resolveDefinedValue(block, rhs_src, rhs_sent_casted)).?;
13726 .needed_comptime_reason = "array sentinel value must be comptime-known",
13727 });
13728 break :s rhs_sent_casted_val;13730 break :s rhs_sent_casted_val;
13729 } else {13731 } else {
13730 break :s null;13732 break :s null;
...@@ -13733,7 +13735,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13733,7 +13735,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13733 };13735 };
1373413736
13735 const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len);13737 const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len);
13736 const rhs_len = try sema.usizeCast(block, lhs_src, rhs_info.len);13738 const rhs_len = try sema.usizeCast(block, rhs_src, rhs_info.len);
13737 const result_len = std.math.add(usize, lhs_len, rhs_len) catch |err| switch (err) {13739 const result_len = std.math.add(usize, lhs_len, rhs_len) catch |err| switch (err) {
13738 error.Overflow => return sema.fail(13740 error.Overflow => return sema.fail(
13739 block,13741 block,
...@@ -13775,14 +13777,18 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13775,14 +13777,18 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13775 rhs_val;13777 rhs_val;
1377613778
13777 const element_vals = try sema.arena.alloc(InternPool.Index, result_len);13779 const element_vals = try sema.arena.alloc(InternPool.Index, result_len);
13778 var elem_i: usize = 0;13780 var elem_i: u32 = 0;
13779 while (elem_i < lhs_len) : (elem_i += 1) {13781 while (elem_i < lhs_len) : (elem_i += 1) {
13780 const lhs_elem_i = elem_i;13782 const lhs_elem_i = elem_i;
13781 const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, mod) else Value.@"unreachable";13783 const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, mod) else Value.@"unreachable";
13782 const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try lhs_sub_val.elemValue(mod, lhs_elem_i) else elem_default_val;13784 const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try lhs_sub_val.elemValue(mod, lhs_elem_i) else elem_default_val;
13783 const elem_val_inst = Air.internedToRef(elem_val.toIntern());13785 const elem_val_inst = Air.internedToRef(elem_val.toIntern());
13784 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded);13786 const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{
13785 const coerced_elem_val = try sema.resolveConstValue(block, .unneeded, coerced_elem_val_inst, undefined);13787 .array_cat_offset = inst_data.src_node,
13788 .elem_index = elem_i,
13789 } };
13790 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, operand_src);
13791 const coerced_elem_val = try sema.resolveConstValue(block, operand_src, coerced_elem_val_inst, undefined);
13786 element_vals[elem_i] = try coerced_elem_val.intern(resolved_elem_ty, mod);13792 element_vals[elem_i] = try coerced_elem_val.intern(resolved_elem_ty, mod);
13787 }13793 }
13788 while (elem_i < result_len) : (elem_i += 1) {13794 while (elem_i < result_len) : (elem_i += 1) {
...@@ -13790,8 +13796,12 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13790,8 +13796,12 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13790 const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, mod) else Value.@"unreachable";13796 const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, mod) else Value.@"unreachable";
13791 const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try rhs_sub_val.elemValue(mod, rhs_elem_i) else elem_default_val;13797 const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try rhs_sub_val.elemValue(mod, rhs_elem_i) else elem_default_val;
13792 const elem_val_inst = Air.internedToRef(elem_val.toIntern());13798 const elem_val_inst = Air.internedToRef(elem_val.toIntern());
13793 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded);13799 const operand_src: LazySrcLoc = .{ .array_cat_rhs = .{
13794 const coerced_elem_val = try sema.resolveConstValue(block, .unneeded, coerced_elem_val_inst, undefined);13800 .array_cat_offset = inst_data.src_node,
13801 .elem_index = @intCast(rhs_elem_i),
13802 } };
13803 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, operand_src);
13804 const coerced_elem_val = try sema.resolveConstValue(block, operand_src, coerced_elem_val_inst, undefined);
13795 element_vals[elem_i] = try coerced_elem_val.intern(resolved_elem_ty, mod);13805 element_vals[elem_i] = try coerced_elem_val.intern(resolved_elem_ty, mod);
13796 }13806 }
13797 return sema.addConstantMaybeRef(try mod.intern(.{ .aggregate = .{13807 return sema.addConstantMaybeRef(try mod.intern(.{ .aggregate = .{
...@@ -13814,19 +13824,28 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13814,19 +13824,28 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13814 .flags = .{ .address_space = ptr_as },13824 .flags = .{ .address_space = ptr_as },
13815 });13825 });
1381613826
13817 var elem_i: usize = 0;13827 var elem_i: u32 = 0;
13818 while (elem_i < lhs_len) : (elem_i += 1) {13828 while (elem_i < lhs_len) : (elem_i += 1) {
13819 const elem_index = try mod.intRef(Type.usize, elem_i);13829 const elem_index = try mod.intRef(Type.usize, elem_i);
13820 const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty);13830 const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty);
13821 const init = try sema.elemVal(block, lhs_src, lhs, elem_index, src, true);13831 const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{
13822 try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store);13832 .array_cat_offset = inst_data.src_node,
13833 .elem_index = elem_i,
13834 } };
13835 const init = try sema.elemVal(block, operand_src, lhs, elem_index, src, true);
13836 try sema.storePtr2(block, src, elem_ptr, src, init, operand_src, .store);
13823 }13837 }
13824 while (elem_i < result_len) : (elem_i += 1) {13838 while (elem_i < result_len) : (elem_i += 1) {
13839 const rhs_elem_i = elem_i - lhs_len;
13825 const elem_index = try mod.intRef(Type.usize, elem_i);13840 const elem_index = try mod.intRef(Type.usize, elem_i);
13826 const rhs_index = try mod.intRef(Type.usize, elem_i - lhs_len);13841 const rhs_index = try mod.intRef(Type.usize, rhs_elem_i);
13827 const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty);13842 const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty);
13828 const init = try sema.elemVal(block, rhs_src, rhs, rhs_index, src, true);13843 const operand_src: LazySrcLoc = .{ .array_cat_rhs = .{
13829 try sema.storePtr2(block, src, elem_ptr, src, init, rhs_src, .store);13844 .array_cat_offset = inst_data.src_node,
13845 .elem_index = @intCast(rhs_elem_i),
13846 } };
13847 const init = try sema.elemVal(block, operand_src, rhs, rhs_index, src, true);
13848 try sema.storePtr2(block, src, elem_ptr, src, init, operand_src, .store);
13830 }13849 }
13831 if (res_sent_val) |sent_val| {13850 if (res_sent_val) |sent_val| {
13832 const elem_index = try mod.intRef(Type.usize, result_len);13851 const elem_index = try mod.intRef(Type.usize, result_len);
...@@ -13840,16 +13859,25 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13840,16 +13859,25 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1384013859
13841 const element_refs = try sema.arena.alloc(Air.Inst.Ref, result_len);13860 const element_refs = try sema.arena.alloc(Air.Inst.Ref, result_len);
13842 {13861 {
13843 var elem_i: usize = 0;13862 var elem_i: u32 = 0;
13844 while (elem_i < lhs_len) : (elem_i += 1) {13863 while (elem_i < lhs_len) : (elem_i += 1) {
13845 const index = try mod.intRef(Type.usize, elem_i);13864 const index = try mod.intRef(Type.usize, elem_i);
13846 const init = try sema.elemVal(block, lhs_src, lhs, index, src, true);13865 const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{
13847 element_refs[elem_i] = try sema.coerce(block, resolved_elem_ty, init, lhs_src);13866 .array_cat_offset = inst_data.src_node,
13867 .elem_index = elem_i,
13868 } };
13869 const init = try sema.elemVal(block, operand_src, lhs, index, src, true);
13870 element_refs[elem_i] = try sema.coerce(block, resolved_elem_ty, init, operand_src);
13848 }13871 }
13849 while (elem_i < result_len) : (elem_i += 1) {13872 while (elem_i < result_len) : (elem_i += 1) {
13850 const index = try mod.intRef(Type.usize, elem_i - lhs_len);13873 const rhs_elem_i = elem_i - lhs_len;
13851 const init = try sema.elemVal(block, rhs_src, rhs, index, src, true);13874 const index = try mod.intRef(Type.usize, rhs_elem_i);
13852 element_refs[elem_i] = try sema.coerce(block, resolved_elem_ty, init, rhs_src);13875 const operand_src: LazySrcLoc = .{ .array_cat_rhs = .{
13876 .array_cat_offset = inst_data.src_node,
13877 .elem_index = @intCast(rhs_elem_i),
13878 } };
13879 const init = try sema.elemVal(block, operand_src, rhs, index, src, true);
13880 element_refs[elem_i] = try sema.coerce(block, resolved_elem_ty, init, operand_src);
13853 }13881 }
13854 }13882 }
1385513883
...@@ -13913,12 +13941,11 @@ fn analyzeTupleMul(...@@ -13913,12 +13941,11 @@ fn analyzeTupleMul(
13913 const mod = sema.mod;13941 const mod = sema.mod;
13914 const operand_ty = sema.typeOf(operand);13942 const operand_ty = sema.typeOf(operand);
13915 const src = LazySrcLoc.nodeOffset(src_node);13943 const src = LazySrcLoc.nodeOffset(src_node);
13916 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node };13944 const len_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };
13917 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };
1391813945
13919 const tuple_len = operand_ty.structFieldCount(mod);13946 const tuple_len = operand_ty.structFieldCount(mod);
13920 const final_len = std.math.mul(usize, tuple_len, factor) catch13947 const final_len = std.math.mul(usize, tuple_len, factor) catch
13921 return sema.fail(block, rhs_src, "operation results in overflow", .{});13948 return sema.fail(block, len_src, "operation results in overflow", .{});
1392213949
13923 if (final_len == 0) {13950 if (final_len == 0) {
13924 return Air.internedToRef(Value.empty_struct.toIntern());13951 return Air.internedToRef(Value.empty_struct.toIntern());
...@@ -13931,7 +13958,10 @@ fn analyzeTupleMul(...@@ -13931,7 +13958,10 @@ fn analyzeTupleMul(
13931 for (0..tuple_len) |i| {13958 for (0..tuple_len) |i| {
13932 types[i] = operand_ty.structFieldType(i, mod).toIntern();13959 types[i] = operand_ty.structFieldType(i, mod).toIntern();
13933 values[i] = operand_ty.structFieldDefaultValue(i, mod).toIntern();13960 values[i] = operand_ty.structFieldDefaultValue(i, mod).toIntern();
13934 const operand_src = lhs_src; // TODO better source location13961 const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{
13962 .array_cat_offset = src_node,
13963 .elem_index = @intCast(i),
13964 } };
13935 if (values[i] == .unreachable_value) {13965 if (values[i] == .unreachable_value) {
13936 runtime_src = operand_src;13966 runtime_src = operand_src;
13937 values[i] = .none; // TODO don't treat unreachable_value as special13967 values[i] = .none; // TODO don't treat unreachable_value as special
...@@ -13963,7 +13993,10 @@ fn analyzeTupleMul(...@@ -13963,7 +13993,10 @@ fn analyzeTupleMul(
13963 const element_refs = try sema.arena.alloc(Air.Inst.Ref, final_len);13993 const element_refs = try sema.arena.alloc(Air.Inst.Ref, final_len);
13964 var i: u32 = 0;13994 var i: u32 = 0;
13965 while (i < tuple_len) : (i += 1) {13995 while (i < tuple_len) : (i += 1) {
13966 const operand_src = lhs_src; // TODO better source location13996 const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{
13997 .array_cat_offset = src_node,
13998 .elem_index = i,
13999 } };
13967 element_refs[i] = try sema.tupleFieldValByIndex(block, operand_src, operand, @intCast(i), operand_ty);14000 element_refs[i] = try sema.tupleFieldValByIndex(block, operand_src, operand, @intCast(i), operand_ty);
13968 }14001 }
13969 i = 1;14002 i = 1;
test/cases/compile_errors/array_cat_invalid_elem.zig created+17
...@@ -0,0 +1,17 @@
1const Foo = enum { a };
2pub export fn entry1() void {
3 const arr = [_]Foo{.a};
4 _ = arr ++ .{.b};
5}
6pub export fn entry2() void {
7 const b = .{.b};
8 const arr = [_]Foo{.a};
9 _ = arr ++ b;
10}
11
12// error
13//
14// :4:19: error: no field named 'b' in enum 'tmp.Foo'
15// :1:13: note: enum declared here
16// :9:16: error: no field named 'b' in enum 'tmp.Foo'
17// :1:13: note: enum declared here