gpt4 book ai didi

rust - 将 Rust 中的错误与特征对象生命周期混淆

转载 作者:行者123 更新时间:2023-11-29 07:47:14 25 4
gpt4 key购买 nike

谁能告诉我下面的代码有什么问题?编译器提示生命周期,但错误消息完全没有意义。我已经尝试了所有我能想到的方法,但似乎没有任何帮助。

use std::borrow::BorrowMut;

trait Trait<'a> {
fn accept(&mut self, &'a u8);
}

struct Impl<'a>{
myref: Option<&'a u8>,
}
impl<'a> Trait<'a> for Impl<'a> {
fn accept(&mut self, inp: &'a u8) { self.myref = Some(inp); }
}

fn new<'a>() -> Box<Trait<'a> + 'a> {
Box::new(Impl{myref: None})
}

fn user<'a>(obj: &mut Trait<'a>) {}

fn parent<'a>(x: &'a u8) {
let mut pool = new();
user(pool.borrow_mut());
}

编译错误是

error: `pool` does not live long enough
--> src/wtf.rs:22:10
|
22 | user(pool.borrow_mut());
| ^^^^ does not live long enough
23 | }
| - borrowed value dropped before borrower
|
= note: values in a scope are dropped in the opposite order they are created

这完全没有意义。借款人如何活得更久?我什至没有使用借来的值!

最佳答案

好吧,这确实是有道理的,但由于生命周期省略,很难看出。因此,这是您的代码,所有 生命周期都明确写出,并剔除不相关的细节:

use std::borrow::BorrowMut;

trait Trait<'a> {}

struct Impl<'a> {
myref: Option<&'a u8>,
}

impl<'a> Trait<'a> for Impl<'a> {}

fn new<'a>() -> Box<Trait<'a> + 'a> {
Box::new(Impl { myref: None })
}

fn user<'a, 'b>(obj: &'b mut (Trait<'a> + 'b)) {}

fn parent() {
/* 'i: */ let mut pool/*: Box<Trait<'x> + 'x>*/ = new();
/* 'j: */ let pool_ref/*: &'i mut Box<Trait<'x> + 'x>*/ = &mut pool;
/* BorrowMut<T>::borrow_mut<'d>(&'d mut Self) -> &'d mut T */
/* 'k: */ let pool_borrow/*: &'i mut (Trait<'x> + 'x)*/ = Box::borrow_mut(pool_ref);
user(pool_borrow);
}

现在,从 parent 的最后一行来看,我们可以通过阅读 user 的定义并代入我们在父级:

  • 'a = 'x
  • 'b = 'i
  • 'b = 'x

此外,这让我们得出结论:

  • 'x = 'i

这就是问题所在。由于您定义 user 的方式,您将自己置于 pool_ref 借用的生命周期(等于 >pool 您借用的存储位置)必须与 pool< 中 stored 中使用的生命周期 'x 相同.

这有点像 Box 在它存在之前能够有一个指向它自己的指针,这没有任何意义。

无论哪种方式,修复都很简单。将 user 更改为实际具有正确的类型:

fn user<'a, 'b>(obj: &'b mut (Trait<'a> + 'a)) {}

这与 new 生成的类型匹配。或者,只是不要使用 borrow_mut:

user(&mut *pool)

之所以有效,是因为它是“再借用”。调用 borrow_mut 或多或少会直接转换生命周期,但重新借用允许编译器将借用范围缩小到更短的生命周期。换句话说,显式调用 borrow_mut 不允许编译器有足够的自由来“捏造”生命周期以使它们全部对齐,重新借用可以

顺便说一句:

I'm not even using the borrowed value!

不相关。Rust 在本地完全进行类型和生命周期检查。它从不查看另一个函数的主体以查看它在做什么;它单独出现在界面上。编译器既不检查也不关心您在不同函数内部所做的事情。

关于rust - 将 Rust 中的错误与特征对象生命周期混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39339419/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com