File tree Expand file tree Collapse file tree 1 file changed +28
-4
lines changed Expand file tree Collapse file tree 1 file changed +28
-4
lines changed Original file line number Diff line number Diff line change @@ -3633,10 +3633,34 @@ test indexOfMinMax {
36333633}
36343634
36353635/// Exchanges contents of two memory locations.
3636- pub fn swap (comptime T : type , a : * T , b : * T ) void {
3637- const tmp = a .* ;
3638- a .* = b .* ;
3639- b .* = tmp ;
3636+ pub fn swap (comptime T : type , noalias a : * T , noalias b : * T ) void {
3637+ if (@inComptime ()) {
3638+ // In comptime, accessing bytes of values with no defined layout is a compile error.
3639+ const tmp = a .* ;
3640+ a .* = b .* ;
3641+ b .* = tmp ;
3642+ } else {
3643+ // Swapping in streaming nature from start to end instead of swapping
3644+ // everything in one step allows easier optimizations and less stack usage.
3645+ const a_bytes : []align (@alignOf (T )) u8 = @ptrCast (a );
3646+ const b_bytes : []align (@alignOf (T )) u8 = @ptrCast (b );
3647+ for (a_bytes , b_bytes ) | * ab , * bb | {
3648+ const tmp = ab .* ;
3649+ ab .* = bb .* ;
3650+ bb .* = tmp ;
3651+ }
3652+ }
3653+ }
3654+
3655+ test "swap works at comptime with types with no defined layout" {
3656+ comptime {
3657+ const T = struct { val : u64 };
3658+ var a : T = .{ .val = 0 };
3659+ var b : T = .{ .val = 1 };
3660+ swap (T , & a , & b );
3661+ try testing .expectEqual (T { .val = 1 }, a );
3662+ try testing .expectEqual (T { .val = 0 }, b );
3663+ }
36403664}
36413665
36423666inline fn reverseVector (comptime N : usize , comptime T : type , a : []T ) [N ]T {
You can’t perform that action at this time.
0 commit comments