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

feat!: Implement support for generic params #17

Draft
wants to merge 18 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 13 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 macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "async-generic"
version = "1.1.2"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this diff. This project uses release-plz (https://release-plz.dev/docs) to manage versioning and that infrastructure will automatically do the necessary updates at the time based on how the PR is labeled.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also questioning whether this PR meets the criteria for bumping to a 2.0. Under the rules of semantic versioning, that should only happen if there's an incompatible API change to the library. I see changes you've made to the async_signature parameter of the macro, but do the break compatibility? If not, let's make this a 1.2.0 release (which would involve removing the ! from the PR title as I've amended it).

Copy link
Author

@DanikVitek DanikVitek Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as I've described in the description of the commit 6d1b01e, the changes are indeed breaking.
async_signature(a: B) means, that the async function does not have a return type, while previously this meta tag affected only the input arguments

version = "2.0.0"
description = "Write code that can be both async and synchronous without duplicating it."
authors = ["Eric Scouten <[email protected]>"]
license = "MIT OR Apache-2.0"
Expand Down
109 changes: 109 additions & 0 deletions macros/src/async_generic_target/fn/kind.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use proc_macro2::{Ident, Span};
use syn::{punctuated::Punctuated, Attribute, FnArg, Generics, ReturnType, Token};

use crate::AsyncSignature;

pub struct Sync;

pub struct Async(pub(super) Option<AsyncSignature>);

pub trait Kind {
fn transform_constness(constness: Option<Token![const]>) -> Option<Token![const]> {
constness
}

fn asyncness() -> Option<Token![async]>;

fn extend_attrs(&mut self, attrs: Vec<Attribute>) -> Vec<Attribute> {
attrs
}

fn transform_ident(ident: Ident) -> Ident {
ident
}

fn transform_generics(&mut self, generics: Generics) -> Generics {
generics
}

fn transform_inputs(
&mut self,
inputs: Punctuated<FnArg, Token![,]>,
) -> Punctuated<FnArg, Token![,]> {
inputs
}

fn transform_output(&mut self, output: ReturnType) -> ReturnType {
output
}
}

impl Kind for Sync {
fn asyncness() -> Option<Token![async]> {
None
}
}

impl Kind for Async {
fn transform_constness(_constness: Option<Token!(const)>) -> Option<Token!(const)> {
None // TODO: retutn `constness` when `const async fn` is stabilized
}

fn asyncness() -> Option<Token![async]> {
Some(Token![async](Span::call_site()))
}

fn extend_attrs(&mut self, mut attrs: Vec<Attribute>) -> Vec<Attribute> {
if let Some(alt_attrs) = self
.0
.as_mut()
.map(|AsyncSignature { attributes, .. }| std::mem::take(attributes))
{
attrs.extend(alt_attrs);
}
attrs
}

fn transform_ident(ident: Ident) -> Ident {
Ident::new(&format!("{ident}_async"), ident.span())
}

fn transform_generics(&mut self, generics: Generics) -> Generics {
if let Some(alt_generics) = self
.0
.as_mut()
.map(|AsyncSignature { generics, .. }| std::mem::take(generics))
{
alt_generics
} else {
generics
}
}

fn transform_inputs(
&mut self,
inputs: Punctuated<FnArg, Token!(,)>,
) -> Punctuated<FnArg, Token!(,)> {
if let Some(alt_inputs) = self
.0
.as_mut()
.map(|AsyncSignature { inputs, .. }| std::mem::take(inputs))
{
alt_inputs
} else {
inputs
}
}

fn transform_output(&mut self, output: ReturnType) -> ReturnType {
if let Some(alt_output) = self.0.as_mut().map(|AsyncSignature { output, .. }| {
let mut default = ReturnType::Default;
std::mem::swap(output, &mut default);
default
}) {
alt_output
} else {
output
}
}
}
Loading
Loading