authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-12-02 20:16:47+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-12-03 00:09:23+02:00
loge2509ddbe69a56bb1f4a56b46946b2a706d5aabe
tree109fc0748d4e735b8a0624907bfb0610c06d8301
parent0e38cc16d51178525e89774ce9151651b6a0e99a

AstGen: add error for invalid string comparisons

These operations are allowed because the string literals are just pointers but they produce unexpected results. These errors prevent beginners from shooting themselves in the foot while still allowing advanced users to circumvent them if they desire to do so. Closes #8290

3 files changed, 43 insertions(+), 1 deletions(-)

src/AstGen.zig+13
......@@ -5628,6 +5628,14 @@ fn simpleBinOp(
56285628 const tree = astgen.tree;
56295629 const node_datas = tree.nodes.items(.data);
56305630
5631 if (op_inst_tag == .cmp_neq or op_inst_tag == .cmp_eq) {
5632 const node_tags = tree.nodes.items(.tag);
5633 const str = if (op_inst_tag == .cmp_eq) "==" else "!=";
5634 if (node_tags[node_datas[node].lhs] == .string_literal or
5635 node_tags[node_datas[node].rhs] == .string_literal)
5636 return astgen.failNode(node, "cannot compare strings with {s}", .{str});
5637 }
5638
56315639 const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node);
56325640 var line: u32 = undefined;
56335641 var column: u32 = undefined;
......@@ -6625,6 +6633,11 @@ fn switchExpr(
66256633 continue;
66266634 }
66276635
6636 for (case.ast.values) |val| {
6637 if (node_tags[val] == .string_literal)
6638 return astgen.failNode(val, "cannot switch on strings", .{});
6639 }
6640
66286641 if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) {
66296642 scalar_cases_len += 1;
66306643 } else {
test/cases/compile_errors/invalid_compare_string.zig created+29
......@@ -0,0 +1,29 @@
1comptime {
2 var a = "foo";
3 if (a == "foo") unreachable;
4}
5comptime {
6 var a = "foo";
7 if (a == ("foo")) unreachable; // intentionally allow
8}
9comptime {
10 var a = "foo";
11 switch (a) {
12 "foo" => unreachable,
13 else => {},
14 }
15}
16comptime {
17 var a = "foo";
18 switch (a) {
19 ("foo") => unreachable, // intentionally allow
20 else => {},
21 }
22}
23
24// error
25// backend=stage2
26// target=native
27//
28// :3:11: error: cannot compare strings with ==
29// :12:9: error: cannot switch on strings
test/cases/compile_errors/switch_on_slice.zig+1-1
......@@ -1,7 +1,7 @@
11pub export fn entry() void {
22 var a: [:0]const u8 = "foo";
33 switch (a) {
4 "--version", "version" => unreachable,
4 ("--version"), ("version") => unreachable,
55 else => {},
66 }
77}