Skip to content

Commit

Permalink
Error crates refactoring (#48)
Browse files Browse the repository at this point in the history
* Reorganize error modules and add HasAsyncErrorType

* Add CanWrapError trait

* Implement RaiseFrom

* Implement DebugError and DisplayError

* Implement RaiseInfallible and ReturnError

* Implement PanicOnError

* Implement DiscardDetail

* Add #![no_std] to all crates

* Use no_std for cgp-component-macro-lib

* Add cgp-error-anyhow crate

* Reorganize anyhow impls

* Reorganize cgp-error-eyre

* Reorganize cgp-error-std

* Import from cgp_error::traits

* Add changelog

* Fix documentation
  • Loading branch information
soareschen authored Jan 5, 2025
1 parent 9a79e8e commit 7476276
Show file tree
Hide file tree
Showing 70 changed files with 509 additions and 105 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

## v0.3.0 (pre-release)

- Error crates refactoring - [#48](https://github.com/contextgeneric/cgp/pull/48)
- Remove `Async` trait bound from `HasErrorType::Error`.
- Introduce `HasAsyncErrorType` trait used for adding `Async` constraint to `HasErrorType::Error`.
- Introduce `CanWrapError` trait.
- Introduce generic `ErrorRaiser` providers in `cgp-error`.
- Rename and reoganize constructs in `cgp-error-eyre` and `cgp-error-std`.
- Introduce `cgp-error-anyhow` crate.

- Decouple component and field macro crates from the library crates - [#47](https://github.com/contextgeneric/cgp/pull/47)
- Remove `cgp-component-macro` crate from being a dependency of `cgp-component`.
- Remove `cgp-field-macro` crate from being a dependency of `cgp-field`.
Expand Down
14 changes: 14 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ members = [
"crates/cgp-field-macro",
"crates/cgp-field-macro-lib",
"crates/cgp-error",
"crates/cgp-error-anyhow",
"crates/cgp-error-eyre",
"crates/cgp-error-std",
"crates/cgp-run",
Expand Down
3 changes: 3 additions & 0 deletions crates/cgp-async-macro/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#![no_std]

/*!
This library provides helper macros for using async functions in traits.
*/

extern crate alloc;
extern crate proc_macro;

use proc_macro::TokenStream;
Expand Down
1 change: 1 addition & 0 deletions crates/cgp-async-macro/src/strip_async.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::vec::Vec;
use proc_macro2::{Group, TokenStream, TokenTree};
use syn::parse::{Parse, ParseStream};
use syn::token::{Async, Await, Dot, Fn};
Expand Down
2 changes: 2 additions & 0 deletions crates/cgp-async/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![no_std]

pub mod traits;

pub use traits::{Async, MaybeSend, MaybeStatic, MaybeSync};
Expand Down
22 changes: 1 addition & 21 deletions crates/cgp-async/src/traits/async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,7 @@ use crate::traits::sync::MaybeSync;

/**
This is defined as a convenient constraint alias to
`Sized + Send + Sync + 'static`.
This constraint is commonly required to be present in almost all associated
types. The `Sized` constraint is commonly required for associated types to be
used as generic parameters. The `Send + Sync + 'static` constraints are
important for the use of async functions inside traits.
Because Rust do not currently natively support the use of async functions
in traits, we use the [`async_trait`] crate to desugar async functions
inside traits into functions returning
`Pin<Box<dyn Future + Send>>`. Due to the additional `Send` and lifetime
trait bounds inside the returned boxed future, almost all values that are
used inside the async functions are required to have types that implement
`Send` and `Sync`.
It is also common to require the associated types to have the `'static`
lifetime for them to be used inside async functions, because Rust would
otherwise infer a more restrictive lifetime that does not outlive the
async functions. The `'static` lifetime constraint here really means
that the types implementing `Async` must not contain any lifetime
parameter.
`Send + Sync + 'static`.
*/
pub trait Async: MaybeSend + MaybeSync + MaybeStatic {}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use alloc::boxed::Box;
use alloc::vec;
use alloc::vec::Vec;
use syn::{parse_quote, Generics, ImplItem, ImplItemType, ItemImpl, Path, Type};

use crate::delegate_components::ast::{ComponentAst, DelegateEntriesAst};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::format;
use proc_macro2::Span;
use quote::ToTokens;
use syn::parse::{Parse, ParseStream};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use alloc::boxed::Box;
use alloc::vec::Vec;
use syn::punctuated::Punctuated;
use syn::token::{Brace, Comma, For, Impl, Plus};
use syn::{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::vec::Vec;
use proc_macro2::TokenStream;
use quote::quote;
use syn::{parse_quote, ImplItemFn, Signature, TypePath, Visibility};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::BTreeMap;
use alloc::collections::BTreeMap;

use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use alloc::boxed::Box;
use alloc::vec::Vec;
use proc_macro2::Span;
use syn::punctuated::Punctuated;
use syn::token::{Brace, Comma, For, Impl, Plus};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::vec::Vec;
use syn::punctuated::Punctuated;
use syn::{parse_quote, Ident, ItemTrait, TraitItem};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::vec::Vec;
use itertools::Itertools;
use proc_macro2::{Group, Ident, TokenStream, TokenTree};
use quote::{format_ident, ToTokens};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::string::{String, ToString};
use proc_macro2::Span;
use syn::Ident;

Expand Down
1 change: 1 addition & 0 deletions crates/cgp-component-macro-lib/src/for_each_replace.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::vec::Vec;
use proc_macro2::{Group, TokenStream, TokenTree};
use quote::{quote, ToTokens};
use syn::__private::parse_brackets;
Expand Down
4 changes: 4 additions & 0 deletions crates/cgp-component-macro-lib/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
#![no_std]

/*!
This is an internal crate used by the `cgp-component-macro` crate. We implement the
proc macros for `cgp-component` as a library, so that it can be more easily tested.
The constructs are then re-exported as proc macros in the `cgp-component-macro` crate,
which is defined as a proc macro crate.
*/

extern crate alloc;

pub mod delegate_components;
pub mod derive_component;
pub mod for_each_replace;
Expand Down
2 changes: 2 additions & 0 deletions crates/cgp-component-macro-lib/src/preset/define_preset.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use alloc::format;
use alloc::string::ToString;
use proc_macro2::{Span, TokenStream};
use quote::ToTokens;
use syn::{parse_quote, Ident, ItemTrait};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::vec::Vec;
use syn::{parse_quote, Generics, Ident, ItemImpl, Type};

use crate::delegate_components::ast::{ComponentAst, DelegateEntriesAst};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use quote::quote;

use crate::delegate_components;
use crate::tests::helper::equal::equal_token_stream;
use crate::tests::helper::format::format_token_stream;

#[test]
fn test_basic_delegate_components() {
Expand Down Expand Up @@ -50,8 +49,6 @@ fn test_delegate_components_containing_generics() {
})
.unwrap();

println!("derived: {}", format_token_stream(&derived));

let expected = quote! {
impl<'a, FooParamA, FooParamB: FooConstraint> DelegateComponent<BarComponentA>
for FooComponents<'a, FooParamA, FooParamB> {
Expand Down
1 change: 1 addition & 0 deletions crates/cgp-component-macro-lib/src/tests/helper/format.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use alloc::string::{String, ToString};
use prettyplease::unparse;
use proc_macro2::TokenStream;
use syn::parse_file;
Expand Down
2 changes: 2 additions & 0 deletions crates/cgp-component-macro/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![no_std]

/*!
This crate provides the proc macros used for defining CGP components.
*/
Expand Down
1 change: 0 additions & 1 deletion crates/cgp-component/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

/*!
This crate defines the core CGP traits, [`DelegateComponent`] and [`HasComponents`].
It also re-export component macros provided by [`cgp_component_macro`].
*/

pub mod traits;
Expand Down
2 changes: 1 addition & 1 deletion crates/cgp-core/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ pub use cgp_component::{DelegateComponent, HasComponents};
pub use cgp_component_macro::{
cgp_component, cgp_preset, delegate_components, for_each_replace, replace_with,
};
pub use cgp_error::{CanRaiseError, HasErrorType};
pub use cgp_error::traits::{CanRaiseError, CanWrapError, HasErrorType};
pub use cgp_field::{Char, Cons, Either, HasField, HasFieldMut, Nil, Void};
pub use cgp_field_macro::{product, symbol, HasField, Product, Sum};
16 changes: 16 additions & 0 deletions crates/cgp-error-anyhow/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[package]
name = "cgp-error-anyhow"
version = "0.2.0"
edition = { workspace = true }
license = { workspace = true }
repository = { workspace = true }
authors = { workspace = true }
rust-version = { workspace = true }
keywords = { workspace = true }
description = """
Context-generic programming error handlers implemented using eyre
"""

[dependencies]
cgp-core = { version = "0.2.0", default-features = false }
anyhow = { version = "1.0.95", default-features = false }
17 changes: 17 additions & 0 deletions crates/cgp-error-anyhow/src/impls/debug_error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use core::fmt::Debug;

use anyhow::{anyhow, Error};
use cgp_core::error::ErrorRaiser;
use cgp_core::prelude::*;

pub struct DebugAnyhowError;

impl<Context, E> ErrorRaiser<Context, E> for DebugAnyhowError
where
Context: HasErrorType<Error = Error>,
E: Debug,
{
fn raise_error(e: E) -> Error {
anyhow!("{:?}", e)
}
}
17 changes: 17 additions & 0 deletions crates/cgp-error-anyhow/src/impls/display_error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use core::fmt::Display;

use anyhow::{anyhow, Error};
use cgp_core::error::ErrorRaiser;
use cgp_core::prelude::*;

pub struct DisplayAnyhowError;

impl<Context, E> ErrorRaiser<Context, E> for DisplayAnyhowError
where
Context: HasErrorType<Error = Error>,
E: Display,
{
fn raise_error(e: E) -> Error {
anyhow!("{e}")
}
}
9 changes: 9 additions & 0 deletions crates/cgp-error-anyhow/src/impls/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pub mod debug_error;
pub mod display_error;
pub mod raise_anyhow_error;
pub mod use_anyhow_error;

pub use debug_error::*;
pub use display_error::*;
pub use raise_anyhow_error::*;
pub use use_anyhow_error::*;
17 changes: 17 additions & 0 deletions crates/cgp-error-anyhow/src/impls/raise_anyhow_error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use core::error::Error as StdError;

use anyhow::Error;
use cgp_core::error::ErrorRaiser;
use cgp_core::prelude::*;

pub struct RaiseAnyhowError;

impl<Context, E> ErrorRaiser<Context, E> for RaiseAnyhowError
where
Context: HasErrorType<Error = Error>,
E: StdError + Send + Sync + 'static,
{
fn raise_error(e: E) -> Error {
e.into()
}
}
8 changes: 8 additions & 0 deletions crates/cgp-error-anyhow/src/impls/use_anyhow_error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use anyhow::Error;
use cgp_core::error::ProvideErrorType;

pub struct UseAnyhowError;

impl<Context> ProvideErrorType<Context> for UseAnyhowError {
type Error = Error;
}
5 changes: 5 additions & 0 deletions crates/cgp-error-anyhow/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#![no_std]

pub mod impls;

pub use impls::*;
2 changes: 1 addition & 1 deletion crates/cgp-error-eyre/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ description = """

[dependencies]
cgp-core = { version = "0.2.0", default-features = false }
eyre = { version = "0.6.11" }
eyre = { version = "0.6.12", default-features = false }
17 changes: 17 additions & 0 deletions crates/cgp-error-eyre/src/impls/debug_error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use core::fmt::Debug;

use cgp_core::error::ErrorRaiser;
use cgp_core::prelude::*;
use eyre::{eyre, Error};

pub struct DebugEyreError;

impl<Context, E> ErrorRaiser<Context, E> for DebugEyreError
where
Context: HasErrorType<Error = Error>,
E: Debug,
{
fn raise_error(e: E) -> Error {
eyre!("{:?}", e)
}
}
17 changes: 17 additions & 0 deletions crates/cgp-error-eyre/src/impls/display_error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use core::fmt::Display;

use cgp_core::error::ErrorRaiser;
use cgp_core::prelude::*;
use eyre::{eyre, Error};

pub struct DisplayEyreError;

impl<Context, E> ErrorRaiser<Context, E> for DisplayEyreError
where
Context: HasErrorType<Error = Error>,
E: Display,
{
fn raise_error(e: E) -> Error {
eyre!("{e}")
}
}
9 changes: 9 additions & 0 deletions crates/cgp-error-eyre/src/impls/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pub mod debug_error;
pub mod display_error;
pub mod raise_eyre_error;
pub mod use_eyre_error;

pub use debug_error::*;
pub use display_error::*;
pub use raise_eyre_error::*;
pub use use_eyre_error::*;
17 changes: 17 additions & 0 deletions crates/cgp-error-eyre/src/impls/raise_eyre_error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use core::error::Error as StdError;

use cgp_core::error::ErrorRaiser;
use cgp_core::prelude::*;
use eyre::Error;

pub struct RaiseEyreError;

impl<Context, E> ErrorRaiser<Context, E> for RaiseEyreError
where
Context: HasErrorType<Error = Error>,
E: StdError + Send + Sync + 'static,
{
fn raise_error(e: E) -> Error {
e.into()
}
}
Loading

0 comments on commit 7476276

Please sign in to comment.