From a227a8786581c0b403cdb5bc7ae99e0c44ad6afd Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 7 Jun 2020 20:30:03 +0900 Subject: [PATCH] Collect lifetimes inside macro invocations --- serde_derive/src/internals/attr.rs | 27 +++++++++++++++++++++++++-- test_suite/tests/test_gen.rs | 12 ++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/serde_derive/src/internals/attr.rs b/serde_derive/src/internals/attr.rs index e6f72dfe..d59e681a 100644 --- a/serde_derive/src/internals/attr.rs +++ b/serde_derive/src/internals/attr.rs @@ -1,6 +1,6 @@ use internals::symbol::*; use internals::{ungroup, Ctxt}; -use proc_macro2::{Group, Span, TokenStream, TokenTree}; +use proc_macro2::{Group, Spacing, Span, TokenStream, TokenTree}; use quote::ToTokens; use std::borrow::Cow; use std::collections::BTreeSet; @@ -1921,17 +1921,40 @@ fn collect_lifetimes(ty: &syn::Type, out: &mut BTreeSet) { syn::Type::Group(ty) => { collect_lifetimes(&ty.elem, out); } + syn::Type::Macro(ty) => { + collect_lifetimes_from_tokens(ty.mac.tokens.clone(), out); + } syn::Type::BareFn(_) | syn::Type::Never(_) | syn::Type::TraitObject(_) | syn::Type::ImplTrait(_) | syn::Type::Infer(_) - | syn::Type::Macro(_) | syn::Type::Verbatim(_) | _ => {} } } +fn collect_lifetimes_from_tokens(tokens: TokenStream, out: &mut BTreeSet) { + let mut iter = tokens.into_iter(); + while let Some(tt) = iter.next() { + match &tt { + TokenTree::Punct(op) if op.as_char() == '\'' && op.spacing() == Spacing::Joint => { + if let Some(TokenTree::Ident(ident)) = iter.next() { + out.insert(syn::Lifetime { + apostrophe: op.span(), + ident, + }); + } + } + TokenTree::Group(group) => { + let tokens = group.stream(); + collect_lifetimes_from_tokens(tokens, out); + } + _ => {} + } + } +} + fn parse_lit_str(s: &syn::LitStr) -> parse::Result where T: Parse, diff --git a/test_suite/tests/test_gen.rs b/test_suite/tests/test_gen.rs index d8def742..73f7fa50 100644 --- a/test_suite/tests/test_gen.rs +++ b/test_suite/tests/test_gen.rs @@ -723,6 +723,18 @@ fn test_gen() { } deriving!(&'a str); + + macro_rules! mac { + ($($tt:tt)*) => { + $($tt)* + }; + } + + #[derive(Deserialize)] + struct BorrowLifetimeInsideMacro<'a> { + #[serde(borrow = "'a")] + f: mac!(Cow<'a, str>), + } } //////////////////////////////////////////////////////////////////////////