How to convert a fn to a fn pointer?

This is my code:

use std::convert::Infallible;
use std::future::Future;

use hyper::{Body, Request, Response};

use crate::router::{Match, Router, Params};

type ResponseType = Result<Response<Body>, Infallible>;

pub fn make_router() -> Router<&'static impl Fn(Request<Body>) -> dyn Future<Output=ResponseType>> {
    let mut router: Router<&'static fn(Request<Body>) -> dyn Future<Output=ResponseType>> = Router::new();
    router.add("/", &hello);
    router.add("/a/*", &request_a);
    router.add("/b/*", &request_b);
    router
}

pub fn match_router(rt: Router<&'static fn(Request<Body>) -> dyn Future<Output=ResponseType>>, url: &str) -> &'static fn(Request<Body>) -> dyn Future<Output=ResponseType>  {
    match rt.recognize(url.as_str()) {
        Ok(Match { handler, params }) => *handler,
        _ => &hello,
    }
}

async fn hello(req: Request<Body>) -> Result<Response<Body>, Infallible> {
    Ok(Response::new(Body::from("Hello, World!\n")))
}

async fn request_a(req: Request<Body>) -> Result<Response<Body>, Infallible> {
    Ok(Response::new(Body::from("Hello, World A!\n")))
}

async fn request_b(req: Request<Body>) -> Result<Response<Body>, Infallible> {
    Ok(Response::new(Body::from("Hello, World B!\n")))
}

When I compiled it, it show me these errors:

error[E0308]: mismatched types
  --> src/dispatcher.rs:12:21
   |
12 |     router.add("/", &hello);
   |                     ^^^^^^ expected fn pointer, found fn item
   |
   = note: expected reference `&'static fn(hyper::Request<hyper::Body>) -> (dyn std::future::Future<Output = std::result::Result<hyper::Response<hyper::Body>, std::convert::Infallible>> + 'static)`
              found reference `&fn(hyper::Request<hyper::Body>) -> impl std::future::Future {dispatcher::hello}`

error[E0308]: mismatched types
  --> src/dispatcher.rs:13:24
   |
13 |     router.add("/a/*", &request_a);
   |                        ^^^^^^^^^^ expected fn pointer, found fn item
   |
   = note: expected reference `&'static fn(hyper::Request<hyper::Body>) -> (dyn std::future::Future<Output = std::result::Result<hyper::Response<hyper::Body>, std::convert::Infallible>> + 'static)`
              found reference `&fn(hyper::Request<hyper::Body>) -> impl std::future::Future {dispatcher::request_a}`

I'm wondering about the fn pointer, how to pass the correct fn pointer?

The problem is not the conversion. The issue is that the return types don't match. When dealing with a trait, the type dyn Trait is a different type from any type MyStruct that happens to implement that trait, and in fact this applies to async functions too.

The fix for this issue should probably happen in Router::add, and not in make_router.

I see. Thanks so much for your help.

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.