简体   繁体   中英

SliceIndex trait bound unsatisfied error when trying to index into a vector in Rust

I have a struct:

pub struct SomeCollection<'a> {
    items: Vec<&'a SomeValue>,
    name_mapping: HashMap<&'a str, usize>,
    index_mapping: HashMap<&'a str, usize>
}

impl<'a> Index for SomeCollection<'a> {
    type Output = Option<&'a SomeValue>;

    fn index(&self, value_name: &str) -> &Self::Output {
        match self.name_mapping.get(value_name) {
            Some(index) => &self.items.get(index),
            None => match self.index_mapping.get(value_name) {
                Some(index) => &self.items.get(index),
                None => &None
            }
        }
    }
}

When I try compiling this code I get the following error:

error[E0277]: the trait bound `&usize: std::slice::SliceIndex<[&SomeValue]>` is not satisfied
  --> src\some_collection.rs:49:48
   |
49 |                 Some(index) => &self.items.get(index),
   |                                            ^^^ slice indices are of 
type `usize` or ranges of `usize`
   |
   = help: the trait `std::slice::SliceIndex<[&SomeValue]>` is not implemented for `&usize`

Rust seems to be telling me that I can't index into a vector with index , which is a usize . I'm not sure why I need to implement this trait as it should be implemented for the default vector already. Can anyone enlighten me as to the real reason I'm getting this error? There may be other errors in this code that haven't surfaced yet so please bear that in mind when answering.

Rust seems to be telling me that I can't index into a vector with index , which is a usize .

No, the compiler is telling you that you can't index a vector with an &usize .

the trait `std::slice::SliceIndex<[&SomeValue]>` is not implemented for `&usize`

Simply using *index instead will fix this particular problem. However, your code has other problems as well:

  • The Index trait needs a type parameter, eg &str in this case.
  • The index() method can generally only return a reference to data stored in the data structure you are indexing. Your code creates a temporary Option , which is not stored in the original data, and then tries to return a reference to that. If this is what you want to do, you need to define your own method (or trait) that returns the Option by value instead.

Maybe the compiler error is hard to understand, but at least it is accurate. It tells you, that index is a reference &usize however a Vec can only be indexed with the value usize . So all you have to do is dereference index .

Moreover, usually indexing panic s if the key/index could not be found. (That's why the standard library offers the Vec::get , and HashMap::get as separate methods alongside indexing, which do not panic but return None if the given key/index not in the collection.)

impl<'a> Index<&str> for SomeCollection<'a> {
    type Output = &'a SomeValue;

    fn index(&self, value_name: &str) -> &Self::Output {
        match self.name_mapping.get(value_name) {
            Some(index) => &self.items[*index],
            None => match self.index_mapping.get(value_name) {
                Some(index) => &self.items[*index],
                None => panic!("Missing key: {:?}", value_name),
            }
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM