Skip to content

Commit c263a6c

Browse files
committed
Update Fairings types to fix issues
1 parent 3fbf1b4 commit c263a6c

File tree

12 files changed

+149
-25
lines changed

12 files changed

+149
-25
lines changed

contrib/dyn_templates/src/fairing.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,10 @@ impl Fairing for TemplateFairing {
6666
}
6767

6868
#[cfg(debug_assertions)]
69-
async fn on_request<'r>(&self, req: &'r mut rocket::Request<'_>, _data: &mut rocket::Data<'_>)
70-
-> Result<(), Box<dyn TypedError<'r> + 'r>>
71-
{
69+
async fn on_request(&self, req: &mut rocket::Request<'_>, _data: &mut rocket::Data<'_>) {
7270
let cm = req.rocket().state::<ContextManager>()
7371
.expect("Template ContextManager registered in on_ignite");
7472

7573
cm.reload_if_needed(&self.callback);
76-
Ok(())
7774
}
7875
}

core/codegen/src/attribute/catch/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ fn error_guard_decl(guard: &ErrorGuard) -> TokenStream {
3131
fn request_guard_decl(guard: &Guard) -> TokenStream {
3232
let (ident, ty) = (guard.fn_ident.rocketized(), &guard.ty);
3333
quote_spanned! { ty.span() =>
34-
let #ident: #ty = match <#ty as #FromError>::from_error(#__status, #__req, __error_init).await {
34+
let #ident: #ty = match <#ty as #FromError>::from_error(
35+
#__status,
36+
#__req,
37+
__error_init
38+
).await {
3539
#_Result::Ok(__v) => __v,
3640
#_Result::Err(__e) => {
3741
::rocket::trace::info!(

core/codegen/src/derive/typed_error.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ pub fn derive_typed_error(input: proc_macro::TokenStream) -> TokenStream {
3737
.inner_mapper(MapperBuild::new()
3838
.with_output(|_, output| quote! {
3939
#[allow(unused_variables)]
40-
fn respond_to(&self, request: &'r #Request<'_>) -> #_Result<#Response<'r>, #_Status> {
40+
fn respond_to(&self, request: &'r #Request<'_>)
41+
-> #_Result<#Response<'r>, #_Status>
42+
{
4143
#output
4244
}
4345
})
@@ -76,7 +78,9 @@ pub fn derive_typed_error(input: proc_macro::TokenStream) -> TokenStream {
7678
None => Member::Unnamed(Index { index: field.index as u32, span })
7779
};
7880

79-
source = Some(quote_spanned!(span => #_Some(&self.#member as &dyn #TypedError<'r>)));
81+
source = Some(quote_spanned!(
82+
span => #_Some(&self.#member as &dyn #TypedError<'r>
83+
)));
8084
}
8185
}
8286
}

core/codegen/tests/typed_error.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#[macro_use] extern crate rocket;
2+
use rocket::catcher::TypedError;
3+
use rocket::http::Status;
4+
5+
fn boxed_error<'r>(_val: Box<dyn TypedError<'r> + 'r>) {}
6+
7+
#[derive(TypedError)]
8+
pub enum Foo<'r> {
9+
First(String),
10+
Second(Vec<u8>),
11+
Third {
12+
#[error(source)]
13+
responder: std::io::Error,
14+
},
15+
#[error(status = 400)]
16+
Fourth {
17+
string: &'r str,
18+
},
19+
}
20+
21+
#[test]
22+
fn validate_foo() {
23+
let first = Foo::First("".into());
24+
assert_eq!(first.status(), Status::InternalServerError);
25+
assert!(first.source().is_none());
26+
boxed_error(Box::new(first));
27+
let second = Foo::Second(vec![]);
28+
assert_eq!(second.status(), Status::InternalServerError);
29+
assert!(second.source().is_none());
30+
boxed_error(Box::new(second));
31+
let third = Foo::Third {
32+
responder: std::io::Error::new(std::io::ErrorKind::NotFound, ""),
33+
};
34+
assert_eq!(third.status(), Status::InternalServerError);
35+
assert!(std::ptr::eq(
36+
third.source().unwrap(),
37+
if let Foo::Third { responder } = &third { responder } else { panic!() }
38+
));
39+
boxed_error(Box::new(third));
40+
let fourth = Foo::Fourth { string: "" };
41+
assert_eq!(fourth.status(), Status::BadRequest);
42+
assert!(fourth.source().is_none());
43+
boxed_error(Box::new(fourth));
44+
}
45+
46+
#[derive(TypedError)]
47+
pub struct InfallibleError {
48+
#[error(source)]
49+
_inner: std::convert::Infallible,
50+
}
51+
52+
#[derive(TypedError)]
53+
pub struct StaticError {
54+
#[error(source)]
55+
inner: std::string::FromUtf8Error,
56+
}
57+
58+
#[test]
59+
fn validate_static() {
60+
let val = StaticError {
61+
inner: String::from_utf8(vec![0xFF]).unwrap_err(),
62+
};
63+
assert_eq!(val.status(), Status::InternalServerError);
64+
assert!(std::ptr::eq(
65+
val.source().unwrap(),
66+
&val.inner,
67+
));
68+
boxed_error(Box::new(val));
69+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#[macro_use] extern crate rocket;
2+
3+
#[derive(TypedError)]
4+
struct InnerError;
5+
struct InnerNonError;
6+
7+
#[derive(TypedError)]
8+
struct Thing1<'a, 'b> {
9+
a: &'a str,
10+
b: &'b str,
11+
}
12+
13+
#[derive(TypedError)]
14+
struct Thing2 {
15+
#[error(source)]
16+
inner: InnerNonError,
17+
}
18+
19+
#[derive(TypedError)]
20+
enum Thing3<'a, 'b> {
21+
A(&'a str),
22+
B(&'b str),
23+
}
24+
25+
#[derive(TypedError)]
26+
enum Thing4 {
27+
A(#[error(source)] InnerNonError),
28+
B(#[error(source)] InnerError),
29+
}
30+
31+
#[derive(TypedError)]
32+
enum EmptyEnum { }

core/lib/src/erased.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ pub struct ErasedError<'r> {
4141

4242
impl<'r> ErasedError<'r> {
4343
pub fn new() -> Self {
44-
Self { error: None }
44+
Self { error: None }
4545
}
4646

4747
pub fn write(&mut self, error: Option<Box<dyn TypedError<'r> + 'r>>) {
@@ -142,11 +142,12 @@ impl ErasedRequest {
142142
// SAFETY: At this point, ErasedRequest contains a request, which is permitted
143143
// to borrow from `Rocket` and `Parts`. They both have stable addresses (due to
144144
// `Arc` and `Box`), and the Request will be dropped first (due to drop order).
145-
// SAFETY: Here, we place the `ErasedRequest` (i.e. the `Request`) behind an `Arc` (TODO: Why not Box?)
145+
// SAFETY: Here, we place the `ErasedRequest` (i.e. the `Request`) behind an `Arc`
146146
// to ensure it has a stable address, and we again use drop order to ensure the `Request`
147147
// is dropped before the values that can borrow from it.
148148
let mut parent = Arc::new(self);
149-
// SAFETY: This error is permitted to borrow from the `Request` (as well as `Rocket` and `Parts`).
149+
// SAFETY: This error is permitted to borrow from the `Request` (as well as `Rocket` and
150+
// `Parts`).
150151
let mut error = ErasedError { error: None };
151152
let token: T = {
152153
let parent: &mut ErasedRequest = Arc::get_mut(&mut parent).unwrap();

core/lib/src/fairing/ad_hoc.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ enum AdHocKind {
6161
Liftoff(Once<dyn for<'a> FnOnce(&'a Rocket<Orbit>) -> BoxFuture<'a, ()> + Send + 'static>),
6262

6363
/// An ad-hoc **request** fairing. Called when a request is received.
64-
Request(Box<dyn for<'a, 'b> Fn(&'a mut Request<'_>, &'b mut Data<'_>)
64+
Request(Box<dyn for<'a> Fn(&'a mut Request<'_>, &'a mut Data<'_>)
6565
-> BoxFuture<'a, ()> + Send + Sync + 'static>),
6666

6767
/// An ad-hoc **request_filter** fairing. Called when a request is received.
@@ -159,7 +159,7 @@ impl AdHoc {
159159
/// });
160160
/// ```
161161
pub fn on_request<F: Send + Sync + 'static>(name: &'static str, f: F) -> AdHoc
162-
where F: for<'a, 'b> Fn(&'a mut Request<'_>, &'b mut Data<'_>)
162+
where F: for<'a> Fn(&'a mut Request<'_>, &'a mut Data<'_>)
163163
-> BoxFuture<'a, ()>
164164
{
165165
AdHoc { name, kind: AdHocKind::Request(Box::new(f)) }
@@ -407,7 +407,7 @@ impl AdHoc {
407407
let _ = self.routes(rocket);
408408
}
409409

410-
async fn on_request<'r>(&self, req: &'r mut Request<'_>, _: &mut Data<'_>) {
410+
async fn on_request(&self, req: &mut Request<'_>, _: &mut Data<'_>) {
411411
// If the URI has no trailing slash, it routes as before.
412412
if req.uri().is_normalized_nontrailing() {
413413
return;
@@ -458,7 +458,7 @@ impl Fairing for AdHoc {
458458
}
459459
}
460460

461-
async fn on_request<'r>(&self, req: &'r mut Request<'_>, data: &mut Data<'_>) {
461+
async fn on_request(&self, req: &mut Request<'_>, data: &mut Data<'_>) {
462462
if let AdHocKind::Request(ref f) = self.kind {
463463
f(req, data).await
464464
}

core/lib/src/fairing/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ pub trait Fairing: Send + Sync + Any + 'static {
511511
/// ## Default Implementation
512512
///
513513
/// The default implementation of this method does nothing.
514-
async fn on_request<'r>(&self, _req: &'r mut Request<'_>, _data: &mut Data<'_>) { }
514+
async fn on_request(&self, _req: &mut Request<'_>, _data: &mut Data<'_>) { }
515515

516516
/// The request filter callback.
517517
///
@@ -582,7 +582,7 @@ impl<T: Fairing + ?Sized> Fairing for std::sync::Arc<T> {
582582
}
583583

584584
#[inline]
585-
async fn on_request<'r>(&self, req: &'r mut Request<'_>, data: &mut Data<'_>) {
585+
async fn on_request(&self, req: &mut Request<'_>, data: &mut Data<'_>) {
586586
(self as &T).on_request(req, data).await
587587
}
588588

core/lib/src/lifecycle.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,9 @@ impl Rocket<Orbit> {
108108
let mut response = if error_ptr.is_some() {
109109
// error_ptr is always some here, we just checked.
110110
self.dispatch_error(error_ptr.get().unwrap().status(), request, error_ptr.get()).await
111-
// We MUST wait until we are inside this block to call `get`, since we HAVE to borrow it for `'r`.
112-
// (And it's invariant, so we can't downcast the borrow to a shorter lifetime)
111+
// We MUST wait until we are inside this block to call `get`, since we HAVE to borrow
112+
// it for `'r`. (And it's invariant, so we can't downcast the borrow to a shorter
113+
// lifetime)
113114
} else {
114115
match self.route(request, data).await {
115116
Outcome::Success(response) => response,

core/lib/src/local/asynchronous/response.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,13 @@ impl Drop for LocalResponse<'_> {
6767
}
6868

6969
impl<'c> LocalResponse<'c> {
70-
pub(crate) fn new<P, PO, F, O>(req: Request<'c>, mut data: Data<'c>, preprocess: P, f: F) -> impl Future<Output = LocalResponse<'c>>
71-
where P: FnOnce(&'c mut Request<'c>, &'c mut Data<'c>, &'c mut ErasedError<'c>) -> PO + Send,
70+
pub(crate) fn new<P, PO, F, O>(req: Request<'c>, mut data: Data<'c>, preprocess: P, f: F)
71+
-> impl Future<Output = LocalResponse<'c>>
72+
where P: FnOnce(&'c mut Request<'c>, &'c mut Data<'c>, &'c mut ErasedError<'c>)
73+
-> PO + Send,
7274
PO: Future<Output = RequestToken> + Send + 'c,
73-
F: FnOnce(RequestToken, &'c Request<'c>, Data<'c>, &'c mut ErasedError<'c>) -> O + Send,
75+
F: FnOnce(RequestToken, &'c Request<'c>, Data<'c>, &'c mut ErasedError<'c>)
76+
-> O + Send,
7477
O: Future<Output = Response<'c>> + Send + 'c
7578
{
7679
// `LocalResponse` is a self-referential structure. In particular,
@@ -121,7 +124,12 @@ impl<'c> LocalResponse<'c> {
121124
// the value is used to set cookie defaults.
122125
// SAFETY: The type of `preprocess` ensures that all of these types have the correct
123126
// lifetime ('c).
124-
let response: Response<'c> = f(token, request, data, unsafe { transmute(&mut error) }).await;
127+
let response: Response<'c> = f(
128+
token,
129+
request,
130+
data,
131+
unsafe { transmute(&mut error) }
132+
).await;
125133
let mut cookies = CookieJar::new(None, request.rocket());
126134
for cookie in response.cookies() {
127135
cookies.add_original(cookie.into_owned());

core/lib/src/server.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ impl Rocket<Orbit> {
4242
span_debug!("request headers" => request.inner().headers().iter().trace_all_debug());
4343
let mut response = request.into_response(
4444
stream,
45-
|rocket, request, data, error_ptr| Box::pin(rocket.preprocess(request, data, error_ptr)),
45+
|rocket, request, data, error_ptr| {
46+
Box::pin(rocket.preprocess(request, data, error_ptr))
47+
},
4648
|token, rocket, request, data, error_ptr| Box::pin(async move {
4749
if !request.errors.is_empty() {
4850
error_ptr.write(Some(Box::new(RequestErrors::new(&request.errors))));

examples/todo/src/main.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,10 @@ async fn toggle(id: i32, conn: DbConn) -> Either<Redirect, Template> {
7070
Ok(_) => Either::Left(Redirect::to("/")),
7171
Err(e) => {
7272
error!("DB toggle({id}) error: {e}");
73-
Either::Right(Template::render("index", Context::err(&conn, "Failed to toggle task.").await))
73+
Either::Right(Template::render(
74+
"index",
75+
Context::err(&conn, "Failed to toggle task.").await
76+
))
7477
}
7578
}
7679
}
@@ -81,7 +84,10 @@ async fn delete(id: i32, conn: DbConn) -> Either<Flash<Redirect>, Template> {
8184
Ok(_) => Either::Left(Flash::success(Redirect::to("/"), "Todo was deleted.")),
8285
Err(e) => {
8386
error!("DB deletion({id}) error: {e}");
84-
Either::Right(Template::render("index", Context::err(&conn, "Failed to delete task.").await))
87+
Either::Right(Template::render(
88+
"index",
89+
Context::err(&conn, "Failed to delete task.").await
90+
))
8591
}
8692
}
8793
}

0 commit comments

Comments
 (0)