mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 19:58:18 +00:00
Merge pull request #4701 from roc-lang/i4697
Fix concat of non-unique list with unique list
This commit is contained in:
commit
36eaed31e3
2 changed files with 42 additions and 1 deletions
|
@ -4,6 +4,8 @@ const UpdateMode = utils.UpdateMode;
|
|||
const mem = std.mem;
|
||||
const math = std.math;
|
||||
|
||||
const expect = std.testing.expect;
|
||||
|
||||
const EqFn = fn (?[*]u8, ?[*]u8) callconv(.C) bool;
|
||||
const CompareFn = fn (?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) u8;
|
||||
const Opaque = ?[*]u8;
|
||||
|
@ -770,7 +772,7 @@ pub fn listConcat(list_a: RocList, list_b: RocList, alignment: u32, element_widt
|
|||
// This first call must use mem.copy because the slices might overlap.
|
||||
const byte_count_a = list_a.len() * element_width;
|
||||
const byte_count_b = list_b.len() * element_width;
|
||||
mem.copy(u8, source_b[byte_count_a .. byte_count_a + byte_count_b], source_b[0..byte_count_b]);
|
||||
mem.copyBackwards(u8, source_b[byte_count_a .. byte_count_a + byte_count_b], source_b[0..byte_count_b]);
|
||||
@memcpy(source_b, source_a, byte_count_a);
|
||||
|
||||
// decrement list a.
|
||||
|
@ -854,3 +856,21 @@ pub fn listIsUnique(
|
|||
) callconv(.C) bool {
|
||||
return list.isEmpty() or list.isUnique();
|
||||
}
|
||||
|
||||
test "listConcat: non-unique with unique overlapping" {
|
||||
var nonUnique = RocList.fromSlice(u8, ([_]u8{1})[0..]);
|
||||
var bytes: [*]u8 = @ptrCast([*]u8, nonUnique.bytes);
|
||||
const ptr_width = @sizeOf(usize);
|
||||
const refcount_ptr = @ptrCast([*]isize, @alignCast(ptr_width, bytes) - ptr_width);
|
||||
utils.increfC(&refcount_ptr[0], 1);
|
||||
defer nonUnique.deinit(u8); // listConcat will dec the other refcount
|
||||
|
||||
var unique = RocList.fromSlice(u8, ([_]u8{ 2, 3, 4 })[0..]);
|
||||
defer unique.deinit(u8);
|
||||
|
||||
var concatted = listConcat(nonUnique, unique, 1, 1);
|
||||
var wanted = RocList.fromSlice(u8, ([_]u8{ 1, 2, 3, 4 })[0..]);
|
||||
defer wanted.deinit(u8);
|
||||
|
||||
try expect(concatted.eql(wanted));
|
||||
}
|
||||
|
|
|
@ -3561,6 +3561,27 @@ fn list_walk_from_until_sum() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn concat_unique_to_nonunique_overlapping_issue_4697() {
|
||||
assert_evals_to!(
|
||||
r#"
|
||||
# originalList is shared, but others is unique.
|
||||
# When we concat originalList with others, others should be re-used.
|
||||
|
||||
originalList = [1u8]
|
||||
others = [2u8, 3u8, 4u8]
|
||||
new = List.concat originalList others
|
||||
{a: originalList, b: new}
|
||||
"#,
|
||||
(
|
||||
RocList::from_slice(&[1u8]),
|
||||
RocList::from_slice(&[1u8, 2, 3, 4]),
|
||||
),
|
||||
(RocList<u8>, RocList<u8>)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn list_walk_from_even_prefix_sum() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue