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

WIP: Add generic async support #337

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft

Conversation

DanikVitek
Copy link

The conversation started in #150.
async-generic PR: scouten/async-generic#17

This implementation should be more flexible, as it allows for different runtimes and provides traits for manual implementation in case of any uncommon runtime.

@DanikVitek DanikVitek marked this pull request as draft January 21, 2025 23:21
@dj8yfo dj8yfo marked this pull request as ready for review January 22, 2025 06:49
@dj8yfo dj8yfo marked this pull request as draft January 22, 2025 06:50
@DanikVitek
Copy link
Author

Should the BorshDeserializeAsync and BorshSerializeAsync extend their sync counterparts and contain only async functions, or should they copy synchronous functions?

@DanikVitek
Copy link
Author

DanikVitek commented Jan 22, 2025

To support deserialize_with functionality for #[derive(BorshDeserializeAsync)], I guess, there should be a separate deserialize_with_async param. Same for the serialize counterpart

@dj8yfo
Copy link
Collaborator

dj8yfo commented Jan 22, 2025

@DanikVitek is this doable without async_trait import?
Not that's its too important to get rid of it, just want to know what are limitations not allowing to get rid of it, what are potential tradeoffs, etc.

@DanikVitek
Copy link
Author

DanikVitek commented Jan 22, 2025

@DanikVitek is this doable without async_trait import? Not that's its too important to get rid of it, just want to know what are limitations not allowing to get rid of it, what are potential tradeoffs, etc.

I guess, if there is no need for the traits to be dyn-compatible, then the only difficulty is making the async_generic generate async functions as sync functions, which return a custom impl Future, because the set MSRV does not yet support async functions in traits. As I can see, the BorshSerialize is not dyn-compatible, and there is no need for BorshDeserialize to be dyn-compatible, so I guess, the same could be true for the async counterparts.

If the MSRV bump is not an issue, then it's even easier

@DanikVitek
Copy link
Author

DanikVitek commented Jan 22, 2025

Ok, no. Both async in traits and -> impl Trait in traits (and hence, impl Future) require the MSRV 1.75. So all return types would still need to be pin-boxed and now we're just reimplementing the async_trait at this point

@dj8yfo
Copy link
Collaborator

dj8yfo commented Jan 23, 2025

@DanikVitek can you support your assertion that the return types will need to be pin-boxed anyway by doing a minimal example in a repo outside of this pr with the right trait (BorshSerializeAsync/BorshDeserializeAsync) signatures and msrv 1.75? I think the common convention is that you cannot bump MSRV in patch releases, but in minor version releases you're free to do so.


EDIT: if so (if they need to be pin-boxed anyway), i think we'll stick with async_trait approach for now, as we'll mark this feature unstable__async anyway to have some freedom in modifying it in the near future and middle-term

@dj8yfo
Copy link
Collaborator

dj8yfo commented Jan 23, 2025

Should the BorshDeserializeAsync and BorshSerializeAsync extend their sync counterparts and contain only async functions, or should they copy synchronous functions?

I think the traits should be completely separate and not extend sync counterparts and lib user should be free to only implement/derive a subset or all of them if he/she desires. I was under the impression it's the case now, maybe i'm mistaken.

@dj8yfo
Copy link
Collaborator

dj8yfo commented Jan 23, 2025

To support deserialize_with functionality for #[derive(BorshDeserializeAsync)], I guess, there should be a separate deserialize_with_async param. Same for the serialize counterpart

Before diving into doing derive for new traits, i'd stop and do some tests with snapshots. @DanikVitek, can you choose some subset of types, which you consider core to borsh , and make sure the async counterparts serialize/deserialize to the same snapthos that the sync interface produces in tests? You're free to modify test code, as long you double check that existing snapshots aren't touched/renamed. Ideally this should be done by pure addition (no replacements/deletions) of test code (not modifying existing tests) and just checking the new snapshots are equal to older ones. This way it would be easy to verify during review that existing serialization format, provided by stable borsh subset, hasn't changed. If the existing test code changes, it kind of needs more attention to verify the old tests still run at all.

It might be somewhat tedious to cover all existing (snapshot) tests at once, but that's one of the reason the feature should be made unstable__ for a while to kind of stress that sync and async interfaces may produce different results due to bugs/typos.

@dj8yfo
Copy link
Collaborator

dj8yfo commented Jan 23, 2025

To support deserialize_with functionality for #[derive(BorshDeserializeAsync)], I guess, there should be a separate deserialize_with_async param. Same for the serialize counterpart

It appears that all of bounds, serialize_with, deserialize_with proc-macro sub-attributes should be cloned to _async counterparts, maybe sharing some part of implementation with their sync versions. Maybe some other sub-attributes too, but these are the ones that come off the top of my head.

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

Successfully merging this pull request may close these issues.

2 participants