diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 7fa1030b1..df76ec631 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -27,15 +27,16 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result(__deserializer: __D) -> _serde::export::Result<#remote #ty_generics, __D::Error> + #vis fn deserialize<__D>(__deserializer: __D) -> #serde::export::Result<#remote #ty_generics, __D::Error> where - __D: _serde::Deserializer<#delife>, + __D: #serde::Deserializer<#delife>, { #used #body @@ -47,10 +48,10 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result for #ident #ty_generics #where_clause { - fn deserialize<__D>(__deserializer: __D) -> _serde::export::Result + impl #de_impl_generics #serde::Deserialize<#delife> for #ident #ty_generics #where_clause { + fn deserialize<__D>(__deserializer: __D) -> #serde::export::Result where - __D: _serde::Deserializer<#delife>, + __D: #serde::Deserializer<#delife>, { #body } @@ -60,7 +61,7 @@ pub fn expand_derive_deserialize(input: &syn::DeriveInput) -> Result TokenStream { +pub fn wrap_in_const(serde_path: Option<&syn::Path>, trait_: &str, ty: &Ident, code: TokenStream) -> TokenStream { let try_replacement = try::replacement(); let dummy_const = Ident::new( @@ -10,13 +11,21 @@ pub fn wrap_in_const(trait_: &str, ty: &Ident, code: TokenStream) -> TokenStream Span::call_site(), ); - quote! { - #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] - const #dummy_const: () = { + let use_serde = serde_path.map(|path| { + quote!(use #path as _serde;) + }).unwrap_or_else(|| { + quote! { #[allow(unknown_lints)] #[cfg_attr(feature = "cargo-clippy", allow(useless_attribute))] #[allow(rust_2018_idioms)] extern crate serde as _serde; + } + }); + + quote! { + #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] + const #dummy_const: () = { + #use_serde #try_replacement #code }; diff --git a/serde_derive/src/internals/attr.rs b/serde_derive/src/internals/attr.rs index b95d490f2..db763e22c 100644 --- a/serde_derive/src/internals/attr.rs +++ b/serde_derive/src/internals/attr.rs @@ -1,6 +1,7 @@ use internals::Ctxt; use proc_macro2::{Group, Span, TokenStream, TokenTree}; use quote::ToTokens; +use std::borrow::Cow; use std::collections::BTreeSet; use std::str::FromStr; use syn; @@ -218,6 +219,7 @@ pub struct Container { remote: Option, identifier: Identifier, has_flatten: bool, + serde_path: Option, } /// Styles of representing an enum. @@ -298,6 +300,7 @@ impl Container { let mut remote = Attr::none(cx, "remote"); let mut field_identifier = BoolAttr::none(cx, "field_identifier"); let mut variant_identifier = BoolAttr::none(cx, "variant_identifier"); + let mut serde_path = Attr::none(cx, "crate"); for meta_items in item.attrs.iter().filter_map(get_serde_meta_items) { for meta_item in meta_items { @@ -582,6 +585,13 @@ impl Container { variant_identifier.set_true(word); } + // Parse `#[serde(crate = "foo")]` + Meta(NameValue(ref m)) if m.ident == "crate" => { + if let Ok(path) = parse_lit_into_path(cx, &m.ident, &m.lit) { + serde_path.set(&m.ident, path) + } + } + Meta(ref meta_item) => { cx.error_spanned_by( meta_item.name(), @@ -613,6 +623,7 @@ impl Container { remote: remote.get(), identifier: decide_identifier(cx, item, field_identifier, variant_identifier), has_flatten: false, + serde_path: serde_path.get(), } } @@ -671,6 +682,16 @@ impl Container { pub fn mark_has_flatten(&mut self) { self.has_flatten = true; } + + pub fn custom_serde_path(&self) -> Option<&syn::Path> { + self.serde_path.as_ref() + } + + pub fn serde_path(&self) -> Cow { + self.custom_serde_path() + .map(Cow::Borrowed) + .unwrap_or_else(|| Cow::Owned(parse_quote!(_serde))) + } } fn decide_tag( diff --git a/serde_derive/src/ser.rs b/serde_derive/src/ser.rs index 4d1f680db..d5c83bc64 100644 --- a/serde_derive/src/ser.rs +++ b/serde_derive/src/ser.rs @@ -22,15 +22,16 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result(__self: &#remote #ty_generics, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error> + #vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> #serde::export::Result<__S::Ok, __S::Error> where - __S: _serde::Serializer, + __S: #serde::Serializer, { #used #body @@ -40,10 +41,10 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result(&self, __serializer: __S) -> _serde::export::Result<__S::Ok, __S::Error> + impl #impl_generics #serde::Serialize for #ident #ty_generics #where_clause { + fn serialize<__S>(&self, __serializer: __S) -> #serde::export::Result<__S::Ok, __S::Error> where - __S: _serde::Serializer, + __S: #serde::Serializer, { #body } @@ -51,7 +52,7 @@ pub fn expand_derive_serialize(input: &syn::DeriveInput) -> Result AssertNotSerdeDeserialize<'a> for Foo {} + + fake_serde::assert::(); +} + +mod fake_serde { + pub use serde::*; + + pub fn assert() + where + T: Serialize, + T: for<'a> Deserialize<'a>, + {} + + pub trait Serialize { + fn serialize(&self, serializer: S) -> Result; + } + + pub trait Deserialize<'a>: Sized { + fn deserialize>(deserializer: D) -> Result; + } +} + +trait AssertNotSerdeSerialize {} + +impl AssertNotSerdeSerialize for T {} + +trait AssertNotSerdeDeserialize<'a> {} + +impl<'a, T: serde::Deserialize<'a>> AssertNotSerdeDeserialize<'a> for T {}