Skip to content

Commit

Permalink
Merge pull request #443 from shepmaster/report-return-inference
Browse files Browse the repository at this point in the history
Improve how the `report` macro handles return type inference
  • Loading branch information
shepmaster authored Mar 11, 2024
2 parents 752e2f7 + 76cb8a4 commit e9cef85
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 28 deletions.
2 changes: 2 additions & 0 deletions compatibility-tests/futures/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ edition = "2018"

[dependencies]
snafu = { path = "../..", features = ["futures"] }
async-std = { version = "1.12.0", features = ["attributes"] }
futures = "0.3.0"
tokio = { version = "1.0", features = ["macros", "rt"] }
1 change: 1 addition & 0 deletions compatibility-tests/futures/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![cfg(test)]

mod location;
mod report;

mod api {
use futures::{stream, StreamExt, TryStream};
Expand Down
83 changes: 83 additions & 0 deletions compatibility-tests/futures/src/report.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use snafu::{prelude::*, Report};

#[derive(Debug, Snafu)]
struct Error;

#[test]
fn tokio_main_attribute_first() {
#[tokio::main(flavor = "current_thread")]
#[snafu::report]
async fn mainlike() -> Result<(), Error> {
Snafu.fail()
}

let _: Report<_> = mainlike();
}

#[test]
fn tokio_main_attribute_last() {
#[snafu::report]
#[tokio::main(flavor = "current_thread")]
async fn mainlike() -> Result<(), Error> {
Snafu.fail()
}

let _: Report<_> = mainlike();
}

#[tokio::test]
#[snafu::report]
async fn tokio_test_attribute_first() -> Result<(), Error> {
Ok(())
}

#[snafu::report]
#[tokio::test]
async fn tokio_test_attribute_last() -> Result<(), Error> {
Ok(())
}

#[test]
fn async_std_main_attribute_last() {
#[derive(Debug, Snafu)]
struct Error;

#[snafu::report]
#[async_std::main]
async fn main() -> Result<(), Error> {
Snafu.fail()
}

let _: Report<_> = main();
}

#[snafu::report]
#[async_std::test]
async fn async_std_test_attribute_last() -> Result<(), Error> {
Ok(())
}

#[test]
fn works_with_tough_inference() {
#[derive(Debug, Snafu)]
struct InnerError;

#[derive(Debug, Snafu)]
struct OuterError {
source: InnerError,
}

fn inner() -> Result<(), InnerError> {
InnerSnafu.fail()
}

#[snafu::report]
#[tokio::main(flavor = "current_thread")]
async fn mainlike() -> Result<(), OuterError> {
loop {
inner().context(OuterSnafu)?;
}
}

let _: Report<_> = mainlike();
}
47 changes: 19 additions & 28 deletions snafu-derive/src/report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,37 +51,28 @@ pub fn body(
quote! { -> ::core::result::Result<(), ::snafu::Report<#error_ty>> }
};

#[allow(clippy::collapsible_else_if)]
let block = if asyncness.is_some() {
if cfg!(feature = "rust_1_61") {
quote! {
{
let __snafu_body = async #block;
<::snafu::Report<_> as ::core::convert::From<_>>::from(__snafu_body.await)
}
}
} else {
quote! {
{
let __snafu_body = async #block;
::core::result::Result::map_err(__snafu_body.await, ::snafu::Report::from_error)
}
let captured_original_body = if asyncness.is_some() {
quote! { async #block.await }
} else {
quote! { (|| #block)() }
};

let ascribed_original_result = quote! {
let __snafu_body: #output_ty = #captured_original_body;
};

let block = if cfg!(feature = "rust_1_61") {
quote! {
{
#ascribed_original_result;
<::snafu::Report<_> as ::core::convert::From<_>>::from(__snafu_body)
}
}
} else {
if cfg!(feature = "rust_1_61") {
quote! {
{
let __snafu_body = || #block;
<::snafu::Report<_> as ::core::convert::From<_>>::from(__snafu_body())
}
}
} else {
quote! {
{
let __snafu_body = || #block;
::core::result::Result::map_err(__snafu_body(), ::snafu::Report::from_error)
}
quote! {
{
#ascribed_original_result;
::core::result::Result::map_err(__snafu_body, ::snafu::Report::from_error)
}
}
};
Expand Down
24 changes: 24 additions & 0 deletions tests/report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,30 @@ fn procedural_macro_works_with_result_return_type() {
let _: Report<Error> = mainlike_result();
}

#[test]
fn procedural_macro_works_with_tough_inference() {
#[derive(Debug, Snafu)]
struct InnerError;

#[derive(Debug, Snafu)]
struct OuterError {
source: InnerError,
}

fn inner() -> Result<(), InnerError> {
InnerSnafu.fail()
}

#[snafu::report]
fn mainlike_result() -> Result<(), OuterError> {
loop {
inner().context(OuterSnafu)?;
}
}

let _: Report<_> = mainlike_result();
}

#[test]
fn termination_returns_failure_code() {
use std::process::Termination;
Expand Down

0 comments on commit e9cef85

Please sign in to comment.