Rust中Result<(), Box<dyn Error>>返回逻辑及代码疑问解析
两段示例代码
第一段代码
use std::error::Error; fn main() -> Result<(), Box<dyn Error>> { Err("March")? }
第二段代码
use std::error::Error; fn main() -> Result<(), Box<dyn Error>> { Err("March".into()) }
疑问解答
1. 为何最后表达式要用Err("March")?而非直接Err("March")
直接写Err("March")时,这个表达式的类型是Result<&str, &str>,但函数声明的返回类型是Result<(), Box<dyn Error>>,两者类型不匹配,编译器会直接报错。
?操作符在这里的作用不只是触发提前返回,它还会自动完成类型适配:当在返回Result<T, E>的函数中使用expr?时,expr的错误分支类型会被自动转换为函数返回的错误类型(也就是这里的Box<dyn Error>),同时Ok分支的类型也会被调整为函数要求的()。也就是说,Err("March")?会把&str类型的错误包装成Box<dyn Error>,最终生成符合返回类型要求的Result<(), Box<dyn Error>>,同时因为是Err分支,直接提前返回这个错误。
2. Err("March".into())中"March".into()的返回值,以及为何不会形成Err(Err())
"March"是&str类型,调用.into()时,Rust会根据上下文推导目标类型——因为函数返回的是Result<(), Box<dyn Error>>,所以Err的参数需要是Box<dyn Error>类型,.into()会自动把&str转换为Box<dyn Error>(因为&str实现了Error trait,满足Box<dyn Error>的要求)。
不会出现Err(Err(...))的原因很简单:.into()做的是类型转换,不是把值包装成Result。"March"本身不是Result类型,转换后的结果也不是Result,而是一个符合Box<dyn Error>要求的错误对象,所以把它放进Err()里,得到的就是Err(Box<dyn Error>),完全符合函数的返回类型,不会出现嵌套的Err结构。
内容的提问来源于stack exchange,提问作者Kodra

