authorgravatar for jahe788@gmail.comIntegratedQuantum <jahe788@gmail.com> 2022-12-11 20:41:42+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-12-11 14:41:42-05:00
log15a6336bb40d413a7c7f140528268bb0397fdb41
tree375e3eedd760a1172b5b303c6d67bbdbdb22045d
parentcd9af0f286725c19f5dc0335fb1db1ab8cf7af0d
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Add a helpful note when using `**` on number types. (#13871)


3 files changed, 50 insertions(+), 8 deletions(-)

src/Module.zig+11
...@@ -2215,6 +2215,12 @@ pub const SrcLoc = struct {...@@ -2215,6 +2215,12 @@ pub const SrcLoc = struct {
2215 assert(src_loc.file_scope.tree_loaded);2215 assert(src_loc.file_scope.tree_loaded);
2216 return nodeToSpan(tree, node);2216 return nodeToSpan(tree, node);
2217 },2217 },
2218 .node_offset_main_token => |node_off| {
2219 const tree = try src_loc.file_scope.getTree(gpa);
2220 const node = src_loc.declRelativeToNodeIndex(node_off);
2221 const main_token = tree.nodes.items(.main_token)[node];
2222 return tokensToSpan(tree, main_token, main_token, main_token);
2223 },
2218 .node_offset_bin_op => |node_off| {2224 .node_offset_bin_op => |node_off| {
2219 const tree = try src_loc.file_scope.getTree(gpa);2225 const tree = try src_loc.file_scope.getTree(gpa);
2220 const node = src_loc.declRelativeToNodeIndex(node_off);2226 const node = src_loc.declRelativeToNodeIndex(node_off);
...@@ -3009,6 +3015,10 @@ pub const LazySrcLoc = union(enum) {...@@ -3009,6 +3015,10 @@ pub const LazySrcLoc = union(enum) {
3009 /// from its containing Decl node AST index.3015 /// from its containing Decl node AST index.
3010 /// The Decl is determined contextually.3016 /// The Decl is determined contextually.
3011 node_offset: TracedOffset,3017 node_offset: TracedOffset,
3018 /// The source location points to the main token of an AST node, found
3019 /// by taking this AST node index offset from the containing Decl AST node.
3020 /// The Decl is determined contextually.
3021 node_offset_main_token: i32,
3012 /// The source location points to the beginning of a struct initializer.3022 /// The source location points to the beginning of a struct initializer.
3013 /// The Decl is determined contextually.3023 /// The Decl is determined contextually.
3014 node_offset_initializer: i32,3024 node_offset_initializer: i32,
...@@ -3275,6 +3285,7 @@ pub const LazySrcLoc = union(enum) {...@@ -3275,6 +3285,7 @@ pub const LazySrcLoc = union(enum) {
3275 .byte_offset,3285 .byte_offset,
3276 .token_offset,3286 .token_offset,
3277 .node_offset,3287 .node_offset,
3288 .node_offset_main_token,
3278 .node_offset_initializer,3289 .node_offset_initializer,
3279 .node_offset_var_decl_ty,3290 .node_offset_var_decl_ty,
3280 .node_offset_var_decl_align,3291 .node_offset_var_decl_align,
src/Sema.zig+29-8
...@@ -12059,8 +12059,12 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12059,8 +12059,12 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12059 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };12059 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
12060 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };12060 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
1206112061
12062 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs);12062 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs) orelse {
12063 const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs);12063 return sema.fail(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(sema.mod)});
12064 };
12065 const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs) orelse {
12066 return sema.fail(block, rhs_src, "expected indexable; found '{}'", .{rhs_ty.fmt(sema.mod)});
12067 };
1206412068
12065 const resolved_elem_ty = t: {12069 const resolved_elem_ty = t: {
12066 var trash_block = block.makeSubBlock();12070 var trash_block = block.makeSubBlock();
...@@ -12220,7 +12224,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12220,7 +12224,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12220 return block.addAggregateInit(result_ty, element_refs);12224 return block.addAggregateInit(result_ty, element_refs);
12221}12225}
1222212226
12223fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) !Type.ArrayInfo {12227fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) !?Type.ArrayInfo {
12224 const operand_ty = sema.typeOf(operand);12228 const operand_ty = sema.typeOf(operand);
12225 switch (operand_ty.zigTypeTag()) {12229 switch (operand_ty.zigTypeTag()) {
12226 .Array => return operand_ty.arrayInfo(),12230 .Array => return operand_ty.arrayInfo(),
...@@ -12248,7 +12252,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins...@@ -12248,7 +12252,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins
12248 },12252 },
12249 else => {},12253 else => {},
12250 }12254 }
12251 return sema.fail(block, src, "expected indexable; found '{}'", .{operand_ty.fmt(sema.mod)});12255 return null;
12252}12256}
1225312257
12254fn analyzeTupleMul(12258fn analyzeTupleMul(
...@@ -12330,16 +12334,33 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -12330,16 +12334,33 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
12330 const lhs_ty = sema.typeOf(lhs);12334 const lhs_ty = sema.typeOf(lhs);
12331 const src: LazySrcLoc = inst_data.src();12335 const src: LazySrcLoc = inst_data.src();
12332 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };12336 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
12337 const operator_src: LazySrcLoc = .{ .node_offset_main_token = inst_data.src_node };
12333 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };12338 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
1233412339
12335 // In `**` rhs must be comptime-known, but lhs can be runtime-known
12336 const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, "array multiplication factor must be comptime-known");
12337
12338 if (lhs_ty.isTuple()) {12340 if (lhs_ty.isTuple()) {
12341 // In `**` rhs must be comptime-known, but lhs can be runtime-known
12342 const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, "array multiplication factor must be comptime-known");
12339 return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor);12343 return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor);
12340 }12344 }
1234112345
12342 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs);12346 // Analyze the lhs first, to catch the case that someone tried to do exponentiation
12347 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs) orelse {
12348 const msg = msg: {
12349 const msg = try sema.errMsg(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(sema.mod)});
12350 errdefer msg.destroy(sema.gpa);
12351 switch (lhs_ty.zigTypeTag()) {
12352 .Int, .Float, .ComptimeFloat, .ComptimeInt, .Vector => {
12353 try sema.errNote(block, operator_src, msg, "this operator multiplies arrays; use std.math.pow for exponentiation", .{});
12354 },
12355 else => {},
12356 }
12357 break :msg msg;
12358 };
12359 return sema.failWithOwnedErrorMsg(msg);
12360 };
12361
12362 // In `**` rhs must be comptime-known, but lhs can be runtime-known
12363 const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, "array multiplication factor must be comptime-known");
1234312364
12344 const result_len_u64 = std.math.mul(u64, lhs_info.len, factor) catch12365 const result_len_u64 = std.math.mul(u64, lhs_info.len, factor) catch
12345 return sema.fail(block, rhs_src, "operation results in overflow", .{});12366 return sema.fail(block, rhs_src, "operation results in overflow", .{});
test/cases/compile_errors/array_mult_with_number_type.zig created+10
...@@ -0,0 +1,10 @@
1export fn entry(base: f32, exponent: f32) f32 {
2 return base ** exponent;
3}
4
5// error
6// backend=stage2
7// target=native
8//
9// :2:12: error: expected indexable; found 'f32'
10// :2:17: note: this operator multiplies arrays; use std.math.pow for exponentiation
\ No newline at end of file