以下 ( playground link )
#[derive(Debug)]
struct MyError();
impl From<::std::net::AddrParseError> for MyError {
fn from(_e: ::std::net::AddrParseError) -> MyError {
MyError()
}
}
fn accept_addr(_addr: ::std::net::SocketAddr) {}
fn main() -> Result<(), MyError> {
let addr = "127.0.0.1:23456".parse();
let addr = addr.map_err(|e| e.into())?;
Ok(accept_addr(addr))
}
不起作用。错误:
error[E0282]: type annotations needed
--> src/main.rs:14:30
|
14 | let addr = addr.map_err(|e| e.into())?;
| ^ consider giving this closure parameter a type
我无法按照上述错误消息中的建议解决此问题。如果我将代码更改为:
let addr = addr.map_err(|e: ::std::net::AddrParseError| e.into())?;
我收到另一个错误:
error[E0282]: type annotations needed
--> src/main.rs:14:16
|
14 | let addr = addr.map_err(|e: ::std::net::AddrParseError| e.into())?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for `_`
我的解决方案是使用 From
代替:
let addr = addr.map_err(|e| <MyError as From<_>>::from(e))?; // Worked!!
更好的是,我后来发现我什至不需要映射错误:
let addr = "127.0.0.1:23456".parse()?;
Ok(accept_addr(addr))
我知道类型推断绝非易事,但为什么上面的代码不能正确推断类型?
最佳答案
关于第二个错误:通过用另一个自定义错误 (MyError2
) 替换解析获得的结果来稍微减少示例,会重现相同的问题 (|e: MyError2| e.into ()
再次没有帮助):
#[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(())
}
error[E0282]: type annotations needed
--> src/main.rs:20:5
|
20 | addr.map_err(|e| e.into())?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for `_`
error: aborting due to previous error
用标准库中的宏定义 (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)
}
error[E0282]: type annotations needed
--> src/main.rs:14:13
|
14 | Err(err) => return Err(::std::convert::From::from(err)),
| ^^^ cannot infer type for `_`
...
20 | let addr = try!(addr.map_err(|e| e.into()));
| -------------------------------- in this macro invocation
应用于宏定义中的 err
的 From::from()
是导致推理失败的原因。将此行: Err(err) => return Err(::std::convert::From::from(err)),
替换为 Err(err) => return Err( err),
解决了问题 - 程序编译。
原因是,通过在 MyError
和 MyError2
之间通过 From::from()
放置两个转换,此转换管道变得不明确。编译器无法确定中间类型。
示例 - 两个有效选项(请注意,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})?;
关于rust - 为什么使用 Into::into 解析字符串映射结果无法推断类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51155605/