Compilation error with Hyper - rust

I'm running into a compilation error I don't quite understand with a slight modification of the examples from the master branch of Hyper. Given the following code:
extern crate futures;
extern crate hyper;
use futures::future::FutureResult;
use hyper::header::{ContentLength, ContentType};
use hyper::server::{Http, Service, Request, Response, Server, NewService};
use hyper::Body;
use std::fmt::Display;
use std::result;
static PHRASE: &'static [u8] = b"Hello World!";
#[derive(Clone, Copy)]
pub struct MyService {}
impl Service for MyService {
type Request = Request;
type Response = Response;
type Error = hyper::Error;
type Future = FutureResult<Response, hyper::Error>;
fn call(&self, _req: Request) -> Self::Future {
return futures::future::ok(Response::new()
.with_header(ContentLength(PHRASE.len() as u64))
.with_header(ContentType::plaintext())
.with_body(PHRASE));
}
}
#[derive(Clone)]
pub struct MyServer {}
#[derive(Debug)]
pub struct MyServeError(String);
impl<T: Display> From<T> for MyServeError {
fn from(e: T) -> MyServeError {
return MyServeError(format!("{}", e));
}
}
type Result<T> = result::Result<T, MyServeError>;
impl MyServer {
pub fn new() -> MyServer {
return MyServer {};
}
fn get_server(&self) -> Result<Server<&MyServer, Body>> {
let addr = format!("127.0.0.1:8080").parse()?;
return Ok(Http::new().bind(&addr, self)?);
}
}
impl NewService for MyServer {
type Request = Request;
type Response = Response;
type Instance = MyService;
type Error = hyper::Error;
fn new_service(&self) -> std::io::Result<Self::Instance> {
let service = MyService {};
Ok(service)
}
}
I get this compilation error:
Compiling hyper-problem-demo v0.1.0 (file:///.../hyper-problem-demo)
error[E0277]: the trait bound `MyServer: std::ops::Fn<()>` is not satisfied
--> src/lib.rs:50:31
|
50 | return Ok(Http::new().bind(&addr, self)?);
| ^^^^ the trait `std::ops::Fn<()>` is not implemented for `MyServer`
|
= note: required because of the requirements on the impl of `std::ops::FnOnce<()>` for `&MyServer`
= note: required because of the requirements on the impl of `hyper::server::NewService` for `&MyServer`
error[E0277]: the trait bound `MyServer: std::ops::FnOnce<()>` is not satisfied
--> src/lib.rs:50:31
|
50 | return Ok(Http::new().bind(&addr, self)?);
| ^^^^ the trait `std::ops::FnOnce<()>` is not implemented for `MyServer`
|
= note: required because of the requirements on the impl of `hyper::server::NewService` for `&MyServer`
Which I don't really understand. My intention was just to use the MyServer object to create new instances of MyService for hyper so it seems to make sense to implement NewService, but I don't understand why that would require an implementation of Fn(). NewService is actually implemented for Fn() -> io::Result<Service so maybe that's clashing somehow?
There's a full sample project here.

You have implemented NewService for MyServer however you are providing bind a &MyServer which it cannot find an implementation of NewService for.
The solution you go for will depend largely upon why you want to do this, but you could implement NewService for &MyServer:
impl<'a> NewService for &'a MyServer {
...
}

Related

TryInto trait asks for more type annotations even though all annotations are in place

I have the following code (constrained example). There is a serial protocol, modelled with Command and Responce enums using enum_dispatch crate - every variant in enum is represented with a struct. Transport struct taskes care of serialization, execution and deserialization of Commands, returning TransportResults back with generic Responce enum(generic impl) or specific struct(templated impl). The generic implementation works just fine, but the templated one fails to compile.
use enum_dispatch::enum_dispatch;
use thiserror::Error;
trait Value{/**/}
trait CommandResponce {type Responce}
#[enum_dipatch(Value)]
enum Command{
Cmd1(Cmd1)
// ...
}
struct Cmd1{}
impl Value for Cmd1{ /**/ }
#[enum_dipatch(Value)]
enum Responce{
Resp1(Resp1)
// ...
}
struct Resp1{}
impl Value for Resp1{/**/}
impl CommandResponce for Cmd1{ type Responce=Resp1 }
#[derive(Error, Debug)]
pub enum ProtocolError{/**/}
type ProtocolResult<T> = Result<T, ProtocolError>;
struct Transport {/**/}
impl Transport {
// generic
pub fn command_generic_with_addr(
&mut self, addr: &mut u8, c: Command
) -> ProtocolResult<Responce>{ /**/ }
// templated
pub fn command_with_addr<T: SerializeCommand + CommandResponce>(
&mut self, addr: &mut u8, c: T) -> ProtocolResult<T::Responce>
where
Command: From<T>, Responce: TryInto<T::Responce, Error=&'static str>,
Responce: TryInto<T::Responce, Error= CommandErrors> {
let resp: Responce = self.command_generic_with_addr(addr, Command::from(c))?;
let ret: T::Responce = resp.try_into()?;
Ok(ret)
}
}
fn main() -> eyre::Result<()>{
let t = Transport::new();
let addr : u8 = 0xFF;
t.command_with_addr(&mut addr, Cmd1{/**/})
}
When I try to compile code, identical to the one above, I get the following error:
error[E0284]: type annotations needed: cannot satisfy `<Responce as TryInto<<T as CommandResponce>::Responce>>::Error == _`
-->
|
85 | let ret: T::Responce = match resp.try_into() {
| ^^^^^^^^ cannot satisfy `<Responce as TryInto<<T as CommandResponce>::Responce>>::Error == _`
I can't understand, what is the error here - I thought I've stated all the neccessary type annotations in the Transport::command_with_addr member function.
Note, enum_dispatch uses the following code to generate try_into conversion, used in the code above:
impl #impl_generics core::convert::TryInto<#variant_type> for #enumname #ty_generics #where_clause {
type Error = &'static str;
fn try_into(self) -> ::core::result::Result<#variant_type, <Self as core::convert::TryInto<#variant_type>>::Error> {
//..
}
}

Can I store an `impl Future` as a concrete type?

tokio::net::TcpStream::connect is an async function, meaning it returns an existential type, impl Future. I would like to store a Vec of these futures in a struct. I've found many questions where someone wants to store multiple different impl Futures in a list, but I only want to store the return type of one. I feel like this should be possible without Box<dyn Future> as I am really only storing a single concrete type, but I cannot figure out how without getting found opaque type errors.
It is possible with the nightly feature min_type_alias_impl_trait. The trick is to create a type alias, and a dummy function from which the compiler can infer a defining use.
#![feature(min_type_alias_impl_trait)]
use tokio::net::TcpStream;
use core::future::Future;
type TcpStreamConnectFut = impl Future<Output = std::io::Result<TcpStream>>;
fn __tcp_stream_connect_defining_use() -> TcpStreamConnectFut {
TcpStream::connect("127.0.0.1:8080")
}
struct Foo {
connection_futs: Vec<TcpStreamConnectFut>,
}
This compiles, but does not work as expected:
impl Foo {
fn push(&mut self) {
self.connection_futs.push(TcpStream::connect("127.0.0.1:8080"));
}
}
error[E0308]: mismatched types
--> src/lib.rs:18:35
|
6 | type TcpStreamConnectFut = impl Future<Output = std::io::Result<TcpStream>>;
| ------------------------------------------------ the expected opaque type
...
18 | self.connection_futs.push(TcpStream::connect("127.0.0.1:8080"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found a different opaque type
|
= note: while checking the return type of the `async fn`
= note: expected opaque type `impl Future` (opaque type at <src/lib.rs:6:28>)
found opaque type `impl Future` (opaque type at </playground/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.7.1/src/net/tcp/stream.rs:111:56>)
= help: consider `await`ing on both `Future`s
= note: distinct uses of `impl Trait` result in different opaque types
Using the dummy function we created does work:
impl Foo {
fn push(&mut self) {
self.connection_futs.push(__tcp_stream_connect_defining_use());
}
}
So we can just create wrapper functions:
fn tcp_stream_connect<A: ToSocketAddrs>(addr: A) -> TcpStreamConnectFut {
TcpStream::connect(addr)
}
Except...
error: type parameter `A` is part of concrete type but not used in parameter list for the `impl Trait` type alias
--> src/main.rs:9:74
|
9 | fn tcp_stream_connect<A: ToSocketAddrs>(addr: A) -> TcpStreamConnectFut {
| __________________________________________________________________________^
10 | | TcpStream::connect(addr)
11 | | }
| |_^
We could just use String or &'static str, and the entire thing compiles:
type TcpStreamConnectFut = impl Future<Output = std::io::Result<TcpStream>>;
fn tcp_stream_connect(addr: &'static str) -> TcpStreamConnectFut {
TcpStream::connect(addr)
}
struct Foo {
connection_futs: Vec<TcpStreamConnectFut>,
}
impl Foo {
fn push(&mut self) {
self.connection_futs.push(tcp_stream_connect("..."));
}
}
You can also add a generic parameter to the type alias itself, but that probably doesn't make sense in this case:
type TcpStreamConnectFut<A> = impl Future<Output = std::io::Result<TcpStream>>;
fn tcp_stream_connect<A: ToSocketAddrs>(addr: A) -> TcpStreamConnectFut<A> {
TcpStream::connect(addr)
}
struct Foo {
connection_futs: Vec<TcpStreamConnectFut<&'static str>>,
}
impl Foo {
fn push(&mut self) {
self.connection_futs.push(tcp_stream_connect("..."));
}
}
So it is possible, but there are a couple of restrictions. I'm not sure how many of these are bugs, and how much of it is intentional behavior. There has been discussion about a typeof operator to make this easier, but this is what we've got at the moment.
You can just use a good old Vec, just like that:
use core::future::Future;
use tokio::net::TcpStream;
fn just_vec() -> Vec<impl Future<Output = std::io::Result<TcpStream>>> {
let mut v = Vec::new();
// connect to several streams
v.push(TcpStream::connect("127.0.0.1:8080"));
v.push(TcpStream::connect("127.0.0.2:8080"));
v
}
However, it gets more tricky if you want to store it in a struct, because unlike above, where concrete type can be inferred, you need to be more explicit with structs.
One stable way to do this, is to use a generic struct. This actually very similar to storing a closure (where you don't have a concrete type either).
use core::future::Future;
use tokio::net::TcpStream;
use tokio::io::AsyncWriteExt;
struct Foo<T> {
connections: Vec<T>,
}
/// This is just like any other vec-wrapper
impl<T> Foo<T> {
pub fn new() -> Self {
Self {
connections: Vec::new(),
}
}
pub fn push(&mut self, conn: T) {
self.connections.push(conn);
}
}
/// Some more specific functios that actually need the Future
impl<T> Foo<T> where T: Future<Output = std::io::Result<TcpStream>> {
pub async fn broadcast(self, data: &[u8]) -> std::io::Result<()> {
for stream in self.connections {
stream.await?.write_all(data).await?
}
Ok(())
}
}
async fn with_struct() -> std::io::Result<()> {
let mut foo = Foo::new();
// connect to several streams
foo.push(TcpStream::connect("127.0.0.1:8080"));
foo.push(TcpStream::connect("127.0.0.2:8080"));
// Do something with the connections
foo.broadcast(&[1,2,3]).await
}

Lifetime issue with Actix Web

I'm implementing middleware with Actix-web and having an issue with lifetime that I couldn't figure out.
extern crate actix_web;
use actix_web::actix::{Actor, Addr, Context, System};
use actix_web::middleware::Middleware;
use actix_web::{http, server, App, HttpRequest, Responder};
use std::collections::HashMap;
pub struct CacheActor {
caches: HashMap<String, String>,
}
impl CacheActor {
pub fn new() -> Self {
CacheActor {
caches: HashMap::new(),
}
}
}
impl Actor for CacheActor {
type Context = Context<Self>;
}
fn create_resource(req: HttpRequest, addr: &Addr<CacheActor>) -> impl Responder {
unimplemented!();
format!("Unimplemented")
}
fn list_resources(req: HttpRequest, addr: &Addr<CacheActor>) -> impl Responder {
unimplemented!();
format!("Unimplemented")
}
pub trait TusMiddlewareTrait {
fn with_tus(self, addr: &Addr<CacheActor>) -> App;
}
impl TusMiddlewareTrait for App {
fn with_tus(self, addr: &Addr<CacheActor>) -> App {
self.route("/files", http::Method::GET, |req| list_resources(req, addr))
.route("/files", http::Method::POST, |req| {
create_resource(req, addr)
})
}
}
fn main() {
let system = System::new("Example");
let cache_addr = CacheActor::new().start();
server::new(|| App::new().with_tus(&cache_addr))
.bind("127.0.0.1:8080")
.unwrap()
.run();
system.run();
}
The error that I get is the following,
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/tus/middleware.rs:84:49
|
84 | .route("/files", http::Method::GET, |req| list_resources(req, addr))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 81:5...
--> src/tus/middleware.rs:81:5
|
81 | / fn with_tus(self, addr: &actix::Addr<cache::CacheActor>) -> App {
82 | | self.middleware(TusMiddleware)
83 | | .route("/files", http::Method::OPTIONS, tus_information)
84 | | .route("/files", http::Method::GET, |req| list_resources(req, addr))
... |
87 | | })
88 | | }
| |_____^
= note: ...so that the types are compatible:
expected &&actix::address::Addr<tus::cache::CacheActor>
found &&actix::address::Addr<tus::cache::CacheActor>
= note: but, the lifetime must be valid for the static lifetime...
As for what I understand, I am passing cache_addr as a reference to with_tus function. Inside each closure in route, addr is also a reference.
I don't understand why the compiler said the lifetime cannot outlive the anonymous lifetime #1. From what I can tell is that cache_addr's lifetime still outlives the closure. The lifetime should cover up until system.run() line. Can someone enlighten me?
Edit:
I updated the code above to MCVE (at least to a point that it is simple enough to copy the whole code and run cargo build while still preserving the same error message). I can't run it on rust-playground. It doesn't support actix crate at this point. I tried reducing it further but it's giving me a different error. Sorry, I am pretty new to Rust.
My questions are twofold, one I like to understand what's the error telling me. Second, I like to know how to properly do this with actix thus why the sample code is dependent on actix.
Look at the App::route signature:
pub fn route<T, F, R>(self, path: &str, method: Method, f: F) -> App<S>
where
F: WithFactory<T, S, R>,
R: Responder + 'static,
T: FromRequest<S> + 'static,
F generic depends on T and R that in turn have 'static lifetime requirement.
Your closure captures an &Addr<CacheActor> that it is not valid for 'static lifetime and this generates the error.
A possibility that I see is to use the App "State", directly from the docs:
Application state is shared with all routes and resources within the same application. When using an http actor, state can be accessed with the HttpRequest::state() as read-only, but interior mutability with RefCell can be used to achieve state mutability. State is also available for route matching predicates and middlewares.
In this case should be something like:
extern crate actix_web;
use actix_web::actix::{Actor, Addr, Context, System};
use actix_web::{http, server, App, HttpRequest, HttpResponse, Result};
use std::collections::HashMap;
use actix_web::dev::Handler;
#[derive(Clone)]
pub struct CacheActor {
caches: HashMap<String, String>,
}
impl CacheActor {
pub fn new() -> Self {
CacheActor {
caches: HashMap::new(),
}
}
}
impl Actor for CacheActor {
type Context = Context<Self>;
}
impl<S> Handler<S> for CacheActor {
type Result = String;
fn handle(&self, _req: &HttpRequest<S>) -> Self::Result {
unimplemented!();
}
}
fn list_resources(req: &HttpRequest<Addr<CacheActor>>) -> Result<HttpResponse> {
Ok(HttpResponse::Found()
.header(http::header::LOCATION, format!("hello {}", req.path()))
.finish())
}
fn main() {
let system = System::new("Example");
server::new(|| {
let cache_addr = CacheActor::new().start();
App::with_state(cache_addr)
.resource("/world", |r| r.method(http::Method::GET).f(list_resources))
})
.bind("127.0.0.1:8080")
.unwrap()
.run();
system.run();
}

Cannot create an Iron handler because the trait bound std::ops::Fn<(&mut iron::Request)> is not satisfied

I'm trying to create a handler for Iron requests:
extern crate iron;
extern crate mount;
use iron::{Iron, Request, Response, IronResult, status};
use mount::Mount;
use iron::middleware::Handler;
struct Server {
message: String
}
impl Server {
pub fn start(&self){
let mut mount = Mount::new();
mount.mount("/", &self);
Iron::new(mount).http("0.0.0.0:3000").unwrap();
}
}
impl Handler for Server {
fn handle(&self, _req: &mut Request) -> IronResult<Response>{
Ok(Response::with((status::Ok, self.message)))
}
}
fn main() {
Server{message: "test".to_string()}.start();
}
but compiler response is:
error[E0277]: the trait bound `for<'r, 'r, 'r> Server: std::ops::Fn<(&'r mut iron::Request<'r, 'r>,)>` is not satisfied
--> src/main.rs:15:15
|
15 | mount.mount("/", &self);
| ^^^^^ trait `for<'r, 'r, 'r> Server: std::ops::Fn<(&'r mut iron::Request<'r, 'r>,)>` not satisfied
|
= note: required because of the requirements on the impl of `std::ops::FnOnce<(&mut iron::Request<'_, '_>,)>` for `&Server`
= note: required because of the requirements on the impl of `iron::Handler` for `&&Server`
I was unable to understand what Rust is saying to me.
Here's a reproduction of your issue; can you spot the problem?
trait Foo {}
struct Bar;
impl Foo for Bar {}
impl Bar {
fn thing(&self) {
requires_bar(self);
}
}
fn requires_bar<F>(foo: F) where F: Foo {}
fn main() {}
Give up?
You've implemented the trait for your struct:
impl Handler for Server
But are then trying to use a reference to a reference to your struct, which does not implement the trait:
pub fn start(&self) {
// ...
mount.mount("/", &self);
// ...
}
So that cannot work. You need to restructure your code or implement the trait for a reference to your struct.

Iron Handler: Missing Lifetime Specifiers

I'm trying to implement an Iron handler that contains a reference to another struct. That struct holds the data and does all operations on the data.
[package]
name = "testcrate"
version = "0.1.0"
authors = ["me"]
[dependencies]
iron = "^0.2"
This is the code:
//! Handlers for the server.
extern crate iron;
use iron::{status, middleware};
use iron::IronResult;
use iron::prelude::Set;
use iron::request::Request;
use iron::response::Response;
/// The MyServer struct holds the data and provides methods
/// to manipulate or retrieve that data.
struct MyServer;
impl MyServer {
pub fn build_response() -> String {
"response".to_string()
}
}
/// The ReadHandler handles the creation of HTTP responses.
pub struct ReadHandler {
pub server: &MyServer,
}
impl middleware::Handler for ReadHandler {
/// Return the current status JSON.
fn handle(&self, req: &mut Request) -> IronResult<Response> {
let body = self.server.build_response();
let response = Response::with((status::Ok, body));
Ok(response)
}
}
Unfortunately I'm getting errors about missing lifetime specifiers:
src/lib.rs:22:17: 22:26 error: missing lifetime specifier [E0106]
src/lib.rs:22 pub server: &MyServer,
^~~~~~~~~
src/lib.rs:22:17: 22:26 help: run `rustc --explain E0106` to see a detailed explanation
But when I add lifetime specifiers (which I didn't fully understand yet)...
pub struct ReadHandler<'a> {
pub server: &'a MyServer,
}
impl<'a> middleware::Handler for ReadHandler<'a> {
// ...
}
...I get another error message:
src/lib.rs:24:1: 32:2 error: the type `ReadHandler<'a>` does not fulfill the required lifetime
src/lib.rs:24 impl<'a> middleware::Handler for ReadHandler<'a> {
src/lib.rs:25
src/lib.rs:26 /// Return the current status JSON.
src/lib.rs:27 fn handle(&self, req: &mut Request) -> IronResult<Response> {
src/lib.rs:28 let body = self.server.build_response();
src/lib.rs:29 let response = Response::with((status::Ok, body));
...
note: type must outlive the static lifetime
There will be other handlers that will access the MyServer in a read-only or read-write mode.
What would be the correct way to add lifetime specifiers? Or do I maybe need a structure like an Arc?
The Handler trait is a subtrait of Any:
pub trait Handler: Send + Sync + Any {
fn handle(&self, &mut Request) -> IronResult<Response>;
}
And the Any trait has a 'static lifetime bound:
pub trait Any: Reflect + 'static {
fn get_type_id(&self) -> TypeId;
}
The 'static bound means that your struct cannot contain references. You'll have to use another type of pointer. Since Handler is also a subtrait of Send and Sync, you'll need to use Arc, since Rc is neither Send nor Sync.

Resources