ProgramGuru

Slices and reference lifetimes

Slices and reference lifetimes

A report can use the first two marks without allocating a second collection. A slice is a borrowed view of consecutive elements. A lifetime describes how long a reference can validly be used; it does not keep the original data alive or allocate a copy.

What you’ll learn

  • Borrow a valid prefix without copying elements.
  • Explain what lifetime relationships require of the owners.

Slices and reference lifetimes in action

  1. Owner: [70, 80, 90]

    The first call selects the smaller of the collection length and two, then borrows that prefix.

    Owner: [70, 80, 90]
  2. Borrow prefix: [70, 80]

    No mark buffer is copied.

    Borrow prefix: [70, 80]
  3. View cannot outlive owner

    The empty slice has length zero, so its prefix is empty rather than out of bounds.

    View cannot outlive owner
The first call selects the smaller of the collection length and two, then borrows that prefix. No mark buffer is copied. The empty slice has length zero, so its prefix is empty rather than out of bounds. Preview remains valid while the original marks are available.

Slices and reference lifetimes explained

&marks[..2] borrows elements zero and one. A function returning a slice can tie its returned reference to the input reference. Rust’s lifetime elision rules infer that relationship here. Explicit lifetime annotations become useful when a signature has multiple relevant references; they describe relationships rather than changing how long values live.

Work through the Rust program

Save the complete source as main.rs in the Rust environment. No standard input is needed.

Rust 2024 · complete program

fn first_two(marks: &[i32]) -> &[i32] {
  &marks[..marks.len().min(2)]
}
fn main() {
  let marks = [70, 80, 90];
  let preview = first_two(&marks);
  println!("{preview:?}");
  println!("{:?}", first_two(&[]));
}

Expected output

[70, 80]
[]

Follow the execution

The first call selects the smaller of the collection length and two, then borrows that prefix. No mark buffer is copied. The empty slice has length zero, so its prefix is empty rather than out of bounds. Preview remains valid while the original marks are available.

Try the complete program in the Rust compiler. For tests, Cargo commands and local files, use the specified local environment.

When a signature needs an explicit lifetime

When a function may return either of two input references, an explicit lifetime parameter can describe their relationship. Here the result must remain within the validity of the input borrows. The annotation does not allocate text or keep an owner alive.

Rust 2024 · complete program

fn longer<'a>(a: &'a str, b: &'a str) -> &'a str {
  if a.len() >= b.len() { a } else { b }
}
fn main() {
  let first = String::from("Diya");
  let second = String::from("Saira");
  println!("{}", longer(&first, &second));
}

Expected output

Saira

Both Strings remain alive through printing. The helper compares byte lengths, selecting the five-byte name. If the selected borrow were used after its owner was dropped, the compiler would reject that use. This signature constrains the returned borrow even if a particular call could select the longer-lived input.

Try a small variation

Your task: Can first_two return a slice into a temporary array created inside the function?

Rust 2024 · complete program

fn first_two(marks: &[i32]) -> &[i32] {
  &marks[..marks.len().min(2)]
}
fn main() {
  let marks = [70, 80, 90];
  let preview = first_two(&marks);
  println!("{preview:?}");
  println!("{:?}", first_two(&[]));
}

Worked answer

No. That local array would be dropped when the function returns, leaving an invalid reference. Return owned data or borrow from an input that remains alive.

Mistakes and limits to recognize

Using a fixed ..2 slice on shorter input would panic, so the minimum calculation matters. String slices also require valid UTF-8 byte boundaries. Lifetime reasoning is about validity, not an estimate of how many milliseconds the operation takes.

Check your understanding

Can first_two return a slice into a temporary array created inside the function?
Choose one answer. You can try again.

Answer and explanation

No.

No. That local array would be dropped when the function returns, leaving an invalid reference. Return owned data or borrow from an input that remains alive.

Apply the rule

A reference points into a local String. What should happen if code tries to use it after that String is dropped?
Choose one answer. You can try again.

Answer and explanation

The compiler should reject that invalid use.

Rust checks that references remain valid for their uses.

Take the idea into your next program

No. That local array would be dropped when the function returns, leaving an invalid reference. Return owned data or borrow from an input that remains alive. Using a fixed ..2 slice on shorter input would panic, so the minimum calculation matters.

Further reading: the official Rust Book on slices and reference lifetimes.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: String, str and Unicode text →