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