| ... | ... | @@ -12178,17 +12178,21 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12178 | 12178 | const rhs_ty = sema.typeOf(rhs); |
| 12179 | 12179 | const src = inst_data.src(); |
| 12180 | 12180 | |
| 12181 | | if (lhs_ty.isTuple() and rhs_ty.isTuple()) { |
| 12181 | const lhs_is_tuple = lhs_ty.isTuple(); |
| 12182 | const rhs_is_tuple = rhs_ty.isTuple(); |
| 12183 | if (lhs_is_tuple and rhs_is_tuple) { |
| 12182 | 12184 | return sema.analyzeTupleCat(block, inst_data.src_node, lhs, rhs); |
| 12183 | 12185 | } |
| 12184 | 12186 | |
| 12185 | 12187 | const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; |
| 12186 | 12188 | const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; |
| 12187 | 12189 | |
| 12188 | | const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs) orelse { |
| 12190 | const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, rhs_ty) orelse lhs_info: { |
| 12191 | if (lhs_is_tuple) break :lhs_info @as(Type.ArrayInfo, undefined); |
| 12189 | 12192 | return sema.fail(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(sema.mod)}); |
| 12190 | 12193 | }; |
| 12191 | | const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs) orelse { |
| 12194 | const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs, lhs_ty) orelse { |
| 12195 | assert(!rhs_is_tuple); |
| 12192 | 12196 | return sema.fail(block, rhs_src, "expected indexable; found '{}'", .{rhs_ty.fmt(sema.mod)}); |
| 12193 | 12197 | }; |
| 12194 | 12198 | |
| ... | ... | @@ -12258,8 +12262,16 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12258 | 12262 | break :p null; |
| 12259 | 12263 | }; |
| 12260 | 12264 | |
| 12261 | | const runtime_src = if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| rs: { |
| 12262 | | if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val| { |
| 12265 | const runtime_src = if (switch (lhs_ty.zigTypeTag()) { |
| 12266 | .Array, .Struct => try sema.resolveMaybeUndefVal(lhs), |
| 12267 | .Pointer => try sema.resolveDefinedValue(block, lhs_src, lhs), |
| 12268 | else => unreachable, |
| 12269 | }) |lhs_val| rs: { |
| 12270 | if (switch (rhs_ty.zigTypeTag()) { |
| 12271 | .Array, .Struct => try sema.resolveMaybeUndefVal(rhs), |
| 12272 | .Pointer => try sema.resolveDefinedValue(block, rhs_src, rhs), |
| 12273 | else => unreachable, |
| 12274 | }) |rhs_val| { |
| 12263 | 12275 | const lhs_sub_val = if (lhs_ty.isSinglePointer()) |
| 12264 | 12276 | (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).? |
| 12265 | 12277 | else |
| ... | ... | @@ -12274,18 +12286,24 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12274 | 12286 | const element_vals = try sema.arena.alloc(Value, final_len_including_sent); |
| 12275 | 12287 | var elem_i: usize = 0; |
| 12276 | 12288 | while (elem_i < lhs_len) : (elem_i += 1) { |
| 12277 | | const elem_val = try lhs_sub_val.elemValue(sema.mod, sema.arena, elem_i); |
| 12278 | | const elem_val_inst = try sema.addConstant(lhs_info.elem_type, elem_val); |
| 12289 | const lhs_elem_i = elem_i; |
| 12290 | const elem_ty = if (lhs_is_tuple) lhs_ty.structFieldType(lhs_elem_i) else lhs_info.elem_type; |
| 12291 | const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i) else Value.initTag(.unreachable_value); |
| 12292 | const elem_val = if (elem_default_val.tag() == .unreachable_value) try lhs_sub_val.elemValue(sema.mod, sema.arena, lhs_elem_i) else elem_default_val; |
| 12293 | const elem_val_inst = try sema.addConstant(elem_ty, elem_val); |
| 12279 | 12294 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded); |
| 12280 | | const coereced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, ""); |
| 12281 | | element_vals[elem_i] = coereced_elem_val; |
| 12295 | const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, ""); |
| 12296 | element_vals[elem_i] = coerced_elem_val; |
| 12282 | 12297 | } |
| 12283 | 12298 | while (elem_i < result_len) : (elem_i += 1) { |
| 12284 | | const elem_val = try rhs_sub_val.elemValue(sema.mod, sema.arena, elem_i - lhs_len); |
| 12285 | | const elem_val_inst = try sema.addConstant(lhs_info.elem_type, elem_val); |
| 12299 | const rhs_elem_i = elem_i - lhs_len; |
| 12300 | const elem_ty = if (rhs_is_tuple) rhs_ty.structFieldType(rhs_elem_i) else rhs_info.elem_type; |
| 12301 | const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i) else Value.initTag(.unreachable_value); |
| 12302 | const elem_val = if (elem_default_val.tag() == .unreachable_value) try rhs_sub_val.elemValue(sema.mod, sema.arena, rhs_elem_i) else elem_default_val; |
| 12303 | const elem_val_inst = try sema.addConstant(elem_ty, elem_val); |
| 12286 | 12304 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded); |
| 12287 | | const coereced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, ""); |
| 12288 | | element_vals[elem_i] = coereced_elem_val; |
| 12305 | const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, ""); |
| 12306 | element_vals[elem_i] = coerced_elem_val; |
| 12289 | 12307 | } |
| 12290 | 12308 | if (res_sent_val) |sent_val| { |
| 12291 | 12309 | element_vals[result_len] = sent_val; |
| ... | ... | @@ -12350,7 +12368,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12350 | 12368 | return block.addAggregateInit(result_ty, element_refs); |
| 12351 | 12369 | } |
| 12352 | 12370 | |
| 12353 | | fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) !?Type.ArrayInfo { |
| 12371 | fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref, peer_ty: Type) !?Type.ArrayInfo { |
| 12354 | 12372 | const operand_ty = sema.typeOf(operand); |
| 12355 | 12373 | switch (operand_ty.zigTypeTag()) { |
| 12356 | 12374 | .Array => return operand_ty.arrayInfo(), |
| ... | ... | @@ -12376,6 +12394,16 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins |
| 12376 | 12394 | .C => {}, |
| 12377 | 12395 | } |
| 12378 | 12396 | }, |
| 12397 | .Struct => { |
| 12398 | if (operand_ty.isTuple() and peer_ty.isIndexable()) { |
| 12399 | assert(!peer_ty.isTuple()); |
| 12400 | return .{ |
| 12401 | .elem_type = peer_ty.elemType2(), |
| 12402 | .sentinel = null, |
| 12403 | .len = operand_ty.arrayLen(), |
| 12404 | }; |
| 12405 | } |
| 12406 | }, |
| 12379 | 12407 | else => {}, |
| 12380 | 12408 | } |
| 12381 | 12409 | return null; |
| ... | ... | @@ -12470,7 +12498,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12470 | 12498 | } |
| 12471 | 12499 | |
| 12472 | 12500 | // Analyze the lhs first, to catch the case that someone tried to do exponentiation |
| 12473 | | const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs) orelse { |
| 12501 | const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, lhs_ty) orelse { |
| 12474 | 12502 | const msg = msg: { |
| 12475 | 12503 | const msg = try sema.errMsg(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(sema.mod)}); |
| 12476 | 12504 | errdefer msg.destroy(sema.gpa); |