How can I write this impl block correctly?

I am trying to use the typestate pattern in a library that I am writing and I am a bit confused about how to correctly constrain the impl block in the following code. The idea is that the serve method should only be available if Config was configured with a server and that server should define the request and response types that will be used by the serve method.

trait Server<Request, Response> {}
struct WithoutServer;
struct Config<S> {
    server: S,
}
impl Config<WithoutServer> {
    fn new() -> Config<WithoutServer> {
        Self { server: WithoutServer }
    }

    fn with_server<Request, Response, S: Server<Request, Response>>(
        self,
        server: S
    ) -> Config<S> {
        Self { .. } = self;
        Config::<S> { server }
    }
}

// this is the impl block that I am having issues with
impl<Request, Response, S> Config<S> where S: Server<Request, Response> {
    fn serve(&self) {
        todo!()
    }
}

The compiler error is as follows:

The error is "the type parameter Request is not constrained by the impl trait, self type, or predicates unconstrained type parameter"

Assuming what I am trying to do makes sense, how can I constrain this impl block so that serve is only available where S: Server<Request, Response> ?

The error code points to E0207 - Error codes index

Any type or const parameter of an impl must meet at least one of the following criteria:

  • it appears in the implementing type of the impl, e.g. impl<T> Foo<T>
  • for a trait impl, it appears in the implemented trait, e.g. impl<T> SomeTrait<T> for Foo
  • it is bound as an associated type, e.g. impl<T, U> SomeTrait for T where T: AnotherTrait<AssocType=U>

Any unconstrained lifetime parameter of an impl is not supported if the lifetime parameter is used by an associated type.


You can instead do this

impl<S> Config<S> {
    fn serve<Request, Response>(&self)
    where
        S: Server<Request, Response>,
    {
        todo!()
    }
}
3 Likes

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.