Help understanding type syntax with :: operator

I'm trying to wrap my head around the actix framework, but I don't understand what's going on with the generic types on some of the functions I need to call.

impl<F, I, S, B> HttpServer<F, I, S, B>
    F: Fn() -> I + Send + Clone + 'static,
    I: IntoServiceFactory<S>,
    S: ServiceFactory<Config = AppConfig, Request = Request>,
    S::Error: Into<Error> + 'static,
    S::InitError: fmt::Debug,
    S::Response: Into<Response<B>> + 'static,
    <S::Service as Service>::Future: 'static,
    B: MessageBody + 'static,

What do those S:: types mean? What are they referencing? Why does this one, <S::Service as Service>::Future: 'static, have angle brackets?

I've looked through "the book" and rust by example, but I can't find any reference to what's happening here.

They’re referring to and placing bounds on associated types. So, in addition to S implementing the ServiceFactory trait, the Error type defined in S’s ServiceFactory implementation must implement Into<Error>+'static, etc.

The angle brackets are there to refer to an associated type of an associated type:

  • S::Service is the Service type defined in S’s ServiceFactory implementation, and
  • <S::Service as Service>::Future is the Future type defined in S::Service’s implementation of the Service trait.

The fully-qualified form is <Type as Trait>::AssocType, but this can be shortened to Type::AssocType when the compiler can infer the correct Trait. In this case, there’s only one trait that S is known to implement (ServiceFactory), so it can use the short form.

Oh, wow that's neat. That's a lot cleaner than a billion nested brackets. Thanks a bunch for the clarity.

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.