Error handling Rust`From`trait,errors,reference vs Box和`?`运算符

Error handling Rust`From`trait,errors,reference vs Box和`?`运算符,error-handling,rust,Error Handling,Rust,我对返回结果的函数中的?运算符感到非常困惑 我有以下代码片段: use std::error; use std::fs; fn foo(s: &str) -> Result<&str, Box<error::Error>> { let result = fs::read_to_string(s)?; return Ok(&result); } fn bar(s: &str) -> Result<&am

我对返回
结果的函数中的
运算符感到非常困惑

我有以下代码片段:

use std::error;
use std::fs;


fn foo(s: &str) -> Result<&str, Box<error::Error>> {
    let result = fs::read_to_string(s)?;
    return Ok(&result);
}

fn bar(s: &str) -> Result<&str, &dyn error::Error> {
    // the trait `std::convert::From<std::io::Error>` is not implemented for `&dyn std::error::Error` (1)
    let result = fs::read_to_string(s)?;
    return Ok(&result);
}

fn main() {
    println!("{}", foo("foo.txt").unwrap());
    println!("{}", bar("bar.txt").unwrap());
}
使用std::error;
使用std::fs;
fn foo(s:&str)->结果{
让result=fs::读取到字符串?;
返回Ok(&结果);
}
fn条(s:&str)->结果{
//特性'std::convert::From'未为`&dyn std::error::error`(1)实现
让result=fs::读取到字符串?;
返回Ok(&结果);
}
fn main(){
println!(“{}”,foo(“foo.txt”).unwrap();
println!(“{}”,bar(“bar.txt”).unwrap();
}
从上面的代码段中可以看到,
运算符可以很好地处理返回的装箱错误,但不能处理动态错误引用(错误位于
(1)


有没有什么具体的原因导致它不起作用?就我对Rust的有限了解而言,返回错误引用比返回装箱对象更为自然:最后,在从
foo
函数返回后,我希望deref强制能够使用它,那么为什么不返回错误引用本身呢?

看看这个函数签名:

fn bar(s: &str) -> Result<&str, &dyn error::Error> {
这个特性没有实现,也不可能实现。要了解原因,请尝试手动执行:

impl<'a> From<io::Error> for &'a dyn error::Error {
    fn from(e: io::Error) -> &'a dyn error::Error {
        // what can go here?
    }
}
impl&'a dyn error::error{
//你能在这里做什么?
}
}
出于完全相同的原因,这种方法不可能实现


为什么它适用于
Box
在堆上分配其数据,但也拥有该数据,并在Box超出范围时解除分配该数据。这与引用是完全不同的,在引用中所有者是独立的,并且通过类型中的生存期参数阻止引用延长数据的时间

另见:


查看此函数签名:

fn bar(s: &str) -> Result<&str, &dyn error::Error> {
这个特性没有实现,也不可能实现。要了解原因,请尝试手动执行:

impl<'a> From<io::Error> for &'a dyn error::Error {
    fn from(e: io::Error) -> &'a dyn error::Error {
        // what can go here?
    }
}
impl&'a dyn error::error{
//你能在这里做什么?
}
}
出于完全相同的原因,这种方法不可能实现


为什么它适用于
Box
在堆上分配其数据,但也拥有该数据,并在Box超出范围时解除分配该数据。这与引用是完全不同的,在引用中所有者是独立的,并且通过类型中的生存期参数阻止引用延长数据的时间

另见:


尽管可以将具体类型
std::io::Error
转换为
dyn Error
,但无法将其作为引用返回,因为“owned”值在函数末尾被删除/擦除/删除,这同样适用于
字符串
->
&str
Box
示例之所以有效,是因为在堆(
Box
)中创建了一个拥有的
错误(
impl Error for Box
),并且std为
Box
实现了
Error

如果要删除具体类型,并且只使用trait的可用方法,可以使用
impl trait

使用std:{error,fs};
fn foo(s:&str)->结果{
让result=fs::读取到字符串?;
好(结果)
}
fn条(s:&str)->结果{
让结果=匹配fs::读取到字符串{
Ok(x)=>x,
Err(x)=>返回Err(x),
};
好(结果)
}
fn main(){
println!(“{}”,foo(“foo.txt”).unwrap();
println!(“{}”,bar(“bar.txt”).unwrap();
}

虽然可以将具体类型
std::io::Error
转换为
dyn Error
,但不可能将其作为引用返回,因为“owned”值在函数末尾被删除/擦除/移除,这同样适用于
字符串
->
&str
Box
示例之所以有效,是因为在堆(
Box
)中创建了一个拥有的
错误(
impl Error for Box
),并且std为
Box
实现了
Error

如果要删除具体类型,并且只使用trait的可用方法,可以使用
impl trait

使用std:{error,fs};
fn foo(s:&str)->结果{
让result=fs::读取到字符串?;
好(结果)
}
fn条(s:&str)->结果{
让结果=匹配fs::读取到字符串{
Ok(x)=>x,
Err(x)=>返回Err(x),
};
好(结果)
}
fn main(){
println!(“{}”,foo(“foo.txt”).unwrap();
println!(“{}”,bar(“bar.txt”).unwrap();
}