Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the mechanism for converting a function to a trait in Rust?

Tags:

rust

actix-web

An example from actix-web is as follows:

use actix_web::{web, App, Responder, HttpServer};

async fn index() -> impl Responder {
    "Hello world!"
}

#[actix_rt::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new().service(
            web::scope("/app").route("/index.html", web::get().to(index)),
        )
    })
    .bind("127.0.0.1:8088")?
    .run()
    .await
}

My question is around how the statement to(index) works in Rust.

Looking at the source code for to we see:

pub fn to<F, T, R, U>(mut self, handler: F) -> Self
where
    F: Factory<T, R, U>,
// --- snip

Where Factory is defined as:

pub trait Factory<T, R, O>: Clone + 'static
where
    R: Future<Output = O>,
    O: Responder,
{
    fn call(&self, param: T) -> R;
}

What is the mechanism by which the function async fn index() -> impl Responder gets converted to Factory<T, R, O>?

like image 864
dav_i Avatar asked Sep 10 '20 10:09

dav_i


People also ask

What does into () mean in Rust?

The Into trait is simply the reciprocal of the From trait. That is, if you have implemented the From trait for your type, Into will call it when necessary.

Should I implement from or into Rust?

Implementing Into for conversions to external types in old versions of Rust. It is important to understand that Into does not provide a From implementation (as From does with Into ). Therefore, you should always try to implement From and then fall back to Into if From can't be implemented.


1 Answers

There is an implementation of the trait just after your snippet:

impl<F, R, O> Factory<(), R, O> for F
where
    F: Fn() -> R + Clone + 'static,
    R: Future<Output = O>,
    O: Responder,
{
    fn call(&self, _: ()) -> R {
        (self)()
    }
}

This can be read as: if a type F implements Fn() -> Future<Output = impl Responder> + ... then it also implements Factory<(), _, _>.

And an async fn is syntactic sugar for a function which returns a Future of some sort (and can use .await internally), so async fn index() -> impl Responder implements Fn() -> impl Future<Output = impl Responder> so it also implements Factory<(), _, _>.

like image 194
rodrigo Avatar answered Oct 06 '22 00:10

rodrigo