| 1 | const base_array = [ |
| 2 | 1, |
| 3 | 2, |
| 4 | ] |
| 5 | |
| 6 | const base_strings = ['a', 'b'] |
| 7 | |
| 8 | struct Point { |
| 9 | x int |
| 10 | y int |
| 11 | } |
| 12 | |
| 13 | const base_points = [Point{1, 2}, Point{3, 4}] |
| 14 | |
| 15 | fn test_array_init_with_spread() { |
| 16 | complete := [...base_array, |
| 17 | 3, |
| 18 | 4, |
| 19 | ] |
| 20 | assert base_array == [1, 2] |
| 21 | assert complete == [1, 2, 3, 4] |
| 22 | assert complete.len == 4 |
| 23 | |
| 24 | second := [...base_array, 5, 6, 7] |
| 25 | assert second == [1, 2, 5, 6, 7] |
| 26 | } |
| 27 | |
| 28 | fn test_array_init_with_only_spread() { |
| 29 | mut copy := [...base_array] |
| 30 | assert copy == [1, 2] |
| 31 | copy << 99 |
| 32 | // spread produces an independent copy |
| 33 | assert base_array == [1, 2] |
| 34 | assert copy == [1, 2, 99] |
| 35 | } |
| 36 | |
| 37 | fn test_array_spread_strings() { |
| 38 | merged := [...base_strings, 'c', 'd'] |
| 39 | assert merged == ['a', 'b', 'c', 'd'] |
| 40 | } |
| 41 | |
| 42 | fn test_array_spread_structs() { |
| 43 | pts := [...base_points, Point{5, 6}] |
| 44 | assert pts.len == 3 |
| 45 | assert pts[0] == Point{1, 2} |
| 46 | assert pts[1] == Point{3, 4} |
| 47 | assert pts[2] == Point{5, 6} |
| 48 | } |
| 49 | |
| 50 | fn test_array_spread_local_var() { |
| 51 | v_arr := [7, 8, 9] |
| 52 | x := [...v_arr, 100] |
| 53 | assert v_arr == [7, 8, 9] |
| 54 | assert x == [7, 8, 9, 100] |
| 55 | } |
| 56 | |
| 57 | fn test_array_spread_chained() { |
| 58 | first := [...base_array, 3] |
| 59 | second := [...first, 4] |
| 60 | assert second == [1, 2, 3, 4] |
| 61 | } |
| 62 | |
| 63 | // Regression: `[...base]` should produce an independent deep copy. Modifying |
| 64 | // an inner []int after the spread must not affect the base. |
| 65 | fn test_array_spread_nested_arrays_are_deep_cloned() { |
| 66 | mut base := [[1, 2], [3, 4]] |
| 67 | mut copy := [...base] |
| 68 | copy[0] << 99 |
| 69 | assert base[0] == [1, 2] |
| 70 | assert copy[0] == [1, 2, 99] |
| 71 | } |
| 72 | |
| 73 | // Regression: assigning into a nested element of the spread copy must not |
| 74 | // mutate the base. Catches shallow-copy regressions in any backend that |
| 75 | // reuses the base's inner storage. |
| 76 | fn test_array_spread_nested_element_assignment_isolated() { |
| 77 | mut base := [[1, 2]] |
| 78 | mut b := [...base] |
| 79 | b[0][0] = 9 |
| 80 | assert base[0][0] == 1 |
| 81 | assert b[0][0] == 9 |
| 82 | } |
| 83 | |
| 84 | // Regression: indexing a spread literal inline (`[...base, 3][0]`) must keep |
| 85 | // the spread base in the AST instead of dropping it during parsing. |
| 86 | fn test_array_spread_indexed_inline() { |
| 87 | assert [...base_array, 3][0] == 1 |
| 88 | assert [...base_array, 3][1] == 2 |
| 89 | assert [...base_array, 3][2] == 3 |
| 90 | } |
| 91 | |
| 92 | // Regression: appended string variables must be cloned, matching the |
| 93 | // behavior of the regular `[s1, s2]` array-literal path. |
| 94 | fn test_array_spread_appended_string_variable() { |
| 95 | base := ['a', 'b'] |
| 96 | mut s := 'c' |
| 97 | arr := [...base, s] |
| 98 | s = 'mutated' |
| 99 | assert arr == ['a', 'b', 'c'] |
| 100 | } |
| 101 | |
| 102 | type Ints = []int |
| 103 | |
| 104 | // Regression: type-alias of an array should be accepted as a spread base. |
| 105 | fn test_array_spread_alias_base() { |
| 106 | a := Ints([10, 20, 30]) |
| 107 | b := [...a, 40] |
| 108 | assert b.len == 4 |
| 109 | assert b[0] == 10 |
| 110 | assert b[3] == 40 |
| 111 | c := [...a] |
| 112 | assert c.len == 3 |
| 113 | } |
| 114 | |