Fn new() for struct & trait impl

Boy, is this confusing me.

This:

use trading:T;

pub struct TService {
    hold: domain::Hold,
}

#[tonic::async_trait]
impl TImpl for TService {
    pub fn new() -> Self {
        let h = domain::Hold::new();
        Self { h }
    }

    ...

fails to compile with:

error[E0407]: method new is not a member of trait T

I am stumped. If the interface is not implemented this syntax works. I've done lots of Googling and don't understand what I'm missing. (T is a tonic-generated gRPC server interface.)

Use a separate impl block for items that aren't in the trait

use trading:T;

pub struct TService {
    hold: domain::Hold,
}

impl TService {
    pub fn new() -> Self {
        let h = domain::Hold::new();
        Self { h }
    }
}

#[tonic::async_trait]
impl TImpl for TService {
//... 
}
2 Likes

I'd actually tried that before and it didn't compile, but I realize now I had a typo.

It does compile.

But it never runs. That's because the TImpl instance is created by tonic.

So it seems that associated some static data with a trait impl when you don't control creation of instances is not straightforward.

I just want the gRPC service to be able to init & cache some data.

How would you go about this? I hope I was clear enough, let me know if not.

Something like this should work.

 let mut server = tonic::transport::Server::builder();
 let svc = T::new(TService::new());
 server.add_service(svc).serve(grpc_addr).await

The fix was to replace

let service = TService::Default();

with

let service = TService::new();

in main() (where the gRPC server is instantiated and handed the service).

Where does the Default implementation come frome? It's usually best practice to make sure that Foo::default and Foo::new behave the same.

1 Like

I did. :slight_smile:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.