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
This commit is contained in:
Veikka Tuominen 2022-12-02 20:16:47 +02:00
parent 0e38cc16d5
commit e2509ddbe6
3 changed files with 43 additions and 1 deletions

View File

@ -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 {

View File

@ -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

View File

@ -1,7 +1,7 @@
pub export fn entry() void {
var a: [:0]const u8 = "foo";
switch (a) {
"--version", "version" => unreachable,
("--version"), ("version") => unreachable,
else => {},
}
}