Skip to content

Commit

Permalink
Support async-generic feature flags in cgp-async (#37)
Browse files Browse the repository at this point in the history
* Add cargo feature flags for cgp-async

* Propagate default features for cgp-async

* Add full feature to cgp and cgp-core

* Fix cgp-error-eyre when default-features = false

* Add changelog
  • Loading branch information
soareschen authored Dec 7, 2024
1 parent fdeaa90 commit 106990f
Show file tree
Hide file tree
Showing 25 changed files with 137 additions and 51 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ jobs:
name: clippy-all-features
token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features --all-targets -- -D warnings
- uses: actions-rs/clippy-check@v1
with:
name: clippy-no-default-features
token: ${{ secrets.GITHUB_TOKEN }}
args: --no-default-features --all-targets -- -D warnings

test:
runs-on: ubuntu-latest
Expand Down
21 changes: 20 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,26 @@

## Pre-Release

- Introduce new cgp-field constructs [#36](https://github.com/contextgeneric/cgp/pull/36)
- Support async-generic feature flags in cgp-async - [#37](https://github.com/contextgeneric/cgp/pull/37)
- Introduce the following feature flags to `cgp-async`:
- `async`
- `send`
- `sync`
- `static`
- `full` - default feature with all enabled
- Introduce the following traits in `cgp-async`:
- `MaybeSend` - alias to `Send` when the `send` feature is enabled, otherwise nothing.
- `MaybeSync` - alias to `Sync` when the `sync` feature is enabled, otherwise nothing.
- `MaybeStatic` - alias to `'static` when the `static` feature is enabled, otherwise nothing.
- Update the `Async` trait from `Sized + Send + Sync + 'static` to `MaybeSend + MaybeSync + MaybeStatic`.
- The `Sized` constraint is removed from `Async` to allow use inside `dyn` traits.
- Update the `#[async_trait]` macro to desugar async functions to return `impl Future<Output: MaybeSend>`.
- Use of `#[async_trait]` now requires import of `cgp::prelude::*` to allow `MaybeSend` to be auto imported.
- `cgp-async` now re-exports `cgp_sync::strip_async` if the `async` feature is not enabled.
- i.e. async functions are desugared into sync functions if the `async` feature is disabled.
- Crates such as `cgp` and `cgp-core` offers the `full` feature, which can be disabled to disable the indirect default features in `cgp-async`.

- Introduce new cgp-field constructs - [#36](https://github.com/contextgeneric/cgp/pull/36)
- Introduce the product type constructs `Cons` and `Nil`.
- Introduce the sum type constructs `Either` and `Void`.
- Introduce the `Field` type for tagged field value.
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion crates/cgp-async-macro/src/impl_async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub fn impl_async(item: TokenStream) -> TokenStream {
};

let impl_return: ReturnType = parse_quote! {
-> impl ::core::future::Future<Output = #return_type> + Send
-> impl ::core::future::Future<Output = #return_type> + MaybeSend
};

trait_fn.sig.output = impl_return;
Expand Down
14 changes: 14 additions & 0 deletions crates/cgp-async/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,19 @@ description = """
Async-generic primitives to support both sync/async in context-generic programming
"""

[features]
default = [ "full" ]
full = [
"async",
"send",
"sync",
"static",
]
async = []
send = [ "async" ]
sync = [ "async" ]
static = [ "async" ]

[dependencies]
cgp-async-macro = { version = "0.1.0" }
cgp-sync = { version = "0.1.0" }
32 changes: 6 additions & 26 deletions crates/cgp-async/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,9 @@
pub use cgp_async_macro::native_async as async_trait;

/**
This is defined as a convenient constraint alias to
`Sized + Send + Sync + 'static`.
pub mod traits;

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.
pub use traits::{Async, MaybeSend, MaybeStatic, MaybeSync};

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.
*/
pub trait Async: Send + Sync + 'static {}
#[cfg(feature = "async")]
pub use cgp_async_macro::native_async as async_trait;

impl<A> Async for A where A: Send + Sync + 'static {}
#[cfg(not(feature = "async"))]
pub use cgp_sync::async_trait;
31 changes: 31 additions & 0 deletions crates/cgp-async/src/traits/async.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use crate::traits::r#static::MaybeStatic;
use crate::traits::send::MaybeSend;
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.
*/
pub trait Async: MaybeSend + MaybeSync + MaybeStatic {}

impl<A> Async for A where A: MaybeSend + MaybeSync + MaybeStatic {}
9 changes: 9 additions & 0 deletions crates/cgp-async/src/traits/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pub mod r#async;
pub mod send;
pub mod r#static;
pub mod sync;

pub use r#async::Async;
pub use r#static::MaybeStatic;
pub use send::MaybeSend;
pub use sync::MaybeSync;
8 changes: 8 additions & 0 deletions crates/cgp-async/src/traits/send.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#[cfg(feature = "send")]
pub use core::marker::Send as MaybeSend;

#[cfg(not(feature = "send"))]
pub trait MaybeSend {}

#[cfg(not(feature = "send"))]
impl<T> MaybeSend for T {}
11 changes: 11 additions & 0 deletions crates/cgp-async/src/traits/static.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#[cfg(feature = "static")]
pub trait MaybeStatic: 'static {}

#[cfg(feature = "static")]
impl<T: 'static> MaybeStatic for T {}

#[cfg(not(feature = "static"))]
pub trait MaybeStatic {}

#[cfg(not(feature = "static"))]
impl<T> MaybeStatic for T {}
8 changes: 8 additions & 0 deletions crates/cgp-async/src/traits/sync.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#[cfg(feature = "sync")]
pub use core::marker::Sync as MaybeSync;

#[cfg(not(feature = "sync"))]
pub trait MaybeSync {}

#[cfg(not(feature = "sync"))]
impl<T> MaybeSync for T {}
1 change: 0 additions & 1 deletion crates/cgp-component/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,4 @@ description = """
"""

[dependencies]
cgp-async = { version = "0.1.0" }
cgp-component-macro = { version = "0.1.0" }
1 change: 0 additions & 1 deletion crates/cgp-component/src/traits/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
pub mod delegate_component;
pub mod has_components;
pub mod sync;

pub use delegate_component::DelegateComponent;
pub use has_components::HasComponents;
1 change: 0 additions & 1 deletion crates/cgp-component/src/traits/sync.rs

This file was deleted.

6 changes: 5 additions & 1 deletion crates/cgp-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ description = """
Context-generic programming core traits
"""

[features]
default = [ "full" ]
full = [ "cgp-async/full" ]

[dependencies]
cgp-async = { version = "0.1.0" }
cgp-async = { version = "0.1.0", default-features = false }
cgp-component = { version = "0.1.0" }
cgp-type = { version = "0.1.0" }
cgp-error = { version = "0.1.0" }
Expand Down
2 changes: 1 addition & 1 deletion crates/cgp-core/src/prelude.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub use cgp_async::{async_trait, Async};
pub use cgp_async::{async_trait, Async, MaybeSend, MaybeStatic, MaybeSync};
pub use cgp_component::{
define_components, delegate_components, derive_component, DelegateComponent, HasComponents,
};
Expand Down
2 changes: 1 addition & 1 deletion crates/cgp-error-eyre/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ description = """
"""

[dependencies]
cgp-core = { version = "0.1.0" }
cgp-core = { version = "0.1.0", default-features = false }
eyre = { version = "0.6.11" }
7 changes: 2 additions & 5 deletions crates/cgp-error-eyre/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ use eyre::{eyre, Report};

pub struct ProvideEyreError;

impl<Context> ProvideErrorType<Context> for ProvideEyreError
where
Context: Async,
{
impl<Context> ProvideErrorType<Context> for ProvideEyreError {
type Error = Report;
}

Expand All @@ -19,7 +16,7 @@ pub struct RaiseStdError;
impl<Context, E> ErrorRaiser<Context, E> for RaiseStdError
where
Context: HasErrorType<Error = Report>,
E: StdError + Async,
E: StdError + Send + Sync + 'static,
{
fn raise_error(e: E) -> Report {
e.into()
Expand Down
2 changes: 1 addition & 1 deletion crates/cgp-error-std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ description = """
"""

[dependencies]
cgp-core = { version = "0.1.0" }
cgp-core = { version = "0.1.0", default-features = false }
2 changes: 1 addition & 1 deletion crates/cgp-error/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ description = """
"""

[dependencies]
cgp-async = { version = "0.1.0" }
cgp-async = { version = "0.1.0", default-features = false }
cgp-component = { version = "0.1.0" }
cgp-type = { version = "0.1.0" }
1 change: 0 additions & 1 deletion crates/cgp-inner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,4 @@ description = """
"""

[dependencies]
cgp-async = { version = "0.1.0" }
cgp-component = { version = "0.1.0" }
5 changes: 2 additions & 3 deletions crates/cgp-inner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@

extern crate alloc;

use cgp_async::Async;
use cgp_component::{derive_component, DelegateComponent, HasComponents};

#[derive_component(InnerComponent, ProvideInner<Context>)]
pub trait HasInner: Async {
type Inner: Async;
pub trait HasInner {
type Inner;

fn inner(&self) -> &Self::Inner;
}
2 changes: 1 addition & 1 deletion crates/cgp-run/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ description = """
"""

[dependencies]
cgp-async = { version = "0.1.0" }
cgp-async = { version = "0.1.0", default-features = false }
cgp-error = { version = "0.1.0" }
cgp-component = { version = "0.1.0" }
4 changes: 2 additions & 2 deletions crates/cgp-run/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ extern crate alloc;
#[allow(unused_imports)]
use alloc::boxed::Box;

use cgp_async::{async_trait, Async};
use cgp_component::{derive_component, DelegateComponent, HasComponents};
use cgp_async::*;
use cgp_component::*;
use cgp_error::HasErrorType;

#[derive_component(RunnerComponent, Runner<Context>)]
Expand Down
7 changes: 6 additions & 1 deletion crates/cgp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ description = """
Context-generic programming meta crate
"""

[features]
default = [ "full" ]
full = [ "cgp-async/full" ]

[dependencies]
cgp-core = { version = "0.1.0" }
cgp-async = { version = "0.1.0", default-features = false }
cgp-core = { version = "0.1.0", default-features = false }
cgp-extra = { version = "0.1.0" }

0 comments on commit 106990f

Please sign in to comment.