11

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>?

1
  • 1
    This is, indeed, a good question. I'm expectating. Commented Sep 10, 2020 at 11:17

1 Answer 1

12

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<(), _, _>.

Sign up to request clarification or add additional context in comments.

1 Comment

Also lingo correction: there is no conversion in the code posted, instead there is a constraint: F needs to implement the specified trait, but its identity doesn't change.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.