diff --git a/compiler/builtins/src/std.rs b/compiler/builtins/src/std.rs index 35ab535a6a..0ec5e0e28a 100644 --- a/compiler/builtins/src/std.rs +++ b/compiler/builtins/src/std.rs @@ -4,9 +4,9 @@ use roc_module::symbol::Symbol; use roc_region::all::Region; use roc_types::builtin_aliases::{ bool_type, dec_type, dict_type, f32_type, f64_type, float_type, i128_type, i16_type, i32_type, - i64_type, i8_type, int_type, list_type, nat_type, num_type, ordering_type, pair_type, - result_type, set_type, str_type, str_utf8_byte_problem_type, u128_type, u16_type, u32_type, - u64_type, u8_type, + i64_type, i8_type, int_type, list_type, nat_type, num_type, ordering_type, result_type, + set_type, str_type, str_utf8_byte_problem_type, u128_type, u16_type, u32_type, u64_type, + u8_type, }; use roc_types::solved_types::SolvedType; use roc_types::subs::VarId; @@ -1056,12 +1056,18 @@ pub fn types() -> MutMap { Box::new(result_type(flex(TVAR1), list_was_empty.clone())), ); - // replace : List elem, Nat, elem -> Result (Pair (List elem) elem) [ OutOfBounds ]* + // replace : List elem, Nat, elem -> Result { list: List elem, value: elem } [ OutOfBounds ]* add_top_level_function_type!( Symbol::LIST_REPLACE, vec![list_type(flex(TVAR1)), nat_type(), flex(TVAR1)], Box::new(result_type( - pair_type(list_type(flex(TVAR1)), flex(TVAR1)), + SolvedType::Record { + fields: vec![ + ("list".into(), RecordField::Required(list_type(flex(TVAR1)))), + ("value".into(), RecordField::Required(flex(TVAR1))), + ], + ext: Box::new(SolvedType::EmptyRecord), + }, index_out_of_bounds )), ); diff --git a/compiler/can/src/builtins.rs b/compiler/can/src/builtins.rs index ae6375ada7..ee035c30cd 100644 --- a/compiler/can/src/builtins.rs +++ b/compiler/can/src/builtins.rs @@ -2304,14 +2304,13 @@ fn list_get(symbol: Symbol, var_store: &mut VarStore) -> Def { ) } -/// List.replace : List elem, Nat, elem -> Result (Pair (List elem) elem) [ OutOfBounds ]* +/// List.replace : List elem, Nat, elem -> Result { list: List elem, value: elem } [ OutOfBounds ]* /// /// List.replace : /// Attr (w | u | v) (List (Attr u a)), /// Attr * Int, /// Attr (u | v) a -/// -> Attr * (List (Attr u a)) -/// -> Attr * (Result (Pair (List (Attr u a)) Attr u a)) (Attr * [ OutOfBounds ]*)) +/// -> Attr * (Result { list: List (Attr u a), value: Attr u a } (Attr * [ OutOfBounds ]*)) fn list_replace(symbol: Symbol, var_store: &mut VarStore) -> Def { let arg_list = Symbol::ARG_1; let arg_index = Symbol::ARG_2; @@ -2320,13 +2319,13 @@ fn list_replace(symbol: Symbol, var_store: &mut VarStore) -> Def { let len_var = var_store.fresh(); let elem_var = var_store.fresh(); let list_arg_var = var_store.fresh(); - let ret_pair_var = var_store.fresh(); + let ret_record_var = var_store.fresh(); - // Perform a bounds check. If it passes, run LowLevel::ListReplace. + // Perform a bounds check. If it passes, run LowLevel::ListReplaceUnsafe. // Otherwise, return the list unmodified. let body = If { cond_var: bool_var, - branch_var: ret_pair_var, + branch_var: ret_record_var, branches: vec![( // if-condition no_region( @@ -2353,16 +2352,15 @@ fn list_replace(symbol: Symbol, var_store: &mut VarStore) -> Def { tag( "Ok", vec![ - // TODO: This should probably call get and then build the pair // List.replaceUnsafe list index elem RunLowLevel { - op: LowLevel::ListReplace, + op: LowLevel::ListReplaceUnsafe, args: vec![ (list_arg_var, Var(arg_list)), (len_var, Var(arg_index)), (elem_var, Var(arg_elem)), ], - ret_var: ret_pair_var, + ret_var: ret_record_var, }, ], var_store, @@ -2391,7 +2389,7 @@ fn list_replace(symbol: Symbol, var_store: &mut VarStore) -> Def { ], var_store, body, - ret_pair_var, + ret_record_var, ) } diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index b44f84767b..347bd2d044 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -13,7 +13,7 @@ use crate::llvm::build_list::{ self, allocate_list, empty_polymorphic_list, list_all, list_any, list_append, list_concat, list_contains, list_drop_at, list_find_unsafe, list_get_unsafe, list_join, list_keep_errs, list_keep_if, list_keep_oks, list_len, list_map, list_map2, list_map3, list_map4, - list_map_with_index, list_prepend, list_range, list_repeat, list_replace, list_reverse, + list_map_with_index, list_prepend, list_range, list_repeat, list_replace_unsafe, list_reverse, list_set, list_single, list_sort_with, list_sublist, list_swap, }; use crate::llvm::build_str::{ @@ -5653,12 +5653,12 @@ fn run_low_level<'a, 'ctx, 'env>( wrapper_struct, ) } - ListReplace => { + ListReplaceUnsafe => { let list = load_symbol(scope, &args[0]); let index = load_symbol(scope, &args[1]); let (element, element_layout) = load_symbol_and_layout(scope, &args[2]); - list_replace( + list_replace_unsafe( env, layout_ids, list, diff --git a/compiler/gen_llvm/src/llvm/build_list.rs b/compiler/gen_llvm/src/llvm/build_list.rs index fa709380a5..fd528bbac1 100644 --- a/compiler/gen_llvm/src/llvm/build_list.rs +++ b/compiler/gen_llvm/src/llvm/build_list.rs @@ -291,8 +291,8 @@ pub fn list_drop_at<'a, 'ctx, 'env>( ) } -/// List.replace : List elem, Nat, elem -> List elem -pub fn list_replace<'a, 'ctx, 'env>( +/// List.replace_unsafe : List elem, Nat, elem -> { list: List elem, value: elem } +pub fn list_replace_unsafe<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, _layout_ids: &mut LayoutIds<'a>, list: BasicValueEnum<'ctx>, diff --git a/compiler/gen_wasm/src/low_level.rs b/compiler/gen_wasm/src/low_level.rs index 8d71d3f484..b68d8e968a 100644 --- a/compiler/gen_wasm/src/low_level.rs +++ b/compiler/gen_wasm/src/low_level.rs @@ -260,7 +260,7 @@ impl<'a> LowLevelCall<'a> { _ => internal_error!("invalid storage for List"), }, - ListGetUnsafe | ListReplace | ListSet | ListSingle | ListRepeat | ListReverse + ListGetUnsafe | ListReplaceUnsafe | ListSet | ListSingle | ListRepeat | ListReverse | ListConcat | ListContains | ListAppend | ListPrepend | ListJoin | ListRange | ListMap | ListMap2 | ListMap3 | ListMap4 | ListMapWithIndex | ListKeepIf | ListWalk | ListWalkUntil | ListWalkBackwards | ListKeepOks | ListKeepErrs diff --git a/compiler/module/src/low_level.rs b/compiler/module/src/low_level.rs index 720382ce1a..ad10a1cbba 100644 --- a/compiler/module/src/low_level.rs +++ b/compiler/module/src/low_level.rs @@ -28,7 +28,7 @@ pub enum LowLevel { ListSet, ListSingle, ListRepeat, - ListReplace, + ListReplaceUnsafe, ListReverse, ListConcat, ListContains, diff --git a/compiler/mono/src/borrow.rs b/compiler/mono/src/borrow.rs index d8ed8fa610..d46ccbc8ee 100644 --- a/compiler/mono/src/borrow.rs +++ b/compiler/mono/src/borrow.rs @@ -935,7 +935,7 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] { match op { ListLen | StrIsEmpty | StrCountGraphemes => arena.alloc_slice_copy(&[borrowed]), ListSet => arena.alloc_slice_copy(&[owned, irrelevant, irrelevant]), - ListReplace => arena.alloc_slice_copy(&[owned, irrelevant, irrelevant]), + ListReplaceUnsafe => arena.alloc_slice_copy(&[owned, irrelevant, irrelevant]), ListGetUnsafe => arena.alloc_slice_copy(&[borrowed, irrelevant]), ListConcat => arena.alloc_slice_copy(&[owned, owned]), StrConcat => arena.alloc_slice_copy(&[owned, borrowed]), diff --git a/compiler/test_gen/src/gen_list.rs b/compiler/test_gen/src/gen_list.rs index ba8270808e..296f083e59 100644 --- a/compiler/test_gen/src/gen_list.rs +++ b/compiler/test_gen/src/gen_list.rs @@ -1710,7 +1710,7 @@ fn replace_unique_int_list() { r#" result = List.replace [ 12, 9, 7, 1, 5 ] 2 33 when result is - Ok (Pair newList _) -> newList + Ok {list, value} -> list Err _ -> [] "# ), @@ -1727,7 +1727,7 @@ fn replace_unique_int_list_get_old_value() { r#" result = List.replace [ 12, 9, 7, 1, 5 ] 2 33 when result is - Ok (Pair _ oldValue) -> oldValue + Ok {list, value} -> value Err _ -> -1 "# ),