Я хотел бы реализовать собственное перечисление для переноса нескольких ошибок, как в приведенном ниже коде.
Я знаю, что могу заставить это работать с 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>>`
Какая часть ответа будет пропущена? Пример функции wrapped_fn как бы дает ответ. Оператор ? преобразует ошибку через From, а ваш тип ошибки, созданный с использованием thiserror, уже реализует From<io::Error>, поскольку он аннотирован для этой цели (#[from]).
Я хочу заставить error_fn().into(); работать. Будет ли map_err единственным ответом?
Проще говоря, error_fn().into() не сработает, и вы это делаете не так. Вы должны либо вызвать map_err, либо какой-либо метод расширения, который возвращает новый Result. Например, snafu предоставляет context методы для инкапсуляции типа ошибки в другой с добавленным контекстом. См. также: stackoverflow.com/q/62375381 stackoverflow.com/questions/42584368/…
Я пытался уловить несколько ошибок из контекста совпадения. Поэтому я хотел знать, как завершить это преобразование. Но теперь я начинаю думать, что мне следует использовать функцию вместо контекста сопоставления. Было бы очень красиво и чисто.

wrapped_fn — это то, что вы обычно хотите сделать! ? на самом деле преобразуетFrom существующую ошибку в желаемый тип ошибки перед ее возвратом в случае возникновения ошибки.
Если вы действительно хотите выполнить преобразование, подобное приведенному в вашем main, без возврата ошибки, то я думаю, что лучший способ написать это действительно так:
fn main() {
let result = error_fn().map_err(MyError::from);
}
Да, часть. Спасибо.