Abstract
Currently the compiler does not emit a clear message when specific operator traits are not implemented.
Example
use std::collections::HashMap;
use std::ops::{Index, IndexMut};
struct Foo {
pub x: u64,
}
impl<'a> Index<&'a u64> for Foo {
type Output = u64;
fn index<'b>(&'b self, _index: &'a u64) -> &'b u64 {
&self.x
}
}
impl<'a> IndexMut<&'a u64> for Foo {
fn index_mut<'b>(&'b mut self, _index: &'a u64) -> &'b mut u64 {
&mut self.x
}
}
fn main() {
let mut foo = Foo{x: 1};
let pos: u64 = 1;
*(&mut foo[&pos]) = 2;
let mut map: HashMap<u64, u64> = HashMap::new();
*(&mut map[&pos]) = 2;
}
Foo
implements the IndexMut
trait similar to the one which a newcomers would expect from HashMap
. The shown code works perfectly. Now let’s have a look at the error that rustc
emits for our wrong usage of the hash map:
src/main.rs:29:12: 29:21 error: cannot borrow immutable indexed content as mutable
src/main.rs:29 *(&mut map[&pos]) = 2;
^~~~~~~~~
This is very similar to what the borrow checker usually tells us when there is an error. The message does not contain any indicator that HashMap
does not implement the relevant operator. This makes it very hard to figure out why the shown code is not working. Clearly someone could look at the API documentation of HashMap
but when you expect that a type implements an operator, you usually look for another reason. In this case, community websites like the Rust user forum or StackOverflow are required to get the right hint.
To make it easier for users to get a the right hint, the following error would be more helpful:
src/main.rs:29:12: 29:21 error: indexing operation in a mutual context is not possible here because HashMap does not implement IndexMut
src/main.rs:29 *(&mut map[&pos]) = 2;
^~~~~~~~~
Given this error it would be easy to lookup IndexMut
within the API docs, see that we indeed requested the right operator but that HashMap
does not implement it.
The generic problem
It seems that the compiler does not have a standardized way to tell users about missing operator implementations, no matter if they are accidentally missing or the users requested an operation that just would not work with the given type. The question that arises here is if and how the compiler should deal with this problem and if this is already covered by some RFC or not.