-
Notifications
You must be signed in to change notification settings - Fork 172
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
Allow trait bounds to be overridden in macro #808
Conversation
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
type ExampleHash = [u8; 32]; | ||
|
||
pub trait Config { | ||
type Hash: Send + Sync + 'static; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC: before/"currently" we add the trait bound the entire trait right?
Can you just verify that we don't add trait bounds on associated types that are not used in the RPC trait?
such as:
pub trait Config {
type Hash: Send + Sync + 'static;
type NotUsed;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debugging the proc-macro, it seems that "currently" (without custom bounds
attribute):
pub trait Config {
type Hash: Send + Sync + 'static;
type NotUsed;
}
#[rpc(server, namespace = "foo")]
pub trait Rpc<Conf: Config> {
#[method(name = "bar")]
fn method(&self) -> Result<Conf::Hash, Error>;
}
The rpc
macro implies just: Conf : Send + Sync + 'static + jsonrpsee :: core :: Serialize
.
Although, this fails to compile due to:
55 | #[rpc(server, client, namespace = "foo", client_bounds(Conf::Hash: jsonrpsee::core::DeserializeOwned))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Serialize` is not implemented for `<Conf as Config>::Hash`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's fine I meant with the overrides for the Hash
pub trait Config {
type Hash: Send + Sync + 'static;
type NotUsed;
}
#[rpc(server, client, client_bounds(Conf::Hash: jsonrpsee::core::Serialize))]
pub trait Rpc<Conf: Config> {
#[method(name = "bar")]
fn method(&self) -> Result<Conf::Hash, Error>;
}
Such that it doesn't expand to something like:
pub trait Rpc<T: Client, C: Config>
where
C::Hash: Serialize,
// NotUsed is not used so the trait bounds are needless
// and should not be added.
C::NotUsed: Send + Sync + Serialize + DeserializeOwned
{
#[method(name = "bar")]
fn method(&self) -> Result<Conf::Hash, Error>;
}
But as it works in subxt all fine, IIRC we only inspect the parameters and return types anyway and add bounds on them so all good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great.
some UI tests that it actually work as well then this should be ready to go :)
I just tested in on my hacky subxt RPC macro PR and it works 🎉 |
Signed-off-by: Alexandru Vasile <[email protected]>
Signed-off-by: Alexandru Vasile <[email protected]>
@@ -63,7 +63,7 @@ impl RpcDescription { | |||
#(#sub_impls)* | |||
} | |||
|
|||
impl<T #(,#type_idents)*> #trait_name #type_generics for T where T: #super_trait #(,#where_clause)* {} | |||
impl<TypeJsonRpseeInteral #(,#type_idents)*> #trait_name #type_generics for TypeJsonRpseeInteral where TypeJsonRpseeInteral: #super_trait #(,#where_clause)* {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
excellent, nice work
some minor suggestions on testing but really good to have this finally
Signed-off-by: Alexandru Vasile <[email protected]>
Just wondering; is it possible to define something like: #[rpc(server, client, client_bounds(Conf::Hash: jsonrpsee::core::Serialize))]
pub trait Rpc<Conf: Config> {
fn generic_input<T>(&self, input: T) -> Result<Conf::Hash, Error>;
fn generic_output<O>(&self, input: T) -> Result<O, Error>;
} And if so, can we control the bounds of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure whether the question above makes sense or not (I can't recall whether it's possible to add generic bounds in that way), but regardless, this looks great; nice job!
Managed to define something similar: #[rpc(client, client_bounds(
Conf::Hash: jsonrpsee::core::DeserializeOwned,
T: jsonrpsee::core::Serialize + Send + Sync + 'static,
O: jsonrpsee::core::DeserializeOwned)
)]
pub trait Rpc2<Conf: Config, T, O> {
#[method(name = "bar")]
fn generic_input<T>(&self, input: T) -> Result<Conf::Hash, Error>;
#[method(name = "foo")]
fn generic_output<T, O>(&self, input: T) -> Result<O, Error>;
} with |
#[rpc(server, client, client_bounds(Conf::Hash: jsonrpsee::core::Serialize))]
pub trait Rpc<Conf: Config> {
fn generic_input<T>(&self, input: T) -> Result<Conf::Hash, Error>;
fn generic_output<O>(&self, input: T) -> Result<O, Error>;
}
Bounds on individual methods doesn't work because the server generates We would need to find all I think the same applies to client trait too i.e, that we don't really parse I guess we should throw a compile error for bounds on individual methods until that's allowed, you must really have a bound on the entire trait for now. |
This PR adds the
server_bounds
andclient_bounds
attributes of therpc
macro.The attributes allow users to specify custom bounds for their traits, as a way to opt-out
of the default
Send + Sync + 'static
where appropriate.Example
Without the custom provided bounds, the RPC macro would add by default
Conf : Send + Sync + 'static + jsonrpsee::core::DeserializeOwned
for client implementation andConf : Send + Sync + 'static + jsonrpsee::core::Serialize
for server implementation.This rule is quite restrictive, as we need just
Conf::Hash
to comply to those rules.While at it, add a new example illustrating the custom bounds and a few UI tests to capture
proper error messages.
Closes #696.