5

I'm trying to implement the Index trait for a simple trait, and I want to use it with usize. I added SliceIndex<[T], Output = T> so I can use T to index the slice inside A.

use std::ops::Index;
use std::slice::SliceIndex;

struct A <'a, T>{
    slice: &'a [T]
}

impl<'a, T: Index<T, Output = T> + SliceIndex<[T], Output = T>> Index<T>
    for A<'a, T>
{
    type Output = T;

    #[inline(always)]
    fn index(&self, index: T) -> &Self::Output {
        self.slice.index(index)
    }
}

fn main() {
    let mut aa: Vec<u64> = vec![0; 10];
    let coefficient_iterable = A{slice: &aa};
    println!("{}", coefficient_iterable[1usize]);
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=9564b39061cae3e19db14217c10b9d8a

But I get:

Error:

error[E0608]: cannot index into a value of type `A<'_, u64>`
  --> src/main.rs:22:20
   |
22 |     println!("{}", coefficient_iterable[1usize]);
   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0608`.
error: could not compile `playground` due to previous error

I have no idea why, since usize implements SliceIndex<[T]>.

0

1 Answer 1

9

Requiring T to be both Index and SliceIndex doesn't make sense because Index describes the behaviour of indexable containers, while SliceIndex is a bound you can put on a generic indexing type to make it more flexible.

You don't want to implement Index<T> because T here is the type of the items in the slice, not the type of the index. For the code in your main function to work you could just implement Index<usize>, but generically implementing Index<Idx> (where Idx: SliceIndex) gives more flexibility so you can use ranges too.

use std::ops::Index;
use std::slice::SliceIndex;

struct A<'a, T> {
    slice: &'a [T],
}

impl<'a, T, Idx> Index<Idx> for A<'a, T>
where
    Idx: SliceIndex<[T], Output = T>,
{
    type Output = T;

    #[inline(always)]
    fn index(&self, index: Idx) -> &Self::Output {
        self.slice.index(index)
    }
}

fn main() {
    let aa: Vec<u64> = vec![0; 10];
    let coefficient_iterable = A { slice: &aa };
    assert_eq!(coefficient_iterable[1], 0);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.