简体   繁体   English

Vec 是如何实现 BorrowMut 的?

[英]How does Vec implement BorrowMut?

I ran the following example in the standard library documentation, and there was a puzzle.我在标准库文档中运行了以下示例,出现了一个难题。

I found an implementation of the BorrowMut trait with Vec , I don't understand how it works.我找到了一个带有VecBorrowMut trait 的实现,我不明白它是如何工作的。 For example, where the code below indicates that No.1 works, why doesn't No.2 work, what does the generic T do?例如,下面的代码表明 No.1 有效,为什么 No.2 无效,泛型T有什么作用?

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);
}

The full error shown by rustc explains it pretty well. rustc 显示的完整错误很好地解释了它。 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. BorrowMut可以在一个类型上实现多次。 For example, both BorrowMut<Foo> and BorrowMut<Bar> could be implemented for Vec<i32> ;例如,可以为Vec<i32>实现BorrowMut<Foo>BorrowMut<Bar> > ; 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").在这些示例中, FooBar代替了在特征BorrowMut上声明的“类型参数Borrowed ”,如其文档中所示(单击“显示声明”)。

In "no.1" you have specified that T: BorrowMut<[i32]> ;在“no.1”中,您已指定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] .由于没有提到TBorrowMut的其他实现,因此可以明确地推断出“在特征BorrowMut上声明的类型参数Borrowed ”是[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);在“no.2”中,您所追求的BorrowMut的实现存在歧义:即使现在 scope 中没有针对Vec<i32>BorrowMut的其他实现,它们也可能潜伏在编译器不知道的某个地方(等待use声明纳入范围); 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.即使现在不存在其他包,上游包(即std库)也可以在将来添加一个包——然后这会破坏你的代码。 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) ".它通过报告“需要类型注释”来做到这一点,甚至向您展示如何:“使用潜在候选人的完全限定路径: <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 .但是,这不起作用有一个单独的原因: Rust仅在使用. 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);方法语法——当像这样调用时,你必须显式传递&mut v而不是v (我已经就这个错误的建议提出了问题); and that still won't work in your case because v was not declared mutable.这在你的情况下仍然不起作用,因为v没有被声明为可变的。

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:您也可以在不提及v类型的情况下通过以下任何一种方式解决它:

<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::Index ), std::ops::DerefMut::deref_mut or (via that) explicit use of the dereference operator.另请注意,在Vec的情况下,您可以通过其固有的as_mut_slice方法索引(通过其std::ops::Index的实现)获取其内容的可变切片(这是BorrowMut的实现为您提供的) )、 std::ops::DerefMut::deref_mut或(通过它)显式使用解引用运算符。 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. 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 . 请参阅 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.但是,为了使代码尽可能清晰(因此可维护),我建议索引方法&mut v[..]最清晰简洁地表明您正在对整个向量进行可变切片.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM