¿Cuál es el tipo de devolución de la operación de indexación?

Intento, sin éxito, jugar con rebanadas.

Reduje mi primer número a:

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

Es mi expectativa que el tipo de devolución de slice[index] sea ​​una referencia, dada la documentación :

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

Sin embargo, el comstackdor me da un 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` 

Lo interpreto como que significa que el tipo de item no coincide con el tipo de devolución de la función (introduje el item únicamente para fines de depuración, para dividir la evaluación de expresión de la devolución).

Si cambio el tipo de devolución a T , que es el tipo de item , recibo otro mensaje de error:

 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]` 

Después de retocar un poco, encontré dos soluciones alternativas:

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

forzar el tipo a ser una referencia hace el truco.

¿Por qué son estas travesuras necesarias en primer lugar? ¿Estoy haciendo algo mal?

Este es un poco de ergonomía útil que el comstackdor hace por usted para hacer que el código se vea un poco mejor.

El valor de retorno del rasgo del Index es una referencia, pero el comstackdor inserta automáticamente una desreferencia cuando usa la syntax azucarada [] . La mayoría de los otros idiomas simplemente devolverían el artículo de la matriz (copiándolo o devolviendo otra referencia al objeto, lo que sea apropiado).

Debido a la importancia de la semántica de mover / copiar de Rust, no siempre se puede hacer una copia de un valor, por lo que en esos casos, generalmente usará un & :

 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 

Tenga en cuenta que el valor de indexación también se toma automáticamente por referencia, similar a la desreferencia automática.

No, estás haciendo todo correctamente. Mientras que el método index() devuelve una referencia, cuando se invoca en una operación de indexación, su resultado se desreferencia automáticamente. Esto se hace para que la indexación sea más natural: en cada idioma donde exista algún tipo de operador de indexación (principalmente C y C ++), devuelve valores en sí mismos, no las referencias en contenedores.

Para obtener una referencia en la colección, debe aplicar un operador de referencia explícitamente (como en su primera “solución alternativa”) o utilizar un patrón de referencia (como en el segundo).