What's the meaning of `self(param)` in traits default impl

Hi, noticed in tower::filter, the code for AsyncPredicate looks like:

impl<F, T, U, R, E> AsyncPredicate<T> for F
where
    F: FnMut(T) -> U,
    U: Future<Output = Result<R, E>>,
    E: Into<BoxError>,
{
    type Future = futures_util::future::ErrInto<U, BoxError>;
    type Request = R;

    fn check(&mut self, request: T) -> Self::Future {
        use futures_util::TryFutureExt;
        self(request).err_into()
    }
}

at the last line there's a self(request) call ... what does `self(request) do? and how would one use it? It looks like self is used as a function.

i don't seem to find much documentation about this.

Self is F. Per the where clauses, F implements FnMut(T) -> U, thereby making it callable in the implementation, and that's what you're seeing there.

3 Likes

Hi, thanks for the clarification ... makes sense now

It is.

There's no need to document it separately. Rust is a uniform language: it doesn't matter much where an expression comes from as long as it has the right type. Calling a callable self() isn't any more special or surprsing than calling a callable foo() or a callable array_of_functions[index]().

i don't remember seeing such usage in Java or C++ where you can use the 'self'/'this' keyword as a function - hence my confusion?

Well, neither Java nor C++ is nearly as consistent as Rust. I'd argue that not being able to use this or self just like any other variable is the surprising behavior. Anyway, I don't know about Java but in C++, it's certainly possible to call this if it is callable.

Ok, may have forgotten my C++ and/or Java.

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.