From dfca18d307e523ee2a5cd28a9c83dba01ffb9130 Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Tue, 14 Jul 2020 00:44:59 -0700 Subject: [PATCH] Generate 'uri!' macro names independently of span. Prior to this commit, codegen used 'Span' information to generate a unique id for a given route. This commit changes the id generation to instead use 1) the route's name and path, 2) a an per-generation atomically increasing ID, and 3) the ids of the process/thread the proc-macro is running in. Together, these values should provide a unique id for a given route, even in the face of the reused processes and threads, while also removing the dependence on unstable Span features. Fixes #1373. --- core/codegen/src/attribute/route.rs | 21 +++++++++++-------- .../tests/typed-uri-docs-redef-issue-1373.rs | 14 +++++++++++++ 2 files changed, 26 insertions(+), 9 deletions(-) create mode 100644 core/lib/tests/typed-uri-docs-redef-issue-1373.rs diff --git a/core/codegen/src/attribute/route.rs b/core/codegen/src/attribute/route.rs index 9a0b316b..9691db8e 100644 --- a/core/codegen/src/attribute/route.rs +++ b/core/codegen/src/attribute/route.rs @@ -1,3 +1,4 @@ +use std::sync::atomic::{AtomicUsize, Ordering}; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; @@ -38,9 +39,9 @@ struct MethodRouteAttribute { /// This structure represents the parsed `route` attribute and associated items. #[derive(Debug)] struct Route { - /// The status associated with the code in the `#[route(code)]` attribute. + /// The attribute: `#[get(path, ...)]`. attribute: RouteAttribute, - /// The function that was decorated with the `route` attribute. + /// The function the attribute decorated, i.e, the handler. function: syn::ItemFn, /// The non-static parameters declared in the route segments. segments: IndexSet, @@ -322,6 +323,9 @@ fn request_guard_expr(ident: &syn::Ident, ty: &syn::Type) -> TokenStream2 { } fn generate_internal_uri_macro(route: &Route) -> TokenStream2 { + // Keep a global counter (+ thread ID later) to generate unique ids. + static COUNTER: AtomicUsize = AtomicUsize::new(0); + let dynamic_args = route.segments.iter() .filter(|seg| seg.source == Source::Path || seg.source == Source::Query) .filter(|seg| seg.kind != Kind::Static) @@ -330,14 +334,13 @@ fn generate_internal_uri_macro(route: &Route) -> TokenStream2 { .map(|(ident, _, ty)| quote!(#ident: #ty)); let mut hasher = DefaultHasher::new(); - let route_span = route.function.span(); - route_span.source_file().path().hash(&mut hasher); - let line_column = route_span.start(); - line_column.line.hash(&mut hasher); - line_column.column.hash(&mut hasher); + route.function.sig.ident.hash(&mut hasher); + route.attribute.path.origin.0.path().hash(&mut hasher); + std::process::id().hash(&mut hasher); + std::thread::current().id().hash(&mut hasher); + COUNTER.fetch_add(1, Ordering::AcqRel).hash(&mut hasher); - let mut generated_macro_name = route.function.sig.ident.prepend(URI_MACRO_PREFIX); - generated_macro_name.set_span(Span::call_site().into()); + let generated_macro_name = route.function.sig.ident.prepend(URI_MACRO_PREFIX); let inner_generated_macro_name = generated_macro_name.append(&hasher.finish().to_string()); let route_uri = route.attribute.path.origin.0.to_string(); diff --git a/core/lib/tests/typed-uri-docs-redef-issue-1373.rs b/core/lib/tests/typed-uri-docs-redef-issue-1373.rs new file mode 100644 index 00000000..ac0f221d --- /dev/null +++ b/core/lib/tests/typed-uri-docs-redef-issue-1373.rs @@ -0,0 +1,14 @@ +#![allow(dead_code)] // This test is only here to ensure it compiles. +#![allow(unused_variables)] // This test is only here to ensure it compiles. + +mod a { + /// Docs. + #[rocket::post("/typed_uris/")] + fn simple(id: i32) { } +} + +mod b { + /// Docs. + #[rocket::post("/typed_uris/")] + fn simple(id: i32) { } +}