Explanation of E0495

#1

I am using rocket to make a web server and I am trying to make a wrapper around the Responder trait so that my route methods can return any struct.

The code below does not compile because of an error about lifetimes that I don’t fully understand.
The error is not listed here: https://doc.rust-lang.org/error-index.html#E0492

It skips from E0492 to E0496

It requires the nightly build.

main.rs

#![feature(custom_attribute, proc_macro_hygiene, decl_macro)]
#[macro_use]
extern crate rocket;
extern crate rocket_contrib;

use rocket::response::Responder;
use rocket_contrib::templates::Template;

fn main() {
    rocket::Rocket::ignite()
        .mount("/", routes![route])
        .launch();
}

#[get("/")]
fn route<'a>() -> DynamicResponder<'a> {
    DynamicResponder::from(Template::render("template", ()))
}

struct DynamicResponder<'a> {
    inner: Box<dyn Responder<'a> + 'a>,
}

impl<'r> DynamicResponder<'r> {
    pub fn from<T: 'r>(responder: T) -> DynamicResponder<'r>
        where T: Responder<'r>
    {
        DynamicResponder {
            inner: Box::new(responder)
        }
    }
}

impl<'r> Responder<'r> for DynamicResponder<'r> {
    fn respond_to<'b>(self, request: &'b Request) -> Result<rocket::response::Response<'r>, Status> {
        self.inner.respond_to(request)
    }
}

Cargo.toml

[package]
name = "rocketing_around"
version = "0.1.0"

[dependencies]
rocket = "0.4.0"

[dependencies.rocket_contrib]
version = "0.4.0"
default_features = false
features = [ "handlebars_templates" ]

compiler output:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'r` due to conflicting requirements
  --> src/main.rs:19:5
   |
19 |     DynamicResponder::from(Template::render("template", ()))
   |     ^^^^^^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 18:10...
  --> src/main.rs:18:10
   |
18 | fn route<'a>() -> DynamicResponder<'a> {
   |          ^^
   = note: ...so that the expression is assignable:
           expected DynamicResponder<'a>
              found DynamicResponder<'_>
   = note: but, the lifetime must be valid for the static lifetime...
   = note: ...so that the types are compatible:
           expected rocket::response::Responder<'_>
              found rocket::response::Responder<'static>

error: aborting due to previous error

For more information about this error, try `rustc --explain E0495`.
error: Could not compile `rocketing_around`.
#2

Please provide exact error message instead of aligning his rust toolchain to yours, and recreate your project just to solve your problem.

#3

Tried this on my machine,and :

The error
   Compiling tmp v0.1.0 (/home/matias/Documents/eclipse_workspace/tmp/tmp)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'r` due to conflicting requirements
  --> src/main.rs:17:5
   |
17 |     DynamicResponder::from(Template::render("template", ()))
   |     ^^^^^^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 16:10...
  --> src/main.rs:16:10
   |
16 | fn route<'a>() -> DynamicResponder<'a> {
   |          ^^
   = note: ...so that the expression is assignable:
           expected DynamicResponder<'a>
              found DynamicResponder<'_>
   = note: but, the lifetime must be valid for the static lifetime...
   = note: ...so that the types are compatible:
           expected rocket::response::responder::Responder<'_>
              found rocket::response::responder::Responder<'static>

error: aborting due to previous error

For more information about this error, try `rustc --explain E0495`.
error: Could not compile `tmp`.

To learn more, run the command again with --verbose.

When I run rustc --explain:

rustc --explain E0495
error: no extended information for E0495

I edited the code to make it work,changing a few things in the process:

The edited code
#![feature(custom_attribute, proc_macro_hygiene, decl_macro)]

use rocket::{get,routes};
use rocket::Request;
use rocket::http::Status;
use rocket::response::Responder;
use rocket_contrib::templates::Template;

fn main() {
    rocket::Rocket::ignite()
        .mount("/", routes![route])
        .launch();
}

#[get("/")]
fn route() -> DynamicResponder<'static> {
    DynamicResponder::from(Template::render("template", ()))
}

struct DynamicResponder<'a> {
    inner: Box<
        dyn FnMut(&Request) -> Result<rocket::response::Response<'a>, Status>
        +'a
    >
}

impl<'r> DynamicResponder<'r> {
    pub fn from<T: 'r>(responder: T) -> DynamicResponder<'r>
        where T: Responder<'r>
    {
        let mut responder=Some(responder);
        DynamicResponder {
            inner: Box::new(move|request|{
                responder.take().unwrap().respond_to(request)
            })
        }
    }
}

impl<'r> Responder<'r> for DynamicResponder<'r> {
    fn respond_to<'b>(mut self, request: &'b Request) -> Result<rocket::response::Response<'r>, Status> {
        (self.inner)(request)
    }
}
1 Like
#4

Thank you! That code works.

I am a newbie when it comes to Rust; can you clarify a few things?

  1. Why does the DynamicResponder have to contain a closure? Why can’t it call methods from the wrapped Responder?
  2. Why does the root method need to return an object with static lifetime?
  3. I was under the impression that static lifetime means that it exists from when the program starts executing until it terminates. How can an object that was just created in the root method have a static lifetime?
#5

A closure is the way I chose to implement it because it was the easiest way to do it.

The chain of reasons it can’t be a wrapped Responder<_> are:

  1. Responder::respond_to takes a self parameter,calling the method moves self into the method(by value).
  2. methods that take self require self to be Sized
  3. dyn Trait types are not Sized.
  4. Box<_> does not implement Responder<_>.

I could not figure out any other lifetime that would work.

DynamicResponder<'static> means that the DynamicResponder doesn’t contain any references to things that live for less than the remaining program execution,you can drop a DynamicResponder<'static> whenever you want.

1 Like
#6

For the record, in rustc there are eleven different categories of lifetime-inference failure that result in E0495. (You can find them here). The variety of causes and the extensive information in the error sequences themselves are probably the reasons why rustc --explain E0495 does not result in any extended information.