Rust:为关联类型实现特征 "From"(错误)
Rust: Implement trait "From" for associated type (Error)
这是我之前问题的后续问题:
我创建了以下结构和函数来从 stdin 读取行并将它们解析为整数并且它有效:
use std::io::BufRead;
use std::{io, num, str};
#[derive(Debug)]
enum InputError {
IOError(io::Error),
ParseIntError(num::ParseIntError),
}
impl From<io::Error> for InputError {
fn from(e: io::Error) -> InputError {
return InputError::IOError(e);
}
}
impl From<num::ParseIntError> for InputError {
fn from(e: num::ParseIntError) -> InputError {
return InputError::ParseIntError(e);
}
}
pub fn get_integer_lines<T>() -> Result<Vec<T>, InputError>
where
T: str::FromStr,
{
let stdin = io::stdin();
let my_values: Result<Vec<_>, InputError> = stdin
.lock()
.lines()
.map(|line| -> Result<T, InputError> { Ok(line?.parse::<T>()?) })
.collect();
my_values
}
现在,我想我会用 u32
替换类型参数 T 以允许任何类型的数字类型。为此,我假设我需要将 T 限制为实现 FromStr 特性的类型,然后以某种方式实现 From 特性以允许从 FromStr::Err 转换为我的 "InputError".
按照我第一次得到的错误
error[E0277]: `?` couldn't convert the error to `InputError`
--> src/lib.rs:30:69
|
30 | .map(|line| -> Result<T, InputError> { Ok(line?.parse::<T>()?) })
| ^ the trait `std::convert::From<<T as std::str::FromStr>::Err>` is not implemented for `InputError`
|
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
= help: consider adding a `where InputError: std::convert::From<<T as std::str::FromStr>::Err>` bound
= note: required by `std::convert::From::from`
我试过这样的事情:
impl std::convert::From<<T as std::str::FromStr>::Err> for InputError {
fn from(e: <T as std::str::FromStr>::Err) -> InputError {
return InputError::ParseIntError(e)
}
}
但这反而会导致:
error[E0412]: cannot find type `T` in this scope
--> src/lib.rs:22:26
|
22 | impl std::convert::From<<T as std::str::FromStr>::Err> for InputError {
| ^ not found in this scope
所以基本上我想表达的是:
“我想为我的 InputError
为每个 T
实现特性 From<T::Err>
,它也实现了 FromStr
。这甚至可能吗?如果可以,怎么做?
So basically what I want to express is something along the lines of:
"I want to implement the trait From<T::Err>
for my InputError
for every T
which also implements FromStr
. Is this even possible and if so, how?
这不是错误的意思。
性状 FromStr
具有关联类型 Err
。错误是说此关联的错误类型无法转换为 InputError
.
首先,让我们通过去掉类型参数来简化:
fn get_integer_lines() -> Result<Vec<u32>, InputError> {
let stdin = io::stdin();
let my_values = stdin
.lock()
.lines()
.map(|line| Ok(line?.parse()?))
.collect();
my_values
}
这有效!
u32
的 FromStr
实现的关联 Err
类型是 ParseIntError
并且您已正确实现 From<ParseIntError> for InputError
.
这对 T
不起作用的原因是因为 T
的 FromStr::Err
类型 可能 是任何东西。通过使用类型参数,您告诉编译器您希望此函数适用于 任何可能的 类型 T
,但它仅适用于 FromStr::Err
的类型可以转换为您的 InputError
类型。
报错信息提示:
= help: consider adding a `where InputError: std::convert::From<<T as std::str::FromStr>::Err>` bound
所以让我们这样做:
fn get_integer_lines<T>() -> Result<Vec<T>, InputError>
where
T: str::FromStr,
InputError: From<<T as str::FromStr>::Err>,
{
let stdin = io::stdin();
let my_values = stdin
.lock()
.lines()
.map(|line| Ok(line?.parse()?))
.collect();
my_values
}
这告诉编译器您希望该函数适用于所有可能的 T
前提是:
T
实施 FromStr
和
- 来自
T
的 FromStr
实现的关联 Err
类型可以转换为 InputError
这是我之前问题的后续问题:
我创建了以下结构和函数来从 stdin 读取行并将它们解析为整数并且它有效:
use std::io::BufRead;
use std::{io, num, str};
#[derive(Debug)]
enum InputError {
IOError(io::Error),
ParseIntError(num::ParseIntError),
}
impl From<io::Error> for InputError {
fn from(e: io::Error) -> InputError {
return InputError::IOError(e);
}
}
impl From<num::ParseIntError> for InputError {
fn from(e: num::ParseIntError) -> InputError {
return InputError::ParseIntError(e);
}
}
pub fn get_integer_lines<T>() -> Result<Vec<T>, InputError>
where
T: str::FromStr,
{
let stdin = io::stdin();
let my_values: Result<Vec<_>, InputError> = stdin
.lock()
.lines()
.map(|line| -> Result<T, InputError> { Ok(line?.parse::<T>()?) })
.collect();
my_values
}
现在,我想我会用 u32
替换类型参数 T 以允许任何类型的数字类型。为此,我假设我需要将 T 限制为实现 FromStr 特性的类型,然后以某种方式实现 From 特性以允许从 FromStr::Err 转换为我的 "InputError".
按照我第一次得到的错误
error[E0277]: `?` couldn't convert the error to `InputError`
--> src/lib.rs:30:69
|
30 | .map(|line| -> Result<T, InputError> { Ok(line?.parse::<T>()?) })
| ^ the trait `std::convert::From<<T as std::str::FromStr>::Err>` is not implemented for `InputError`
|
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
= help: consider adding a `where InputError: std::convert::From<<T as std::str::FromStr>::Err>` bound
= note: required by `std::convert::From::from`
我试过这样的事情:
impl std::convert::From<<T as std::str::FromStr>::Err> for InputError {
fn from(e: <T as std::str::FromStr>::Err) -> InputError {
return InputError::ParseIntError(e)
}
}
但这反而会导致:
error[E0412]: cannot find type `T` in this scope
--> src/lib.rs:22:26
|
22 | impl std::convert::From<<T as std::str::FromStr>::Err> for InputError {
| ^ not found in this scope
所以基本上我想表达的是:
“我想为我的 InputError
为每个 T
实现特性 From<T::Err>
,它也实现了 FromStr
。这甚至可能吗?如果可以,怎么做?
So basically what I want to express is something along the lines of: "I want to implement the trait
From<T::Err>
for myInputError
for everyT
which also implementsFromStr
. Is this even possible and if so, how?
这不是错误的意思。
性状 FromStr
具有关联类型 Err
。错误是说此关联的错误类型无法转换为 InputError
.
首先,让我们通过去掉类型参数来简化:
fn get_integer_lines() -> Result<Vec<u32>, InputError> {
let stdin = io::stdin();
let my_values = stdin
.lock()
.lines()
.map(|line| Ok(line?.parse()?))
.collect();
my_values
}
这有效!
u32
的 FromStr
实现的关联 Err
类型是 ParseIntError
并且您已正确实现 From<ParseIntError> for InputError
.
这对 T
不起作用的原因是因为 T
的 FromStr::Err
类型 可能 是任何东西。通过使用类型参数,您告诉编译器您希望此函数适用于 任何可能的 类型 T
,但它仅适用于 FromStr::Err
的类型可以转换为您的 InputError
类型。
报错信息提示:
= help: consider adding a `where InputError: std::convert::From<<T as std::str::FromStr>::Err>` bound
所以让我们这样做:
fn get_integer_lines<T>() -> Result<Vec<T>, InputError>
where
T: str::FromStr,
InputError: From<<T as str::FromStr>::Err>,
{
let stdin = io::stdin();
let my_values = stdin
.lock()
.lines()
.map(|line| Ok(line?.parse()?))
.collect();
my_values
}
这告诉编译器您希望该函数适用于所有可能的 T
前提是:
T
实施FromStr
和- 来自
T
的FromStr
实现的关联Err
类型可以转换为InputError