Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a non-static lifetime to Rocket's manage

How can I pass an object with a non-static lifetime to Rocket's manage? Currently I have something along these lines:

fn foo<'a>(bar: Bar<'a>) -> Result<(), Error> {
  rocket::ignite()
    .manage(bar)
    .mount("/", routes![index])
    .launch();

  Ok(())
}

But I get the following error:

cannot infer an appropriate lifetime due to conflicting requirements

note: ...so that the expression is assignable:
      expected bar::Bar<'_>
         found bar::Bar<'a>
note: but, the lifetime must be valid for the static lifetime...

To add more context, Bar is a struct containing boxed closures that get initialised using runtime args. The args contain things like passwords, keys and secrets - the actual code is open source so can be found here. It's WIP so will change and isn't entirely up-to-date, but hopefully gives an idea for the end goal.

like image 573
Will Squire Avatar asked Jan 27 '23 09:01

Will Squire


1 Answers

You can't use a non-static lifetime because the signature of manage() literally says Send + Sync + 'static. The reason for this is stated in the documentation for State:

The type being managed must be thread safe and sendable across thread boundaries. In other words, it must implement Send + Sync + 'static.

That is, since (worker) threads may access the managed state at any time, and since there is no guarantee when those threads might exit, the managed state must live for at least as long as the entire program; that's 'static.

You can try altering your foo() to take bar: Bar<'static> instead of a generic lifetime and work your way up from there. The requirement for 'static is usually not as bad as it sounds, since all owned values (like String::new()) are 'static as long as they do not contain references to other things.

If you can't provide a Bar<'static>, you might be able to use an Arc instead of plain references so Bar<'a> becomes Bar. The rationale here is that Bar holds atomically counted references instead of references, so holding a Bar guarantees that all members are alive while Bar is alive. This makes Bar 'static.


As a side-note: It might be helpful when thinking about 'static that the requirement for some type to be 'static does not mean that the value does, in fact, live forever. It just means that the value could be made to live forever. In your case, the State has no way to force other threads to not exit and destroy their values. Hence State must guarantee that all the values it operates on can be made to live as long as State wants. This is only true if those values are 'static at the thread-boundary.

like image 107
user2722968 Avatar answered Jan 31 '23 06:01

user2722968