-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: Allow &mut references to be held by Next's state. (#280)
Two issues combined: - We were running `Next`'s state constructors through the same validation of user-registered constructors, but that's inappropriate. It's OK for them to hold &mut references, since they might be needed later in the pipeline. - There was a bug in our code to determine which request scoped components should be built. The set of prebuilt ids didn't include components that might later become relevant because they are "passed through" without being touched.
- Loading branch information
1 parent
a0def0f
commit 8a0365f
Showing
9 changed files
with
400 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
12 changes: 0 additions & 12 deletions
12
libs/pavex_cli/tests/ui_tests/middlewares/next_handles_lifetimes/expectations/stderr.txt
This file was deleted.
Oops, something went wrong.
235 changes: 235 additions & 0 deletions
235
libs/pavex_cli/tests/ui_tests/middlewares/next_handles_mut_references/expectations/app.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,235 @@ | ||
//! Do NOT edit this code. | ||
//! It was automatically generated by Pavex. | ||
//! All manual edits will be lost next time the code is generated. | ||
extern crate alloc; | ||
struct ServerState { | ||
router: pavex_matchit::Router<u32>, | ||
#[allow(dead_code)] | ||
application_state: ApplicationState, | ||
} | ||
pub struct ApplicationState {} | ||
pub async fn build_application_state() -> crate::ApplicationState { | ||
crate::ApplicationState {} | ||
} | ||
pub fn run( | ||
server_builder: pavex::server::Server, | ||
application_state: ApplicationState, | ||
) -> pavex::server::ServerHandle { | ||
let server_state = std::sync::Arc::new(ServerState { | ||
router: build_router(), | ||
application_state, | ||
}); | ||
server_builder.serve(route_request, server_state) | ||
} | ||
fn build_router() -> pavex_matchit::Router<u32> { | ||
let mut router = pavex_matchit::Router::new(); | ||
router.insert("/home", 0u32).unwrap(); | ||
router | ||
} | ||
async fn route_request( | ||
request: http::Request<hyper::body::Incoming>, | ||
_connection_info: Option<pavex::connection::ConnectionInfo>, | ||
server_state: std::sync::Arc<ServerState>, | ||
) -> pavex::response::Response { | ||
let (request_head, request_body) = request.into_parts(); | ||
#[allow(unused)] | ||
let request_body = pavex::request::body::RawIncomingBody::from(request_body); | ||
let request_head: pavex::request::RequestHead = request_head.into(); | ||
let matched_route = match server_state.router.at(&request_head.target.path()) { | ||
Ok(m) => m, | ||
Err(_) => { | ||
let allowed_methods: pavex::router::AllowedMethods = pavex::router::MethodAllowList::from_iter( | ||
vec![], | ||
) | ||
.into(); | ||
return route_1::entrypoint(&allowed_methods).await; | ||
} | ||
}; | ||
let route_id = matched_route.value; | ||
#[allow(unused)] | ||
let url_params: pavex::request::path::RawPathParams<'_, '_> = matched_route | ||
.params | ||
.into(); | ||
match route_id { | ||
0u32 => { | ||
match &request_head.method { | ||
&pavex::http::Method::GET => route_0::entrypoint().await, | ||
_ => { | ||
let allowed_methods: pavex::router::AllowedMethods = pavex::router::MethodAllowList::from_iter([ | ||
pavex::http::Method::GET, | ||
]) | ||
.into(); | ||
route_1::entrypoint(&allowed_methods).await | ||
} | ||
} | ||
} | ||
i => unreachable!("Unknown route id: {}", i), | ||
} | ||
} | ||
pub mod route_0 { | ||
pub async fn entrypoint() -> pavex::response::Response { | ||
let response = wrapping_0().await; | ||
response | ||
} | ||
async fn stage_1(mut s_0: app::A) -> pavex::response::Response { | ||
let response = wrapping_1(&mut s_0).await; | ||
let response = post_processing_0(s_0, response).await; | ||
response | ||
} | ||
async fn stage_2<'a>(s_0: &'a mut app::A) -> pavex::response::Response { | ||
let response = handler(s_0).await; | ||
response | ||
} | ||
async fn wrapping_0() -> pavex::response::Response { | ||
let v0 = app::a(); | ||
let v1 = crate::route_0::Next0 { | ||
s_0: v0, | ||
next: stage_1, | ||
}; | ||
let v2 = pavex::middleware::Next::new(v1); | ||
let v3 = pavex::middleware::wrap_noop(v2).await; | ||
<pavex::response::Response as pavex::response::IntoResponse>::into_response(v3) | ||
} | ||
async fn wrapping_1(v0: &mut app::A) -> pavex::response::Response { | ||
let v1 = crate::route_0::Next1 { | ||
s_0: v0, | ||
next: stage_2, | ||
}; | ||
let v2 = pavex::middleware::Next::new(v1); | ||
let v3 = app::mw(v2); | ||
<pavex::response::Response as pavex::response::IntoResponse>::into_response(v3) | ||
} | ||
async fn post_processing_0( | ||
v0: app::A, | ||
v1: pavex::response::Response, | ||
) -> pavex::response::Response { | ||
let v2 = app::post(v0, v1); | ||
<pavex::response::Response as pavex::response::IntoResponse>::into_response(v2) | ||
} | ||
async fn handler(v0: &mut app::A) -> pavex::response::Response { | ||
let v1 = app::handler(v0); | ||
<pavex::response::Response as pavex::response::IntoResponse>::into_response(v1) | ||
} | ||
struct Next0<T> | ||
where | ||
T: std::future::Future<Output = pavex::response::Response>, | ||
{ | ||
s_0: app::A, | ||
next: fn(app::A) -> T, | ||
} | ||
impl<T> std::future::IntoFuture for Next0<T> | ||
where | ||
T: std::future::Future<Output = pavex::response::Response>, | ||
{ | ||
type Output = pavex::response::Response; | ||
type IntoFuture = T; | ||
fn into_future(self) -> Self::IntoFuture { | ||
(self.next)(self.s_0) | ||
} | ||
} | ||
struct Next1<'a, T> | ||
where | ||
T: std::future::Future<Output = pavex::response::Response>, | ||
{ | ||
s_0: &'a mut app::A, | ||
next: fn(&'a mut app::A) -> T, | ||
} | ||
impl<'a, T> std::future::IntoFuture for Next1<'a, T> | ||
where | ||
T: std::future::Future<Output = pavex::response::Response>, | ||
{ | ||
type Output = pavex::response::Response; | ||
type IntoFuture = T; | ||
fn into_future(self) -> Self::IntoFuture { | ||
(self.next)(self.s_0) | ||
} | ||
} | ||
} | ||
pub mod route_1 { | ||
pub async fn entrypoint<'a>( | ||
s_0: &'a pavex::router::AllowedMethods, | ||
) -> pavex::response::Response { | ||
let response = wrapping_0(s_0).await; | ||
response | ||
} | ||
async fn stage_1<'a>( | ||
s_0: &'a pavex::router::AllowedMethods, | ||
) -> pavex::response::Response { | ||
let response = wrapping_1(s_0).await; | ||
let response = post_processing_0(response).await; | ||
response | ||
} | ||
async fn stage_2<'a>( | ||
s_0: &'a pavex::router::AllowedMethods, | ||
) -> pavex::response::Response { | ||
let response = handler(s_0).await; | ||
response | ||
} | ||
async fn wrapping_0( | ||
v0: &pavex::router::AllowedMethods, | ||
) -> pavex::response::Response { | ||
let v1 = crate::route_1::Next0 { | ||
s_0: v0, | ||
next: stage_1, | ||
}; | ||
let v2 = pavex::middleware::Next::new(v1); | ||
let v3 = pavex::middleware::wrap_noop(v2).await; | ||
<pavex::response::Response as pavex::response::IntoResponse>::into_response(v3) | ||
} | ||
async fn wrapping_1( | ||
v0: &pavex::router::AllowedMethods, | ||
) -> pavex::response::Response { | ||
let v1 = crate::route_1::Next1 { | ||
s_0: v0, | ||
next: stage_2, | ||
}; | ||
let v2 = pavex::middleware::Next::new(v1); | ||
let v3 = app::mw(v2); | ||
<pavex::response::Response as pavex::response::IntoResponse>::into_response(v3) | ||
} | ||
async fn post_processing_0( | ||
v0: pavex::response::Response, | ||
) -> pavex::response::Response { | ||
let v1 = app::a(); | ||
let v2 = app::post(v1, v0); | ||
<pavex::response::Response as pavex::response::IntoResponse>::into_response(v2) | ||
} | ||
async fn handler(v0: &pavex::router::AllowedMethods) -> pavex::response::Response { | ||
let v1 = pavex::router::default_fallback(v0).await; | ||
<pavex::response::Response as pavex::response::IntoResponse>::into_response(v1) | ||
} | ||
struct Next0<'a, T> | ||
where | ||
T: std::future::Future<Output = pavex::response::Response>, | ||
{ | ||
s_0: &'a pavex::router::AllowedMethods, | ||
next: fn(&'a pavex::router::AllowedMethods) -> T, | ||
} | ||
impl<'a, T> std::future::IntoFuture for Next0<'a, T> | ||
where | ||
T: std::future::Future<Output = pavex::response::Response>, | ||
{ | ||
type Output = pavex::response::Response; | ||
type IntoFuture = T; | ||
fn into_future(self) -> Self::IntoFuture { | ||
(self.next)(self.s_0) | ||
} | ||
} | ||
struct Next1<'a, T> | ||
where | ||
T: std::future::Future<Output = pavex::response::Response>, | ||
{ | ||
s_0: &'a pavex::router::AllowedMethods, | ||
next: fn(&'a pavex::router::AllowedMethods) -> T, | ||
} | ||
impl<'a, T> std::future::IntoFuture for Next1<'a, T> | ||
where | ||
T: std::future::Future<Output = pavex::response::Response>, | ||
{ | ||
type Output = pavex::response::Response; | ||
type IntoFuture = T; | ||
fn into_future(self) -> Self::IntoFuture { | ||
(self.next)(self.s_0) | ||
} | ||
} | ||
} |
87 changes: 87 additions & 0 deletions
87
...x_cli/tests/ui_tests/middlewares/next_handles_mut_references/expectations/diagnostics.dot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
digraph "GET /home - 0" { | ||
0 [ label = "pavex::middleware::wrap_noop(pavex::middleware::Next<crate::route_0::Next0>) -> pavex::response::Response"] | ||
1 [ label = "pavex::middleware::Next::new(crate::route_0::Next0) -> pavex::middleware::Next<crate::route_0::Next0>"] | ||
2 [ label = "crate::route_0::Next0(app::A) -> crate::route_0::Next0"] | ||
3 [ label = "app::a() -> app::A"] | ||
4 [ label = "<pavex::response::Response as pavex::response::IntoResponse>::into_response(pavex::response::Response) -> pavex::response::Response"] | ||
1 -> 0 [ ] | ||
2 -> 1 [ ] | ||
3 -> 2 [ ] | ||
0 -> 4 [ ] | ||
} | ||
|
||
digraph "GET /home - 1" { | ||
0 [ label = "app::mw(pavex::middleware::Next<crate::route_0::Next1<'a>>) -> pavex::response::Response"] | ||
1 [ label = "pavex::middleware::Next::new(crate::route_0::Next1<'a>) -> pavex::middleware::Next<crate::route_0::Next1<'a>>"] | ||
2 [ label = "crate::route_0::Next1(&'a mut app::A) -> crate::route_0::Next1<'a>"] | ||
4 [ label = "<pavex::response::Response as pavex::response::IntoResponse>::into_response(pavex::response::Response) -> pavex::response::Response"] | ||
5 [ label = "&mut app::A"] | ||
1 -> 0 [ ] | ||
2 -> 1 [ ] | ||
0 -> 4 [ ] | ||
5 -> 2 [ ] | ||
} | ||
|
||
digraph "GET /home - 2" { | ||
0 [ label = "app::post(app::A, pavex::response::Response) -> pavex::response::Response"] | ||
1 [ label = "app::A"] | ||
2 [ label = "pavex::response::Response"] | ||
3 [ label = "<pavex::response::Response as pavex::response::IntoResponse>::into_response(pavex::response::Response) -> pavex::response::Response"] | ||
2 -> 0 [ ] | ||
1 -> 0 [ ] | ||
0 -> 3 [ ] | ||
} | ||
|
||
digraph "GET /home - 3" { | ||
0 [ label = "app::handler(&mut app::A) -> pavex::response::Response"] | ||
2 [ label = "<pavex::response::Response as pavex::response::IntoResponse>::into_response(pavex::response::Response) -> pavex::response::Response"] | ||
3 [ label = "&mut app::A"] | ||
0 -> 2 [ ] | ||
3 -> 0 [ ] | ||
} | ||
|
||
digraph "* /home - 0" { | ||
0 [ label = "pavex::middleware::wrap_noop(pavex::middleware::Next<crate::route_1::Next0<'a>>) -> pavex::response::Response"] | ||
1 [ label = "pavex::middleware::Next::new(crate::route_1::Next0<'a>) -> pavex::middleware::Next<crate::route_1::Next0<'a>>"] | ||
2 [ label = "crate::route_1::Next0(&'a pavex::router::AllowedMethods) -> crate::route_1::Next0<'a>"] | ||
4 [ label = "<pavex::response::Response as pavex::response::IntoResponse>::into_response(pavex::response::Response) -> pavex::response::Response"] | ||
5 [ label = "&pavex::router::AllowedMethods"] | ||
1 -> 0 [ ] | ||
2 -> 1 [ ] | ||
0 -> 4 [ ] | ||
5 -> 2 [ ] | ||
} | ||
|
||
digraph "* /home - 1" { | ||
0 [ label = "app::mw(pavex::middleware::Next<crate::route_1::Next1<'a>>) -> pavex::response::Response"] | ||
1 [ label = "pavex::middleware::Next::new(crate::route_1::Next1<'a>) -> pavex::middleware::Next<crate::route_1::Next1<'a>>"] | ||
2 [ label = "crate::route_1::Next1(&'a pavex::router::AllowedMethods) -> crate::route_1::Next1<'a>"] | ||
4 [ label = "<pavex::response::Response as pavex::response::IntoResponse>::into_response(pavex::response::Response) -> pavex::response::Response"] | ||
5 [ label = "&pavex::router::AllowedMethods"] | ||
1 -> 0 [ ] | ||
2 -> 1 [ ] | ||
0 -> 4 [ ] | ||
5 -> 2 [ ] | ||
} | ||
|
||
digraph "* /home - 2" { | ||
0 [ label = "app::post(app::A, pavex::response::Response) -> pavex::response::Response"] | ||
1 [ label = "app::a() -> app::A"] | ||
2 [ label = "pavex::response::Response"] | ||
3 [ label = "<pavex::response::Response as pavex::response::IntoResponse>::into_response(pavex::response::Response) -> pavex::response::Response"] | ||
2 -> 0 [ ] | ||
1 -> 0 [ ] | ||
0 -> 3 [ ] | ||
} | ||
|
||
digraph "* /home - 3" { | ||
0 [ label = "pavex::router::default_fallback(&pavex::router::AllowedMethods) -> pavex::response::Response"] | ||
2 [ label = "<pavex::response::Response as pavex::response::IntoResponse>::into_response(pavex::response::Response) -> pavex::response::Response"] | ||
3 [ label = "&pavex::router::AllowedMethods"] | ||
0 -> 2 [ ] | ||
3 -> 0 [ ] | ||
} | ||
|
||
digraph app_state { | ||
0 [ label = "crate::ApplicationState() -> crate::ApplicationState"] | ||
} |
Oops, something went wrong.