Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
277 views
in Technique[技术] by (71.8m points)

rust - What is the return type of the indexing operation?

I am trying, quite unsuccessfully, to play around with slices.

I have reduced my first issue to:

fn at<'a, T>(slice: &'a [T], index: usize) -> &'a T {
    let item = slice[index];
    item
}

It is my expectation that the return type of slice[index] be a reference, given the documentation:

pub trait Index<Index> {
    type Output;
    fn index(&'a self, index: &Index) -> &'a <Self as Index<Index>>::Output;
//                                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}

However, the compiler gives me an error:

error[E0308]: mismatched types
 --> src/main.rs:3:5
  |
3 |     item
  |     ^^^^ expected reference, found type parameter
  |
  = note: expected type `&'a T`
             found type `T`

Which I interpret as meaning that the type of item does not match the return type of the function (I introduced item solely for debugging purpose, to split expression evaluation from return).

If I switch the return type to T, which is the type of item, I get another error message:

error[E0508]: cannot move out of type `[T]`, a non-copy slice
 --> src/main.rs:2:16
  |
2 |     let item = slice[index];
  |                ^^^^^^^^^^^^
  |                |
  |                cannot move out of here
  |                help: consider using a reference instead: `&slice[index]`

After tinkering a bit, I found two work-arounds:

fn at<'a, T>(slice: &'a [T], index: usize) -> &'a T {
    &slice[index]
//  ^
}

fn at<'a, T>(slice: &'a [T], index: usize) -> &'a T {
    let ref item = slice[index];
//      ^~~
    item
}

forcing the type to be a reference does the trick.

Why are these shenanigans necessary in the first place? Am I doing something wrong?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is a bit of helpful ergonomics that the compiler does for you in order to make the code look a bit nicer.

The return value of the Index trait is a reference, but the compiler automatically inserts a dereference for you when you use the sugared syntax []. Most other languages would just return the item from the array (copying it or returning another reference to the object, whatever is appropriate).

Due to Rust's importance of move / copy semantics, you can't always make a copy a value, so in those cases, you will usually use a &:

let items = &[1u8, 2, 3, 4];

let a: u8 = items[0];
let a: u8 = *items.index(&0); // Equivalent of above

let b: &u8 = &items[0];
let b: &u8 = &*items.index(&0); // Equivalent of above

Note that the indexing value is also automatically taken by reference, similar to the automatic dereference.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...