Fix Outgoing derive missing lifetimes when branching for emitting code

This commit is contained in:
Devin Ragotzy 2020-08-06 16:15:17 -04:00 committed by Jonas Platte
parent 7e3ebff089
commit 770a68d49b

View File

@ -41,11 +41,11 @@ pub fn expand_derive_outgoing(input: DeriveInput) -> syn::Result<TokenStream> {
match data { match data {
DataKind::Unit => Ok(impl_outgoing_with_incoming_self(&input)), DataKind::Unit => Ok(impl_outgoing_with_incoming_self(&input)),
DataKind::Enum(mut vars) => { DataKind::Enum(mut vars) => {
let mut any_attribute = false; let mut found_lifetime = false;
for var in &mut vars { for var in &mut vars {
for field in &mut var.fields { for field in &mut var.fields {
if strip_lifetimes(&mut field.ty) { if strip_lifetimes(&mut field.ty) {
any_attribute = true; found_lifetime = true;
} }
} }
} }
@ -53,7 +53,7 @@ pub fn expand_derive_outgoing(input: DeriveInput) -> syn::Result<TokenStream> {
let original_ident = &input.ident; let original_ident = &input.ident;
let (original_impl_gen, original_ty_gen, _) = input.generics.split_for_impl(); let (original_impl_gen, original_ty_gen, _) = input.generics.split_for_impl();
if !any_attribute { if !found_lifetime {
return Ok(impl_outgoing_with_incoming_self(&input)); return Ok(impl_outgoing_with_incoming_self(&input));
} }
@ -75,17 +75,17 @@ pub fn expand_derive_outgoing(input: DeriveInput) -> syn::Result<TokenStream> {
}) })
} }
DataKind::Struct(mut fields, struct_kind) => { DataKind::Struct(mut fields, struct_kind) => {
let mut any_attribute = false; let mut found_lifetime = false;
for field in &mut fields { for field in &mut fields {
if strip_lifetimes(&mut field.ty) { if strip_lifetimes(&mut field.ty) {
any_attribute = true; found_lifetime = true;
} }
} }
let original_ident = &input.ident; let original_ident = &input.ident;
let (original_impl_gen, original_ty_gen, _) = input.generics.split_for_impl(); let (original_impl_gen, original_ty_gen, _) = input.generics.split_for_impl();
if !any_attribute { if !found_lifetime {
return Ok(impl_outgoing_with_incoming_self(&input)); return Ok(impl_outgoing_with_incoming_self(&input));
} }
@ -121,6 +121,7 @@ fn no_deserialize_in_attrs(attrs: &[Attribute]) -> bool {
fn impl_outgoing_with_incoming_self(input: &DeriveInput) -> TokenStream { fn impl_outgoing_with_incoming_self(input: &DeriveInput) -> TokenStream {
let ident = &input.ident; let ident = &input.ident;
let (impl_gen, ty_gen, _) = input.generics.split_for_impl(); let (impl_gen, ty_gen, _) = input.generics.split_for_impl();
quote! { quote! {
impl #impl_gen ::ruma_api::Outgoing for #ident #ty_gen { impl #impl_gen ::ruma_api::Outgoing for #ident #ty_gen {
type Incoming = Self; type Incoming = Self;
@ -146,6 +147,8 @@ fn strip_lifetimes(field_type: &mut Type) -> bool {
// The IncomingT has to be declared by the user of this derive macro. // The IncomingT has to be declared by the user of this derive macro.
Type::Path(TypePath { path, .. }) => { Type::Path(TypePath { path, .. }) => {
let mut has_lifetimes = false; let mut has_lifetimes = false;
let mut generic_lifetime = false;
for seg in &mut path.segments { for seg in &mut path.segments {
// strip generic lifetimes // strip generic lifetimes
match &mut seg.arguments { match &mut seg.arguments {
@ -157,13 +160,15 @@ fn strip_lifetimes(field_type: &mut Type) -> bool {
.into_iter() .into_iter()
.map(|mut ty| { .map(|mut ty| {
if let GenericArgument::Type(ty) = &mut ty { if let GenericArgument::Type(ty) = &mut ty {
strip_lifetimes(ty); if strip_lifetimes(ty) {
has_lifetimes = true;
};
} }
ty ty
}) })
.filter(|arg| { .filter(|arg| {
if let GenericArgument::Lifetime(_) = arg { if let GenericArgument::Lifetime(_) = arg {
has_lifetimes = true; generic_lifetime = true;
false false
} else { } else {
true true
@ -178,7 +183,9 @@ fn strip_lifetimes(field_type: &mut Type) -> bool {
.clone() .clone()
.into_iter() .into_iter()
.map(|mut ty| { .map(|mut ty| {
strip_lifetimes(&mut ty); if strip_lifetimes(&mut ty) {
has_lifetimes = true;
};
ty ty
}) })
.collect(); .collect();
@ -187,14 +194,15 @@ fn strip_lifetimes(field_type: &mut Type) -> bool {
} }
} }
if has_lifetimes { // If a type has a generic lifetime parameter there must be an `Incoming` variant of that type.
if generic_lifetime {
if let Some(name) = path.segments.last_mut() { if let Some(name) = path.segments.last_mut() {
let incoming_ty_ident = format_ident!("Incoming{}", name.ident); let incoming_ty_ident = format_ident!("Incoming{}", name.ident);
name.ident = incoming_ty_ident; name.ident = incoming_ty_ident;
} }
} }
has_lifetimes has_lifetimes || generic_lifetime
} }
Type::Reference(TypeReference { elem, .. }) => match &mut **elem { Type::Reference(TypeReference { elem, .. }) => match &mut **elem {
Type::Path(ty_path) => { Type::Path(ty_path) => {