[英]Why does moving a function to a default trait method introduce a borrowing error?
[英]How does borrowing Box<Trait> contents work?
我有这个最小的示例代码 :
use std::borrow::BorrowMut;
trait Foo {}
struct Bar;
impl Foo for Bar {}
fn main() {
let mut encryptor: Box<Foo> = Box::new(Bar);
encrypt(encryptor.borrow_mut());
}
fn encrypt(encryptor: &mut Foo) { }
但它失败了这个错误:
error: `encryptor` does not live long enough
--> src/main.rs:11:1
|
10 | encrypt(encryptor.borrow_mut());
| --------- borrow occurs here
11 | }
| ^ `encryptor` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
#rustbeginners的善良人士发现我必须取消引用该框以获取内容,然后借用内容。 像这样 :
trait Foo {}
struct Bar;
impl Foo for Bar {}
fn main() {
let mut encryptor: Box<Foo> = Box::new(Bar);
encrypt(&mut *encryptor);
}
fn encrypt(encryptor: &mut Foo) { }
它有效,但我不明白。
为什么我需要先取消引用? 想说什么错误? 通常,在函数结束时删除值不是错误。
让我们从允许代码工作的更改开始:
fn encrypt(encryptor: &mut (Foo + 'static)) { }
重要的区别是向特征对象添加了+ 'static
- 优先需要parens。
需要认识到的重要一点是&Foo
中存在两个生命周期 :
&'a Foo
&(Foo + 'b)
。 如果我正确地读取RFC,这是由RFC 192引入的, RFC 599指定了生命周期的合理默认值。 在这种情况下,生命周期应该扩展如下:
fn encrypt(encryptor: &mut Foo) { }
fn encrypt<'a>(encryptor: &'a mut (Foo + 'a)) { }
在管道的另一端,我们有一个Box<Foo>
。 扩展了RFC的规则,这就变成了Box<Foo + 'static>
。 当我们借用它并尝试将其传递给函数时,我们有一个等式来解决:
'static
。 'static
。 哦哦! Box
将在块的末尾被删除,因此它肯定不是静态的。
具有明确的寿命的修复程序允许参考性状对象的生命周期从性状对象内部的参考文献的寿命不同。
如果您需要支持具有内部引用的特征对象,则替代方法是执行以下操作:
fn encrypt<'a>(encryptor: &mut (Foo + 'a)) { }
这个解释真正归功于nikomatsakis和他对GitHub的评论 ,我只是稍微扩展了一下。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.