Skip to content

Conversation

@d0cd
Copy link
Collaborator

@d0cd d0cd commented Jan 12, 2026

Motivation

This PR adds array slicing and concatenation support to Leo, enabling more expressive and convenient array manipulation.

Array Slicing allows extracting a contiguous portion of an array using Rust-like syntax:

let arr: [u32; 8] = [0u32, 1u32, 2u32, 3u32, 4u32, 5u32, 6u32, 7u32];
let a: [u32; 3] = arr[2..5];    // [2, 3, 4] - exclusive end
let b: [u32; 4] = arr[2..=5];   // [2, 3, 4, 5] - inclusive end
let c: [u32; 5] = arr[3..];     // [3, 4, 5, 6, 7] - slice to end
let d: [u32; 4] = arr[..4];     // [0, 1, 2, 3] - slice from start
let e: [u32; 8] = arr[..];      // full copy

Array Concatenation allows combining two arrays with matching element types using the + operator:

let a: [u32; 2] = [1u32, 2u32];
let b: [u32; 2] = [3u32, 4u32];
let c: [u32; 4] = a + b;        // [1, 2, 3, 4]
let d: [u32; 6] = a + b + a;    // chained concatenation
let e: [u32; 4] = a[0..1] + b;  // slice then concatenate

Both features are resolved at compile time - slices and concatenations are expanded to individual element accesses, ensuring no runtime overhead.

Test Plan

Slicing Tests:

Test Description
slice_basic.leo Basic arr[2..5] exclusive end slice
slice_inclusive.leo Inclusive arr[2..=5] slice
slice_from_start.leo Open-start arr[..5] slice
slice_to_end.leo Open-end arr[3..] slice
slice_full.leo Full slice arr[..]
slice_with_variables.leo Const variable bounds
slice_out_of_bounds_fail.leo Error: bounds exceed array length
slice_invalid_range_fail.leo Error: start > end

Concatenation Tests:

Test Description
array_concat.leo Basic a + b, nested arrays, different sizes
array_concat_chained.leo Chained a + b + c
array_concat_with_slice.leo Combined a[0..2] + b[2..4]
array_concat_type_mismatch_fail.leo Error: mismatched element types

Related PRs

@d0cd
Copy link
Collaborator Author

d0cd commented Jan 16, 2026

Self-Review Finding

Found one bug that should be fixed:

BUG: Empty slices pass type checking but fail at runtime

Location: compiler/passes/src/type_checking/ast.rs (around line 536)

Empty slices like arr[5..5] pass type checking but fail in the interpreter due to inconsistent boundary checks:

Component Check Allows start == end?
Type checker end < start Yes (produces 0-length slice)
Interpreter end <= start No (returns None, causing runtime error)

Fix: Change the type checker to reject start == end:

// Before
if end < start {
    self.emit_err(TypeCheckerError::slice_range_invalid(start, end, input.span()));

// After  
if end <= start {
    self.emit_err(TypeCheckerError::slice_range_invalid(start, end, input.span()));

Consider adding a test case like slice_empty_fail.leo with arr[5..5] to verify the fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants