How is the `[]` operator on Vec/Slice implemented?

Is the [] operator on Vec/Slice supported via operator overloading? If so, does it overload the get_unchecked method?

operator[] uses Index in std::ops - Rust.

Vec::operator[]'s behavior is roughly equivlent to v.get(i).unwrap().

Vec gets that via deref coercion to the slice methods: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.get_unchecked

As for the operators, see https://doc.rust-lang.org/std/ops/index.html#traits.

2 Likes

Indexing on slices and arrays by usize is actually built-in (though they implement the traits as well), and does have at least one magical property compared to an Index trait implementation: it is considered pure and transparent in some sense and supports borrow-splitting "through" the indexing operation as a result.

// Works
fn foo(v: &mut [S]) {
    let one = &mut v[0].a;
    let two = &mut v[0].b;
    println!("{one} {two}");
}

// Fails
fn bar(mut v: Vec<S>) {
    let one = &mut v[0].a;
    let two = &mut v[0].b;
    println!("{one} {two}");
}

Playground.

5 Likes

No, that would be impossible. Doing so would allow causing UB by indexing out of bounds in safe code (since indexing isn't unsafe), which would be unsound.

1 Like

That's awesome tips! Another convincing reason to use Slice instead of Vec as function interfaces.

Thank everyone for discussions! It helps a lot.

Eh, definitely use &[_] instead of &Vec<_>, but in that case you don't need to split the borrows anyway, since they're shared. And there's a larger difference between &mut [_] and &mut Vec<_> that should guide your choice (do you want to be able to push, etc, or just edit the current elements?).

(And you can get a &mut [_] out of a &mut Vec<_> if you need the borrow splitting, or other ways around it more generally.)

4 Likes