From 39eb59e466843774067f37c8464db0d9b00b157d Mon Sep 17 00:00:00 2001 From: Yong Wen Chua Date: Wed, 14 Feb 2018 13:37:48 +0800 Subject: [PATCH] Address ICE related to impl trait Original bug: https://github.com/rust-lang/rust/issues/43380 Fixes #33 --- examples/manual.rs | 10 ++++++++-- src/lib.rs | 21 +++++++++++++++------ tests/manual.rs | 6 +++--- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/examples/manual.rs b/examples/manual.rs index 420d827..e61d52c 100644 --- a/examples/manual.rs +++ b/examples/manual.rs @@ -11,16 +11,20 @@ use rocket::response::Responder; use rocket_cors::{AllowedHeaders, AllowedOrigins, Cors}; /// Using a borrowed Cors +/// Note that the `'r` lifetime annotation is not requred here because `State` borrows with lifetime +/// `'r` and so does `Responder`! #[get("/")] -fn borrowed<'r>(options: State<'r, Cors>) -> impl Responder<'r> { +fn borrowed(options: State) -> impl Responder { options .inner() .respond_borrowed(|guard| guard.responder("Hello CORS")) } /// Using a `Response` instead of a `Responder`. You generally won't have to do this. +/// Note that the `'r` lifetime annotation is not requred here because `State` borrows with lifetime +/// `'r` and so does `Responder`! #[get("/response")] -fn response<'r>(options: State<'r, Cors>) -> impl Responder<'r> { +fn response(options: State) -> impl Responder { let mut response = Response::new(); response.set_sized_body(Cursor::new("Hello CORS!")); @@ -30,6 +34,7 @@ fn response<'r>(options: State<'r, Cors>) -> impl Responder<'r> { } /// Create and use an ad-hoc Cors +/// Note that the `'r` lifetime is needed because the compiler cannot elide anything. #[get("/owned")] fn owned<'r>() -> impl Responder<'r> { let options = cors_options(); @@ -39,6 +44,7 @@ fn owned<'r>() -> impl Responder<'r> { /// You need to define an OPTIONS route for preflight checks if you want to use `Cors` struct /// that is not in Rocket's managed state. /// These routes can just return the unit type `()` +/// Note that the `'r` lifetime is needed because the compiler cannot elide anything. #[options("/owned")] fn owned_options<'r>() -> impl Responder<'r> { let options = cors_options(); diff --git a/src/lib.rs b/src/lib.rs index 9393a47..a205c3c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -250,7 +250,7 @@ //! In this case, you might as well use the `Guard` method above and place the `Cors` struct in //! Rocket's [state](https://rocket.rs/guide/state/). //! Alternatively, you can create a `Cors` struct directly in the route. -//! - Your routes will need to have a `'r` lifetime and return `impl Responder<'r>`. +//! - Your routes _might_ need to have a `'r` lifetime and return `impl Responder<'r>`. See below. //! - Using the `Cors` struct, use either the //! [`respond_owned`](struct.Cors.html#method.respond_owned) or //! [`respond_borrowed`](struct.Cors.html#method.respond_borrowed) function and pass in a handler @@ -260,11 +260,20 @@ //! - You will have to manually define your own `OPTIONS` routes. //! //! ### Notes about route lifetime -//! It is unfortunate that you have to manually specify the `'r` lifetimes in your routes. -//! Leaving out the lifetime will result in a -//! [compiler panic](https://github.com/rust-lang/rust/issues/43380). Even if the panic is fixed, -//! it is not known if we can exclude the lifetime because lifetimes are _elided_ in Rust, -//! not inferred. +//! You might have to specify a `'r` lifetime in your routes and then return `impl Responder<'r>`. +//! If you are not sure what to do, you can try to leave the lifetime out and then add it in +//! when the compiler complains. +//! +//! Generally, you will need to manually annotate the lifetime for the following cases where +//! the compiler is unable to [elide](https://doc.rust-lang.org/beta/nomicon/lifetime-elision.html) +//! the lifetime: +//! +//! - Your function arguments do not borrow anything. +//! - Your function arguments borrow from more than one lifetime. +//! - Your function arguments borrow from a lifetime that is shorter than the `'r` lifetime +//! required. +//! +//! You can see examples when the lifetime annotation is required (or not) in `examples/manual.rs`. //! //! ### Owned example //! This is the most likely scenario when you want to have manual CORS validation. You can use this diff --git a/tests/manual.rs b/tests/manual.rs index 7b00492..6d0b189 100644 --- a/tests/manual.rs +++ b/tests/manual.rs @@ -17,14 +17,14 @@ use rocket_cors::*; /// Using a borrowed `Cors` #[get("/")] -fn cors<'r>(options: State<'r, Cors>) -> impl Responder<'r> { +fn cors(options: State) -> impl Responder { options .inner() .respond_borrowed(|guard| guard.responder("Hello CORS")) } #[get("/panic")] -fn panicking_route<'r>(options: State<'r, Cors>) -> impl Responder<'r> { +fn panicking_route(options: State) -> impl Responder { options.inner().respond_borrowed(|_| -> () { panic!("This route will panic"); }) @@ -51,7 +51,7 @@ fn owned<'r>() -> impl Responder<'r> { /// `Responder` with String #[allow(unmounted_route)] #[get("/")] -fn responder_string<'r>(options: State<'r, Cors>) -> impl Responder<'r> { +fn responder_string(options: State) -> impl Responder { options .inner() .respond_borrowed(|guard| guard.responder("Hello CORS".to_string()))