Skip to content

Commit 39a966b

Browse files
committed
Sema: improve error location for array cat/mul
1 parent 1e42a3d commit 39a966b

File tree

3 files changed

+130
-42
lines changed

3 files changed

+130
-42
lines changed

src/Module.zig

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,6 +1608,33 @@ pub const SrcLoc = struct {
16081608
const node_datas = tree.nodes.items(.data);
16091609
return nodeToSpan(tree, node_datas[node].rhs);
16101610
},
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

16121639
.node_offset_switch_operand => |node_off| {
16131640
const tree = try src_loc.file_scope.getTree(gpa);
@@ -2297,6 +2324,15 @@ pub const LazySrcLoc = union(enum) {
22972324
/// The index of the parameter the source location points to.
22982325
param_index: u32,
22992326
},
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

23012337
pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
23022338

@@ -2387,6 +2423,8 @@ pub const LazySrcLoc = union(enum) {
23872423
.node_offset_store_operand,
23882424
.for_input,
23892425
.for_capture_from_input,
2426+
.array_cat_lhs,
2427+
.array_cat_rhs,
23902428
=> .{
23912429
.file_scope = decl.getFileScope(mod),
23922430
.parent_decl_node = decl.src_node,

src/Sema.zig

Lines changed: 75 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -13565,8 +13565,6 @@ fn analyzeTupleCat(
1356513565
const lhs_ty = sema.typeOf(lhs);
1356613566
const rhs_ty = sema.typeOf(rhs);
1356713567
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

1357113569
const lhs_len = lhs_ty.structFieldCount(mod);
1357213570
const rhs_len = rhs_ty.structFieldCount(mod);
@@ -13581,7 +13579,7 @@ fn analyzeTupleCat(
1358113579
if (rhs_len == 0) {
1358213580
return lhs;
1358313581
}
13584-
const final_len = try sema.usizeCast(block, rhs_src, dest_fields);
13582+
const final_len = try sema.usizeCast(block, src, dest_fields);
1358513583

1358613584
const types = try sema.arena.alloc(InternPool.Index, final_len);
1358713585
const values = try sema.arena.alloc(InternPool.Index, final_len);
@@ -13593,7 +13591,10 @@ fn analyzeTupleCat(
1359313591
types[i] = lhs_ty.structFieldType(i, mod).toIntern();
1359413592
const default_val = lhs_ty.structFieldDefaultValue(i, mod);
1359513593
values[i] = default_val.toIntern();
13596-
const operand_src = lhs_src; // TODO better source location
13594+
const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{
13595+
.array_cat_offset = src_node,
13596+
.elem_index = i,
13597+
} };
1359713598
if (default_val.toIntern() == .unreachable_value) {
1359813599
runtime_src = operand_src;
1359913600
values[i] = .none;
@@ -13604,7 +13605,10 @@ fn analyzeTupleCat(
1360413605
types[i + lhs_len] = rhs_ty.structFieldType(i, mod).toIntern();
1360513606
const default_val = rhs_ty.structFieldDefaultValue(i, mod);
1360613607
values[i + lhs_len] = default_val.toIntern();
13607-
const operand_src = rhs_src; // TODO better source location
13608+
const operand_src: LazySrcLoc = .{ .array_cat_rhs = .{
13609+
.array_cat_offset = src_node,
13610+
.elem_index = i,
13611+
} };
1360813612
if (default_val.toIntern() == .unreachable_value) {
1360913613
runtime_src = operand_src;
1361013614
values[i + lhs_len] = .none;
@@ -13632,12 +13636,18 @@ fn analyzeTupleCat(
1363213636
const element_refs = try sema.arena.alloc(Air.Inst.Ref, final_len);
1363313637
var i: u32 = 0;
1363413638
while (i < lhs_len) : (i += 1) {
13635-
const operand_src = lhs_src; // TODO better source location
13639+
const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{
13640+
.array_cat_offset = src_node,
13641+
.elem_index = i,
13642+
} };
1363613643
element_refs[i] = try sema.tupleFieldValByIndex(block, operand_src, lhs, i, lhs_ty);
1363713644
}
1363813645
i = 0;
1363913646
while (i < rhs_len) : (i += 1) {
13640-
const operand_src = rhs_src; // TODO better source location
13647+
const operand_src: LazySrcLoc = .{ .array_cat_rhs = .{
13648+
.array_cat_offset = src_node,
13649+
.elem_index = i,
13650+
} };
1364113651
element_refs[i + lhs_len] =
1364213652
try sema.tupleFieldValByIndex(block, operand_src, rhs, i, rhs_ty);
1364313653
}
@@ -13700,31 +13710,23 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1370013710
const rhs_sent = Air.internedToRef(rhs_sent_val.toIntern());
1370113711
const lhs_sent_casted = try sema.coerce(block, resolved_elem_ty, lhs_sent, lhs_src);
1370213712
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, .{
13704-
.needed_comptime_reason = "array sentinel value must be comptime-known",
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-
});
13713+
const lhs_sent_casted_val = (try sema.resolveDefinedValue(block, lhs_src, lhs_sent_casted)).?;
13714+
const rhs_sent_casted_val = (try sema.resolveDefinedValue(block, rhs_src, rhs_sent_casted)).?;
1370913715
if (try sema.valuesEqual(lhs_sent_casted_val, rhs_sent_casted_val, resolved_elem_ty)) {
1371013716
break :s lhs_sent_casted_val;
1371113717
} else {
1371213718
break :s null;
1371313719
}
1371413720
} else {
1371513721
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, .{
13717-
.needed_comptime_reason = "array sentinel value must be comptime-known",
13718-
});
13722+
const lhs_sent_casted_val = (try sema.resolveDefinedValue(block, lhs_src, lhs_sent_casted)).?;
1371913723
break :s lhs_sent_casted_val;
1372013724
}
1372113725
} else {
1372213726
if (rhs_info.sentinel) |rhs_sent_val| {
1372313727
const rhs_sent = Air.internedToRef(rhs_sent_val.toIntern());
1372413728
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, .{
13726-
.needed_comptime_reason = "array sentinel value must be comptime-known",
13727-
});
13729+
const rhs_sent_casted_val = (try sema.resolveDefinedValue(block, rhs_src, rhs_sent_casted)).?;
1372813730
break :s rhs_sent_casted_val;
1372913731
} else {
1373013732
break :s null;
@@ -13733,7 +13735,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1373313735
};
1373413736

1373513737
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);
1373713739
const result_len = std.math.add(usize, lhs_len, rhs_len) catch |err| switch (err) {
1373813740
error.Overflow => return sema.fail(
1373913741
block,
@@ -13775,23 +13777,31 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1377513777
rhs_val;
1377613778

1377713779
const element_vals = try sema.arena.alloc(InternPool.Index, result_len);
13778-
var elem_i: usize = 0;
13780+
var elem_i: u32 = 0;
1377913781
while (elem_i < lhs_len) : (elem_i += 1) {
1378013782
const lhs_elem_i = elem_i;
1378113783
const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, mod) else Value.@"unreachable";
1378213784
const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try lhs_sub_val.elemValue(mod, lhs_elem_i) else elem_default_val;
1378313785
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);
13785-
const coerced_elem_val = try sema.resolveConstValue(block, .unneeded, coerced_elem_val_inst, undefined);
13786+
const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{
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);
1378613792
element_vals[elem_i] = try coerced_elem_val.intern(resolved_elem_ty, mod);
1378713793
}
1378813794
while (elem_i < result_len) : (elem_i += 1) {
1378913795
const rhs_elem_i = elem_i - lhs_len;
1379013796
const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, mod) else Value.@"unreachable";
1379113797
const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try rhs_sub_val.elemValue(mod, rhs_elem_i) else elem_default_val;
1379213798
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);
13794-
const coerced_elem_val = try sema.resolveConstValue(block, .unneeded, coerced_elem_val_inst, undefined);
13799+
const operand_src: LazySrcLoc = .{ .array_cat_rhs = .{
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);
1379513805
element_vals[elem_i] = try coerced_elem_val.intern(resolved_elem_ty, mod);
1379613806
}
1379713807
return sema.addConstantMaybeRef(try mod.intern(.{ .aggregate = .{
@@ -13814,19 +13824,28 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1381413824
.flags = .{ .address_space = ptr_as },
1381513825
});
1381613826

13817-
var elem_i: usize = 0;
13827+
var elem_i: u32 = 0;
1381813828
while (elem_i < lhs_len) : (elem_i += 1) {
1381913829
const elem_index = try mod.intRef(Type.usize, elem_i);
1382013830
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);
13822-
try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store);
13831+
const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{
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);
1382313837
}
1382413838
while (elem_i < result_len) : (elem_i += 1) {
13839+
const rhs_elem_i = elem_i - lhs_len;
1382513840
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);
1382713842
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);
13829-
try sema.storePtr2(block, src, elem_ptr, src, init, rhs_src, .store);
13843+
const operand_src: LazySrcLoc = .{ .array_cat_rhs = .{
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);
1383013849
}
1383113850
if (res_sent_val) |sent_val| {
1383213851
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
1384013859

1384113860
const element_refs = try sema.arena.alloc(Air.Inst.Ref, result_len);
1384213861
{
13843-
var elem_i: usize = 0;
13862+
var elem_i: u32 = 0;
1384413863
while (elem_i < lhs_len) : (elem_i += 1) {
1384513864
const index = try mod.intRef(Type.usize, elem_i);
13846-
const init = try sema.elemVal(block, lhs_src, lhs, index, src, true);
13847-
element_refs[elem_i] = try sema.coerce(block, resolved_elem_ty, init, lhs_src);
13865+
const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{
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);
1384813871
}
1384913872
while (elem_i < result_len) : (elem_i += 1) {
13850-
const index = try mod.intRef(Type.usize, elem_i - lhs_len);
13851-
const init = try sema.elemVal(block, rhs_src, rhs, index, src, true);
13852-
element_refs[elem_i] = try sema.coerce(block, resolved_elem_ty, init, rhs_src);
13873+
const rhs_elem_i = elem_i - lhs_len;
13874+
const index = try mod.intRef(Type.usize, rhs_elem_i);
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);
1385313881
}
1385413882
}
1385513883

@@ -13913,12 +13941,11 @@ fn analyzeTupleMul(
1391313941
const mod = sema.mod;
1391413942
const operand_ty = sema.typeOf(operand);
1391513943
const src = LazySrcLoc.nodeOffset(src_node);
13916-
const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node };
13917-
const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };
13944+
const len_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };
1391813945

1391913946
const tuple_len = operand_ty.structFieldCount(mod);
1392013947
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

1392313950
if (final_len == 0) {
1392413951
return Air.internedToRef(Value.empty_struct.toIntern());
@@ -13931,7 +13958,10 @@ fn analyzeTupleMul(
1393113958
for (0..tuple_len) |i| {
1393213959
types[i] = operand_ty.structFieldType(i, mod).toIntern();
1393313960
values[i] = operand_ty.structFieldDefaultValue(i, mod).toIntern();
13934-
const operand_src = lhs_src; // TODO better source location
13961+
const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{
13962+
.array_cat_offset = src_node,
13963+
.elem_index = @intCast(i),
13964+
} };
1393513965
if (values[i] == .unreachable_value) {
1393613966
runtime_src = operand_src;
1393713967
values[i] = .none; // TODO don't treat unreachable_value as special
@@ -13963,7 +13993,10 @@ fn analyzeTupleMul(
1396313993
const element_refs = try sema.arena.alloc(Air.Inst.Ref, final_len);
1396413994
var i: u32 = 0;
1396513995
while (i < tuple_len) : (i += 1) {
13966-
const operand_src = lhs_src; // TODO better source location
13996+
const operand_src: LazySrcLoc = .{ .array_cat_lhs = .{
13997+
.array_cat_offset = src_node,
13998+
.elem_index = i,
13999+
} };
1396714000
element_refs[i] = try sema.tupleFieldValByIndex(block, operand_src, operand, @intCast(i), operand_ty);
1396814001
}
1396914002
i = 1;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const Foo = enum { a };
2+
pub export fn entry1() void {
3+
const arr = [_]Foo{.a};
4+
_ = arr ++ .{.b};
5+
}
6+
pub 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

0 commit comments

Comments
 (0)