Using futures in condition causes incompatible types

#1

I would like use condition for return futures.
If I use something like this:

    if 1==2 {
        Ok(actix_web::HttpResponse::Ok()
            .content_type("text/plain")
            .body("ss"))
    } else {
        Ok(actix_web::HttpResponse::Ok()
            .content_type("text/plain")
            .body("ss"))
    }

it’s work very fine but below form will not work.

    request.body().map_err(|e| e.into()).and_then(move |f| {
        result.extend("\r\n".as_bytes());
        result.extend(f);
        if 1==2 {
	        Ok(actix_web::HttpResponse::Ok()
                .content_type("text/plain")
                .body("ss"))
        } else {
	        client::ClientRequest::get("http://example.com/")
		        .finish()
		        .unwrap()
		        .send()
		        .map_err(Error::from)
		        .and_then(|resp| {
			        resp.body()
				        .from_err()
				        .and_then(|body| {
					        result.extend(body);
					        Ok(HttpResponse::Ok().body(result))
				        })
		        })
        }
    }).responder()

error :

    error[E0308]: if and else have incompatible types
       --> src/sample.rs:103:9
        |
    103 | /         if 1==2 {
    104 | |             Ok(actix_web::HttpResponse::Ok()
    105 | |                 .content_type("text/plain")
    106 | |                 .body("ss"))
    ...   |
    120 | |                 })
    121 | |         }
        | |_________^ expected enum `std::result::Result`, found struct `futures::future::and_then::AndThen`
        |
        = note: expected type `std::result::Result<actix_web::httpresponse::HttpResponse, _>`
                   found type `futures::future::and_then::AndThen<futures::future::map_err::MapErr<actix_web::client::pipeline::SendRequest, fn(actix_web::client::pipeline::SendRequestError) -> actix_web::error::Error {<actix_web::error::Error as std::convert::From<actix_web::client::pipeline::SendRequestError>>::from}>, futures::future::and_then::AndThen<futures::future::from_err::FromErr<actix_web::httpmessage::MessageBody<actix_web::client::response::ClientResponse>, actix_web::error::Error>, std::result::Result<actix_web::httpresponse::HttpResponse, actix_web::error::Error>, [closure@src/sample.rs:116:23: 119:14 result:_]>, [closure@src/sample.rs:113:21: 120:12 result:_]>`

    error[E0308]: if and else have incompatible types
       --> src/sample.rs:103:9
        |
    103 | /         if 1==2 {
    104 | |             Ok(actix_web::HttpResponse::Ok()
    105 | |                 .content_type("text/plain")
    106 | |                 .body("ss"))
    ...   |
    120 | |                 })
    121 | |         }
        | |_________^ expected enum `std::result::Result`, found struct `futures::future::and_then::AndThen`
        |
        = note: expected type `std::result::Result<actix_web::httpresponse::HttpResponse, _>`
                   found type `futures::future::and_then::AndThen<futures::future::map_err::MapErr<actix_web::client::pipeline::SendRequest, fn(actix_web::client::pipeline::SendRequestError) -> actix_web::error::Error {<actix_web::error::Error as std::convert::From<actix_web::client::pipeline::SendRequestError>>::from}>, futures::future::and_then::AndThen<futures::future::from_err::FromErr<actix_web::httpmessage::MessageBody<actix_web::client::response::ClientResponse>, actix_web::error::Error>, std::result::Result<actix_web::httpresponse::HttpResponse, actix_web::error::Error>, [closure@src/sample.rs:116:23: 119:14 result:_]>, [closure@src/sample.rs:113:21: 120:12 result:_]>`
#2

The issue is that since the two branches use different combinators, the results end up being different types. You can look into using the Either type to unify them: https://docs.rs/futures/0.1/futures/future/enum.Either.html

e.g.,

if some_condition {
  Either::A(future1)
} else {
  Either::B(future2)
}
2 Likes