@@ -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 };
0 commit comments