The full error shown by rustc explains it pretty well. With emphasis added:
error[E0283]: type annotations needed
--> src/main.rs:9:7
|
9 | v.borrow_mut(); //! no.2 Can't call,Why?
| --^^^^^^^^^^--
| | |
| | cannot infer type for type parameter `Borrowed` declared on the trait `BorrowMut`
| this method call resolves to `&mut Borrowed`
| help: use the fully qualified path for the potential candidate: `<Vec<T> as BorrowMut<[T]>>::borrow_mut(v)`
|
= note: cannot satisfy `Vec<i32>: BorrowMut<_>`
BorrowMut
can be implemented multiple times on a type. For example, both BorrowMut<Foo>
and BorrowMut<Bar>
could be implemented for Vec<i32>
; in those examples, Foo
and Bar
take the place of the "type parameter Borrowed
declared on the trait BorrowMut
", as shown in its documentation (click "Show declaration").
In "no.1" you have specified that T: BorrowMut<[i32]>
; since no other implementations of BorrowMut
for T
have been mentioned, the "type parameter Borrowed
declared on the trait BorrowMut
" can unambiguously be inferred to be [i32]
.
In "no.2", there is ambiguity over which implementation of BorrowMut
you're after: even if no other implementations of BorrowMut
for Vec<i32>
are in scope right now, they could be lurking somewhere the compiler doesn't know about (pending being brought in-scope with a use
statement); and even if no others exist right now, an upstream crate (namely, the std
library) could add one in the future—and that would then break your code. Therefore the compiler asks you to remove the ambiguity by explicitly informing it which implementation you're after. It does this by reporting "type annotations needed", and even shows you how: "use the fully qualified path for the potential candidate: <Vec<T> as BorrowMut<[T]>>::borrow_mut(v)
". We can do that here:
<Vec<i32> as BorrowMut<[i32]>>::borrow_mut(v)
However this won't work for a separate reason: Rust only performs deref coercion when calling with the .
method syntax—when calling like this instead, you'd have to explicitly pass &mut v
instead of v
(I've filed an issue about this erroneous suggestion); and that still won't work in your case because v
was not declared mutable.
The compiler also concluded with:
For more information about an error, try `rustc --explain E0283`.
Doing that would have displayed this extra information, which may also have helped.
Do please suggest how the error message could have explained the problem more clearly.
In actual fact, the compiler's suggestion above is more verbose than it requires to resolve the ambiguity in this case. You could also have resolved it without mentioning the type of v
in either of these ways:
<dyn BorrowMut<[i32]>>::borrow_mut(&mut v)
BorrowMut::<[i32]>::borrow_mut(&mut v)
Also note that, in the case of Vec
, you can obtain a mutable slice of its content (which is what this implementation of BorrowMut
provides for you) via its intrinsic as_mut_slice
method, indexing (via its implementation of std::ops::IndexMut
), or calling upon std::ops::DerefMut::deref_mut
whether explicitly or implicitly (i.e. using the dereference operator). Respectively:
v.as_mut_slice()
&mut v[..]
v.deref_mut() // DerefMut must be in scope, else qualify as above
&mut *v
Indeed, because of the dereferencing, &mut Vec
also coerces to a mutable slice at coercion sites such as function arguments and let
bindings—so you can often just use &mut v
and Rust will do the rest for you.
See all approaches discussed in this answer on the Rust Playground.
Given that they all compile down to exactly the same code, which you use is really just a matter of preference. But, in order to keep the code as clear (and therefore maintainable) as possible, I would suggest that the indexing approach &mut v[..]
most clearly and concisely indicates that you're taking a mutable slice over the whole of the vector.