From c10b25cf6e8a69b4c95ce9eeeb2ce29cda6ec85f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Geron?= Date: Thu, 19 Sep 2024 10:43:05 +1200 Subject: [PATCH] Fixes #7065 in List.dropAt, author: @bhansconnect --- crates/compiler/builtins/bitcode/src/list.zig | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/crates/compiler/builtins/bitcode/src/list.zig b/crates/compiler/builtins/bitcode/src/list.zig index e89b39c561..c95e6e8063 100644 --- a/crates/compiler/builtins/bitcode/src/list.zig +++ b/crates/compiler/builtins/bitcode/src/list.zig @@ -618,6 +618,16 @@ pub fn listDropAt( ) callconv(.C) RocList { const size = list.len(); const size_u64 = @as(u64, @intCast(size)); + + // NOTE + // we need to return an empty list explicitly, + // because we rely on the pointer field being null if the list is empty + // which also requires duplicating the utils.decref call to spend the RC token + if (size <= 1) { + list.decref(alignment, element_width, elements_refcounted, dec); + return RocList.empty(); + } + // If droping the first or last element, return a seamless slice. // For simplicity, do this by calling listSublist. // In the future, we can test if it is faster to manually inline the important parts here. @@ -638,25 +648,16 @@ pub fn listDropAt( // were >= than `size`, and we know `size` fits in usize. const drop_index: usize = @intCast(drop_index_u64); - if (elements_refcounted) { - const element = source_ptr + drop_index * element_width; - dec(element); - } - - // NOTE - // we need to return an empty list explicitly, - // because we rely on the pointer field being null if the list is empty - // which also requires duplicating the utils.decref call to spend the RC token - if (size < 2) { - list.decref(alignment, element_width, elements_refcounted, dec); - return RocList.empty(); - } - if (list.isUnique()) { - var i = drop_index; - const copy_target = source_ptr; + if (elements_refcounted) { + const element = source_ptr + drop_index * element_width; + dec(element); + } + + const copy_target = source_ptr + (drop_index * element_width); const copy_source = copy_target + element_width; - std.mem.copyForwards(u8, copy_target[i..size], copy_source[i..size]); + const copy_size = (size - drop_index - 1) * element_width; + std.mem.copyForwards(u8, copy_target[0..copy_size], copy_source[0..copy_size]); var new_list = list;