Преобразование Result<_, error> в Result<_, MyError> с этой ошибкой в ​​Rust

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

Я знаю, что могу заставить это работать с map_err, но это не выглядит аккуратно. А поскольку Result не определен в текущем ящике, я не могу реализовать его преобразование.

Как вы справитесь с этим в этой ситуации?

Глядя на wrapped_fn, кажется, что он реализует Result<_, io::Error> преобразование. Не могли бы вы рассказать мне, почему это может сработать?

use anyhow::Result;
use std::io;
use thiserror::Error;

#[derive(Debug, Error)]
enum MyError {
    #[error("CustomError {0}")]
    CustomError(#[from] io::Error),
}

struct MyStruct {}

fn error_fn() -> Result<(), io::Error> {
    return Err(io::Error::new(io::ErrorKind::Other, "other"));
}

fn wrapped_fn() -> Result<(), MyError> {
    error_fn()?;  // no idea why this works because it seems like implement `Result` conversion.
    Ok(())
}


fn main() {
    let result: Result<(), MyError> = error_fn().into(); // I want to make this work.
    // let result: Result<(), MyError> = error_fn().map_err(MyError::from); // This works.
}

// This cannot be implemented as well.
// impl<T> std::convert::From<Result<T, io::Error>> for Result<T, MyError>{
//     fn from(result: io::Error) -> Self{
//         result.map_err(MyError::from)
//     }
// }

Вывод ошибки

error[E0277]: the trait bound `Result<(), MyError>: From<Result<(), std::io::Error>>` is not satisfied
  --> src/main.rs:19:50
   |
19 |     let result: Result<(), MyError> = error_fn().into();
   |                                                  ^^^^ the trait `From<Result<(), std::io::Error>>` is not implemented for `Result<(), MyError>`
   |
   = note: required for `Result<(), std::io::Error>` to implement `Into<Result<(), MyError>>`

Да, часть. Спасибо.

kirin 20.02.2024 12:52

Какая часть ответа будет пропущена? Пример функции wrapped_fn как бы дает ответ. Оператор ? преобразует ошибку через From, а ваш тип ошибки, созданный с использованием thiserror, уже реализует From<io::Error>, поскольку он аннотирован для этой цели (#[from]).

E_net4 20.02.2024 12:53

Я хочу заставить error_fn().into(); работать. Будет ли map_err единственным ответом?

kirin 20.02.2024 12:58

Проще говоря, error_fn().into() не сработает, и вы это делаете не так. Вы должны либо вызвать map_err, либо какой-либо метод расширения, который возвращает новый Result. Например, snafu предоставляет context методы для инкапсуляции типа ошибки в другой с добавленным контекстом. См. также: stackoverflow.com/q/62375381 stackoverflow.com/questions/42584368/…

E_net4 20.02.2024 13:05

Я пытался уловить несколько ошибок из контекста совпадения. Поэтому я хотел знать, как завершить это преобразование. Но теперь я начинаю думать, что мне следует использовать функцию вместо контекста сопоставления. Было бы очень красиво и чисто.

kirin 20.02.2024 13:11
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
0
5
129
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

wrapped_fn — это то, что вы обычно хотите сделать! ? на самом деле преобразуетFrom существующую ошибку в желаемый тип ошибки перед ее возвратом в случае возникновения ошибки.

Если вы действительно хотите выполнить преобразование, подобное приведенному в вашем main, без возврата ошибки, то я думаю, что лучший способ написать это действительно так:

fn main() {
    let result = error_fn().map_err(MyError::from);
}

Другие вопросы по теме