Есть ли способ получить SNAFU `.backtrace ()` на произвольных объектах-признаках `& dyn std :: error :: Error`? - PullRequest
0 голосов
/ 20 сентября 2019

RFC 2504 добавит обязательный fn backtrace(&self) -> Option<&Backtrace> ко всем std::error::Error.Это еще не готово, поэтому на данный момент SNAFU , макрос помощника по ошибкам, заполняет это, связывая черту ErrorCompat со всеми типами, сгенерированными макросом.Это позволяет поддерживать обратную трассировку до того, как она появится в Rust по ночам.

Однако эта черта ErrorCompat реализована не для всех разработчиков std::error::Error.Я хочу - в некотором родовом коде печати ошибок - иметь возможность отображать цепочку причин вместе с трассировкой стека, связанной с тем, где была создана ошибка SNAFU.К сожалению, функция source() возвращает &(dyn Error + 'static).

use std::error::Error as StdError;
use snafu::{ResultExt, ErrorCompat};

fn main() {
    let err: Result<(), _> = Err(std::io::Error::new(std::io::ErrorKind::Other, "oh no!"));

    let err = err.with_context(|| parse_error::ReadInput {
        filename: "hello"
    });

    let err = err.with_context(|| compile_error::ParseStage);

    // some generic error handling code
    if let Err(err) = err {
        // `cause` is type &(dyn std::error::Error + 'static)
        let cause = err.source().unwrap();

        if let Some(err) = /* attempt to downcast cause into &dyn snafu::ErrorCompat trait object */ {
            println!("{}", err.backtrace().unwrap());
        }
    }
}

pub mod compile_error {
    use snafu::{Snafu, Backtrace};
    #[derive(Debug, Snafu)]
    #[snafu(visibility(pub(super)))]
    pub enum Error {
        #[snafu(display("Error parsing code: {}", source))]
        ParseStage {
           source: crate::parse_error::Error,
           backtrace: Backtrace
        },
    }
}

pub mod parse_error {
    use snafu::{Snafu, Backtrace};
    #[derive(Debug, Snafu)]
    #[snafu(visibility(pub(super)))]
    pub enum Error {
        #[snafu(display("Could not read input {:?}: {}", filename, source))]
        ReadInput {
           filename: std::path::PathBuf,
           source: std::io::Error,
           backtrace: Backtrace
        },
    }
}

Я смотрел на std::any::Any::downcast_ref, но это для понижения в структуру, а не для понижения объекта черты доеще одна черта объекта.Я хотел бы избежать перечисления всех возможных ошибок SNAFU конкретного типа в моем коде обработки ошибок.

Я мог бы заморозить себя, пока RFC 2504 (полностью) не будет (полностью) реализован, но, безусловно, есть какой-то способсделай это.

Ответы [ 2 ]

1 голос
/ 20 сентября 2019

A dyn Error имеет методы Error и ничего больше.Если обратный след не может быть выведен из этих методов, то откуда еще эта информация может поступить?

К сожалению, RFC 2504 еще не стабилизирован, поэтому вам нужно будет криогенно заморозить, по крайней мере, до Rust1,39, если вы хотите подождать.

0 голосов
/ 21 сентября 2019

Кажется, я пропустил это, потому что ночные std документы не были перекомпилированы, но #![feature(backtrace)] сейчас ночью.SNAFU по-прежнему необходимо добавить поддержку, поэтому я все еще застрял на том, чтобы все это заработало.

...