Slices

Passing Slices to Functions

Functions that inspect or mutate contiguous sequences without taking ownership or growing the allocation should accept slice references (&[T], &mut [T], or &str) rather than references to specific container types (&Vec<T>, &[T; N], or &String).

Why &[T] and &str Beat &Vec<T> and &String

Through deref coercion (Vec<T>: Deref<Target = [T]> and String: Deref<Target = str>) and unsized coercion (&[T; N] -> &[T]), a single function taking &[T] or &str accepts every contiguous sequence representation in Rust without copying or allocating:

Caller Argument Type Passed to fn f(s: &[T]) Passed to fn f(v: &Vec<T>)
&Vec<T> Works (via Deref coercion) Works
&[T; N] (stack array) Works (via unsized coercion) Compile error (unless heap-allocated into a Vec)
&[T] (existing subslice) Works directly Compile error
&Box<[T]> / &Arc<[T]> Works (via Deref coercion) Compile error
&'static [T] (static slice) Works directly Compile error
One Function Signature (`fn process(data: &[i32])`) Accepts All Contiguous Sources:

  &Vec<i32>       ──(Deref)────┐
  &[i32; 4]       ──(Unsize)───┼──>  data: &[i32] (ptr + len)
  &Box<[i32]>     ──(Deref)────┤
  &slice[1..3]    ──(Direct)───┘

Accepting Shared Slices (&[T] and &str)

fn mean(samples: &[f64]) -> Option<f64> {
    if samples.is_empty() {
        return None;
    }
    let sum: f64 = samples.iter().sum();
    Some(sum / samples.len() as f64)
}

fn count_vowels(text: &str) -> usize {
    text.chars()
        .filter(|c| matches!(c.to_ascii_lowercase(), 'a' | 'e' | 'i' | 'o' | 'u'))
        .count()
}

fn main() {
    let heap_vec: Vec<f64> = vec![10.0, 20.0, 30.0, 40.0];
    let stack_arr: [f64; 3] = [5.0, 15.0, 25.0];

    // Pass a `Vec<f64>`, a fixed array `[f64; 3]`, and a subslice `&[f64]`:
    println!("Mean of Vec:      {:?}", mean(&heap_vec));
    println!("Mean of Array:    {:?}", mean(&stack_arr));
    println!("Mean of Subslice: {:?}", mean(&heap_vec[1..3]));

    // Pass a `String`, a string literal `&'static str`, and a substring slice:
    let owned_string = String::from("Rust Programming");
    println!("Vowels in String:  {}", count_vowels(&owned_string));
    println!("Vowels in literal: {}", count_vowels("Systems"));
    println!("Vowels in slice:   {}", count_vowels(&owned_string[0..4]));
}
Mean of Vec:      Some(25.0)
Mean of Array:    Some(15.0)
Mean of Subslice: Some(25.0)
Vowels in String:  4
Vowels in literal: 1
Vowels in slice:   1

Accepting Mutable Slices (&mut [T]) for In-Place Algorithms

When a function modifies elements in place—such as sorting, reversing, normalizing, or zeroing a buffer—without inserting or removing elements, accept &mut [T]:

fn clamp_in_place(values: &mut [i32], min: i32, max: i32) {
    for val in values {
        *val = (*val).clamp(min, max);
    }
}

fn main() {
    let mut readings = vec![-10, 15, 42, 120, 88];

    // Mutate only the middle 3 elements via a mutable subslice:
    clamp_in_place(&mut readings[1..4], 0, 100);
    println!("Middle clamped: {readings:?}");

    // Mutate the entire vector via deref coercion `&mut Vec<i32>` -> `&mut [i32]`:
    clamp_in_place(&mut readings, 0, 100);
    println!("All clamped:    {readings:?}");
}
Middle clamped: [-10, 15, 42, 100, 88]
All clamped:    [0, 15, 42, 100, 88]

Generic Slice Conversions with AsRef<[T]> and AsRef<str>

If you want callers to pass arguments either by reference or by value (or accept wrapper types that convert cheaply to a slice, such as String, &str, Vec<u8>, or &[u8]), you can make the parameter generic over AsRef<[T]> or AsRef<str> while delegating immediately to a non-generic inner function taking &[T] or &str to avoid monomorphization bloat:

fn checksum(bytes: impl AsRef<[u8]>) -> u32 {
    fn inner(slice: &[u8]) -> u32 {
        slice.iter().map(|&b| u32::from(b)).sum()
    }
    inner(bytes.as_ref())
}

fn main() {
    println!("From &str:   {}", checksum("ABC"));
    println!("From &[u8]:  {}", checksum(&[65u8, 66, 67]));
    println!("From Vec:    {}", checksum(vec![65u8, 66, 67]));
}
From &str:   198
From &[u8]:  198
From Vec:    198