Sitelet https://github.com/starkware-libs/cairo/commit/98110144096b36ec077e7891abaace567e6aff96
Skip to content

Commit 9811014

Browse files
feature(cairo): Support Span<T> destructuring via fixed-size array pa… (#9823)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent fd6e910 commit 9811014

6 files changed

Lines changed: 1872 additions & 20 deletions

File tree

‎corelib/src/test/language_features/match_test.cairo‎

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,29 @@ fn test_match_multienum_binding() {
1212
panic!("Match expression did not return - this should be unreachable");
1313
}
1414

15+
#[test]
16+
fn test_match_span_to_fixed_size_array() {
17+
let span: Span<u32> = array![10, 20, 30].span();
18+
19+
match span {
20+
[_a, _b, _c, _d] => { panic!("Expected 3 elements, but got 4"); },
21+
[_a, _b] => { panic!("Expected 3 elements, but got 2"); },
22+
[a, b, c] => { assert_eq!((*a, *b, *c), (10, 20, 30)); },
23+
_ => panic!("Expected 3 elements, but got a different pattern"),
24+
}
25+
}
26+
27+
#[test]
28+
fn test_match_span_empty_pattern() {
29+
let span: Span<u32> = array![].span();
30+
31+
match span {
32+
[_a] => { panic!("Expected 0 elements, but got 1"); },
33+
[] => {},
34+
_ => panic!("Expected 0 elements, but got a different count"),
35+
}
36+
}
37+
1538
#[test]
1639
fn test_match_extern_multilevel() {
1740
if true {
@@ -24,3 +47,59 @@ fn test_match_extern_multilevel() {
2447
}
2548
panic!("Match expression did not return - this should be unreachable");
2649
}
50+
51+
52+
#[test]
53+
fn test_match_span_inner_pattern_mismatch() {
54+
let matcher = |s: Array<Option<felt252>>| match s.span() {
55+
[Some(_)] => 1,
56+
[None] => 2,
57+
_ => 0,
58+
};
59+
60+
assert_eq!(matcher(array![Some(42)]), 1);
61+
assert_eq!(matcher(array![None]), 2);
62+
assert_eq!(matcher(array![Some(1), Some(2)]), 0);
63+
}
64+
65+
#[test]
66+
fn test_match_span_fsa_with_struct_catch_all() {
67+
let matcher = |s: Span<u32>| match s {
68+
[a] => *a,
69+
Span { snapshot: inner } => inner.len(),
70+
};
71+
72+
assert_eq!(matcher(array![42].span()), 42);
73+
assert_eq!(matcher(array![].span()), 0);
74+
assert_eq!(matcher(array![1, 2, 3].span()), 3);
75+
}
76+
77+
#[test]
78+
fn test_match_span_fsa_struct_between_sizes() {
79+
let matcher = |s: Span<u32>, val: u32| match (s, val) {
80+
([a], v) => *a + v,
81+
(Span { snapshot: inner }, 5) => 2 * inner.len(),
82+
([a, b], v) => *a + *b + v,
83+
([a, b, c], v) => *a + *b + *c + v,
84+
_ => 0,
85+
};
86+
87+
// `[a]` arm wins for size 1 regardless of `val`.
88+
assert_eq!(matcher(array![10].span(), 7), 17);
89+
assert_eq!(matcher(array![10].span(), 5), 15);
90+
91+
// Struct arm wins when `val == 5` and size != 1 (covers sizes outside `[a, b]` / `[a, b, c]`
92+
// too).
93+
assert_eq!(matcher(array![].span(), 5), 0);
94+
assert_eq!(matcher(array![1, 2].span(), 5), 4);
95+
assert_eq!(matcher(array![1, 2, 3].span(), 5), 6);
96+
assert_eq!(matcher(array![1, 2, 3, 4].span(), 5), 8);
97+
98+
// `[a, b]` and `[a, b, c]` arms win for their sizes when `val != 5`.
99+
assert_eq!(matcher(array![10, 20].span(), 7), 37);
100+
assert_eq!(matcher(array![10, 20, 30].span(), 7), 67);
101+
102+
// Wildcard arm — `val != 5` and size not in {1, 2, 3}.
103+
assert_eq!(matcher(array![].span(), 7), 0);
104+
assert_eq!(matcher(array![1, 2, 3, 4].span(), 7), 0);
105+
}

0 commit comments

Comments
 (0)