From 9f0e02fe27460a8901ef3e96987087a21503ade8 Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Thu, 6 Feb 2020 21:04:01 -0800 Subject: [PATCH] Make references to core types absolute in codegen. Prior to this commit, codegen emitted tokens containing bare types like 'Result' and 'Box' as well as presumed imported variants such as 'None' and 'Ok'. However, users are free to shadow these, and if they do, the generated code will fail to compile, or worse, be incorrect. To avoid this, this commit makes all references to these core types and imports absolute. --- core/codegen/src/attribute/route.rs | 37 +++++++++++----------- core/codegen/src/derive/from_form.rs | 9 +++--- core/codegen/src/derive/from_form_value.rs | 11 ++++--- core/codegen/src/derive/responder.rs | 3 +- core/codegen/src/http_codegen.rs | 5 +-- core/codegen/src/lib.rs | 6 ++++ 6 files changed, 41 insertions(+), 30 deletions(-) diff --git a/core/codegen/src/attribute/route.rs b/core/codegen/src/attribute/route.rs index 6f7763f6..e91a40df 100644 --- a/core/codegen/src/attribute/route.rs +++ b/core/codegen/src/attribute/route.rs @@ -127,7 +127,7 @@ fn parse_route(attr: RouteAttribute, function: syn::ItemFn) -> Result { } fn param_expr(seg: &Segment, ident: &syn::Ident, ty: &syn::Type) -> TokenStream2 { - define_vars_and_mods!(req, data, error, log, request, Outcome); + define_vars_and_mods!(req, data, error, log, request, _None, _Some, _Ok, _Err, Outcome); let i = seg.index.expect("dynamic parameters must be indexed"); let span = ident.span().unstable().join(ty.span()).unwrap().into(); let name = ident.to_string(); @@ -149,20 +149,20 @@ fn param_expr(seg: &Segment, ident: &syn::Ident, ty: &syn::Type) -> TokenStream2 let expr = match seg.kind { Kind::Single => quote_spanned! { span => match #req.raw_segment_str(#i) { - Some(__s) => match <#ty as #request::FromParam>::from_param(__s) { - Ok(__v) => __v, - Err(#error) => return #parse_error, + #_Some(__s) => match <#ty as #request::FromParam>::from_param(__s) { + #_Ok(__v) => __v, + #_Err(#error) => return #parse_error, }, - None => return #internal_error + #_None => return #internal_error } }, Kind::Multi => quote_spanned! { span => match #req.raw_segments(#i) { - Some(__s) => match <#ty as #request::FromSegments>::from_segments(__s) { - Ok(__v) => __v, - Err(#error) => return #parse_error, + #_Some(__s) => match <#ty as #request::FromSegments>::from_segments(__s) { + #_Ok(__v) => __v, + #_Err(#error) => return #parse_error, }, - None => return #internal_error + #_None => return #internal_error } }, Kind::Static => return quote!() @@ -204,6 +204,7 @@ fn data_expr(ident: &syn::Ident, ty: &syn::Type) -> TokenStream2 { } fn query_exprs(route: &Route) -> Option { + define_vars_and_mods!(_None, _Some, _Ok, _Err, _Option); define_vars_and_mods!(data, trail, log, request, req, Outcome, SmallVec, Query); let query_segments = route.attribute.path.query.as_ref()?; let (mut decls, mut matchers, mut builders) = (vec![], vec![], vec![]); @@ -224,7 +225,7 @@ fn query_exprs(route: &Route) -> Option { let decl = match segment.kind { Kind::Single => quote_spanned! { span => #[allow(non_snake_case)] - let mut #ident: Option<#ty> = None; + let mut #ident: #_Option<#ty> = #_None; }, Kind::Multi => quote_spanned! { span => #[allow(non_snake_case)] @@ -238,14 +239,14 @@ fn query_exprs(route: &Route) -> Option { (_, #name, __v) => { #[allow(unreachable_patterns, unreachable_code)] let __v = match <#ty as #request::FromFormValue>::from_form_value(__v) { - Ok(__v) => __v, - Err(__e) => { + #_Ok(__v) => __v, + #_Err(__e) => { #log::warn_(&format!("Failed to parse '{}': {:?}", #name, __e)); return #Outcome::Forward(#data); } }; - #ident = Some(__v); + #ident = #_Some(__v); } }, Kind::Static => quote! { @@ -260,8 +261,8 @@ fn query_exprs(route: &Route) -> Option { Kind::Single => quote_spanned! { span => #[allow(non_snake_case)] let #ident = match #ident.or_else(<#ty as #request::FromFormValue>::default) { - Some(__v) => __v, - None => { + #_Some(__v) => __v, + #_None => { #log::warn_(&format!("Missing required query parameter '{}'.", #name)); return #Outcome::Forward(#data); } @@ -270,8 +271,8 @@ fn query_exprs(route: &Route) -> Option { Kind::Multi => quote_spanned! { span => #[allow(non_snake_case)] let #ident = match <#ty as #request::FromQuery>::from_query(#Query(&#trail)) { - Ok(__v) => __v, - Err(__e) => { + #_Ok(__v) => __v, + #_Err(__e) => { #log::warn_(&format!("Failed to parse '{}': {:?}", #name, __e)); return #Outcome::Forward(#data); } @@ -289,7 +290,7 @@ fn query_exprs(route: &Route) -> Option { Some(quote! { #(#decls)* - if let Some(__items) = #req.raw_query_items() { + if let #_Some(__items) = #req.raw_query_items() { for __i in __items { match (__i.raw.as_str(), __i.key.as_str(), __i.value) { #( diff --git a/core/codegen/src/derive/from_form.rs b/core/codegen/src/derive/from_form.rs index 7517c43f..5b906a70 100644 --- a/core/codegen/src/derive/from_form.rs +++ b/core/codegen/src/derive/from_form.rs @@ -82,6 +82,7 @@ pub fn derive_from_form(input: TokenStream) -> TokenStream { } }) .try_map_fields(move |_, fields| { + define_vars_and_mods!(_None, _Some, _Ok, _Err); let (constructors, matchers, builders) = fields.iter().map(|field| { let (ident, span) = (&field.ident, field.span().into()); let default_name = ident.as_ref().expect("named").to_string(); @@ -94,10 +95,10 @@ pub fn derive_from_form(input: TokenStream) -> TokenStream { span => <#ty as ::rocket::request::FromFormValue> }; - let constructor = quote_spanned!(span => let mut #ident = None;); + let constructor = quote_spanned!(span => let mut #ident = #_None;); let matcher = quote_spanned! { span => - #name => { #ident = Some(#ty::from_form_value(__v) + #name => { #ident = #_Some(#ty::from_form_value(__v) .map_err(|_| #form_error::BadValue(__k, __v))?); }, }; @@ -116,13 +117,13 @@ pub fn derive_from_form(input: TokenStream) -> TokenStream { match __k.as_str() { #(#matchers)* _ if __strict && __k != "_method" => { - return Err(#form_error::Unknown(__k, __v)); + return #_Err(#form_error::Unknown(__k, __v)); } _ => { /* lenient or "method"; let it pass */ } } } - Ok(Self { #(#builders)* }) + #_Ok(Self { #(#builders)* }) }) }) .to_tokens() diff --git a/core/codegen/src/derive/from_form_value.rs b/core/codegen/src/derive/from_form_value.rs index ca206ef6..f83c7383 100644 --- a/core/codegen/src/derive/from_form_value.rs +++ b/core/codegen/src/derive/from_form_value.rs @@ -7,6 +7,7 @@ struct Form { } pub fn derive_from_form_value(input: TokenStream) -> TokenStream { + define_vars_and_mods!(_Ok, _Err, _Result); DeriveGenerator::build_for(input, quote!(impl<'__v> ::rocket::request::FromFormValue<'__v>)) .generic_support(GenericSupport::None) .data_support(DataSupport::Enum) @@ -25,19 +26,19 @@ pub fn derive_from_form_value(input: TokenStream) -> TokenStream { Ok(()) }) - .function(|_, inner| quote! { + .function(move |_, inner| quote! { type Error = &'__v ::rocket::http::RawStr; fn from_form_value( value: &'__v ::rocket::http::RawStr - ) -> ::std::result::Result { + ) -> #_Result { let uncased = value.as_uncased_str(); #inner - ::std::result::Result::Err(value) + #_Err(value) } }) .try_map_enum(null_enum_mapper) - .try_map_variant(|_, variant| { + .try_map_variant(move |_, variant| { let variant_str = Form::from_attrs("form", &variant.attrs) .unwrap_or_else(|| Ok(Form { value: variant.ident.to_string() }))? .value; @@ -45,7 +46,7 @@ pub fn derive_from_form_value(input: TokenStream) -> TokenStream { let builder = variant.builder(|_| unreachable!()); Ok(quote! { if uncased == #variant_str { - return ::std::result::Result::Ok(#builder); + return #_Ok(#builder); } }) }) diff --git a/core/codegen/src/derive/responder.rs b/core/codegen/src/derive/responder.rs index 4e181209..a547ce72 100644 --- a/core/codegen/src/derive/responder.rs +++ b/core/codegen/src/derive/responder.rs @@ -38,6 +38,7 @@ pub fn derive_responder(input: TokenStream) -> TokenStream { } }) .try_map_fields(|_, fields| { + define_vars_and_mods!(_Ok); fn set_header_tokens(item: T) -> TokenStream2 { quote_spanned!(item.span().into() => __res.set_header(#item);) } @@ -74,7 +75,7 @@ pub fn derive_responder(input: TokenStream) -> TokenStream { #(#headers)* #content_type #status - Ok(__res) + #_Ok(__res) }) }) .to_tokens() diff --git a/core/codegen/src/http_codegen.rs b/core/codegen/src/http_codegen.rs index a88570fa..1281bd16 100644 --- a/core/codegen/src/http_codegen.rs +++ b/core/codegen/src/http_codegen.rs @@ -235,9 +235,10 @@ impl FromMeta for RoutePath { impl ToTokens for Optional { fn to_tokens(&self, tokens: &mut TokenStream2) { + define_vars_and_mods!(_Some, _None); let opt_tokens = match self.0 { - Some(ref val) => quote!(Some(#val)), - None => quote!(None) + Some(ref val) => quote!(#_Some(#val)), + None => quote!(#_None) }; tokens.extend(opt_tokens); diff --git a/core/codegen/src/lib.rs b/core/codegen/src/lib.rs index 6764e293..34d6538d 100644 --- a/core/codegen/src/lib.rs +++ b/core/codegen/src/lib.rs @@ -96,6 +96,12 @@ vars_and_mods! { Data => rocket::Data, StaticRouteInfo => rocket::StaticRouteInfo, SmallVec => rocket::http::private::SmallVec, + _Option => ::std::option::Option, + _Result => ::std::result::Result, + _Some => ::std::option::Option::Some, + _None => ::std::option::Option::None, + _Ok => ::std::result::Result::Ok, + _Err => ::std::result::Result::Err, } macro_rules! define_vars_and_mods {