From e2509ddbe69a56bb1f4a56b46946b2a706d5aabe Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Fri, 2 Dec 2022 20:16:47 +0200 Subject: [PATCH] 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 --- src/AstGen.zig | 13 +++++++++ .../compile_errors/invalid_compare_string.zig | 29 +++++++++++++++++++ test/cases/compile_errors/switch_on_slice.zig | 2 +- 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 test/cases/compile_errors/invalid_compare_string.zig diff --git a/src/AstGen.zig b/src/AstGen.zig index b18d5503471e9a8a58be5b94712c5212baf6249e..1ec0cfa78f0ec3385be94b3bf22d45f8c54ddc24 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -5628,6 +5628,14 @@ fn simpleBinOp( const tree = astgen.tree; const node_datas = tree.nodes.items(.data); + if (op_inst_tag == .cmp_neq or op_inst_tag == .cmp_eq) { + const node_tags = tree.nodes.items(.tag); + const str = if (op_inst_tag == .cmp_eq) "==" else "!="; + if (node_tags[node_datas[node].lhs] == .string_literal or + node_tags[node_datas[node].rhs] == .string_literal) + return astgen.failNode(node, "cannot compare strings with {s}", .{str}); + } + const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node); var line: u32 = undefined; var column: u32 = undefined; @@ -6625,6 +6633,11 @@ fn switchExpr( continue; } + for (case.ast.values) |val| { + if (node_tags[val] == .string_literal) + return astgen.failNode(val, "cannot switch on strings", .{}); + } + if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) { scalar_cases_len += 1; } else { diff --git a/test/cases/compile_errors/invalid_compare_string.zig b/test/cases/compile_errors/invalid_compare_string.zig new file mode 100644 index 0000000000000000000000000000000000000000..a5c7f041a5649d9608ce6d65ec2b1f43c0864799 --- /dev/null +++ b/test/cases/compile_errors/invalid_compare_string.zig @@ -0,0 +1,29 @@ +comptime { + var a = "foo"; + if (a == "foo") unreachable; +} +comptime { + var a = "foo"; + if (a == ("foo")) unreachable; // intentionally allow +} +comptime { + var a = "foo"; + switch (a) { + "foo" => unreachable, + else => {}, + } +} +comptime { + var a = "foo"; + switch (a) { + ("foo") => unreachable, // intentionally allow + else => {}, + } +} + +// error +// backend=stage2 +// target=native +// +// :3:11: error: cannot compare strings with == +// :12:9: error: cannot switch on strings diff --git a/test/cases/compile_errors/switch_on_slice.zig b/test/cases/compile_errors/switch_on_slice.zig index b4644b132c7dbb1ad2fc2eec62623f3091c4e70c..c2b28f67abb931404b9bb5fa41cf606a1f622820 100644 --- a/test/cases/compile_errors/switch_on_slice.zig +++ b/test/cases/compile_errors/switch_on_slice.zig @@ -1,7 +1,7 @@ pub export fn entry() void { var a: [:0]const u8 = "foo"; switch (a) { - "--version", "version" => unreachable, + ("--version"), ("version") => unreachable, else => {}, } } -- 2.54.0