aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIntegratedQuantum <43880493+IntegratedQuantum@users.noreply.github.com>2022-12-11 20:41:42 +0100
committerGitHub <noreply@github.com>2022-12-11 14:41:42 -0500
commit15a6336bb40d413a7c7f140528268bb0397fdb41 (patch)
tree375e3eedd760a1172b5b303c6d67bbdbdb22045d /src
parentcd9af0f286725c19f5dc0335fb1db1ab8cf7af0d (diff)
downloadzig-15a6336bb40d413a7c7f140528268bb0397fdb41.tar.gz
zig-15a6336bb40d413a7c7f140528268bb0397fdb41.zip
Add a helpful note when using `**` on number types. (#13871)
Diffstat (limited to 'src')
-rw-r--r--src/Module.zig11
-rw-r--r--src/Sema.zig37
2 files changed, 40 insertions, 8 deletions
diff --git a/src/Module.zig b/src/Module.zig
index 074e25470c..57745a3276 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -2215,6 +2215,12 @@ pub const SrcLoc = struct {
assert(src_loc.file_scope.tree_loaded);
return nodeToSpan(tree, node);
},
+ .node_offset_main_token => |node_off| {
+ const tree = try src_loc.file_scope.getTree(gpa);
+ const node = src_loc.declRelativeToNodeIndex(node_off);
+ const main_token = tree.nodes.items(.main_token)[node];
+ return tokensToSpan(tree, main_token, main_token, main_token);
+ },
.node_offset_bin_op => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const node = src_loc.declRelativeToNodeIndex(node_off);
@@ -3009,6 +3015,10 @@ pub const LazySrcLoc = union(enum) {
/// from its containing Decl node AST index.
/// The Decl is determined contextually.
node_offset: TracedOffset,
+ /// The source location points to the main token of an AST node, found
+ /// by taking this AST node index offset from the containing Decl AST node.
+ /// The Decl is determined contextually.
+ node_offset_main_token: i32,
/// The source location points to the beginning of a struct initializer.
/// The Decl is determined contextually.
node_offset_initializer: i32,
@@ -3275,6 +3285,7 @@ pub const LazySrcLoc = union(enum) {
.byte_offset,
.token_offset,
.node_offset,
+ .node_offset_main_token,
.node_offset_initializer,
.node_offset_var_decl_ty,
.node_offset_var_decl_align,
diff --git a/src/Sema.zig b/src/Sema.zig
index 7109a3c385..3bad0b2b5f 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -12059,8 +12059,12 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
- const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs);
- const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs);
+ const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs) orelse {
+ return sema.fail(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(sema.mod)});
+ };
+ const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs) orelse {
+ return sema.fail(block, rhs_src, "expected indexable; found '{}'", .{rhs_ty.fmt(sema.mod)});
+ };
const resolved_elem_ty = t: {
var trash_block = block.makeSubBlock();
@@ -12220,7 +12224,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
return block.addAggregateInit(result_ty, element_refs);
}
-fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) !Type.ArrayInfo {
+fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) !?Type.ArrayInfo {
const operand_ty = sema.typeOf(operand);
switch (operand_ty.zigTypeTag()) {
.Array => return operand_ty.arrayInfo(),
@@ -12248,7 +12252,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins
},
else => {},
}
- return sema.fail(block, src, "expected indexable; found '{}'", .{operand_ty.fmt(sema.mod)});
+ return null;
}
fn analyzeTupleMul(
@@ -12330,16 +12334,33 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const lhs_ty = sema.typeOf(lhs);
const src: LazySrcLoc = inst_data.src();
const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
+ const operator_src: LazySrcLoc = .{ .node_offset_main_token = inst_data.src_node };
const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
- // In `**` rhs must be comptime-known, but lhs can be runtime-known
- const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, "array multiplication factor must be comptime-known");
-
if (lhs_ty.isTuple()) {
+ // In `**` rhs must be comptime-known, but lhs can be runtime-known
+ const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, "array multiplication factor must be comptime-known");
return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor);
}
- const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs);
+ // Analyze the lhs first, to catch the case that someone tried to do exponentiation
+ const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs) orelse {
+ const msg = msg: {
+ const msg = try sema.errMsg(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(sema.mod)});
+ errdefer msg.destroy(sema.gpa);
+ switch (lhs_ty.zigTypeTag()) {
+ .Int, .Float, .ComptimeFloat, .ComptimeInt, .Vector => {
+ try sema.errNote(block, operator_src, msg, "this operator multiplies arrays; use std.math.pow for exponentiation", .{});
+ },
+ else => {},
+ }
+ break :msg msg;
+ };
+ return sema.failWithOwnedErrorMsg(msg);
+ };
+
+ // In `**` rhs must be comptime-known, but lhs can be runtime-known
+ const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, "array multiplication factor must be comptime-known");
const result_len_u64 = std.math.mul(u64, lhs_info.len, factor) catch
return sema.fail(block, rhs_src, "operation results in overflow", .{});