| ... | ... | @@ -22483,11 +22483,18 @@ fn ptrCastFull( |
| 22483 | 22483 | .slice => {}, |
| 22484 | 22484 | .many, .c, .one => break :len null, |
| 22485 | 22485 | } |
| 22486 | | // `null` means the operand is a runtime-known slice (so the length is runtime-known). |
| 22487 | | const opt_src_len: ?u64 = switch (src_info.flags.size) { |
| 22488 | | .one => 1, |
| 22489 | | .slice => src_len: { |
| 22490 | | const operand_val = try sema.resolveValue(operand) orelse break :src_len null; |
| 22486 | // A `null` length means the operand is a runtime-known slice (so the length is runtime-known). |
| 22487 | // `src_elem_type` is different from `src_info.child` if the latter is an array, to ensure we ignore sentinels. |
| 22488 | const src_elem_ty: Type, const opt_src_len: ?u64 = switch (src_info.flags.size) { |
| 22489 | .one => src: { |
| 22490 | const true_child: Type = .fromInterned(src_info.child); |
| 22491 | break :src switch (true_child.zigTypeTag(zcu)) { |
| 22492 | .array => .{ true_child.childType(zcu), true_child.arrayLen(zcu) }, |
| 22493 | else => .{ true_child, 1 }, |
| 22494 | }; |
| 22495 | }, |
| 22496 | .slice => src: { |
| 22497 | const operand_val = try sema.resolveValue(operand) orelse break :src .{ .fromInterned(src_info.child), null }; |
| 22491 | 22498 | if (operand_val.isUndef(zcu)) break :len .undef; |
| 22492 | 22499 | const slice_val = switch (operand_ty.zigTypeTag(zcu)) { |
| 22493 | 22500 | .optional => operand_val.optionalValue(zcu) orelse break :len .undef, |
| ... | ... | @@ -22496,14 +22503,13 @@ fn ptrCastFull( |
| 22496 | 22503 | }; |
| 22497 | 22504 | const slice_len_resolved = try sema.resolveLazyValue(.fromInterned(zcu.intern_pool.sliceLen(slice_val.toIntern()))); |
| 22498 | 22505 | if (slice_len_resolved.isUndef(zcu)) break :len .undef; |
| 22499 | | break :src_len slice_len_resolved.toUnsignedInt(zcu); |
| 22506 | break :src .{ .fromInterned(src_info.child), slice_len_resolved.toUnsignedInt(zcu) }; |
| 22500 | 22507 | }, |
| 22501 | 22508 | .many, .c => { |
| 22502 | 22509 | return sema.fail(block, src, "cannot infer length of slice from {s}", .{pointerSizeString(src_info.flags.size)}); |
| 22503 | 22510 | }, |
| 22504 | 22511 | }; |
| 22505 | 22512 | const dest_elem_ty: Type = .fromInterned(dest_info.child); |
| 22506 | | const src_elem_ty: Type = .fromInterned(src_info.child); |
| 22507 | 22513 | if (dest_elem_ty.toIntern() == src_elem_ty.toIntern()) { |
| 22508 | 22514 | break :len if (opt_src_len) |l| .{ .constant = l } else .equal_runtime_src_slice; |
| 22509 | 22515 | } |
| ... | ... | @@ -22519,7 +22525,7 @@ fn ptrCastFull( |
| 22519 | 22525 | const bytes = src_len * src_elem_size; |
| 22520 | 22526 | const dest_len = std.math.divExact(u64, bytes, dest_elem_size) catch switch (src_info.flags.size) { |
| 22521 | 22527 | .slice => return sema.fail(block, src, "slice length '{d}' does not divide exactly into destination elements", .{src_len}), |
| 22522 | | .one => return sema.fail(block, src, "type '{f}' does not divide exactly into destination elements", .{src_elem_ty.fmt(pt)}), |
| 22528 | .one => return sema.fail(block, src, "type '{f}' does not divide exactly into destination elements", .{Type.fromInterned(src_info.child).fmt(pt)}), |
| 22523 | 22529 | else => unreachable, |
| 22524 | 22530 | }; |
| 22525 | 22531 | break :len .{ .constant = dest_len }; |