-1

我在标准库文档中运行了以下示例,出现了一个难题。

我找到了一个trait的实现BorrowMutVec,我不明白它是如何工作的。比如下面的代码表明No.1有效,为什么No.2无效,泛型T有什么作用?</p>

use std::borrow::BorrowMut;

fn check<T: BorrowMut<[i32]>>(mut v: T) {
    assert_eq!(&mut [1, 2, 3], v.borrow_mut()); // ! no.1 can call, Why?
}

fn main() {
    let v = vec![1, 2, 3];
    // v.borrow_mut();  // ! no.2 Can't call,Why?

    check(v);
}
4

1 回答 1

3

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>; 在这些示例中,FooBar替换“在 trait 上声明的类型参数BorrowedBorrowMut”,如其文档中所示(单击“显示声明”)。

在“no.1”中,您已指定T: BorrowMut<[i32]>;由于没有提到BorrowMutfor 的其他实现,因此“在 trait 上声明的类型参数”可以明确地推断为.TBorrowedBorrowMut[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[..]最清晰简洁地表明您正在对整个向量进行可变切片。

于 2021-04-13T09:35:29.823 回答