mirror of https://github.com/rwf2/Rocket.git
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.
This commit is contained in:
parent
816b8c44ab
commit
dfca18d307
|
@ -1,3 +1,4 @@
|
||||||
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
|
@ -38,9 +39,9 @@ struct MethodRouteAttribute {
|
||||||
/// This structure represents the parsed `route` attribute and associated items.
|
/// This structure represents the parsed `route` attribute and associated items.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Route {
|
struct Route {
|
||||||
/// The status associated with the code in the `#[route(code)]` attribute.
|
/// The attribute: `#[get(path, ...)]`.
|
||||||
attribute: RouteAttribute,
|
attribute: RouteAttribute,
|
||||||
/// The function that was decorated with the `route` attribute.
|
/// The function the attribute decorated, i.e, the handler.
|
||||||
function: syn::ItemFn,
|
function: syn::ItemFn,
|
||||||
/// The non-static parameters declared in the route segments.
|
/// The non-static parameters declared in the route segments.
|
||||||
segments: IndexSet<Segment>,
|
segments: IndexSet<Segment>,
|
||||||
|
@ -322,6 +323,9 @@ fn request_guard_expr(ident: &syn::Ident, ty: &syn::Type) -> TokenStream2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_internal_uri_macro(route: &Route) -> 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()
|
let dynamic_args = route.segments.iter()
|
||||||
.filter(|seg| seg.source == Source::Path || seg.source == Source::Query)
|
.filter(|seg| seg.source == Source::Path || seg.source == Source::Query)
|
||||||
.filter(|seg| seg.kind != Kind::Static)
|
.filter(|seg| seg.kind != Kind::Static)
|
||||||
|
@ -330,14 +334,13 @@ fn generate_internal_uri_macro(route: &Route) -> TokenStream2 {
|
||||||
.map(|(ident, _, ty)| quote!(#ident: #ty));
|
.map(|(ident, _, ty)| quote!(#ident: #ty));
|
||||||
|
|
||||||
let mut hasher = DefaultHasher::new();
|
let mut hasher = DefaultHasher::new();
|
||||||
let route_span = route.function.span();
|
route.function.sig.ident.hash(&mut hasher);
|
||||||
route_span.source_file().path().hash(&mut hasher);
|
route.attribute.path.origin.0.path().hash(&mut hasher);
|
||||||
let line_column = route_span.start();
|
std::process::id().hash(&mut hasher);
|
||||||
line_column.line.hash(&mut hasher);
|
std::thread::current().id().hash(&mut hasher);
|
||||||
line_column.column.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);
|
let generated_macro_name = route.function.sig.ident.prepend(URI_MACRO_PREFIX);
|
||||||
generated_macro_name.set_span(Span::call_site().into());
|
|
||||||
let inner_generated_macro_name = generated_macro_name.append(&hasher.finish().to_string());
|
let inner_generated_macro_name = generated_macro_name.append(&hasher.finish().to_string());
|
||||||
let route_uri = route.attribute.path.origin.0.to_string();
|
let route_uri = route.attribute.path.origin.0.to_string();
|
||||||
|
|
||||||
|
|
|
@ -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/<id>")]
|
||||||
|
fn simple(id: i32) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
mod b {
|
||||||
|
/// Docs.
|
||||||
|
#[rocket::post("/typed_uris/<id>")]
|
||||||
|
fn simple(id: i32) { }
|
||||||
|
}
|
Loading…
Reference in New Issue