Why a trait could be used as the return type?


The method call returns a trait (no impl or Box).

But I try this way in my personal project, it would fail, why?

Self::Future is a type, not a trait. (It's different from the std::future::Future trait.)

Specifically, it's this associated type defined on line 53:

type Future = Ret;

which says that it's equal to the generic type parameter Ret defined in the header of this impl block:

impl<F, ReqBody, Ret, ResBody, E> tower_service::Service<crate::Request<ReqBody>>
    for ServiceFn<F, ReqBody>

Future is not a type.

std::future::Future isn't the same thing as Self::Future. The former is a trait, but the latter an associated type.

Of course, I know the difference between trait and associate type.

Here call method returns Self.Future, and Self.Future is Ret, and Ret is Future<Output = Result<Response<ResBody>, E>>, and Future is use here: use crate::common::{task, Future, Poll};, and common::Future is an re-export from std::future::Future: pub(crate) use std::{future::Future, pin::Pin};.

So it looks like call method returns a trait.

Now you see my question?

This statement is not quite right. Ret is some type which implements Future<Output = Result<Response<ResBody>, E>>. Which specific type Ret is will be inferred from context: It will be whatever type the closure self.f returns.


Ret is a generic parameter so Self::Future is anything implementing Future<Output = Result<Response<ResBody>, E>>. See https://docs.rs/hyper/0.14.7/src/hyper/service/util.rs.html#49