diff --git a/contrib/codegen/Cargo.toml b/contrib/codegen/Cargo.toml index b2f07c03..94b90703 100644 --- a/contrib/codegen/Cargo.toml +++ b/contrib/codegen/Cargo.toml @@ -20,7 +20,7 @@ proc-macro = true [dependencies] quote = "1.0" -devise = { git = "https://github.com/SergioBenitez/Devise.git", rev = "e58b3ac9a" } +devise = { git = "https://github.com/SergioBenitez/Devise.git", rev = "57d6eb80" } [build-dependencies] yansi = "0.5" diff --git a/contrib/codegen/src/database.rs b/contrib/codegen/src/database.rs index 2fea4263..6cad8adc 100644 --- a/contrib/codegen/src/database.rs +++ b/contrib/codegen/src/database.rs @@ -1,5 +1,6 @@ use proc_macro::TokenStream; -use devise::{Spanned, Result}; +use devise::{Spanned, Result, ext::SpanDiagnosticExt}; + use crate::syn::{DataStruct, Fields, Data, Type, LitStr, DeriveInput, Ident, Visibility}; #[derive(Debug)] diff --git a/contrib/codegen/src/lib.rs b/contrib/codegen/src/lib.rs index e45cefc9..b32a9b11 100644 --- a/contrib/codegen/src/lib.rs +++ b/contrib/codegen/src/lib.rs @@ -1,4 +1,3 @@ -#![feature(proc_macro_diagnostic)] #![recursion_limit="256"] #![warn(rust_2018_idioms)] @@ -42,8 +41,6 @@ use proc_macro::TokenStream; #[cfg(feature = "database_attribute")] #[proc_macro_attribute] pub fn database(attr: TokenStream, input: TokenStream) -> TokenStream { - crate::database::database_attr(attr, input).unwrap_or_else(|diag| { - diag.emit(); - TokenStream::new() - }) + crate::database::database_attr(attr, input) + .unwrap_or_else(|diag| diag.emit_as_tokens().into()) } diff --git a/core/codegen/Cargo.toml b/core/codegen/Cargo.toml index e3d70c20..3bb3385a 100644 --- a/core/codegen/Cargo.toml +++ b/core/codegen/Cargo.toml @@ -19,7 +19,7 @@ proc-macro = true indexmap = "1.0" quote = "1.0" rocket_http = { version = "0.5.0-dev", path = "../http/" } -devise = { git = "https://github.com/SergioBenitez/Devise.git", rev = "e58b3ac9a" } +devise = { git = "https://github.com/SergioBenitez/Devise.git", rev = "17f647e" } glob = "0.3" [build-dependencies] diff --git a/core/codegen/src/attribute/async_entry.rs b/core/codegen/src/attribute/async_entry.rs index edb1f367..c6c75625 100644 --- a/core/codegen/src/attribute/async_entry.rs +++ b/core/codegen/src/attribute/async_entry.rs @@ -1,15 +1,13 @@ -use proc_macro::{TokenStream, Span}; -use devise::{syn, Spanned, Result}; - -use crate::proc_macro2::TokenStream as TokenStream2; -use crate::syn_ext::syn_to_diag; +use devise::{syn, Diagnostic, Spanned, Result}; +use devise::ext::SpanDiagnosticExt; +use devise::proc_macro2::{TokenStream, Span}; trait EntryAttr { /// Whether the attribute requires the attributed function to be `async`. const REQUIRES_ASYNC: bool; /// Return a new or rewritten function, using block as the main execution. - fn function(f: &syn::ItemFn, body: &syn::Block) -> Result; + fn function(f: &syn::ItemFn, body: &syn::Block) -> Result; } struct Main; @@ -17,13 +15,12 @@ struct Main; impl EntryAttr for Main { const REQUIRES_ASYNC: bool = true; - fn function(f: &syn::ItemFn, block: &syn::Block) -> Result { + fn function(f: &syn::ItemFn, block: &syn::Block) -> Result { let (attrs, vis, mut sig) = (&f.attrs, &f.vis, f.sig.clone()); if sig.ident != "main" { - Span::call_site() + return Err(Span::call_site() .warning("attribute is typically applied to `main` function") - .span_note(sig.span(), "this function is not `main`") - .emit(); + .span_note(sig.span(), "this function is not `main`")); } sig.asyncness = None; @@ -38,7 +35,7 @@ struct Test; impl EntryAttr for Test { const REQUIRES_ASYNC: bool = true; - fn function(f: &syn::ItemFn, block: &syn::Block) -> Result { + fn function(f: &syn::ItemFn, block: &syn::Block) -> Result { let (attrs, vis, mut sig) = (&f.attrs, &f.vis, f.sig.clone()); sig.asyncness = None; Ok(quote_spanned!(block.span().into() => #(#attrs)* #[test] #vis #sig { @@ -52,7 +49,7 @@ struct Launch; impl EntryAttr for Launch { const REQUIRES_ASYNC: bool = false; - fn function(f: &syn::ItemFn, block: &syn::Block) -> Result { + fn function(f: &syn::ItemFn, block: &syn::Block) -> Result { if f.sig.ident == "main" { return Err(Span::call_site() .error("attribute cannot be applied to `main` function") @@ -89,9 +86,9 @@ impl EntryAttr for Launch { } } -fn parse_input(input: TokenStream) -> Result { +fn parse_input(input: proc_macro::TokenStream) -> Result { let function: syn::ItemFn = syn::parse(input) - .map_err(syn_to_diag) + .map_err(Diagnostic::from) .map_err(|d| d.help("attribute can only be applied to functions"))?; if A::REQUIRES_ASYNC && function.sig.asyncness.is_none() { @@ -109,19 +106,26 @@ fn parse_input(input: TokenStream) -> Result { Ok(function) } -fn _async_entry(_args: TokenStream, input: TokenStream) -> Result { +fn _async_entry( + _args: proc_macro::TokenStream, + input: proc_macro::TokenStream +) -> Result { let function = parse_input::(input)?; A::function(&function, &function.block).map(|t| t.into()) } -pub fn async_test_attribute(args: TokenStream, input: TokenStream) -> TokenStream { - _async_entry::(args, input).unwrap_or_else(|d| { d.emit(); TokenStream::new() }) +macro_rules! async_entry { + ($name:ident, $kind:ty, $default:expr) => ( + pub fn $name(a: proc_macro::TokenStream, i: proc_macro::TokenStream) -> TokenStream { + _async_entry::<$kind>(a, i).unwrap_or_else(|d| { + let d = d.emit_as_tokens(); + let default = $default; + quote!(#d #default) + }) + } + ) } -pub fn main_attribute(args: TokenStream, input: TokenStream) -> TokenStream { - _async_entry::
(args, input).unwrap_or_else(|d| { d.emit(); quote!(fn main() {}).into() }) -} - -pub fn launch_attribute(args: TokenStream, input: TokenStream) -> TokenStream { - _async_entry::(args, input).unwrap_or_else(|d| { d.emit(); quote!(fn main() {}).into() }) -} +async_entry!(async_test_attribute, Test, quote!()); +async_entry!(main_attribute, Main, quote!(fn main() {})); +async_entry!(launch_attribute, Launch, quote!(fn main() {})); diff --git a/core/codegen/src/attribute/catch.rs b/core/codegen/src/attribute/catch.rs index 294d841a..2e9363d9 100644 --- a/core/codegen/src/attribute/catch.rs +++ b/core/codegen/src/attribute/catch.rs @@ -1,9 +1,9 @@ -use proc_macro::{TokenStream, Span}; -use devise::{syn, Spanned, Result, FromMeta}; -use crate::proc_macro2::TokenStream as TokenStream2; +use devise::{syn, Spanned, Result, FromMeta, Diagnostic}; +use devise::ext::SpanDiagnosticExt; +use crate::proc_macro2::{TokenStream, Span}; use crate::http_codegen::Status; -use crate::syn_ext::{syn_to_diag, IdentExt, ReturnTypeExt, TokenStreamExt}; +use crate::syn_ext::{IdentExt, ReturnTypeExt, TokenStreamExt}; use self::syn::{Attribute, parse::Parser}; use crate::{CATCH_FN_PREFIX, CATCH_STRUCT_PREFIX}; @@ -22,12 +22,16 @@ struct CatchParams { function: syn::ItemFn, } -fn parse_params(args: TokenStream2, input: TokenStream) -> Result { - let function: syn::ItemFn = syn::parse(input).map_err(syn_to_diag) +fn parse_params( + args: TokenStream, + input: proc_macro::TokenStream +) -> Result { + let function: syn::ItemFn = syn::parse(input) + .map_err(Diagnostic::from) .map_err(|diag| diag.help("`#[catch]` can only be used on functions"))?; let full_attr = quote!(#[catch(#args)]); - let attrs = Attribute::parse_outer.parse2(full_attr).map_err(syn_to_diag)?; + let attrs = Attribute::parse_outer.parse2(full_attr)?; let attribute = match CatchAttribute::from_attrs("catch", &attrs) { Some(result) => result.map_err(|d| { d.help("`#[catch]` expects a single status integer, e.g.: #[catch(404)]") @@ -38,9 +42,12 @@ fn parse_params(args: TokenStream2, input: TokenStream) -> Result { Ok(CatchParams { status: attribute.status, function }) } -pub fn _catch(args: TokenStream, input: TokenStream) -> Result { +pub fn _catch( + args: proc_macro::TokenStream, + input: proc_macro::TokenStream +) -> Result { // Parse and validate all of the user's input. - let catch = parse_params(TokenStream2::from(args), input)?; + let catch = parse_params(args.into(), input)?; // Gather everything we'll need to generate the catcher. let user_catcher_fn = &catch.function; @@ -124,9 +131,12 @@ pub fn _catch(args: TokenStream, input: TokenStream) -> Result { code: #status_code, handler: #generated_fn_name, }; - }.into()) + }) } -pub fn catch_attribute(args: TokenStream, input: TokenStream) -> TokenStream { - _catch(args, input).unwrap_or_else(|d| { d.emit(); TokenStream::new() }) +pub fn catch_attribute( + args: proc_macro::TokenStream, + input: proc_macro::TokenStream +) -> TokenStream { + _catch(args, input).unwrap_or_else(|d| d.emit_as_tokens()) } diff --git a/core/codegen/src/attribute/route.rs b/core/codegen/src/attribute/route.rs index 9691db8e..698dafa8 100644 --- a/core/codegen/src/attribute/route.rs +++ b/core/codegen/src/attribute/route.rs @@ -2,17 +2,17 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; -use proc_macro::{TokenStream, Span}; -use crate::proc_macro2::TokenStream as TokenStream2; -use devise::{syn, Spanned, SpanWrapped, Result, FromMeta, ext::TypeExt}; +use devise::{syn, Spanned, SpanWrapped, Result, FromMeta, Diagnostic}; +use devise::ext::{SpanDiagnosticExt, TypeExt}; use indexmap::IndexSet; use crate::proc_macro_ext::{Diagnostics, StringLit}; -use crate::syn_ext::{syn_to_diag, IdentExt}; -use self::syn::{Attribute, parse::Parser}; - +use crate::syn_ext::IdentExt; +use crate::proc_macro2::{TokenStream, Span}; use crate::http_codegen::{Method, MediaType, RoutePath, DataSegment, Optional}; use crate::attribute::segments::{Source, Kind, Segment}; +use crate::syn::{Attribute, parse::Parser}; + use crate::{ROUTE_FN_PREFIX, ROUTE_STRUCT_PREFIX, URI_MACRO_PREFIX, ROCKET_PARAM_PREFIX}; /// The raw, parsed `#[route]` attribute. @@ -59,9 +59,10 @@ fn parse_route(attr: RouteAttribute, function: syn::ItemFn) -> Result { if let Some(ref data) = attr.data { if !attr.method.0.supports_payload() { let msg = format!("'{}' does not typically support payloads", attr.method.0); + // FIXME(diag: warning) data.full_span.warning("`data` used with non-payload-supporting method") .span_note(attr.method.span, msg) - .emit() + .emit_as_tokens(); } } @@ -127,10 +128,10 @@ fn parse_route(attr: RouteAttribute, function: syn::ItemFn) -> Result { diags.head_err_or(Route { attribute: attr, function, inputs, segments }) } -fn param_expr(seg: &Segment, ident: &syn::Ident, ty: &syn::Type) -> TokenStream2 { +fn param_expr(seg: &Segment, ident: &syn::Ident, ty: &syn::Type) -> TokenStream { 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 span = ident.span().join(ty.span()).unwrap_or_else(|| ty.span()); let name = ident.to_string(); // All dynamic parameter should be found if this function is being called; @@ -175,9 +176,9 @@ fn param_expr(seg: &Segment, ident: &syn::Ident, ty: &syn::Type) -> TokenStream2 } } -fn data_expr(ident: &syn::Ident, ty: &syn::Type) -> TokenStream2 { +fn data_expr(ident: &syn::Ident, ty: &syn::Type) -> TokenStream { define_vars_and_mods!(req, data, FromTransformedData, Outcome, Transform); - let span = ident.span().unstable().join(ty.span()).unwrap().into(); + let span = ident.span().join(ty.span()).unwrap_or_else(|| ty.span()); quote_spanned! { span => let __transform = <#ty as #FromTransformedData>::transform(#req, #data).await; @@ -204,7 +205,7 @@ fn data_expr(ident: &syn::Ident, ty: &syn::Type) -> TokenStream2 { } } -fn query_exprs(route: &Route) -> Option { +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()?; @@ -217,7 +218,7 @@ fn query_exprs(route: &Route) -> Option { .map(|(_, rocket_ident, ty)| (rocket_ident, ty)) .unwrap(); - let span = ident.span().unstable().join(ty.span()).unwrap(); + let span = ident.span().join(ty.span()).unwrap_or_else(|| ty.span()); (Some(ident), Some(ty), span.into()) } else { (None, None, segment.span.into()) @@ -309,9 +310,9 @@ fn query_exprs(route: &Route) -> Option { }) } -fn request_guard_expr(ident: &syn::Ident, ty: &syn::Type) -> TokenStream2 { +fn request_guard_expr(ident: &syn::Ident, ty: &syn::Type) -> TokenStream { define_vars_and_mods!(req, data, request, Outcome); - let span = ident.span().unstable().join(ty.span()).unwrap().into(); + let span = ident.span().join(ty.span()).unwrap_or_else(|| ty.span()); quote_spanned! { span => #[allow(non_snake_case, unreachable_patterns, unreachable_code)] let #ident: #ty = match <#ty as #request::FromRequest>::from_request(#req).await { @@ -322,7 +323,7 @@ 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) -> TokenStream { // Keep a global counter (+ thread ID later) to generate unique ids. static COUNTER: AtomicUsize = AtomicUsize::new(0); @@ -344,7 +345,7 @@ fn generate_internal_uri_macro(route: &Route) -> TokenStream2 { let inner_generated_macro_name = generated_macro_name.append(&hasher.finish().to_string()); let route_uri = route.attribute.path.origin.0.to_string(); - quote! { + quote_spanned! { Span::call_site() => #[doc(hidden)] #[macro_export] macro_rules! #inner_generated_macro_name { @@ -360,7 +361,7 @@ fn generate_internal_uri_macro(route: &Route) -> TokenStream2 { } } -fn generate_respond_expr(route: &Route) -> TokenStream2 { +fn generate_respond_expr(route: &Route) -> TokenStream { let ret_span = match route.function.sig.output { syn::ReturnType::Default => route.function.sig.ident.span(), syn::ReturnType::Type(_, ref ty) => ty.span().into() @@ -460,12 +461,13 @@ fn codegen_route(route: Route) -> Result { }.into()) } -fn complete_route(args: TokenStream2, input: TokenStream) -> Result { - let function: syn::ItemFn = syn::parse(input).map_err(syn_to_diag) +fn complete_route(args: TokenStream, input: TokenStream) -> Result { + let function: syn::ItemFn = syn::parse2(input) + .map_err(|e| Diagnostic::from(e)) .map_err(|diag| diag.help("`#[route]` can only be used on functions"))?; let full_attr = quote!(#[route(#args)]); - let attrs = Attribute::parse_outer.parse2(full_attr).map_err(syn_to_diag)?; + let attrs = Attribute::parse_outer.parse2(full_attr)?; let attribute = match RouteAttribute::from_attrs("route", &attrs) { Some(result) => result?, None => return Err(Span::call_site().error("internal error: bad attribute")) @@ -476,7 +478,7 @@ fn complete_route(args: TokenStream2, input: TokenStream) -> Result fn incomplete_route( method: crate::http::Method, - args: TokenStream2, + args: TokenStream, input: TokenStream ) -> Result { let method_str = method.to_string().to_lowercase(); @@ -486,11 +488,12 @@ fn incomplete_route( let method_ident = syn::Ident::new(&method_str, method_span.into()); - let function: syn::ItemFn = syn::parse(input).map_err(syn_to_diag) + let function: syn::ItemFn = syn::parse2(input) + .map_err(|e| Diagnostic::from(e)) .map_err(|d| d.help(format!("#[{}] can only be used on functions", method_str)))?; let full_attr = quote!(#[#method_ident(#args)]); - let attrs = Attribute::parse_outer.parse2(full_attr).map_err(syn_to_diag)?; + let attrs = Attribute::parse_outer.parse2(full_attr)?; let method_attribute = match MethodRouteAttribute::from_attrs(&method_str, &attrs) { Some(result) => result?, None => return Err(Span::call_site().error("internal error: bad attribute")) @@ -511,13 +514,13 @@ fn incomplete_route( pub fn route_attribute>>( method: M, - args: TokenStream, - input: TokenStream + args: proc_macro::TokenStream, + input: proc_macro::TokenStream ) -> TokenStream { let result = match method.into() { - Some(method) => incomplete_route(method, args.into(), input), - None => complete_route(args.into(), input) + Some(method) => incomplete_route(method, args.into(), input.into()), + None => complete_route(args.into(), input.into()) }; - result.unwrap_or_else(|diag| { diag.emit(); TokenStream::new() }) + result.unwrap_or_else(|diag| diag.emit_as_tokens()) } diff --git a/core/codegen/src/attribute/segments.rs b/core/codegen/src/attribute/segments.rs index b1aa62d5..e306db1f 100644 --- a/core/codegen/src/attribute/segments.rs +++ b/core/codegen/src/attribute/segments.rs @@ -1,7 +1,7 @@ use std::hash::{Hash, Hasher}; -use devise::syn; -use proc_macro::{Span, Diagnostic}; +use devise::{syn, Diagnostic, ext::SpanDiagnosticExt}; +use crate::proc_macro2::Span; use crate::http::uri::{UriPart, Path}; use crate::http::route::RouteSegment; @@ -36,7 +36,7 @@ impl From<&syn::Ident> for Segment { Segment { kind: Kind::Static, source: Source::Unknown, - span: ident.span().unstable(), + span: ident.span(), name: ident.to_string(), index: None, } diff --git a/core/codegen/src/bang/mod.rs b/core/codegen/src/bang/mod.rs index ca633c0c..fd05a192 100644 --- a/core/codegen/src/bang/mod.rs +++ b/core/codegen/src/bang/mod.rs @@ -1,9 +1,9 @@ -use proc_macro::TokenStream; -use crate::proc_macro2::TokenStream as TokenStream2; +use devise::Result; -use devise::{syn, Spanned, Result}; -use self::syn::{Path, punctuated::Punctuated, parse::Parser, token::Comma}; -use crate::syn_ext::{IdentExt, syn_to_diag}; +use crate::syn_ext::IdentExt; +use crate::syn::{Path, punctuated::Punctuated, parse::Parser, Token}; +use crate::syn::spanned::Spanned; +use crate::proc_macro2::TokenStream; use crate::{ROUTE_STRUCT_PREFIX, CATCH_STRUCT_PREFIX}; mod uri; @@ -17,13 +17,11 @@ pub fn prefix_last_segment(path: &mut Path, prefix: &str) { fn _prefixed_vec( prefix: &str, - input: TokenStream, - ty: &TokenStream2 -) -> Result { + input: proc_macro::TokenStream, + ty: &TokenStream +) -> Result { // Parse a comma-separated list of paths. - let mut paths = >::parse_terminated - .parse(input) - .map_err(syn_to_diag)?; + let mut paths = >::parse_terminated.parse(input)?; // Prefix the last segment in each path with `prefix`. paths.iter_mut().for_each(|p| prefix_last_segment(p, prefix)); @@ -35,39 +33,46 @@ fn _prefixed_vec( Ok(quote!(vec![#(#prefixed_mapped_paths),*])) } -fn prefixed_vec(prefix: &str, input: TokenStream, ty: TokenStream2) -> TokenStream { - let vec = _prefixed_vec(prefix, input, &ty) - .map_err(|diag| diag.emit()) - .unwrap_or_else(|_| quote!(vec![])); - - quote!({ - let __vector: Vec<#ty> = #vec; - __vector - }).into() +fn prefixed_vec( + prefix: &str, + input: proc_macro::TokenStream, + ty: TokenStream +) -> TokenStream { + define_vars_and_mods!(_Vec); + _prefixed_vec(prefix, input, &ty) + .map(|vec| quote!({ + let __vector: #_Vec<#ty> = #vec; + __vector + })) + .unwrap_or_else(|diag| { + let diag_tokens = diag.emit_as_tokens(); + quote!({ + #diag_tokens + let __vec: #_Vec<#ty> = vec![]; + __vec + }) + }) } -pub fn routes_macro(input: TokenStream) -> TokenStream { +pub fn routes_macro(input: proc_macro::TokenStream) -> TokenStream { prefixed_vec(ROUTE_STRUCT_PREFIX, input, quote!(::rocket::Route)) } -pub fn catchers_macro(input: TokenStream) -> TokenStream { +pub fn catchers_macro(input: proc_macro::TokenStream) -> TokenStream { prefixed_vec(CATCH_STRUCT_PREFIX, input, quote!(::rocket::Catcher)) } -pub fn uri_macro(input: TokenStream) -> TokenStream { - uri::_uri_macro(input) - .map_err(|diag| diag.emit()) - .unwrap_or_else(|_| quote!(()).into()) +pub fn uri_macro(input: proc_macro::TokenStream) -> TokenStream { + uri::_uri_macro(input.into()) + .unwrap_or_else(|diag| diag.emit_as_tokens()) } -pub fn uri_internal_macro(input: TokenStream) -> TokenStream { - uri::_uri_internal_macro(input) - .map_err(|diag| diag.emit()) - .unwrap_or_else(|_| quote!(()).into()) +pub fn uri_internal_macro(input: proc_macro::TokenStream) -> TokenStream { + uri::_uri_internal_macro(input.into()) + .unwrap_or_else(|diag| diag.emit_as_tokens()) } -pub fn guide_tests_internal(input: TokenStream) -> TokenStream { +pub fn guide_tests_internal(input: proc_macro::TokenStream) -> TokenStream { test_guide::_macro(input) - .map_err(|diag| diag.emit()) - .unwrap_or_else(|_| quote!(()).into()) + .unwrap_or_else(|diag| diag.emit_as_tokens()) } diff --git a/core/codegen/src/bang/test_guide.rs b/core/codegen/src/bang/test_guide.rs index 971c2c23..906d1ad2 100644 --- a/core/codegen/src/bang/test_guide.rs +++ b/core/codegen/src/bang/test_guide.rs @@ -1,16 +1,14 @@ use std::path::Path; use std::error::Error; -use proc_macro::TokenStream; -use devise::{syn::{self, Ident, LitStr}, Result}; +use devise::ext::SpanDiagnosticExt; +use devise::syn::{self, Ident, LitStr}; +use devise::proc_macro2::TokenStream; -use crate::syn_ext::syn_to_diag; -use crate::proc_macro2::TokenStream as TokenStream2; - -pub fn _macro(input: TokenStream) -> Result { - let root_glob = syn::parse::(input.into()).map_err(syn_to_diag)?; +pub fn _macro(input: proc_macro::TokenStream) -> devise::Result { + let root_glob = syn::parse::(input.into())?; let modules = entry_to_modules(&root_glob) - .map_err(|e| root_glob.span().unstable().error(format!("failed to read: {}", e)))?; + .map_err(|e| root_glob.span().error(format!("failed to read: {}", e)))?; Ok(quote_spanned!(root_glob.span() => #[allow(dead_code)] @@ -19,7 +17,7 @@ pub fn _macro(input: TokenStream) -> Result { ).into()) } -fn entry_to_modules(root_glob: &LitStr) -> std::result::Result, Box> { +fn entry_to_modules(root_glob: &LitStr) -> Result, Box> { let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").expect("MANIFEST_DIR"); let full_glob = Path::new(&manifest_dir).join(&root_glob.value()).display().to_string(); diff --git a/core/codegen/src/bang/uri.rs b/core/codegen/src/bang/uri.rs index 77cbda84..f7fe7d83 100644 --- a/core/codegen/src/bang/uri.rs +++ b/core/codegen/src/bang/uri.rs @@ -1,15 +1,15 @@ use std::fmt::Display; -use proc_macro::TokenStream; -use crate::proc_macro2::TokenStream as TokenStream2; -use devise::{syn, Result}; -use devise::syn::{Expr, Ident, Type, spanned::Spanned}; +use devise::{syn, Result, ext::SpanDiagnosticExt}; + use crate::http::{uri::{Origin, Path, Query}, ext::IntoOwned}; use crate::http::route::{RouteSegment, Kind, Source}; +use crate::syn::{Expr, Ident, Type, spanned::Spanned}; use crate::http_codegen::Optional; -use crate::syn_ext::{IdentExt, syn_to_diag}; +use crate::syn_ext::IdentExt; use crate::bang::{prefix_last_segment, uri_parsing::*}; +use crate::proc_macro2::TokenStream; use crate::URI_MACRO_PREFIX; @@ -24,12 +24,12 @@ macro_rules! p { } pub fn _uri_macro(input: TokenStream) -> Result { - let input2: TokenStream2 = input.clone().into(); - let mut params = syn::parse::(input).map_err(syn_to_diag)?; + let input2: TokenStream = input.clone().into(); + let mut params = syn::parse2::(input)?; prefix_last_segment(&mut params.route_path, URI_MACRO_PREFIX); let path = ¶ms.route_path; - Ok(quote!(#path!(#input2)).into()) + Ok(quote!(#path!(#input2))) } fn extract_exprs<'a>(internal: &'a InternalUriParams) -> Result<( @@ -43,8 +43,7 @@ fn extract_exprs<'a>(internal: &'a InternalUriParams) -> Result<( let path_param_count = internal.route_uri.path().matches('<').count(); for expr in exprs.iter().take(path_param_count) { if !expr.as_expr().is_some() { - return Err(expr.span().unstable() - .error("path parameters cannot be ignored")); + return Err(expr.span().error("path parameters cannot be ignored")); } } @@ -91,13 +90,13 @@ fn extract_exprs<'a>(internal: &'a InternalUriParams) -> Result<( if !extra.is_empty() { let (ps, msg) = join(extra.iter()); - let spans: Vec<_> = extra.iter().map(|ident| ident.span().unstable()).collect(); + let spans: Vec<_> = extra.iter().map(|ident| ident.span()).collect(); diag = diag.span_help(spans, format!("unknown {}: {}", ps, msg)); } if !dup.is_empty() { let (ps, msg) = join(dup.iter()); - let spans: Vec<_> = dup.iter().map(|ident| ident.span().unstable()).collect(); + let spans: Vec<_> = dup.iter().map(|ident| ident.span()).collect(); diag = diag.span_help(spans, format!("duplicate {}: {}", ps, msg)); } @@ -106,7 +105,7 @@ fn extract_exprs<'a>(internal: &'a InternalUriParams) -> Result<( } } -fn add_binding(to: &mut Vec, ident: &Ident, ty: &Type, expr: &Expr, source: Source) { +fn add_binding(to: &mut Vec, ident: &Ident, ty: &Type, expr: &Expr, source: Source) { let uri_mod = quote!(rocket::http::uri); let (span, ident_tmp) = (expr.span(), ident.prepend("__tmp_")); let from_uri_param = if source == Source::Query { @@ -124,9 +123,9 @@ fn add_binding(to: &mut Vec, ident: &Ident, ty: &Type, expr: &Expr fn explode_path<'a, I: Iterator>( uri: &Origin<'_>, - bindings: &mut Vec, + bindings: &mut Vec, mut items: I -) -> TokenStream2 { +) -> TokenStream { let (uri_mod, path) = (quote!(rocket::http::uri), uri.path()); if !path.contains('<') { return quote!(#uri_mod::UriArgumentsKind::Static(#path)); @@ -153,9 +152,9 @@ fn explode_path<'a, I: Iterator>( fn explode_query<'a, I: Iterator>( uri: &Origin<'_>, - bindings: &mut Vec, + bindings: &mut Vec, mut items: I -) -> Option { +) -> Option { let (uri_mod, query) = (quote!(rocket::http::uri), uri.query()?); if !query.contains('<') { return Some(quote!(#uri_mod::UriArgumentsKind::Static(#query))); @@ -215,7 +214,7 @@ fn build_origin(internal: &InternalUriParams) -> Origin<'static> { pub fn _uri_internal_macro(input: TokenStream) -> Result { // Parse the internal invocation and the user's URI param expressions. - let internal = syn::parse::(input).map_err(syn_to_diag)?; + let internal = syn::parse2::(input)?; let (path_params, query_params) = extract_exprs(&internal)?; let mut bindings = vec![]; @@ -227,5 +226,5 @@ pub fn _uri_internal_macro(input: TokenStream) -> Result { Ok(quote!({ #(#bindings)* #uri_mod::UriArguments { path: #path, query: #query, }.into_origin() - }).into()) + })) } diff --git a/core/codegen/src/bang/uri_parsing.rs b/core/codegen/src/bang/uri_parsing.rs index ab6edf8b..63ba28ad 100644 --- a/core/codegen/src/bang/uri_parsing.rs +++ b/core/codegen/src/bang/uri_parsing.rs @@ -1,16 +1,15 @@ -use proc_macro::Span; - -use devise::{syn, Spanned}; -use devise::proc_macro2::TokenStream as TokenStream2; -use devise::ext::TypeExt; +use indexmap::IndexMap; +use devise::{Spanned, ext::TypeExt}; use quote::ToTokens; -use self::syn::{Expr, Ident, LitStr, Path, Token, Type}; -use self::syn::parse::{self, Parse, ParseStream}; -use self::syn::punctuated::Punctuated; +use crate::syn::{self, Expr, Ident, LitStr, Path, Token, Type}; +use crate::syn::parse::{self, Parse, ParseStream}; +use crate::syn::punctuated::Punctuated; use crate::http::{uri::Origin, ext::IntoOwned}; -use indexmap::IndexMap; +use crate::proc_macro2::{TokenStream, Span}; + +// TODO(diag): Use 'Diagnostic' in place of syn::Error. #[derive(Debug)] pub enum ArgExpr { @@ -124,7 +123,7 @@ impl Parse for UriParams { })?; if !input.peek(Token![,]) && input.cursor().eof() { - return err(string.span().unstable(), "unexpected end of input: \ + return err(string.span(), "unexpected end of input: \ expected ',' followed by route path"); } @@ -327,7 +326,7 @@ impl ArgExpr { } impl ToTokens for ArgExpr { - fn to_tokens(&self, tokens: &mut TokenStream2) { + fn to_tokens(&self, tokens: &mut TokenStream) { match self { ArgExpr::Expr(e) => e.to_tokens(tokens), ArgExpr::Ignored(e) => e.to_tokens(tokens) @@ -336,7 +335,7 @@ impl ToTokens for ArgExpr { } impl ToTokens for Arg { - fn to_tokens(&self, tokens: &mut TokenStream2) { + fn to_tokens(&self, tokens: &mut TokenStream) { match self { Arg::Unnamed(e) => e.to_tokens(tokens), Arg::Named(ident, eq, expr) => tokens.extend(quote!(#ident #eq #expr)), @@ -345,7 +344,7 @@ impl ToTokens for Arg { } impl ToTokens for Args { - fn to_tokens(&self, tokens: &mut TokenStream2) { + fn to_tokens(&self, tokens: &mut TokenStream) { match self { Args::Unnamed(e) | Args::Named(e) => e.to_tokens(tokens) } diff --git a/core/codegen/src/derive/from_form.rs b/core/codegen/src/derive/from_form.rs index 5b906a70..67531df4 100644 --- a/core/codegen/src/derive/from_form.rs +++ b/core/codegen/src/derive/from_form.rs @@ -1,5 +1,6 @@ -use proc_macro::{Span, TokenStream}; -use devise::{*, ext::{TypeExt, Split3}}; +use devise::{*, ext::{TypeExt, Split3, SpanDiagnosticExt}}; + +use crate::proc_macro2::{Span, TokenStream}; #[derive(FromMeta)] pub struct Form { @@ -57,7 +58,7 @@ fn validate_struct(gen: &DeriveGenerator, data: Struct<'_>) -> Result<()> { Ok(()) } -pub fn derive_from_form(input: TokenStream) -> TokenStream { +pub fn derive_from_form(input: proc_macro::TokenStream) -> TokenStream { let form_error = quote!(::rocket::request::FormParseError); DeriveGenerator::build_for(input, quote!(impl<'__f> ::rocket::request::FromForm<'__f>)) .generic_support(GenericSupport::Lifetime | GenericSupport::Type) @@ -126,5 +127,5 @@ pub fn derive_from_form(input: TokenStream) -> TokenStream { #_Ok(Self { #(#builders)* }) }) }) - .to_tokens() + .to_tokens2() } diff --git a/core/codegen/src/derive/from_form_value.rs b/core/codegen/src/derive/from_form_value.rs index aa796d63..30ef3697 100644 --- a/core/codegen/src/derive/from_form_value.rs +++ b/core/codegen/src/derive/from_form_value.rs @@ -1,12 +1,13 @@ -use devise::*; -use proc_macro::TokenStream; +use devise::{*, ext::SpanDiagnosticExt}; + +use crate::proc_macro2::TokenStream; #[derive(FromMeta)] struct Form { value: String, } -pub fn derive_from_form_value(input: TokenStream) -> TokenStream { +pub fn derive_from_form_value(input: proc_macro::TokenStream) -> TokenStream { define_vars_and_mods!(_Ok, _Err, _Result); DeriveGenerator::build_for(input, quote!(impl<'__v> ::rocket::request::FromFormValue<'__v>)) .generic_support(GenericSupport::None) @@ -21,7 +22,8 @@ pub fn derive_from_form_value(input: TokenStream) -> TokenStream { // Emit a warning if the enum is empty. if data.variants.is_empty() { - generator.input.span().warning("deriving for empty enum").emit(); + return Err(generator.input.span() + .error("enum must have at least one field")); } Ok(()) @@ -51,5 +53,5 @@ pub fn derive_from_form_value(input: TokenStream) -> TokenStream { } }) }) - .to_tokens() + .to_tokens2() } diff --git a/core/codegen/src/derive/responder.rs b/core/codegen/src/derive/responder.rs index 3c7bae76..abd2b8ba 100644 --- a/core/codegen/src/derive/responder.rs +++ b/core/codegen/src/derive/responder.rs @@ -1,8 +1,8 @@ -use quote::ToTokens; -use proc_macro::TokenStream; -use devise::{*, ext::TypeExt}; -use devise::proc_macro2::TokenStream as TokenStream2; +use quote::ToTokens; +use devise::{*, ext::{TypeExt, SpanDiagnosticExt}}; + +use crate::proc_macro2::TokenStream; use crate::http_codegen::{ContentType, Status}; #[derive(Default, FromMeta)] @@ -16,15 +16,11 @@ struct FieldAttr { ignore: bool, } -pub fn derive_responder(input: TokenStream) -> TokenStream { - // NOTE: Due to a bug in devise, we can't do the more correct: - // quote!(impl<'__r, '__o: '__r> ::rocket::response::Responder<'__r, '__o>)) - // replace_generic(1, 0) - // A bugfix (on devise master) fixes this so the above works. Hack. - DeriveGenerator::build_for(input, quote!(impl<'__r> ::rocket::response::Responder<'__r, '__r>)) +pub fn derive_responder(input: proc_macro::TokenStream) -> TokenStream { + DeriveGenerator::build_for(input, quote!(impl<'__r, '__o: '__r> ::rocket::response::Responder<'__r, '__o>)) .generic_support(GenericSupport::Lifetime) .data_support(DataSupport::Struct | DataSupport::Enum) - .replace_generic(0, 0) + .replace_generic(1, 0) .validate_generics(|_, generics| match generics.lifetimes().count() > 1 { true => Err(generics.span().error("only one lifetime is supported")), false => Ok(()) @@ -37,13 +33,13 @@ pub fn derive_responder(input: TokenStream) -> TokenStream { fn respond_to( self, __req: &'__r ::rocket::request::Request - ) -> ::rocket::response::Result<'__r> { + ) -> ::rocket::response::Result<'__o> { #inner } }) .try_map_fields(|_, fields| { define_vars_and_mods!(_Ok); - fn set_header_tokens(item: T) -> TokenStream2 { + fn set_header_tokens(item: T) -> TokenStream { quote_spanned!(item.span().into() => __res.set_header(#item);) } @@ -82,5 +78,5 @@ pub fn derive_responder(input: TokenStream) -> TokenStream { #_Ok(__res) }) }) - .to_tokens() + .to_tokens2() } diff --git a/core/codegen/src/derive/uri_display.rs b/core/codegen/src/derive/uri_display.rs index aaf0fb94..521dc984 100644 --- a/core/codegen/src/derive/uri_display.rs +++ b/core/codegen/src/derive/uri_display.rs @@ -1,8 +1,8 @@ -use proc_macro::{Span, TokenStream}; -use devise::*; + +use devise::{*, ext::SpanDiagnosticExt}; use crate::derive::from_form::Form; -use crate::proc_macro2::TokenStream as TokenStream2; +use crate::proc_macro2::{TokenStream, Span}; const NO_EMPTY_FIELDS: &str = "fieldless structs or variants are not supported"; const NO_NULLARY: &str = "nullary items are not supported"; @@ -39,7 +39,7 @@ fn validate_enum(gen: &DeriveGenerator, data: Enum<'_>) -> Result<()> { } #[allow(non_snake_case)] -pub fn derive_uri_display_query(input: TokenStream) -> TokenStream { +pub fn derive_uri_display_query(input: proc_macro::TokenStream) -> TokenStream { let Query = quote!(::rocket::http::uri::Query); let UriDisplay = quote!(::rocket::http::uri::UriDisplay<#Query>); let Formatter = quote!(::rocket::http::uri::Formatter<#Query>); @@ -116,15 +116,15 @@ pub fn derive_uri_display_query(input: TokenStream) -> TokenStream { }) .to_tokens(); - let mut ts = TokenStream2::from(uri_display); - ts.extend(TokenStream2::from(from_self)); - ts.extend(TokenStream2::from(from_ref)); - ts.extend(TokenStream2::from(from_mut)); + let mut ts = TokenStream::from(uri_display); + ts.extend(TokenStream::from(from_self)); + ts.extend(TokenStream::from(from_ref)); + ts.extend(TokenStream::from(from_mut)); ts.into() } #[allow(non_snake_case)] -pub fn derive_uri_display_path(input: TokenStream) -> TokenStream { +pub fn derive_uri_display_path(input: proc_macro::TokenStream) -> TokenStream { let Path = quote!(::rocket::http::uri::Path); let UriDisplay = quote!(::rocket::http::uri::UriDisplay<#Path>); let Formatter = quote!(::rocket::http::uri::Formatter<#Path>); @@ -179,8 +179,8 @@ pub fn derive_uri_display_path(input: TokenStream) -> TokenStream { }) .to_tokens(); - let mut ts = TokenStream2::from(uri_display); - ts.extend(TokenStream2::from(from_self)); - ts.extend(TokenStream2::from(from_ref)); + let mut ts = TokenStream::from(uri_display); + ts.extend(TokenStream::from(from_self)); + ts.extend(TokenStream::from(from_ref)); ts.into() } diff --git a/core/codegen/src/http_codegen.rs b/core/codegen/src/http_codegen.rs index 1281bd16..823673cd 100644 --- a/core/codegen/src/http_codegen.rs +++ b/core/codegen/src/http_codegen.rs @@ -1,6 +1,7 @@ use quote::ToTokens; -use crate::proc_macro2::TokenStream as TokenStream2; -use devise::{FromMeta, MetaItem, Result, ext::{Split2, PathExt}}; +use devise::{FromMeta, MetaItem, Result, ext::{Split2, PathExt, SpanDiagnosticExt}}; + +use crate::proc_macro2::TokenStream; use crate::http::{self, ext::IntoOwned}; use crate::http::uri::{Path, Query}; use crate::attribute::segments::{parse_segments, parse_data_segment, Segment, Kind}; @@ -53,7 +54,7 @@ impl FromMeta for Status { } impl ToTokens for Status { - fn to_tokens(&self, tokens: &mut TokenStream2) { + fn to_tokens(&self, tokens: &mut TokenStream) { let (code, reason) = (self.0.code, self.0.reason); tokens.extend(quote!(rocket::http::Status { code: #code, reason: #reason })); } @@ -68,7 +69,7 @@ impl FromMeta for ContentType { } impl ToTokens for ContentType { - fn to_tokens(&self, tokens: &mut TokenStream2) { + fn to_tokens(&self, tokens: &mut TokenStream) { // Yeah, yeah. (((((i))).kn0w())) let media_type = MediaType((self.0).clone().0); tokens.extend(quote!(::rocket::http::ContentType(#media_type))); @@ -81,9 +82,10 @@ impl FromMeta for MediaType { .ok_or(meta.value_span().error("invalid or unknown media type"))?; if !mt.is_known() { + // FIXME(diag: warning) meta.value_span() .warning(format!("'{}' is not a known media type", mt)) - .emit(); + .emit_as_tokens(); } Ok(MediaType(mt)) @@ -91,7 +93,7 @@ impl FromMeta for MediaType { } impl ToTokens for MediaType { - fn to_tokens(&self, tokens: &mut TokenStream2) { + fn to_tokens(&self, tokens: &mut TokenStream) { use std::iter::repeat; let (top, sub) = (self.0.top().as_str(), self.0.sub().as_str()); let (keys, values) = self.0.params().split2(); @@ -150,7 +152,7 @@ impl FromMeta for Method { } impl ToTokens for Method { - fn to_tokens(&self, tokens: &mut TokenStream2) { + fn to_tokens(&self, tokens: &mut TokenStream) { let method_tokens = match self.0 { http::Method::Get => quote!(::rocket::http::Method::Get), http::Method::Put => quote!(::rocket::http::Method::Put), @@ -234,7 +236,7 @@ impl FromMeta for RoutePath { } impl ToTokens for Optional { - fn to_tokens(&self, tokens: &mut TokenStream2) { + fn to_tokens(&self, tokens: &mut TokenStream) { define_vars_and_mods!(_Some, _None); let opt_tokens = match self.0 { Some(ref val) => quote!(#_Some(#val)), diff --git a/core/codegen/src/lib.rs b/core/codegen/src/lib.rs index 39d8f151..2ee24ad2 100644 --- a/core/codegen/src/lib.rs +++ b/core/codegen/src/lib.rs @@ -1,4 +1,3 @@ -#![feature(proc_macro_diagnostic, proc_macro_span)] #![recursion_limit="128"] #![doc(html_root_url = "https://api.rocket.rs/v0.5")] @@ -101,6 +100,7 @@ vars_and_mods! { _Ok => ::std::result::Result::Ok, _Err => ::std::result::Result::Err, _Box => ::std::boxed::Box, + _Vec => ::std::vec::Vec, } macro_rules! define_vars_and_mods { @@ -118,7 +118,7 @@ mod syn_ext; use crate::http::Method; use proc_macro::TokenStream; -use devise::proc_macro2; +use devise::{proc_macro2, syn}; static ROUTE_STRUCT_PREFIX: &str = "static_rocket_route_info_for_"; static CATCH_STRUCT_PREFIX: &str = "static_rocket_catch_info_for_"; @@ -129,15 +129,19 @@ static ROCKET_PARAM_PREFIX: &str = "__rocket_param_"; macro_rules! emit { ($tokens:expr) => ({ - let tokens = $tokens; + use devise::ext::SpanDiagnosticExt; + + let mut tokens = $tokens; if std::env::var_os("ROCKET_CODEGEN_DEBUG").is_some() { - proc_macro::Span::call_site() + let debug_tokens = proc_macro2::Span::call_site() .note("emitting Rocket code generation debug output") .note(tokens.to_string()) - .emit() + .emit_as_tokens(); + + tokens.extend(debug_tokens); } - tokens + tokens.into() }) } diff --git a/core/codegen/src/proc_macro_ext.rs b/core/codegen/src/proc_macro_ext.rs index 66e1359b..72776020 100644 --- a/core/codegen/src/proc_macro_ext.rs +++ b/core/codegen/src/proc_macro_ext.rs @@ -1,6 +1,8 @@ use std::ops::RangeBounds; -use proc_macro::{Span, Diagnostic, Literal}; +use devise::Diagnostic; + +use crate::proc_macro2::{Span, Literal}; pub type PResult = std::result::Result; @@ -27,7 +29,8 @@ impl Diagnostics { let mut iter = self.0.into_iter(); let mut last = iter.next().expect("Diagnostic::emit_head empty"); for diag in iter { - last.emit(); + // FIXME(diag: emit, can there be errors here?) + last.emit_as_tokens(); last = diag; } @@ -86,7 +89,8 @@ impl StringLit { } /// Attempt to obtain a subspan, or, failing that, produce the full span. - /// This will create suboptimal diagnostics, but better than failing to build entirely. + /// This will create suboptimal diagnostics, but better than failing to + /// build entirely. pub fn subspan>(&self, range: R) -> Span { self.1.subspan(range).unwrap_or_else(|| self.span()) } diff --git a/core/codegen/src/syn_ext.rs b/core/codegen/src/syn_ext.rs index ef60d37b..736d48a5 100644 --- a/core/codegen/src/syn_ext.rs +++ b/core/codegen/src/syn_ext.rs @@ -1,11 +1,6 @@ //! Extensions to `syn` types. use devise::syn; -use proc_macro::Diagnostic; - -pub fn syn_to_diag(error: syn::parse::Error) -> Diagnostic { - error.span().unstable().error(error.to_string()) -} pub trait IdentExt { fn prepend(&self, string: &str) -> syn::Ident; diff --git a/core/codegen/tests/ui-fail/from_form_value.rs b/core/codegen/tests/ui-fail/from_form_value.rs index ccf44a93..ebc131df 100644 --- a/core/codegen/tests/ui-fail/from_form_value.rs +++ b/core/codegen/tests/ui-fail/from_form_value.rs @@ -22,7 +22,7 @@ enum Foo4 { #[derive(FromFormValue)] enum Foo5 { } -//~^ WARNING empty enum +//~^ ERROR at least one field #[derive(FromFormValue)] enum Foo6 { diff --git a/core/codegen/tests/ui-fail/from_form_value.stderr b/core/codegen/tests/ui-fail/from_form_value.stderr index f49e5468..d5fb24f9 100644 --- a/core/codegen/tests/ui-fail/from_form_value.stderr +++ b/core/codegen/tests/ui-fail/from_form_value.stderr @@ -53,11 +53,18 @@ note: error occurred while deriving `FromFormValue` | ^^^^^^^^^^^^^ = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) -warning: deriving for empty enum +error: enum must have at least one field --> $DIR/from_form_value.rs:24:1 | 24 | enum Foo5 { } | ^^^^^^^^^^^^^ + | +note: error occurred while deriving `FromFormValue` + --> $DIR/from_form_value.rs:23:10 + | +23 | #[derive(FromFormValue)] + | ^^^^^^^^^^^^^ + = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type generics are not supported --> $DIR/from_form_value.rs:28:11 @@ -98,5 +105,5 @@ note: error occurred while deriving `FromFormValue` | ^^^^^^^^^^^^^ = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 7 previous errors; 1 warning emitted +error: aborting due to 8 previous errors diff --git a/core/codegen/tests/ui-fail/uri_display.stderr b/core/codegen/tests/ui-fail/uri_display.stderr index 9fa32284..a6348be0 100644 --- a/core/codegen/tests/ui-fail/uri_display.stderr +++ b/core/codegen/tests/ui-fail/uri_display.stderr @@ -51,10 +51,10 @@ note: error occurred while deriving `UriDisplay` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: tuple structs or variants must have exactly one field - --> $DIR/uri_display.rs:39:12 + --> $DIR/uri_display.rs:39:13 | 39 | struct Foo5(String, String); - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | note: error occurred while deriving `UriDisplay` --> $DIR/uri_display.rs:35:10 @@ -77,10 +77,10 @@ note: error occurred while deriving `UriDisplay` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) error: struct must have exactly one field - --> $DIR/uri_display.rs:55:12 + --> $DIR/uri_display.rs:55:13 | 55 | struct Foo7(String, usize); - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | note: error occurred while deriving `UriDisplay` --> $DIR/uri_display.rs:52:10 diff --git a/examples/uuid/Cargo.toml b/examples/uuid/Cargo.toml index d64ae72b..3744508a 100644 --- a/examples/uuid/Cargo.toml +++ b/examples/uuid/Cargo.toml @@ -8,7 +8,6 @@ publish = false [dependencies] rocket = { path = "../../core/lib" } lazy_static = "1.0" -uuid = "0.8" [dependencies.rocket_contrib] default-features = false diff --git a/examples/uuid/src/main.rs b/examples/uuid/src/main.rs index 18f048c1..dfb5bf63 100644 --- a/examples/uuid/src/main.rs +++ b/examples/uuid/src/main.rs @@ -2,7 +2,9 @@ #[macro_use] extern crate lazy_static; use std::collections::HashMap; + use rocket_contrib::uuid::Uuid; +use rocket_contrib::uuid::uuid_crate as uuid; #[cfg(test)] mod tests;