diff options
| author | IntegratedQuantum <43880493+IntegratedQuantum@users.noreply.github.com> | 2022-12-11 20:41:42 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-12-11 14:41:42 -0500 |
| commit | 15a6336bb40d413a7c7f140528268bb0397fdb41 (patch) | |
| tree | 375e3eedd760a1172b5b303c6d67bbdbdb22045d /src | |
| parent | cd9af0f286725c19f5dc0335fb1db1ab8cf7af0d (diff) | |
| download | zig-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.zig | 11 | ||||
| -rw-r--r-- | src/Sema.zig | 37 |
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", .{}); |
