gpt4 book ai didi

rust - 包含引用时如何返回错误?

转载 作者:行者123 更新时间:2023-11-29 08:27:37 24 4
gpt4 key购买 nike

我有一个返回 Result<_, MyError> 的 Rust 方法.此方法在 State 上运行结构和 MyError有生命周期说明符 'a因为它需要保留一些 &str

我正在尝试编写这样的特征:

trait MyTrait {
type Error;

fn work(&self) -> Result<(), Self::Error>;
}

impl<'a> MyTrait for MyImpl<'a> {
type Error = MyError<'a>;

fn work(&self) -> Result<(), MyError<'a>> {
let state = State::new();

state.work() // returns Result<(), MyError> but state doesn't live long enough
}
}

如何解决这个错误?我应该更改 MyError保持String而不是 &'a str ?我应该保留 state 吗? MyImpl 内部?这是trait吗定义明确?

我想创建一个 State对于 do() 的每次运行.

这是一个 MCVE:

enum MyError<'a> {
Some(&'a str),
}

trait MyTrait {
type Error;

fn work(&self) -> Result<(), Self::Error>;
}

struct MyImpl<'a> {
pub some_string: &'a str,
}

impl<'a> MyTrait for MyImpl<'a> {
type Error = MyError<'a>;

fn work(&self) -> Result<(), MyError<'a>> {
let state = State::new();

state.work() // returns Result<(), MyError> but state doesn't live long enough
}
}

struct State;

impl State {
pub fn new() -> State {
State
}

pub fn work(&self) -> Result<(), MyError> {
Err(MyError::Some("hi"))
}
}

fn main() {}

( Playground )

最佳答案

问题是根据State::work()的签名MyError 的生命周期参数与 &self 相关联引用:

// without lifetime elision
pub fn work<'a>(&'a self) -> Result<(), MyError<'a>>

然后这个值在 MyImpl::work() 中返回:

fn work(&self) -> Result<(), MyError<'a>> {
let state = State::new();

state.work()
}

问题是,生命周期参数'aimpl<'a> MyTrait for MyImpl<'a>表示严格大于MyError的生命周期由 State::work() 返回.为什么会这样?好吧,让我们看看MyImpl::work()再次:

fn work(&self) -> Result<(), MyError<'a>> {
let state = State::new();
state.work()
}

记住 State::work(&self)返回 MyError生命周期与 &self 的生命周期相关,也就是说,在这种特殊情况下,它将是 state 的生命周期.后者是一个局部变量,在 work() 之后立即销毁。返回。

然而,'aimpl<'a> MyTrait for MyImpl<'a>表示存储在 MyImpl 中的字符串切片的生命周期(即,在 self 中)。自然地,因为MyImpl::work()完全可以被调用,这意味着它被调用的值处于有效状态并且包含一个活跃的切片。因此,它的生命周期大于任何可以在 MyImpl::work() 中创建的东西。 .所以返回任何不是从 MyImpl 中的这个字符串切片派生的东西是不合理的;例如,这是有效的:

impl<'a> MyTrait for MyImpl<'a> {
type Error = MyError<'a>;

fn work(&self) -> Result<(), MyError<'a>> {
Err(MyError::Some(self.some_string))
}
}

现在 MyError 的生命周期值恰好是 self.some_string 的值, 借用检查员变得很高兴。

现在,有哪些选择?首先,最简单的方法是存储一个拥有的 String里面MyError :

enum MyError {
Some(String)
}

impl<'a> MyTrait for MyImpl<'a> {
type Error = MyError;

fn work(&self) -> Result<(), MyError> {
let state = State::new();
state.work()
}
}

struct State;

impl State {
pub fn new() -> State {
State
}

pub fn work(&self) -> Result<(), MyError> {
Err(MyError::Some("hi".into()))
}
}

我相信,这是最惯用且最灵活的方法。具有非自给自足的错误值实际上是非常罕见的;我想我以前从未见过。另一种选择是使用 &'static str :

enum MyError {
Some(&'static str)
}

struct State;

impl State {
pub fn new() -> State {
State
}

pub fn work(&self) -> Result<(), MyError> {
Err(MyError::Some("hi"))
}
}

这种方法不允许您动态创建错误消息(您只能为错误消息使用字符串文字)但它更有效,因为它不需要为程序中的不愉快路径分配内存,并且可能就足够了用于您的用例。

关于rust - 包含引用时如何返回错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36333789/

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