Skip to content

Commit 160caca

Browse files
committed
der_derive: handle type generics in sequence
1 parent b1b6b73 commit 160caca

File tree

3 files changed

+29
-30
lines changed

3 files changed

+29
-30
lines changed

der/derive/src/choice.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@ impl DeriveChoice {
6161

6262
let lifetime = match self.lifetime {
6363
Some(ref lifetime) => quote!(#lifetime),
64-
None => default_lifetime(),
64+
None => {
65+
let lifetime = default_lifetime();
66+
quote!(#lifetime)
67+
}
6568
};
6669

6770
// Lifetime parameters

der/derive/src/lib.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -141,13 +141,11 @@ use crate::{
141141
use proc_macro::TokenStream;
142142
use proc_macro2::Span;
143143
use proc_macro_error::proc_macro_error;
144-
use quote::quote;
145144
use syn::{parse_macro_input, DeriveInput, Lifetime};
146145

147146
/// Get the default lifetime.
148-
fn default_lifetime() -> proc_macro2::TokenStream {
149-
let lifetime = Lifetime::new("'__der_lifetime", Span::call_site());
150-
quote!(#lifetime)
147+
fn default_lifetime() -> Lifetime {
148+
Lifetime::new("'__der_lifetime", Span::call_site())
151149
}
152150

153151
/// Derive the [`Choice`][1] trait on an `enum`.

der/derive/src/sequence.rs

+23-25
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ use field::SequenceField;
88
use proc_macro2::TokenStream;
99
use proc_macro_error::abort;
1010
use quote::quote;
11-
use syn::{DeriveInput, Ident, Lifetime};
11+
use syn::{DeriveInput, GenericParam, Generics, Ident, Lifetime, LifetimeParam};
1212

1313
/// Derive the `Sequence` trait for a struct
1414
pub(crate) struct DeriveSequence {
1515
/// Name of the sequence struct.
1616
ident: Ident,
1717

18-
/// Lifetime of the struct.
19-
lifetime: Option<Lifetime>,
18+
/// Generics of the struct.
19+
generics: Generics,
2020

2121
/// Fields of the struct.
2222
fields: Vec<SequenceField>,
@@ -33,13 +33,6 @@ impl DeriveSequence {
3333
),
3434
};
3535

36-
// TODO(tarcieri): properly handle multiple lifetimes
37-
let lifetime = input
38-
.generics
39-
.lifetimes()
40-
.next()
41-
.map(|lt| lt.lifetime.clone());
42-
4336
let type_attrs = TypeAttrs::parse(&input.attrs);
4437

4538
let fields = data
@@ -50,27 +43,32 @@ impl DeriveSequence {
5043

5144
Self {
5245
ident: input.ident,
53-
lifetime,
46+
generics: input.generics.clone(),
5447
fields,
5548
}
5649
}
5750

5851
/// Lower the derived output into a [`TokenStream`].
5952
pub fn to_tokens(&self) -> TokenStream {
6053
let ident = &self.ident;
61-
62-
let lifetime = match self.lifetime {
63-
Some(ref lifetime) => quote!(#lifetime),
64-
None => default_lifetime(),
54+
let mut generics = self.generics.clone();
55+
56+
// Use the first lifetime parameter as lifetime for Decode/Encode lifetime
57+
// if none found, add one.
58+
let lifetime: Lifetime = if let Some(lt) = generics.lifetimes().next() {
59+
lt.lifetime.clone()
60+
} else {
61+
let lifetime = default_lifetime();
62+
generics.params.insert(
63+
0,
64+
GenericParam::Lifetime(LifetimeParam::new(lifetime.clone())),
65+
);
66+
lifetime
6567
};
6668

67-
// Lifetime parameters
68-
// TODO(tarcieri): support multiple lifetimes
69-
let lt_params = self
70-
.lifetime
71-
.as_ref()
72-
.map(|_| lifetime.clone())
73-
.unwrap_or_default();
69+
// We may or may not have inserted a lifetime.
70+
let (_impl_generics, ty_generics, where_clause) = self.generics.split_for_impl();
71+
let (impl_generics, _ty_generics, _where_clause) = generics.split_for_impl();
7472

7573
let mut decode_body = Vec::new();
7674
let mut decode_result = Vec::new();
@@ -87,7 +85,7 @@ impl DeriveSequence {
8785
}
8886

8987
quote! {
90-
impl<#lifetime> ::der::DecodeValue<#lifetime> for #ident<#lt_params> {
88+
impl #impl_generics ::der::DecodeValue<#lifetime> for #ident #ty_generics #where_clause {
9189
fn decode_value<R: ::der::Reader<#lifetime>>(
9290
reader: &mut R,
9391
header: ::der::Header,
@@ -104,7 +102,7 @@ impl DeriveSequence {
104102
}
105103
}
106104

107-
impl<#lifetime> ::der::EncodeValue for #ident<#lt_params> {
105+
impl #impl_generics ::der::EncodeValue for #ident #ty_generics #where_clause {
108106
fn value_len(&self) -> ::der::Result<::der::Length> {
109107
use ::der::Encode as _;
110108

@@ -122,7 +120,7 @@ impl DeriveSequence {
122120
}
123121
}
124122

125-
impl<#lifetime> ::der::Sequence<#lifetime> for #ident<#lt_params> {}
123+
impl #impl_generics ::der::Sequence<#lifetime> for #ident #ty_generics #where_clause {}
126124
}
127125
}
128126
}

0 commit comments

Comments
 (0)