rustc 显示的完整错误很好地解释了它。重点补充:
错误[E0283]:需要类型注释
--> src/main.rs:9:7
|
9 | v.borrow_mut(); //! no.2 不能打电话,为什么?
| --^^^^^^^^^^^--
| | |
| | 无法推断在特征“BorrowMut”上声明的类型参数“Borrowed”的类型
| 此方法调用解析为 `&mut Borrowed`
| 帮助:使用潜在候选人的完全限定路径:`<Vec<T> as BorrowMut<[T]>>::borrow_mut(v)`
|
= 注意:不能满足 `Vec<i32>: BorrowMut<_>`
BorrowMut
可以在一个类型上多次实现。例如,两者BorrowMut<Foo>
和BorrowMut<Bar>
都可以用于Vec<i32>
; 在这些示例中,Foo
并Bar
替换“在 trait 上声明的类型参数Borrowed
BorrowMut
”,如其文档中所示(单击“显示声明”)。
在“no.1”中,您已指定T: BorrowMut<[i32]>
;由于没有提到BorrowMut
for 的其他实现,因此“在 trait 上声明的类型参数”可以明确地推断为.T
Borrowed
BorrowMut
[i32]
在“no.2”中,您所追求的实现存在歧义BorrowMut
:即使 for 的其他实现BorrowMut
目前Vec<i32>
不在范围内,它们也可能潜伏在编译器不知道的某个地方(等待引入-范围与use
声明);即使现在不存在其他包,上游板条箱(即std
库)也可以在将来添加一个包——这会破坏你的代码。因此,编译器要求您通过明确告知您要使用哪种实现来消除歧义。它通过报告“需要类型注释”来做到这一点,甚至向您展示如何:“为潜在候选人使用完全限定的路径:<Vec<T> as BorrowMut<[T]>>::borrow_mut(v)
”。我们可以在这里做到:
<Vec<i32> as BorrowMut<[i32]>>::borrow_mut(v)
然而,这不起作用有一个单独的原因:Rust 只在使用方法语法调用时执行deref 强制.
——当像这样调用时,你必须显式传递&mut v
而不是v
(我已经提交了关于这个错误建议的问题) ; 这仍然不适用于您的情况,因为v
未声明为可变的。
编译器还得出以下结论:
有关错误的更多信息,请尝试“rustc --explain E0283”。
这样做会显示这些额外的信息,这可能也有帮助。
请建议错误消息如何更清楚地解释问题。
实际上,上面的编译器建议比解决这种情况下的歧义所需要的更冗长。您也可以在不提及以下v
任何一种方式的类型的情况下解决它:
<dyn BorrowMut<[i32]>>::borrow_mut(&mut v)
BorrowMut::<[i32]>::borrow_mut(&mut v)
另请注意,在 的情况下Vec
,您可以BorrowMut
通过其内在as_mut_slice
方法、索引(通过 的实现std::ops::IndexMut
)或std::ops::DerefMut::deref_mut
显式或隐式调用(即使用取消引用运算符)。分别:
v.as_mut_slice()
&mut v[..]
v.deref_mut() // DerefMut must be in scope, else qualify as above
&mut *v
事实上,由于解引用,&mut Vec
还会在强制位置(例如函数参数和绑定)强制转换为可变切片——let
因此您通常可以只使用&mut v
,Rust 会为您完成剩下的工作。
请参阅 Rust Playground 上此答案中讨论的所有方法。
鉴于它们都编译成完全相同的代码,您使用的代码实际上只是一个偏好问题。但是,为了使代码尽可能清晰(因此可维护),我建议索引方法&mut v[..]
最清晰简洁地表明您正在对整个向量进行可变切片。