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)
}