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

Add support for impl Traits and macro_rules! #1279

Open
JadKHaddad opened this issue Jan 6, 2025 · 3 comments
Open

Add support for impl Traits and macro_rules! #1279

JadKHaddad opened this issue Jan 6, 2025 · 3 comments
Labels
enhancement New feature or request

Comments

@JadKHaddad
Copy link

Consider the following state with some generic types:

#[derive(Debug, Clone)]
struct MyState<D, A, O> {
    database: D,
    auth: A,
    other: O,
}

trait DatabaseService {}

#[derive(Debug, Clone)]
struct DatabaseImpl {}

impl DatabaseService for DatabaseImpl {}

trait AuthService {}

#[derive(Debug, Clone)]
struct AuthImpl {}

impl AuthService for AuthImpl {}

trait OtherService {}

#[derive(Debug, Clone)]
struct OtherImpl;

impl OtherService for OtherImpl {}

Axum allows extracting the state with impl Traits:

async fn index(
    State(my_state): State<MyState<impl DatabaseService, impl AuthService, impl OtherService>>,
) -> String {
    String::from("Hi")
}

However, if we want to add a new generic type to the state or remove an old one, we have to adjust every route that uses the state, which can be very challenging. So let's define a macro that expands to our state and use it instead:

macro_rules! State {
    () => {
        MyState<impl DatabaseService, impl AuthService, impl OtherService>
    };
}

async fn index(State(my_state): State<State!()>) -> String {
    String::from("Hi")
}

Unfortunately, utoipa does not support either of the approaches above:

unexpected type in component part get type path, expected one of: Path, Tuple, Reference, Group, Array, Slice, TraitObject
@JadKHaddad JadKHaddad changed the title Add suppot for impl Traits and macro_rules! Add support for impl Traits and macro_rules! Jan 6, 2025
@juhaku
Copy link
Owner

juhaku commented Jan 6, 2025

Sure this would be enhancement for sure, but it needs some experimenting around. It might just be quick and simple thing to add but cannot state for sure.

@juhaku juhaku added the enhancement New feature or request label Jan 6, 2025
@JadKHaddad
Copy link
Author

The Impl Trait can be as easy as updating TypeTree::get_type_tree_values like:

//...
Type::ImplTrait(impl_trait) => impl_trait
        .bounds
        .iter()
        .find_map(|bound| match &bound {
            syn::TypeParamBound::Trait(trait_bound) => Some(&trait_bound.path),
            syn::TypeParamBound::Lifetime(_) => None,
            syn::TypeParamBound::Verbatim(_) => None,
            _ => todo!("TypeTree impl trait found unrecognized TypeParamBound"),
        })
        .map(|path| TypeTreeValueIter::once(TypeTreeValue::Path(path)))
        .unwrap_or_else(TypeTreeValueIter::empty)
//...

For the macro_rules!, I added

//...
Type::Macro(_) => TypeTreeValueIter::once(TypeTreeValue::UnitType)
//...

But I'm not sure, if this is the right way to do it

@juhaku
Copy link
Owner

juhaku commented Jan 6, 2025

Yup, something like that should be done, the macro_rules needs some experimenting on how and if possible to parse the macro rules body if necessary in first place.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants