Merge pull request #19 from dtolnay/infer

Consolidate to one Context impl for Result to improve inference
This commit is contained in:
David Tolnay 2019-10-11 18:31:53 -07:00 committed by GitHub
commit 499e265ce3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 49 additions and 29 deletions

View File

@ -65,15 +65,49 @@ pub trait Context<T, E>: private::Sealed {
F: FnOnce() -> C;
}
mod ext {
use super::*;
pub trait StdError {
fn ext_context<C>(self, context: C) -> Error
where
C: Display + Send + Sync + 'static;
}
impl<E> StdError for E
where
E: std::error::Error + Send + Sync + 'static,
{
fn ext_context<C>(self, context: C) -> Error
where
C: Display + Send + Sync + 'static,
{
Error::new(ContextError {
error: self,
context,
})
}
}
impl StdError for Error {
fn ext_context<C>(self, context: C) -> Error
where
C: Display + Send + Sync + 'static,
{
self.context(context)
}
}
}
impl<T, E> Context<T, E> for Result<T, E>
where
E: StdError + Send + Sync + 'static,
E: ext::StdError + Send + Sync + 'static,
{
fn context<C>(self, context: C) -> Result<T, Error>
where
C: Display + Send + Sync + 'static,
{
self.map_err(|error| Error::new(ContextError { error, context }))
self.map_err(|error| error.ext_context(context))
}
fn with_context<C, F>(self, context: F) -> Result<T, Error>
@ -81,29 +115,7 @@ where
C: Display + Send + Sync + 'static,
F: FnOnce() -> C,
{
self.map_err(|error| {
Error::new(ContextError {
error,
context: context(),
})
})
}
}
impl<T> Context<T, Error> for Result<T, Error> {
fn context<C>(self, context: C) -> Result<T, Error>
where
C: Display + Send + Sync + 'static,
{
self.map_err(|error| error.context(context))
}
fn with_context<C, F>(self, context: F) -> Result<T, Error>
where
C: Display + Send + Sync + 'static,
F: FnOnce() -> C,
{
self.map_err(|error| error.context(context()))
self.map_err(|error| error.ext_context(context()))
}
}
@ -198,12 +210,10 @@ where
}
mod private {
use crate::Error;
use std::error::Error as StdError;
use super::*;
pub trait Sealed {}
impl<T, E> Sealed for Result<T, E> where E: StdError + Send + Sync + 'static {}
impl<T> Sealed for Result<T, Error> {}
impl<T, E> Sealed for Result<T, E> where E: ext::StdError {}
impl<T> Sealed for Option<T> {}
}

10
tests/test_context.rs Normal file
View File

@ -0,0 +1,10 @@
use anyhow::{Context, Result};
// https://github.com/dtolnay/anyhow/issues/18
#[test]
fn test_inference() -> Result<()> {
let x = "1";
let y: u32 = x.parse().context("...")?;
assert_eq!(y, 1);
Ok(())
}