Skip to content

std.mem.copy does not work if slices overlap #382

Description

@andrewrk

Zig's current implementation of std.mem.copy is this:

/// Copy all of source into dest at position 0.
/// dest.len must be >= source.len.
/// The memory areas must not overlap.
pub fn copy(comptime T: type, dest: []T, source: []const T) {
    for (source) |s, i| dest[i] = s;
}

"The memory areas must not overlap" is a pretty lame restriction, especially since the single branch it takes to make it work either way is a low cost. So this could be:

/// Copy all of source into dest at position 0.
/// dest.len must be >= source.len.
pub fn copy(comptime T: type, dest: []T, source: []const T) {
    if (usize(dest.ptr) < usize(source.ptr) or
        usize(source.ptr) + source.len <= usize(dest.ptr))
    {
        for (source) |s, i| dest[i] = s;
    } else {
        for (source) |s, i| dest[source.len - i] = source[source.len - i];
    }
}

If we want to have another function, copyAssumeNoOverlap with this branch optimized away, that's fine. We'd still need to add that assert though:

/// Copy all of source into dest at position 0.
/// dest.len must be >= source.len.
/// The memory areas must not overlap.
pub fn copyAssumeNoOverlap(comptime T: type, dest: []T, source: []const T) {
    assert(usize(dest.ptr) < usize(source.ptr) or usize(source.ptr) + source.len <= usize(dest.ptr));
    for (source) |s, i| dest[i] = s;
}

Now here's the problem:

  • usize(slice.ptr) does not work at compile time
  • std.mem.copy should work at compile time

At compile time we still have this concept of overlapping memory, but the way we want to check for overlapping memory doesn't work.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementSolving this issue will likely involve adding new logic or components to the codebase.

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions