| ... | @@ -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 }; |
| 12061 | | 12061 | |
| 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 | }; |
| 12064 | | 12068 | |
| 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 | } |
| 12222 | | 12226 | |
| 12223 | fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) !Type.ArrayInfo { | 12227 | fn 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 | } |
| 12253 | | 12257 | |
| 12254 | fn analyzeTupleMul( | 12258 | fn 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 }; |
| 12334 | | 12339 | |
| 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 | } |
| 12341 | | 12345 | |
| 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"); |
| 12343 | | 12364 | |
| 12344 | const result_len_u64 = std.math.mul(u64, lhs_info.len, factor) catch | 12365 | 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", .{}); |