diff --git a/libs/pavex_cli/tests/ui_tests/reflection/reexported_type_alias_work/dep.rs b/libs/pavex_cli/tests/ui_tests/reflection/reexported_type_alias_work/dep.rs new file mode 100644 index 00000000..87039c6b --- /dev/null +++ b/libs/pavex_cli/tests/ui_tests/reflection/reexported_type_alias_work/dep.rs @@ -0,0 +1,12 @@ +#[doc(inline)] +pub use api::engine; +#[doc(inline)] +pub use api::Surreal; + +mod api { + pub struct Surreal(T); + + pub mod engine { + pub struct Any; + } +} diff --git a/libs/pavex_cli/tests/ui_tests/reflection/reexported_type_alias_work/expectations/app.rs b/libs/pavex_cli/tests/ui_tests/reflection/reexported_type_alias_work/expectations/app.rs new file mode 100644 index 00000000..84e0f6d1 --- /dev/null +++ b/libs/pavex_cli/tests/ui_tests/reflection/reexported_type_alias_work/expectations/app.rs @@ -0,0 +1,164 @@ +//! 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, + application_state: ApplicationState, +} +pub struct ApplicationState { + s0: dep::Surreal, +} +pub async fn build_application_state() -> crate::ApplicationState { + let v0 = app::constructor(); + crate::ApplicationState { s0: v0 } +} +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 { + let mut router = pavex_matchit::Router::new(); + router.insert("/", 0u32).unwrap(); + router +} +async fn route_request( + request: http::Request, + _connection_info: Option, + server_state: std::sync::Arc, +) -> 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(&server_state.application_state.s0).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<'a>( + s_0: &'a dep::Surreal, + ) -> pavex::response::Response { + let response = wrapping_0(s_0).await; + response + } + async fn stage_1<'a>( + s_0: &'a dep::Surreal, + ) -> pavex::response::Response { + let response = handler(s_0).await; + response + } + async fn wrapping_0( + v0: &dep::Surreal, + ) -> pavex::response::Response { + 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; + ::into_response(v3) + } + async fn handler(v0: &dep::Surreal) -> pavex::response::Response { + let v1 = app::handler(v0); + ::into_response(v1) + } + struct Next0<'a, T> + where + T: std::future::Future, + { + s_0: &'a dep::Surreal, + next: fn(&'a dep::Surreal) -> T, + } + impl<'a, T> std::future::IntoFuture for Next0<'a, T> + where + T: std::future::Future, + { + 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 = 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; + ::into_response(v3) + } + async fn handler(v0: &pavex::router::AllowedMethods) -> pavex::response::Response { + let v1 = pavex::router::default_fallback(v0).await; + ::into_response(v1) + } + struct Next0<'a, T> + where + T: std::future::Future, + { + 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, + { + type Output = pavex::response::Response; + type IntoFuture = T; + fn into_future(self) -> Self::IntoFuture { + (self.next)(self.s_0) + } + } +} \ No newline at end of file diff --git a/libs/pavex_cli/tests/ui_tests/reflection/reexported_type_alias_work/expectations/diagnostics.dot b/libs/pavex_cli/tests/ui_tests/reflection/reexported_type_alias_work/expectations/diagnostics.dot new file mode 100644 index 00000000..4692f6cc --- /dev/null +++ b/libs/pavex_cli/tests/ui_tests/reflection/reexported_type_alias_work/expectations/diagnostics.dot @@ -0,0 +1,45 @@ +digraph "GET / - 0" { + 0 [ label = "pavex::middleware::wrap_noop(pavex::middleware::Next>) -> pavex::response::Response"] + 1 [ label = "pavex::middleware::Next::new(crate::route_0::Next0<'a>) -> pavex::middleware::Next>"] + 2 [ label = "crate::route_0::Next0(&'a dep::Surreal) -> crate::route_0::Next0<'a>"] + 4 [ label = "::into_response(pavex::response::Response) -> pavex::response::Response"] + 5 [ label = "&dep::Surreal"] + 1 -> 0 [ ] + 2 -> 1 [ ] + 0 -> 4 [ ] + 5 -> 2 [ ] +} + +digraph "GET / - 1" { + 0 [ label = "app::handler(&dep::Surreal) -> pavex::response::Response"] + 2 [ label = "::into_response(pavex::response::Response) -> pavex::response::Response"] + 3 [ label = "&dep::Surreal"] + 0 -> 2 [ ] + 3 -> 0 [ ] +} + +digraph "* / - 0" { + 0 [ label = "pavex::middleware::wrap_noop(pavex::middleware::Next>) -> pavex::response::Response"] + 1 [ label = "pavex::middleware::Next::new(crate::route_1::Next0<'a>) -> pavex::middleware::Next>"] + 2 [ label = "crate::route_1::Next0(&'a pavex::router::AllowedMethods) -> crate::route_1::Next0<'a>"] + 4 [ label = "::into_response(pavex::response::Response) -> pavex::response::Response"] + 5 [ label = "&pavex::router::AllowedMethods"] + 1 -> 0 [ ] + 2 -> 1 [ ] + 0 -> 4 [ ] + 5 -> 2 [ ] +} + +digraph "* / - 1" { + 0 [ label = "pavex::router::default_fallback(&pavex::router::AllowedMethods) -> pavex::response::Response"] + 2 [ label = "::into_response(pavex::response::Response) -> pavex::response::Response"] + 3 [ label = "&pavex::router::AllowedMethods"] + 0 -> 2 [ ] + 3 -> 0 [ ] +} + +digraph app_state { + 0 [ label = "crate::ApplicationState(dep::Surreal) -> crate::ApplicationState"] + 1 [ label = "app::constructor() -> dep::Surreal"] + 1 -> 0 [ ] +} \ No newline at end of file diff --git a/libs/pavex_cli/tests/ui_tests/reflection/reexported_type_alias_work/lib.rs b/libs/pavex_cli/tests/ui_tests/reflection/reexported_type_alias_work/lib.rs new file mode 100644 index 00000000..693244a4 --- /dev/null +++ b/libs/pavex_cli/tests/ui_tests/reflection/reexported_type_alias_work/lib.rs @@ -0,0 +1,20 @@ +use pavex::blueprint::{router::GET, Blueprint}; +use pavex::f; +use pavex::response::Response; + +pub type RemoteAlias = dep::Surreal; + +pub fn constructor() -> RemoteAlias { + todo!() +} + +pub fn handler(_a: &RemoteAlias) -> Response { + todo!() +} + +pub fn blueprint() -> Blueprint { + let mut bp = Blueprint::new(); + bp.singleton(f!(crate::constructor)); + bp.route(GET, "/", f!(crate::handler)); + bp +} diff --git a/libs/pavex_cli/tests/ui_tests/reflection/reexported_type_alias_work/test_config.toml b/libs/pavex_cli/tests/ui_tests/reflection/reexported_type_alias_work/test_config.toml new file mode 100644 index 00000000..4fde42c9 --- /dev/null +++ b/libs/pavex_cli/tests/ui_tests/reflection/reexported_type_alias_work/test_config.toml @@ -0,0 +1,7 @@ +description = "Reproduction of a reported bug" + +[expectations] +codegen = "pass" + +[ephemeral_dependencies] +dep = { path = "dep.rs" } diff --git a/libs/pavexc/src/compiler/app.rs b/libs/pavexc/src/compiler/app.rs index 77d8f669..b1705626 100644 --- a/libs/pavexc/src/compiler/app.rs +++ b/libs/pavexc/src/compiler/app.rs @@ -95,6 +95,7 @@ impl App { ) else { return Err(diagnostics); }; + let framework_item_db = FrameworkItemDb::new(&package_graph, &krate_collection); let mut component_db = ComponentDb::build( user_component_db, diff --git a/libs/pavexc/src/rustdoc/queries.rs b/libs/pavexc/src/rustdoc/queries.rs index 60400cd7..ecfc4517 100644 --- a/libs/pavexc/src/rustdoc/queries.rs +++ b/libs/pavexc/src/rustdoc/queries.rs @@ -698,6 +698,7 @@ impl Crate { &mut id2private_import_paths, &mut re_exports, &krate.root, + true, )?; import_path2id.reserve(id2public_import_paths.len()); @@ -870,6 +871,7 @@ fn index_local_types<'a>( private_path_index: &mut HashMap>>, re_exports: &mut HashMap, (Vec, u32)>, current_item_id: &rustdoc_types::Id, + is_public: bool, ) -> Result<(), anyhow::Error> { // TODO: the way we handle `current_path` is extremely wasteful, // we can likely reuse the same buffer throughout. @@ -890,6 +892,8 @@ fn index_local_types<'a>( Some(i) => i, }; + let is_public = is_public && current_item.visibility == Visibility::Public; + match ¤t_item.inner { ItemEnum::Module(m) => { let current_path_segment = current_item @@ -906,6 +910,7 @@ fn index_local_types<'a>( private_path_index, re_exports, item_id, + is_public, )?; } } @@ -949,6 +954,7 @@ fn index_local_types<'a>( private_path_index, re_exports, re_exported_item_id, + is_public, )?; } } else { @@ -960,6 +966,7 @@ fn index_local_types<'a>( private_path_index, re_exports, imported_id, + is_public, )?; } } @@ -977,7 +984,7 @@ fn index_local_types<'a>( current_path.push(name); let path = current_path.into_iter().map(|s| s.to_string()).collect(); - let index = if current_item.visibility == Visibility::Public { + let index = if is_public { public_path_index } else { private_path_index