Trouble passing a client to a function
Migrating discussion from here.
I'm running into a lot of trouble when trying to pass a client to a function. It looks like the accepting function needs to have very specific bounds on the client type in order for it to match the generated bounds on the client's RPC functions.
Minimal reproduction: https://github.com/GeorgeHahn/tower-grpc/blob/pass-client-to-fn/tower-grpc-examples/src/helloworld/client.rs#L60
Generates the following client in helloworld.rs:
pub mod client {
use ::tower_grpc::codegen::client::*;
use super::{HelloRequest, HelloReply};
/// The greeting service definition.
#[derive(Debug, Clone)]
pub struct Greeter<T> {
inner: grpc::Grpc<T>,
}
impl<T> Greeter<T> {
pub fn new(inner: T) -> Self {
let inner = grpc::Grpc::new(inner);
Self { inner }
}
pub fn poll_ready<R>(&mut self) -> futures::Poll<(), grpc::Status>
where T: grpc::GrpcService<R>,
{
self.inner.poll_ready()
}
/// The greeting service definition.
pub fn say_hello<R>(&mut self, request: grpc::Request<HelloRequest>) -> grpc::unary::ResponseFuture<HelloReply, T::Future, T::ResponseBody>
where T: grpc::GrpcService<R>,
grpc::unary::Once<HelloRequest>: grpc::Encodable<R>,
{
let path = http::PathAndQuery::from_static("/helloworld.Greeter/SayHello");
self.inner.unary(request, path)
}
}
}
Am I thinking about this wrong? My gut feeling is that a generated client trait would help solve this cleanly.
@GeorgeHahn you probably want to do something like this https://github.com/toshi-search/Toshi/blob/master/src/cluster/rpc_server.rs#L29 This is how we type alias the client in toshi. Which then allows us to pass it around.
Though it is an interesting idea, if the client could generate a trait... It'd be nicer to be generic over T: Greeter than Greeter<T> with T: GrpcService<R>...