Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions manual/src/snippets/slices.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ assert_eq([30, 40, 50, 60], my_list[3..=6]);
// Negative indices: Counting from the end of the list
assert_eq([80, 90], my_list[-3..-1]);
```

A range whose start lands after its end (for example `my_list[6..3]`) is out of
bounds and raises an error rather than returning a reversed or empty slice. This
holds for lists, strings, tuples and deques alike.
8 changes: 8 additions & 0 deletions ndc_stdlib/src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,14 @@ fn extract_vm_offset(index_value: &Value, size: usize) -> Result<VmOffset, VmErr
if let Some((start, end, inclusive)) = iter_ref.range_bounds() {
let from_idx = to_forward_index(start, size, true)?;
let to_idx = to_forward_index(end, size, true)?;
// Reject reversed ranges before widening an inclusive end, otherwise
// an off-by-one inclusive range like `1..=0` would survive the `+1`
// and silently produce an empty slice instead of an error.
if to_idx < from_idx {
Comment thread
timfennis marked this conversation as resolved.
Outdated
Comment thread
timfennis marked this conversation as resolved.
Outdated
return Err(VmError::native(format!(
"{from_idx}..{to_idx} out of bounds"
)));
}
let to_idx = if inclusive {
(to_idx + 1).min(size)
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// expect-error: 3..1 out of bounds
// A reversed range on a string used to panic with "attempt to subtract with
// overflow"; it must now error gracefully like list/tuple slices do.
"hello"[3..1]
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// expect-error: 1..0 out of bounds
// A reversed range on a deque used to panic with "attempt to subtract with
// overflow"; it must now error gracefully.
let d = Deque();
d.push_back(1);
d.push_back(2);
d.push_back(3);
d[1..0]
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// expect-error: 3..1 out of bounds
// Assigning into a reversed slice used to panic with "attempt to subtract with
// overflow"; it must now error gracefully.
let x = [1, 2, 3, 4];
x[3..1] = [9]
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// expect-error: 2..1 out of bounds
// An inclusive range whose start is after its end (off-by-one, so the `+1`
// widening would otherwise mask it) must error, not return an empty slice.
"hello"[2..=1]
Loading