Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to nightly's new Error::provide API #319

Merged
merged 1 commit into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ backtrace = { version = "0.3.51", optional = true }
futures = { version = "0.3", default-features = false }
rustversion = "1.0.6"
syn = { version = "2.0", features = ["full"] }
thiserror = "1.0"
thiserror = "1.0.45"
trybuild = { version = "1.0.66", features = ["diff"] }

[lib]
Expand Down
47 changes: 18 additions & 29 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,49 +11,38 @@ compile_error! {
"`backtrace` feature without `std` feature is not supported"
}

// This code exercises the surface area that we expect of the std Backtrace
// type. If the current toolchain is able to compile it, we go ahead and use
// backtrace in anyhow.
// This code exercises the surface area that we expect of the Error generic
// member access API. If the current toolchain is able to compile it, then
// anyhow is able to provide backtrace support.
const PROBE: &str = r#"
#![feature(error_generic_member_access, provide_any)]
#![feature(error_generic_member_access)]

use std::any::{Demand, Provider};
use std::backtrace::{Backtrace, BacktraceStatus};
use std::error::Error;
use std::fmt::{self, Display};
use std::backtrace::Backtrace;
use std::error::{self, Error, Request};
use std::fmt::{self, Debug, Display};

#[derive(Debug)]
struct E {
backtrace: Backtrace,
}
struct MyError(Thing);
struct Thing;

impl Display for E {
impl Debug for MyError {
fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result {
unimplemented!()
}
}

impl Error for E {
fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
demand.provide_ref(&self.backtrace);
impl Display for MyError {
fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result {
unimplemented!()
}
}

struct P;

impl Provider for P {
fn provide<'a>(&'a self, _demand: &mut Demand<'a>) {}
}

const _: fn() = || {
let backtrace: Backtrace = Backtrace::capture();
let status: BacktraceStatus = backtrace.status();
match status {
BacktraceStatus::Captured | BacktraceStatus::Disabled | _ => {}
impl Error for MyError {
fn provide<'a>(&'a self, request: &mut Request<'a>) {
request.provide_ref(&self.0);
}
};
}

const _: fn(&dyn Error) -> Option<&Backtrace> = |err| err.request_ref::<Backtrace>();
const _: fn(&dyn Error) -> Option<&Backtrace> = |err| error::request_ref::<Backtrace>(err);
"#;

fn main() {
Expand Down
2 changes: 1 addition & 1 deletion src/backtrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ macro_rules! backtrace {
#[cfg(backtrace)]
macro_rules! backtrace_if_absent {
($err:expr) => {
match ($err as &dyn std::error::Error).request_ref::<std::backtrace::Backtrace>() {
match std::error::request_ref::<std::backtrace::Backtrace>($err as &dyn std::error::Error) {
Some(_) => None,
None => backtrace!(),
}
Expand Down
10 changes: 5 additions & 5 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use core::convert::Infallible;
use core::fmt::{self, Debug, Display, Write};

#[cfg(backtrace)]
use std::any::{Demand, Provider};
use std::error::Request;

mod ext {
use super::*;
Expand Down Expand Up @@ -144,8 +144,8 @@ where
}

#[cfg(backtrace)]
fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
StdError::provide(&self.error, demand);
fn provide<'a>(&'a self, request: &mut Request<'a>) {
StdError::provide(&self.error, request);
}
}

Expand All @@ -158,8 +158,8 @@ where
}

#[cfg(backtrace)]
fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
Provider::provide(&self.error, demand);
fn provide<'a>(&'a self, request: &mut Request<'a>) {
Error::provide(&self.error, request);
}
}

Expand Down
30 changes: 17 additions & 13 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ use crate::ptr::Mut;
use crate::ptr::{Own, Ref};
use crate::{Error, StdError};
use alloc::boxed::Box;
#[cfg(backtrace)]
use core::any::Demand;
use core::any::TypeId;
use core::fmt::{self, Debug, Display};
use core::mem::ManuallyDrop;
#[cfg(not(anyhow_no_ptr_addr_of))]
use core::ptr;
use core::ptr::NonNull;
#[cfg(backtrace)]
use std::error::{self, Request};

#[cfg(feature = "std")]
use core::ops::{Deref, DerefMut};
Expand Down Expand Up @@ -522,17 +522,21 @@ impl Error {
Some(addr.cast::<E>().deref_mut())
}
}
}

#[cfg(backtrace)]
impl std::any::Provider for Error {
#[cfg(backtrace)]
pub(crate) fn provide<'a>(&'a self, request: &mut Request<'a>) {
unsafe { ErrorImpl::provide(self.inner.by_ref(), request) }
}

// Called by thiserror when you have `#[source] anyhow::Error`. This provide
// implementation includes the anyhow::Error's Backtrace if any, unlike
// deref'ing to dyn Error where the provide implementation would include
// only the original error's Backtrace from before it got wrapped into an
// anyhow::Error.
fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
unsafe { ErrorImpl::provide(self.inner.by_ref(), demand) }
#[cfg(backtrace)]
#[doc(hidden)]
pub fn thiserror_provide<'a>(&'a self, request: &mut Request<'a>) {
Self::provide(self, request);
}
}

Expand Down Expand Up @@ -900,19 +904,19 @@ impl ErrorImpl {
.as_ref()
.or_else(|| {
#[cfg(backtrace)]
return Self::error(this).request_ref::<Backtrace>();
return error::request_ref::<Backtrace>(Self::error(this));
#[cfg(not(backtrace))]
return (vtable(this.ptr).object_backtrace)(this);
})
.expect("backtrace capture failed")
}

#[cfg(backtrace)]
unsafe fn provide<'a>(this: Ref<'a, Self>, demand: &mut Demand<'a>) {
unsafe fn provide<'a>(this: Ref<'a, Self>, request: &mut Request<'a>) {
if let Some(backtrace) = &this.deref().backtrace {
demand.provide_ref(backtrace);
request.provide_ref(backtrace);
}
Self::error(this).provide(demand);
Self::error(this).provide(request);
}

#[cold]
Expand All @@ -930,8 +934,8 @@ where
}

#[cfg(backtrace)]
fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
unsafe { ErrorImpl::provide(self.erase(), demand) }
fn provide<'a>(&'a self, request: &mut Request<'a>) {
unsafe { ErrorImpl::provide(self.erase(), request) }
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@
//! non-Anyhow error type inside a function that returns Anyhow's error type.

#![doc(html_root_url = "https://docs.rs/anyhow/1.0.72")]
#![cfg_attr(backtrace, feature(error_generic_member_access, provide_any))]
#![cfg_attr(backtrace, feature(error_generic_member_access))]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![cfg_attr(not(feature = "std"), no_std)]
#![deny(dead_code, unused_imports, unused_mut)]
Expand Down
6 changes: 3 additions & 3 deletions src/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::StdError;
use core::fmt::{self, Debug, Display};

#[cfg(backtrace)]
use std::any::Demand;
use std::error::Request;

#[repr(transparent)]
pub struct MessageError<M>(pub M);
Expand Down Expand Up @@ -75,7 +75,7 @@ impl StdError for BoxedError {
}

#[cfg(backtrace)]
fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
self.0.provide(demand);
fn provide<'a>(&'a self, request: &mut Request<'a>) {
self.0.provide(request);
}
}