Rust 为什么使用Into::Into将解析字符串的结果映射为无法推断类型?
以下() 我无法按照上面错误消息中的建议解决此问题。如果我将代码更改为:Rust 为什么使用Into::Into将解析字符串的结果映射为无法推断类型?,rust,type-inference,Rust,Type Inference,以下() 我无法按照上面错误消息中的建议解决此问题。如果我将代码更改为: let addr = addr.map_err(|e: ::std::net::AddrParseError| e.into())?; 我得到另一个错误: 错误[E0282]:需要类型注释 -->src/main.rs:14:16 | 14 |让addr=addr.map_err(| e:::std::net::AddrParseError | e.into())?; |^^^^^^^^^^^^^^^^^^^^^^^^^
let addr = addr.map_err(|e: ::std::net::AddrParseError| e.into())?;
我得到另一个错误:
错误[E0282]:需要类型注释
-->src/main.rs:14:16
|
14 |让addr=addr.map_err(| e:::std::net::AddrParseError | e.into())?;
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^无法推断`_`
我的解决方案是使用来自的:
let addr = addr.map_err(|e| <MyError as From<_>>::from(e))?; // Worked!!
我知道类型推断从来都不容易,但是为什么上面的代码不能正确地推断类型呢?:
然后,您试图将未知类型转换为MyError
,从而导致错误
了解错误类型是不够的,因为可以使用相同的错误类型实现多个类型:
pub trait FromStr {
type Err;
fn from_str(s: &str) -> Result<Self, Self::Err>;
}
我甚至不需要映射错误
是的,因为?
为您做了这件事。关于您的第二个错误:通过用另一个自定义错误(MyError2
)替换从解析中获得的结果来减少您的示例,这会重现相同的问题(| e:MyError2 | e.into()
):
用标准库中的宏定义(try!
)替换?
,将显示:
macro_rules! try {
($e:expr) => (match $e {
Ok(val) => val,
Err(err) => return Err(::std::convert::From::from(err)),
});
}
fn main() -> Result<(),MyError> {
let addr = Err(MyError2{});
let addr = try!(addr.map_err(|e| e.into()));
Ok(addr)
}
在宏定义中的err
上应用的From::From()
导致推断失败。将这一行:Err(Err)=>returnerr(::std::convert::From::From(Err)),
替换为Err(Err)=>returnerr(Err),
解决了问题-程序编译
原因是通过From::From()
在MyError
和MyError2
之间放置两个转换,此转换管道变得不明确。编译器无法确定中间类型
示例-两个有效选项(请注意,From::From
是反射性实现的):
MyError2
->MyError2
->MyError
编译:let addr=addr.map_err(| e |{let e2:MyError2=e.into();e2})代码>
MyError2
->MyError
->MyError
编译:let addr=addr.map_err(|e |{let e2:MyError=e.into();e2})代码>
pub fn parse<F>(&self) -> Result<F, <F as FromStr>::Err>
where
F: FromStr,
let addr = "127.0.0.1:23456".parse();
let addr = addr.map_err(|e| e.into())?;
let addr = addr.map_err(|e: ::std::net::AddrParseError| e.into())?;
pub trait FromStr {
type Err;
fn from_str(s: &str) -> Result<Self, Self::Err>;
}
let addr = addr.map_err(|e| <MyError as From<_>>::from(e))?;
let addr = addr.map_err(|e| MyError::from(e))?;
#[derive(Debug)]
struct MyError();
struct MyError2();
impl From<MyError2> for MyError {
fn from(_e: MyError2) -> MyError{
MyError()
}
}
fn main() -> Result<(),MyError> {
let addr = Err(MyError2{});
addr.map_err(|e| e.into())?;
Ok(())
}
macro_rules! try {
($e:expr) => (match $e {
Ok(val) => val,
Err(err) => return Err(::std::convert::From::from(err)),
});
}
fn main() -> Result<(),MyError> {
let addr = Err(MyError2{});
let addr = try!(addr.map_err(|e| e.into()));
Ok(addr)
}