diff --git a/compiler/can/src/builtins.rs b/compiler/can/src/builtins.rs index 6b85c8343d..6cf4146ab0 100644 --- a/compiler/can/src/builtins.rs +++ b/compiler/can/src/builtins.rs @@ -1557,6 +1557,7 @@ fn str_from_utf8_range(symbol: Symbol, var_store: &mut VarStore) -> Def { let start_var = var_store.fresh(); let start_bool = var_store.fresh(); + let add_var = var_store.fresh(); let body = If { cond_var: start_bool, @@ -1567,12 +1568,31 @@ fn str_from_utf8_range(symbol: Symbol, var_store: &mut VarStore) -> Def { args: vec![ ( start_var, - Access { - record_var: arg_record_var, - ext_var: var_store.fresh(), - field: "start".into(), - field_var: var_store.fresh(), - loc_expr: Box::new(no_region(Var(Symbol::ARG_2))), + RunLowLevel { + op: LowLevel::NumAdd, + args: vec![ + ( + add_var, + Access { + record_var: arg_record_var, + ext_var: var_store.fresh(), + field: "start".into(), + field_var: var_store.fresh(), + loc_expr: Box::new(no_region(Var(Symbol::ARG_2))), + }, + ), + ( + add_var, + Access { + record_var: arg_record_var, + ext_var: var_store.fresh(), + field: "count".into(), + field_var: var_store.fresh(), + loc_expr: Box::new(no_region(Var(Symbol::ARG_2))), + }, + ), + ], + ret_var: add_var, }, ), ( diff --git a/compiler/test_gen/src/gen_str.rs b/compiler/test_gen/src/gen_str.rs index 4cbb2d9942..e0978817f9 100644 --- a/compiler/test_gen/src/gen_str.rs +++ b/compiler/test_gen/src/gen_str.rs @@ -896,7 +896,7 @@ fn str_from_utf8_range_order_does_not_matter() { } #[test] -fn str_from_utf8_range_out_of_bounds() { +fn str_from_utf8_range_out_of_bounds_start_value() { assert_evals_to!( indoc!( r#" @@ -911,3 +911,37 @@ fn str_from_utf8_range_out_of_bounds() { RocStr ); } + +#[test] +fn str_from_utf8_range_count_too_high() { + assert_evals_to!( + indoc!( + r#" + bytes = Str.toUtf8 "hello" + when Str.fromUtf8Range bytes { start: 0, count: 6 } is + Ok _ -> "" + Err (BadUtf8 _ _) -> "" + Err OutOfBounds -> "out of bounds" + "# + ), + RocStr::from("out of bounds"), + RocStr + ); +} + +#[test] +fn str_from_utf8_range_count_too_high_for_start() { + assert_evals_to!( + indoc!( + r#" + bytes = Str.toUtf8 "hello" + when Str.fromUtf8Range bytes { start: 4, count: 3 } is + Ok _ -> "" + Err (BadUtf8 _ _) -> "" + Err OutOfBounds -> "out of bounds" + "# + ), + RocStr::from("out of bounds"), + RocStr + ); +}