1#![cfg_attr(
9 not(test),
10 deny(
11 clippy::indexing_slicing,
12 clippy::unwrap_used,
13 clippy::expect_used,
14 clippy::panic,
15 clippy::exhaustive_structs,
16 clippy::exhaustive_enums,
17 clippy::trivially_copy_pass_by_ref,
18 missing_debug_implementations,
19 )
20)]
21
22use core::mem;
23use proc_macro::TokenStream;
24use proc_macro2::{Span, TokenStream as TokenStream2};
25use quote::quote;
26use std::collections::{HashMap, HashSet};
27use syn::fold::{self, Fold};
28use syn::punctuated::Punctuated;
29use syn::spanned::Spanned;
30use syn::{
31 parse_macro_input, parse_quote, DeriveInput, Ident, Lifetime, MetaList, Token,
32 TraitBoundModifier, Type, TypeParamBound, TypePath, WherePredicate,
33};
34use synstructure::Structure;
35mod visitor;
36
37#[proc_macro_derive(ZeroFrom, attributes(zerofrom))]
53pub fn zf_derive(input: TokenStream) -> TokenStream {
54 let input = match ::syn::parse::<DeriveInput>(input) {
::syn::__private::Ok(data) => data,
::syn::__private::Err(err) => {
return ::syn::__private::TokenStream::from(err.to_compile_error());
}
}parse_macro_input!(input as DeriveInput);
55 TokenStream::from(zf_derive_impl(&input))
56}
57
58fn has_attr(attrs: &[syn::Attribute], name: &str) -> bool {
59 attrs.iter().any(|a| {
60 if let Ok(i) = a.parse_args::<Ident>() {
61 if i == name {
62 return true;
63 }
64 }
65 false
66 })
67}
68
69fn get_may_borrow_attr(attrs: &[syn::Attribute]) -> Result<HashSet<Ident>, Span> {
73 let mut params = HashSet::new();
74 for attr in attrs {
75 if let Ok(list) = attr.parse_args::<MetaList>() {
76 if list.path.is_ident("may_borrow") {
77 if let Ok(list) =
78 list.parse_args_with(Punctuated::<Ident, Token![,]>::parse_terminated)
79 {
80 params.extend(list)
81 } else {
82 return Err(attr.span());
83 }
84 }
85 }
86 }
87 Ok(params)
88}
89
90fn zf_derive_impl(input: &DeriveInput) -> TokenStream2 {
91 let mut tybounds = input
92 .generics
93 .type_params()
94 .map(|ty| {
95 let mut ty = ty.clone();
97 ty.eq_token = None;
98 ty.default = None;
99 ty
100 })
101 .collect::<Vec<_>>();
102 let typarams = tybounds
103 .iter()
104 .map(|ty| ty.ident.clone())
105 .collect::<Vec<_>>();
106 let lts = input.generics.lifetimes().count();
107 let name = &input.ident;
108 let structure = Structure::new(input);
109
110 let may_borrow_attrs = match get_may_borrow_attr(&input.attrs) {
111 Ok(mb) => mb,
112 Err(span) => {
113 return syn::Error::new(
114 span,
115 "#[zerofrom(may_borrow)] on the struct takes in a comma separated list of type parameters, like so: `#[zerofrom(may_borrow(A, B, C, D)]`",
116 ).to_compile_error();
117 }
118 };
119
120 let generics_env: HashMap<Ident, Option<Ident>> = tybounds
125 .iter_mut()
126 .map(|param| {
127 let maybe_new_param = if has_attr(¶m.attrs, "may_borrow")
129 || may_borrow_attrs.contains(¶m.ident)
130 {
131 let mut bounds = core::mem::take(&mut param.bounds);
134 while let Some(bound_pair) = bounds.pop() {
135 let bound = bound_pair.into_value();
136 if let TypeParamBound::Trait(ref trait_bound) = bound {
137 if trait_bound.path.get_ident().map(|ident| ident == "Sized") == Some(true)
138 && #[allow(non_exhaustive_omitted_patterns)] match trait_bound.modifier {
TraitBoundModifier::Maybe(_) => true,
_ => false,
}matches!(trait_bound.modifier, TraitBoundModifier::Maybe(_))
139 {
140 continue;
141 }
142 }
143 param.bounds.push(bound);
144 }
145 Some(Ident::new(
146 &::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}ZFParamC", param.ident))
})format!("{}ZFParamC", param.ident),
147 param.ident.span(),
148 ))
149 } else {
150 None
151 };
152 (param.ident.clone(), maybe_new_param)
153 })
154 .collect();
155
156 let generics_may_borrow = generics_env.values().any(|x| x.is_some());
158
159 if lts == 0 && !generics_may_borrow {
160 let has_clone = structure
161 .variants()
162 .iter()
163 .flat_map(|variant| variant.bindings().iter())
164 .any(|binding| has_attr(&binding.ast().attrs, "clone"));
165 let (clone, clone_trait) = if has_clone {
166 ({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "this");
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "clone");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
_s
}quote!(this.clone()), {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "Clone");
_s
}quote!(Clone))
167 } else {
168 ({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_star(&mut _s);
::quote::__private::push_ident(&mut _s, "this");
_s
}quote!(*this), {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "Copy");
_s
}quote!(Copy))
169 };
170 let bounds: Vec<WherePredicate> = typarams
171 .iter()
172 .map(|ty| ::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&ty, &mut _s);
::quote::__private::push_colon(&mut _s);
::quote::ToTokens::to_tokens(&clone_trait, &mut _s);
::quote::__private::push_add(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'static");
_s
})parse_quote!(#ty: #clone_trait + 'static))
173 .collect();
174 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "impl");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'zf");
::quote::__private::push_comma(&mut _s);
{
use ::quote::__private::ext::*;
let mut _i = 0usize;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut tybounds, i) = tybounds.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let tybounds =
match tybounds.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
if _i > 0 { ::quote::__private::push_comma(&mut _s); }
_i += 1;
::quote::ToTokens::to_tokens(&tybounds, &mut _s);
}
}
::quote::__private::push_gt(&mut _s);
::quote::__private::push_ident(&mut _s, "zerofrom");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ZeroFrom");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'zf");
::quote::__private::push_comma(&mut _s);
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::__private::push_lt(&mut _s);
{
use ::quote::__private::ext::*;
let mut _i = 0usize;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut typarams, i) = typarams.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let typarams =
match typarams.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
if _i > 0 { ::quote::__private::push_comma(&mut _s); }
_i += 1;
::quote::ToTokens::to_tokens(&typarams, &mut _s);
}
}
::quote::__private::push_shr(&mut _s);
::quote::__private::push_ident(&mut _s, "for");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::__private::push_lt(&mut _s);
{
use ::quote::__private::ext::*;
let mut _i = 0usize;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut typarams, i) = typarams.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let typarams =
match typarams.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
if _i > 0 { ::quote::__private::push_comma(&mut _s); }
_i += 1;
::quote::ToTokens::to_tokens(&typarams, &mut _s);
}
}
::quote::__private::push_gt(&mut _s);
::quote::__private::push_ident(&mut _s, "where");
{
use ::quote::__private::ext::*;
let mut _i = 0usize;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut bounds, i) = bounds.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let bounds =
match bounds.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
if _i > 0 { ::quote::__private::push_comma(&mut _s); }
_i += 1;
::quote::ToTokens::to_tokens(&bounds, &mut _s);
}
}
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "zero_from");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "this");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'zf");
::quote::__private::push_ident(&mut _s, "Self");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&clone, &mut _s);
_s
});
_s
});
_s
}quote! {
175 impl<'zf, #(#tybounds),*> zerofrom::ZeroFrom<'zf, #name<#(#typarams),*>> for #name<#(#typarams),*> where #(#bounds),* {
176 fn zero_from(this: &'zf Self) -> Self {
177 #clone
178 }
179 }
180 }
181 } else {
182 if lts > 1 {
183 return syn::Error::new(
184 input.generics.span(),
185 "derive(ZeroFrom) cannot have multiple lifetime parameters",
186 )
187 .to_compile_error();
188 }
189
190 let mut zf_bounds: Vec<WherePredicate> = ::alloc::vec::Vec::new()vec![];
191 let body = structure.each_variant(|vi| {
192 vi.construct(|f, i| {
193 let binding = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("__binding_{0}", i))
})format!("__binding_{i}");
194 let field = Ident::new(&binding, Span::call_site());
195
196 if has_attr(&f.attrs, "clone") {
197 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&field, &mut _s);
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "clone");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
_s
}quote! {
198 #field.clone()
199 }
200 } else {
201 let fty = replace_lifetime(&f.ty, custom_lt("'zf"));
203 let lifetime_ty =
205 replace_lifetime_and_type(&f.ty, custom_lt("'zf_inner"), &generics_env);
206
207 let (has_ty, has_lt) = visitor::check_type_for_parameters(&f.ty, &generics_env);
208 if has_ty {
209 if has_lt {
214 zf_bounds
215 .push(::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&fty, &mut _s);
::quote::__private::push_colon(&mut _s);
::quote::__private::push_ident(&mut _s, "zerofrom");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ZeroFrom");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'zf");
::quote::__private::push_comma(&mut _s);
::quote::ToTokens::to_tokens(&lifetime_ty, &mut _s);
::quote::__private::push_gt(&mut _s);
_s
})parse_quote!(#fty: zerofrom::ZeroFrom<'zf, #lifetime_ty>));
216 } else {
217 zf_bounds.push(::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&fty, &mut _s);
::quote::__private::push_colon(&mut _s);
::quote::__private::push_ident(&mut _s, "zerofrom");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ZeroFrom");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'zf");
::quote::__private::push_comma(&mut _s);
::quote::ToTokens::to_tokens(&fty, &mut _s);
::quote::__private::push_gt(&mut _s);
_s
})parse_quote!(#fty: zerofrom::ZeroFrom<'zf, #fty>));
218 }
219 }
220 if has_ty || has_lt {
221 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&fty, &mut _s);
::quote::__private::push_ident(&mut _s, "as");
::quote::__private::push_ident(&mut _s, "zerofrom");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ZeroFrom");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'zf");
::quote::__private::push_comma(&mut _s);
::quote::ToTokens::to_tokens(&lifetime_ty, &mut _s);
::quote::__private::push_shr(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "zero_from");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&field, &mut _s);
_s
});
_s
}quote! {
224 <#fty as zerofrom::ZeroFrom<'zf, #lifetime_ty>>::zero_from(#field)
225 }
226 } else {
227 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_star(&mut _s);
::quote::ToTokens::to_tokens(&field, &mut _s);
_s
}quote! { *#field }
229 }
230 }
231 })
232 });
233 let (maybe_zf_lifetime, maybe_zf_inner_lifetime) = if lts == 0 {
236 (::quote::__private::TokenStream::new()quote!(), ::quote::__private::TokenStream::new()quote!())
237 } else {
238 ({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_lifetime(&mut _s, "\'zf");
::quote::__private::push_comma(&mut _s);
_s
}quote!('zf,), {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_lifetime(&mut _s, "\'zf_inner");
::quote::__private::push_comma(&mut _s);
_s
}quote!('zf_inner,))
239 };
240
241 let mut typarams_c = typarams.clone();
243
244 if generics_may_borrow {
245 for typaram_c in &mut typarams_c {
246 if let Some(Some(replacement)) = generics_env.get(typaram_c) {
247 let typaram_t = mem::replace(typaram_c, replacement.clone());
249 zf_bounds
250 .push(::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&typaram_c, &mut _s);
::quote::__private::push_colon(&mut _s);
::quote::__private::push_ident(&mut _s, "zerofrom");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ZeroFrom");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'zf_inner");
::quote::__private::push_comma(&mut _s);
::quote::ToTokens::to_tokens(&typaram_t, &mut _s);
::quote::__private::push_gt(&mut _s);
_s
})parse_quote!(#typaram_c: zerofrom::ZeroFrom<'zf_inner, #typaram_t>));
251 tybounds.push(::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&typaram_c, &mut _s);
_s
})parse_quote!(#typaram_c));
252 }
253 }
254 }
255
256 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "impl");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'zf");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'zf_inner");
::quote::__private::push_comma(&mut _s);
{
use ::quote::__private::ext::*;
let mut _i = 0usize;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut tybounds, i) = tybounds.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let tybounds =
match tybounds.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
if _i > 0 { ::quote::__private::push_comma(&mut _s); }
_i += 1;
::quote::ToTokens::to_tokens(&tybounds, &mut _s);
}
}
::quote::__private::push_gt(&mut _s);
::quote::__private::push_ident(&mut _s, "zerofrom");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ZeroFrom");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'zf");
::quote::__private::push_comma(&mut _s);
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&maybe_zf_inner_lifetime, &mut _s);
{
use ::quote::__private::ext::*;
let mut _i = 0usize;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut typarams_c, i) = typarams_c.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let typarams_c =
match typarams_c.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
if _i > 0 { ::quote::__private::push_comma(&mut _s); }
_i += 1;
::quote::ToTokens::to_tokens(&typarams_c, &mut _s);
}
}
::quote::__private::push_shr(&mut _s);
::quote::__private::push_ident(&mut _s, "for");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&maybe_zf_lifetime, &mut _s);
{
use ::quote::__private::ext::*;
let mut _i = 0usize;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut typarams, i) = typarams.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let typarams =
match typarams.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
if _i > 0 { ::quote::__private::push_comma(&mut _s); }
_i += 1;
::quote::ToTokens::to_tokens(&typarams, &mut _s);
}
}
::quote::__private::push_gt(&mut _s);
::quote::__private::push_ident(&mut _s, "where");
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut zf_bounds, i) = zf_bounds.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let zf_bounds =
match zf_bounds.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&zf_bounds, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "zero_from");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "this");
::quote::__private::push_colon(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'zf");
::quote::ToTokens::to_tokens(&name, &mut _s);
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&maybe_zf_inner_lifetime,
&mut _s);
{
use ::quote::__private::ext::*;
let mut _i = 0usize;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut typarams_c, i) = typarams_c.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let typarams_c =
match typarams_c.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
if _i > 0 { ::quote::__private::push_comma(&mut _s); }
_i += 1;
::quote::ToTokens::to_tokens(&typarams_c, &mut _s);
}
}
::quote::__private::push_gt(&mut _s);
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "match");
::quote::__private::push_star(&mut _s);
::quote::__private::push_ident(&mut _s, "this");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&body, &mut _s);
_s
});
_s
});
_s
});
_s
}quote! {
257 impl<'zf, 'zf_inner, #(#tybounds),*> zerofrom::ZeroFrom<'zf, #name<#maybe_zf_inner_lifetime #(#typarams_c),*>> for #name<#maybe_zf_lifetime #(#typarams),*>
258 where
259 #(#zf_bounds,)* {
260 fn zero_from(this: &'zf #name<#maybe_zf_inner_lifetime #(#typarams_c),*>) -> Self {
261 match *this { #body }
262 }
263 }
264 }
265 }
266}
267
268fn custom_lt(s: &str) -> Lifetime {
269 Lifetime::new(s, Span::call_site())
270}
271
272fn replace_lifetime(x: &Type, lt: Lifetime) -> Type {
274 struct ReplaceLifetime(Lifetime);
275
276 impl Fold for ReplaceLifetime {
277 fn fold_lifetime(&mut self, _: Lifetime) -> Lifetime {
278 self.0.clone()
279 }
280 }
281 ReplaceLifetime(lt).fold_type(x.clone())
282}
283
284fn replace_lifetime_and_type(
287 x: &Type,
288 lt: Lifetime,
289 generics_env: &HashMap<Ident, Option<Ident>>,
290) -> Type {
291 struct ReplaceLifetimeAndTy<'a>(Lifetime, &'a HashMap<Ident, Option<Ident>>);
292
293 impl Fold for ReplaceLifetimeAndTy<'_> {
294 fn fold_lifetime(&mut self, _: Lifetime) -> Lifetime {
295 self.0.clone()
296 }
297 fn fold_type_path(&mut self, i: TypePath) -> TypePath {
298 if i.qself.is_none() {
299 if let Some(ident) = i.path.get_ident() {
300 if let Some(Some(replacement)) = self.1.get(ident) {
301 return ::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&replacement, &mut _s);
_s
})parse_quote!(#replacement);
302 }
303 }
304 }
305 fold::fold_type_path(self, i)
306 }
307 }
308 ReplaceLifetimeAndTy(lt, generics_env).fold_type(x.clone())
309}