Реализовать черту для другой черты Тип предмета - PullRequest
0 голосов
/ 26 мая 2019

Мне нужно преобразовать ошибку разбора в мой собственный тип ошибки при возврате Result. Упрощенно это выглядит следующим образом:

enum MyError {
    Parse,
    ...,
}

fn process<R: FromStr>(s: &str) -> Result<(), MyError> {
    Ok(s.parse::<R>()?)
}

Для работы над чертой должно быть реализовано. Это не работает:

impl From<std::str::FromStr::Err> for MyError {
    fn from(e: std::str::FromStr::Err) -> MyError {
        MyError::Parse
    }
}

Диагностика компилятора:

help: use fully-qualified syntax: `<Type as std::str::FromStr>::Err`

Но я не знаю точного Type здесь. Весь смысл в том, чтобы разрешить преобразование от всех возможных ошибок.

Ответы [ 2 ]

2 голосов
/ 27 мая 2019

Тип FromStr::Err является ассоциированным типом черты FromStr.Каждая реализация FromStr имеет свой собственный связанный тип, и этот тип совершенно не ограничен - это может быть любой тип.Это означает, что вам потребуется преобразование из любого типа в MyError для достижения того, что вы хотите:

impl<T> From<T> for MyError {
    fn from(e: T) -> MyError {
        MyError::Parse
    }
}

Однако эта реализация запрещена правилами согласованности - она ​​конфликтует с реализацией From<T> длялюбой тип T в стандартной библиотеке.И даже если бы эта реализация была разрешена, она на самом деле не делала бы, что вы хотите - любой тип ошибки будет преобразован в MyError::Parse, а не просто в разборе ошибок.

Один из возможных способов эточтобы ввести признак маркера для типов ошибок разбора:

trait ParseError {}

impl<T: ParseError> From<T> for MyError {
    fn from(e: T) -> MyError {
        MyError::Parse
    }
}

Затем вы можете реализовать эту особенность маркера для всех типов ошибок разбора:

impl ParseError for std::str::ParseBoolError {}
impl ParseError for std::num::ParseFloatError {}
impl ParseError for std::num::ParseIntError {}
impl ParseError for std::net::AddrParseError {}
impl ParseError for std::char::ParseCharError {}
1 голос
/ 27 мая 2019

Если вы все равно отбрасываете ошибку разбора, используйте map_err, чтобы локально изменить ошибку:

fn process<R: FromStr>(s: &str) -> Result<(), MyError> {
    let _ = s.parse::<R>().map_err(|_| MyError::Parse)?;
    Ok(())
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...