rental_impl/
lib.rs

1#![recursion_limit = "512"]
2
3extern crate proc_macro;
4extern crate proc_macro2;
5#[macro_use]
6extern crate syn;
7#[macro_use]
8extern crate quote;
9
10use std::iter::{self, FromIterator};
11use syn::spanned::Spanned;
12use syn::visit::Visit;
13use syn::fold::Fold;
14use quote::ToTokens;
15use proc_macro2::Span;
16
17
18/// From `procedural_masquerade` crate
19#[doc(hidden)]
20fn _extract_input(derive_input: &str) -> &str {
21	let mut input = derive_input;
22
23	for expected in &["#[allow(unused)]", "enum", "ProceduralMasqueradeDummyType", "{", "Input", "=", "(0,", "stringify!", "("] {
24		input = input.trim_start();
25		assert!(input.starts_with(expected), "expected prefix {:?} not found in {:?}", expected, derive_input);
26		input = &input[expected.len()..];
27	}
28
29	for expected in [")", ").0,", "}"].iter().rev() {
30		input = input.trim_end();
31		assert!(input.ends_with(expected), "expected suffix {:?} not found in {:?}", expected, derive_input);
32		let end = input.len() - expected.len();
33		input = &input[..end];
34	}
35
36	input
37}
38
39
40#[doc(hidden)]
41#[allow(non_snake_case)]
42#[proc_macro_derive(__rental_traits)]
43pub fn __rental_traits(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
44	let mut tokens = proc_macro2::TokenStream::new();
45
46	let max_arity = _extract_input(&input.to_string()).parse::<usize>().expect("Input must be an integer literal.");
47	write_rental_traits(&mut tokens, max_arity);
48
49	tokens.into()
50}
51
52
53#[doc(hidden)]
54#[allow(non_snake_case)]
55#[proc_macro_derive(__rental_structs_and_impls)]
56pub fn __rental_structs_and_impls(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
57	let mut tokens = proc_macro2::TokenStream::new();
58
59	for item in syn::parse_str::<syn::File>(_extract_input(&input.to_string())).expect("Failed to parse items in module body.").items.iter() {
60		match *item {
61			syn::Item::Use(..) => {
62				item.to_tokens(&mut tokens);
63			},
64			syn::Item::Type(..) => {
65				item.to_tokens(&mut tokens);
66			},
67			syn::Item::Struct(ref struct_info) => {
68				write_rental_struct_and_impls(&mut tokens, &struct_info);
69			},
70			_ => panic!("Item must be a `use` or `struct`."),
71		}
72	}
73
74	tokens.into()
75}
76
77
78fn write_rental_traits(tokens: &mut proc_macro2::TokenStream, max_arity: usize) {
79	let call_site: Span = Span::call_site();
80
81	let mut lt_params = vec![syn::LifetimeDef::new(syn::Lifetime::new("'a0", call_site))];
82
83	for arity in 2 .. max_arity + 1 {
84		let trait_ident = &syn::Ident::new(&format!("Rental{}", arity), call_site);
85		let lt_param = syn::LifetimeDef::new(syn::Lifetime::new(&format!("'a{}", arity - 1), call_site));
86		lt_params[arity - 2].bounds.push(lt_param.lifetime.clone());
87		lt_params.push(lt_param);
88
89		let lt_params_iter = &lt_params;
90		quote!(
91			#[doc(hidden)]
92			pub unsafe trait #trait_ident<#(#lt_params_iter),*> {
93				type Borrow;
94				type BorrowMut;
95			}
96		).to_tokens(tokens);
97	}
98}
99
100
101fn write_rental_struct_and_impls(tokens: &mut proc_macro2::TokenStream, struct_info: &syn::ItemStruct) {
102	let def_site: Span = Span::call_site(); // FIXME: hygiene
103	let call_site: Span = Span::call_site();
104
105	if let syn::Visibility::Inherited = struct_info.vis {
106		panic!("Struct `{}` must be non-private.", struct_info.ident);
107	}
108
109	let attribs = get_struct_attribs(struct_info);
110	let (fields, fields_brace) = prepare_fields(struct_info);
111
112	let struct_generics = &struct_info.generics;
113	let struct_rlt_args = &fields.iter().fold(Vec::new(), |mut rlt_args, field| { rlt_args.extend(field.self_rlt_args.iter()); rlt_args });
114	if let Some(collide) = struct_rlt_args.iter().find(|rlt_arg| struct_generics.lifetimes().any(|lt_def| lt_def.lifetime == ***rlt_arg)) {
115		panic!("Struct `{}` lifetime parameter `{}` collides with rental lifetime.", struct_info.ident, collide);
116	}
117	let last_rlt_arg = &struct_rlt_args[struct_rlt_args.len() - 1];
118	let static_rlt_args = &iter::repeat(syn::Lifetime::new("'static", def_site)).take(struct_rlt_args.len()).collect::<Vec<_>>();
119	let self_rlt_args = &iter::repeat(syn::Lifetime::new("'__s", def_site)).take(struct_rlt_args.len()).collect::<Vec<_>>();
120
121	let item_ident = &struct_info.ident;
122	let item_vis = &struct_info.vis;
123	let item_ident_str = syn::LitStr::new(&item_ident.to_string(), item_ident.span());
124
125	let (struct_impl_params, struct_impl_args, struct_where_clause) = struct_generics.split_for_impl();
126	let where_extra = if let Some(ref struct_where_clause) = struct_where_clause {
127		if struct_where_clause.predicates.is_empty() {
128			quote!(where)
129		} else if struct_where_clause.predicates.trailing_punct() {
130			quote!()
131		} else {
132			quote!(,)
133		}
134	} else {
135		quote!(where)
136	};
137	let struct_lt_params = &struct_generics.lifetimes().collect::<Vec<_>>();
138	let struct_nonlt_params = &struct_generics.params.iter().filter(|param| if let syn::GenericParam::Lifetime(..) = **param { false } else { true }).collect::<Vec<_>>();
139	let struct_lt_args = &struct_lt_params.iter().map(|lt_def| &lt_def.lifetime).collect::<Vec<_>>();
140
141	let struct_nonlt_args = &struct_nonlt_params.iter().map(|param| match **param {
142		syn::GenericParam::Type(ref ty) => &ty.ident,
143		syn::GenericParam::Const(ref co) => &co.ident,
144		syn::GenericParam::Lifetime(..) => unreachable!(),
145	}).collect::<Vec<_>>();
146
147	let rental_trait_ident = syn::Ident::new(&format!("Rental{}", struct_rlt_args.len()), def_site);
148	let field_idents = &fields.iter().map(|field| &field.name).collect::<Vec<_>>();
149	let local_idents = field_idents;
150	let field_ident_strs = &field_idents.iter().map(|ident| syn::LitStr::new(&ident.to_string(), ident.span())).collect::<Vec<_>>();
151
152	let (ref self_ref_param, ref self_lt_ref_param, ref self_mut_param, ref self_move_param, ref self_arg) = if attribs.is_deref_suffix {
153		(quote!(_self: &Self), quote!(_self: &'__s Self),  quote!(_self: &mut Self), quote!(_self: Self), quote!(_self))
154	} else {
155		(quote!(&self), quote!(&'__s self), quote!(&mut self), quote!(self), quote!(self))
156	};
157
158	let borrow_ident = syn::Ident::new(&(struct_info.ident.to_string() + "_Borrow"), call_site);
159	let borrow_mut_ident = syn::Ident::new(&(struct_info.ident.to_string() + "_BorrowMut"), call_site);
160	let borrow_quotes = &make_borrow_quotes(self_arg, &fields, attribs.is_rental_mut);
161	let borrow_tys = &borrow_quotes.iter().map(|&BorrowQuotes{ref ty, ..}| ty).collect::<Vec<_>>();
162	let borrow_ty_hacks = &borrow_quotes.iter().map(|&BorrowQuotes{ref ty_hack, ..}| ty_hack).collect::<Vec<_>>();
163	let borrow_suffix_ty = &borrow_tys[fields.len() - 1];
164	let borrow_exprs = &borrow_quotes.iter().map(|&BorrowQuotes{ref expr, ..}| expr).collect::<Vec<_>>();
165	let borrow_suffix_expr = &borrow_exprs[fields.len() - 1];
166	let borrow_mut_tys = &borrow_quotes.iter().map(|&BorrowQuotes{ref mut_ty, ..}| mut_ty).collect::<Vec<_>>();
167	let borrow_mut_ty_hacks = &borrow_quotes.iter().map(|&BorrowQuotes{ref mut_ty_hack, ..}| mut_ty_hack).collect::<Vec<_>>();
168	let borrow_mut_suffix_ty = &borrow_mut_tys[fields.len() - 1];
169	let borrow_mut_exprs = &borrow_quotes.iter().map(|&BorrowQuotes{ref mut_expr, ..}| mut_expr).collect::<Vec<_>>();
170	let borrow_mut_suffix_expr = &borrow_mut_exprs[fields.len() - 1];
171
172	let struct_rlt_params = &struct_rlt_args.iter().zip(struct_rlt_args.iter().skip(1)).map(|(rlt_arg, next_rlt_arg)| {
173		syn::LifetimeDef {
174			attrs: Vec::with_capacity(0),
175			lifetime: (*rlt_arg).clone(),
176			bounds: vec![(*next_rlt_arg).clone()].into_iter().collect(),
177			colon_token: Default::default(),
178		}
179	}).chain(Some(syn::LifetimeDef {
180			attrs: Vec::with_capacity(0),
181			lifetime: struct_rlt_args[struct_rlt_args.len() - 1].clone(),
182			bounds: syn::punctuated::Punctuated::new(),
183			colon_token: Default::default(),
184	})).collect::<Vec<_>>();
185
186	let borrow_lt_params = &struct_rlt_params.iter().cloned()
187		.chain( struct_lt_params.iter().map(|lt_def| {
188			let mut lt_def = (*lt_def).clone();
189			lt_def.bounds.push(struct_rlt_args[0].clone());
190			lt_def
191		})).collect::<Vec<_>>();
192
193	let field_tys = &fields.iter().map(|field| &field.erased.ty).collect::<Vec<_>>();
194	let head_ident = &local_idents[0];
195	let head_ident_rep = &iter::repeat(&head_ident).take(fields.len() - 1).collect::<Vec<_>>();
196	let head_ty = &fields[0].orig_ty;
197	let tail_tys = &field_tys.iter().skip(1).collect::<Vec<_>>();
198	let tail_idents = &local_idents.iter().skip(1).collect::<Vec<_>>();
199	let tail_closure_tys = &fields.iter().skip(1).map(|field| syn::Ident::new(&format!("__F{}", field.name), call_site)).collect::<Vec<_>>();
200	let tail_closure_quotes = make_tail_closure_quotes(&fields, borrow_quotes, attribs.is_rental_mut);
201	let tail_closure_bounds = &tail_closure_quotes.iter().map(|&ClosureQuotes{ref bound, ..}| bound).collect::<Vec<_>>();
202	let tail_closure_exprs = &tail_closure_quotes.iter().map(|&ClosureQuotes{ref expr, ..}| expr).collect::<Vec<_>>();
203	let tail_try_closure_bounds = &tail_closure_quotes.iter().map(|&ClosureQuotes{ref try_bound, ..}| try_bound).collect::<Vec<_>>();
204	let tail_try_closure_exprs = &tail_closure_quotes.iter().map(|&ClosureQuotes{ref try_expr, ..}| try_expr).collect::<Vec<_>>();
205	let suffix_ident = &field_idents[fields.len() - 1];
206	let suffix_ty = &fields[fields.len() - 1].erased.ty;
207	let suffix_rlt_args = &fields[fields.len() - 1].self_rlt_args.iter().chain(fields[fields.len() - 1].used_rlt_args.iter()).collect::<Vec<_>>();
208	let suffix_ident_str = syn::LitStr::new(&suffix_ident.to_string(), suffix_ident.span());
209	let suffix_orig_ty = &fields[fields.len() - 1].orig_ty;
210
211	let rstruct = syn::ItemStruct{
212		ident: struct_info.ident.clone(),
213		vis: item_vis.clone(),
214		attrs: attribs.doc.clone(),
215		fields: syn::Fields::Named(syn::FieldsNamed{
216			brace_token: fields_brace,
217			named: fields.iter().enumerate().map(|(i, field)| {
218				let mut field_erased = field.erased.clone();
219				if i < fields.len() - 1 {
220					field_erased.attrs.push(parse_quote!(#[allow(dead_code)]));
221				}
222				field_erased
223			}).rev().collect(),
224		}),
225		generics: struct_info.generics.clone(),
226		struct_token: struct_info.struct_token,
227		semi_token: None,
228	};
229
230	let borrow_struct = syn::ItemStruct{
231		ident: borrow_ident.clone(),
232		vis: item_vis.clone(),
233		attrs: Vec::with_capacity(0),
234		fields: syn::Fields::Named(syn::FieldsNamed{
235			brace_token: Default::default(),
236			named: fields.iter().zip(borrow_tys).enumerate().map(|(idx, (field, borrow_ty))| {
237				let mut field = field.erased.clone();
238				field.vis = if !attribs.is_rental_mut || idx == fields.len() - 1 { item_vis.clone() } else { syn::Visibility::Inherited };
239				field.ty = syn::parse::<syn::Type>((**borrow_ty).clone().into()).unwrap();
240				field
241			}).collect(),
242		}),
243		generics: {
244			let mut gen = struct_generics.clone();
245			let params = borrow_lt_params.iter().map(|lt| syn::GenericParam::Lifetime(lt.clone()))
246				.chain(gen.type_params().map(|p| syn::GenericParam::Type(p.clone())))
247				.chain(gen.const_params().map(|p| syn::GenericParam::Const(p.clone())))
248				.collect();
249			gen.params = params;
250			gen
251		},
252		struct_token: Default::default(),
253		semi_token: None,
254	};
255
256	let borrow_mut_struct = syn::ItemStruct{
257		ident: borrow_mut_ident.clone(),
258		vis: item_vis.clone(),
259		attrs: Vec::with_capacity(0),
260		fields: syn::Fields::Named(syn::FieldsNamed{
261			brace_token: Default::default(),
262			named: fields.iter().zip(borrow_mut_tys).enumerate().map(|(idx, (field, borrow_mut_ty))| {
263				let mut field = field.erased.clone();
264				field.vis = if idx == fields.len() - 1 || !attribs.is_rental_mut { (*item_vis).clone() } else { syn::Visibility::Inherited };
265				field.ty = syn::parse::<syn::Type>((**borrow_mut_ty).clone().into()).unwrap();
266				field
267			}).collect(),
268		}),
269		generics: {
270			let mut gen = struct_generics.clone();
271			let params = borrow_lt_params.iter().map(|lt| syn::GenericParam::Lifetime(lt.clone()))
272				.chain(gen.type_params().map(|p| syn::GenericParam::Type(p.clone())))
273				.chain(gen.const_params().map(|p| syn::GenericParam::Const(p.clone())))
274				.collect();
275			gen.params = params;
276			gen
277		},
278		struct_token: Default::default(),
279		semi_token: None,
280	};
281
282	let prefix_tys = &fields.iter().map(|field| &field.erased.ty).take(fields.len() - 1).collect::<Vec<_>>();
283	let static_assert_prefix_stable_derefs = &prefix_tys.iter().map(|field| {
284		if attribs.is_rental_mut {
285			quote_spanned!(field.span()/*.resolved_at(def_site)*/ => __rental_prelude::static_assert_mut_stable_deref::<#field>();)
286		} else {
287			quote_spanned!(field.span()/*.resolved_at(def_site)*/ => __rental_prelude::static_assert_stable_deref::<#field>();)
288		}
289	}).collect::<Vec<_>>();
290	let prefix_clone_traits = iter::repeat(quote!(__rental_prelude::CloneStableDeref)).take(prefix_tys.len());
291
292	let struct_span = struct_info.span()/*.resolved_at(def_site)*/;
293	let suffix_ty_span = suffix_ty.span()/*.resolved_at(def_site)*/;
294
295	quote_spanned!(struct_span =>
296		#rstruct
297
298		/// Shared borrow of a rental struct.
299		#[allow(non_camel_case_types, non_snake_case, dead_code)]
300		#borrow_struct
301
302		/// Mutable borrow of a rental struct.
303		#[allow(non_camel_case_types, non_snake_case, dead_code)]
304		#borrow_mut_struct
305	).to_tokens(tokens);
306
307	quote_spanned!(struct_span =>
308		#[allow(dead_code)]
309		impl<#(#borrow_lt_params,)* #(#struct_nonlt_params),*> #borrow_ident<#(#struct_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*> #struct_where_clause {
310			fn unify_tys_hack(#(#local_idents: #borrow_ty_hacks),*) -> #borrow_ident<#(#struct_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*> {
311				#borrow_ident {
312					#(#field_idents: #local_idents,)*
313				}
314			}
315		}
316	).to_tokens(tokens);
317
318	quote_spanned!(struct_span =>
319		#[allow(dead_code)]
320		impl<#(#borrow_lt_params,)* #(#struct_nonlt_params),*> #borrow_mut_ident<#(#struct_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*> #struct_where_clause {
321			fn unify_tys_hack(#(#local_idents: #borrow_mut_ty_hacks),*) -> #borrow_mut_ident<#(#struct_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*> {
322				#borrow_mut_ident {
323					#(#field_idents: #local_idents,)*
324				}
325			}
326		}
327	).to_tokens(tokens);
328
329	quote_spanned!(struct_span =>
330		unsafe impl<#(#borrow_lt_params,)* #(#struct_nonlt_params),*> __rental_prelude::#rental_trait_ident<#(#struct_rlt_args),*> for #item_ident #struct_impl_args #struct_where_clause {
331			type Borrow = #borrow_ident<#(#struct_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*>;
332			type BorrowMut = #borrow_mut_ident<#(#struct_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*>;
333		}
334	).to_tokens(tokens);
335
336	quote_spanned!(struct_span =>
337		#[allow(dead_code, unused_mut, unused_unsafe, non_camel_case_types)]
338		impl #struct_impl_params #item_ident #struct_impl_args #struct_where_clause {
339			/// Create a new instance of the rental struct.
340			///
341			/// The first argument provided is the head, followed by a series of closures, one for each tail field. Each of these closures will receive, as its arguments, a borrow of the previous field, followed by borrows of the remaining prefix fields if the struct is a shared rental. If the struct is a mutable rental, only the immediately preceding field is passed.
342			pub fn new<#(#tail_closure_tys),*>(
343				mut #head_ident: #head_ty,
344				#(#tail_idents: #tail_closure_tys),*
345			) -> Self where #(#tail_closure_tys: #tail_closure_bounds),*
346			{
347				#(#static_assert_prefix_stable_derefs)*
348
349				#(let mut #tail_idents = unsafe { __rental_prelude::transmute::<_, #tail_tys>(#tail_closure_exprs) };)*
350
351				#item_ident {
352					#(#field_idents: #local_idents,)*
353				}
354			}
355
356			/// Attempt to create a new instance of the rental struct.
357			///
358			/// As `new`, but each closure returns a `Result`. If one of them fails, execution is short-circuited and a tuple of the error and the original head value is returned to you.
359			pub fn try_new<#(#tail_closure_tys,)* __E>(
360				mut #head_ident: #head_ty,
361				#(#tail_idents: #tail_closure_tys),*
362			) -> __rental_prelude::RentalResult<Self, __E, #head_ty> where
363				#(#tail_closure_tys: #tail_try_closure_bounds,)*
364			{
365				#(#static_assert_prefix_stable_derefs)*
366
367				#(let mut #tail_idents = {
368					let temp = #tail_try_closure_exprs.map(|t| unsafe { __rental_prelude::transmute::<_, #tail_tys>(t) });
369					match temp {
370						__rental_prelude::Result::Ok(t) => t,
371						__rental_prelude::Result::Err(e) => return __rental_prelude::Result::Err(__rental_prelude::RentalError(e.into(), #head_ident_rep)),
372					}
373				};)*
374
375				__rental_prelude::Result::Ok(#item_ident {
376					#(#field_idents: #local_idents,)*
377				})
378			}
379
380			/// Attempt to create a new instance of the rental struct.
381			///
382			/// As `try_new`, but only the error value is returned upon failure; the head value is dropped. This method interacts more smoothly with existing error conversions.
383			pub fn try_new_or_drop<#(#tail_closure_tys,)* __E>(
384				mut #head_ident: #head_ty,
385				#(#tail_idents: #tail_closure_tys),*
386			) -> __rental_prelude::Result<Self, __E> where
387				#(#tail_closure_tys: #tail_try_closure_bounds,)*
388			{
389				#(#static_assert_prefix_stable_derefs)*
390
391				#(let mut #tail_idents = {
392					let temp = #tail_try_closure_exprs.map(|t| unsafe { __rental_prelude::transmute::<_, #tail_tys>(t) });
393					match temp {
394						__rental_prelude::Result::Ok(t) => t,
395						__rental_prelude::Result::Err(e) => return __rental_prelude::Result::Err(e.into()),
396					}
397				};)*
398
399				__rental_prelude::Result::Ok(#item_ident {
400					#(#field_idents: #local_idents,)*
401				})
402			}
403
404			/// Return lifetime-erased shared borrows of the fields of the struct.
405			///
406			/// This is unsafe because the erased lifetimes are fake. Use this only if absolutely necessary and be very mindful of what the true lifetimes are.
407			pub unsafe fn all_erased(#self_ref_param) -> <Self as __rental_prelude::#rental_trait_ident>::Borrow {
408				#borrow_ident::unify_tys_hack(#(__rental_prelude::transmute(#borrow_exprs),)*)
409			}
410
411			/// Return a lifetime-erased mutable borrow of the suffix of the struct.
412			///
413			/// This is unsafe because the erased lifetimes are fake. Use this only if absolutely necessary and be very mindful of what the true lifetimes are.
414			pub unsafe fn all_mut_erased(#self_mut_param) -> <Self as __rental_prelude::#rental_trait_ident>::BorrowMut {
415				#borrow_mut_ident::unify_tys_hack(#(__rental_prelude::transmute(#borrow_mut_exprs),)*)
416			}
417
418			/// Execute a closure on the shared suffix of the struct.
419			///
420			/// The closure may return any value not bounded by one of the special rental lifetimes of the struct.
421			pub fn rent<__F, __R>(#self_ref_param, f: __F) -> __R where
422				__F: for<#(#suffix_rlt_args,)*> __rental_prelude::FnOnce(#borrow_suffix_ty) -> __R,
423				__R: #(#struct_lt_args +)*,
424			{
425				f(#borrow_suffix_expr)
426			}
427
428			/// Execute a closure on the mutable suffix of the struct.
429			///
430			/// The closure may return any value not bounded by one of the special rental lifetimes of the struct.
431			pub fn rent_mut<__F, __R>(#self_mut_param, f: __F) -> __R where
432				__F: for<#(#suffix_rlt_args,)*> __rental_prelude::FnOnce(#borrow_mut_suffix_ty) -> __R,
433				__R: #(#struct_lt_args +)*,
434			{
435				f(#borrow_mut_suffix_expr)
436			}
437
438			/// Return a shared reference from the shared suffix of the struct.
439			///
440			/// This is a subtle variation of `rent` where it is legal to return a reference bounded by a rental lifetime, because that lifetime is reborrowed away before it is returned to you.
441			pub fn ref_rent<__F, __R>(#self_ref_param, f: __F) -> &__R where
442				__F: for<#(#suffix_rlt_args,)*> __rental_prelude::FnOnce(#borrow_suffix_ty) -> &#last_rlt_arg __R,
443				__R: ?Sized //#(#struct_lt_args +)*,
444			{
445				f(#borrow_suffix_expr)
446			}
447
448			/// Optionally return a shared reference from the shared suffix of the struct.
449			///
450			/// This is a subtle variation of `rent` where it is legal to return a reference bounded by a rental lifetime, because that lifetime is reborrowed away before it is returned to you.
451			pub fn maybe_ref_rent<__F, __R>(#self_ref_param, f: __F) -> __rental_prelude::Option<&__R> where
452				__F: for<#(#suffix_rlt_args,)*> __rental_prelude::FnOnce(#borrow_suffix_ty) -> __rental_prelude::Option<&#last_rlt_arg __R>,
453				__R: ?Sized //#(#struct_lt_args +)*,
454			{
455				f(#borrow_suffix_expr)
456			}
457
458			/// Try to return a shared reference from the shared suffix of the struct, or an error on failure.
459			///
460			/// This is a subtle variation of `rent` where it is legal to return a reference bounded by a rental lifetime, because that lifetime is reborrowed away before it is returned to you.
461			pub fn try_ref_rent<__F, __R, __E>(#self_ref_param, f: __F) -> __rental_prelude::Result<&__R, __E> where
462				__F: for<#(#suffix_rlt_args,)*> __rental_prelude::FnOnce(#borrow_suffix_ty) -> __rental_prelude::Result<&#last_rlt_arg __R, __E>,
463				__R: ?Sized //#(#struct_lt_args +)*,
464			{
465				f(#borrow_suffix_expr)
466			}
467
468			/// Return a mutable reference from the mutable suffix of the struct.
469			///
470			/// This is a subtle variation of `rent_mut` where it is legal to return a reference bounded by a rental lifetime, because that lifetime is reborrowed away before it is returned to you.
471			pub fn ref_rent_mut<__F, __R>(#self_mut_param, f: __F) -> &mut __R where
472				__F: for<#(#suffix_rlt_args,)*> __rental_prelude::FnOnce(#borrow_mut_suffix_ty) -> &#last_rlt_arg  mut __R,
473				__R: ?Sized //#(#struct_lt_args +)*,
474			{
475				f(#borrow_mut_suffix_expr)
476			}
477
478			/// Optionally return a mutable reference from the mutable suffix of the struct.
479			///
480			/// This is a subtle variation of `rent_mut` where it is legal to return a reference bounded by a rental lifetime, because that lifetime is reborrowed away before it is returned to you.
481			pub fn maybe_ref_rent_mut<__F, __R>(#self_mut_param, f: __F) -> __rental_prelude::Option<&mut __R> where
482				__F: for<#(#suffix_rlt_args,)*> __rental_prelude::FnOnce(#borrow_mut_suffix_ty) -> __rental_prelude::Option<&#last_rlt_arg  mut __R>,
483				__R: ?Sized //#(#struct_lt_args +)*,
484			{
485				f(#borrow_mut_suffix_expr)
486			}
487
488			/// Try to return a mutable reference from the mutable suffix of the struct, or an error on failure.
489			///
490			/// This is a subtle variation of `rent_mut` where it is legal to return a reference bounded by a rental lifetime, because that lifetime is reborrowed away before it is returned to you.
491			pub fn try_ref_rent_mut<__F, __R, __E>(#self_mut_param, f: __F) -> __rental_prelude::Result<&mut __R, __E> where
492				__F: for<#(#suffix_rlt_args,)*> __rental_prelude::FnOnce(#borrow_mut_suffix_ty) -> __rental_prelude::Result<&#last_rlt_arg  mut __R, __E>,
493				__R: ?Sized //#(#struct_lt_args +)*,
494			{
495				f(#borrow_mut_suffix_expr)
496			}
497
498			/// Drop the rental struct and return the original head value to you.
499			pub fn into_head(#self_move_param) -> #head_ty {
500				let Self{#head_ident, ..} = #self_arg;
501				#head_ident
502			}
503		}
504	).to_tokens(tokens);
505
506	if !attribs.is_rental_mut {
507		quote_spanned!(struct_span =>
508			#[allow(dead_code)]
509			impl #struct_impl_params #item_ident #struct_impl_args #struct_where_clause {
510				/// Return a shared reference to the head field of the struct.
511				pub fn head(#self_ref_param) -> &<#head_ty as __rental_prelude::Deref>::Target {
512					&*#self_arg.#head_ident
513				}
514
515				/// Execute a closure on shared borrows of the fields of the struct.
516				///
517				/// The closure may return any value not bounded by one of the special rental lifetimes of the struct.
518				pub fn rent_all<__F, __R>(#self_ref_param, f: __F) -> __R where
519					__F: for<#(#struct_rlt_args,)*> __rental_prelude::FnOnce(#borrow_ident<#(#struct_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*>) -> __R,
520					__R: #(#struct_lt_args +)*,
521				{
522					f(unsafe { #item_ident::all_erased(#self_arg) })
523				}
524
525				/// Return a shared reference from shared borrows of the fields of the struct.
526				///
527				/// This is a subtle variation of `rent_all` where it is legal to return a reference bounded by a rental lifetime, because that lifetime is reborrowed away before it is returned to you.
528				pub fn ref_rent_all<__F, __R>(#self_ref_param, f: __F) -> &__R where
529					__F: for<#(#struct_rlt_args,)*> __rental_prelude::FnOnce(#borrow_ident<#(#struct_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*>) -> &#last_rlt_arg __R,
530					__R: ?Sized //#(#struct_lt_args +)*,
531				{
532					f(unsafe { #item_ident::all_erased(#self_arg) })
533				}
534
535				/// Optionally return a shared reference from shared borrows of the fields of the struct.
536				///
537				/// This is a subtle variation of `rent_all` where it is legal to return a reference bounded by a rental lifetime, because that lifetime is reborrowed away before it is returned to you.
538				pub fn maybe_ref_rent_all<__F, __R>(#self_ref_param, f: __F) -> __rental_prelude::Option<&__R> where
539					__F: for<#(#struct_rlt_args,)*> __rental_prelude::FnOnce(#borrow_ident<#(#struct_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*>) -> __rental_prelude::Option<&#last_rlt_arg __R>,
540					__R: ?Sized //#(#struct_lt_args +)*,
541				{
542					f(unsafe { #item_ident::all_erased(#self_arg) })
543				}
544
545				/// Try to return a shared reference from shared borrows of the fields of the struct, or an error on failure.
546				///
547				/// This is a subtle variation of `rent_all` where it is legal to return a reference bounded by a rental lifetime, because that lifetime is reborrowed away before it is returned to you.
548				pub fn try_ref_rent_all<__F, __R, __E>(#self_ref_param, f: __F) -> __rental_prelude::Result<&__R, __E> where
549					__F: for<#(#struct_rlt_args,)*> __rental_prelude::FnOnce(#borrow_ident<#(#struct_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*>) -> __rental_prelude::Result<&#last_rlt_arg __R, __E>,
550					__R: ?Sized //#(#struct_lt_args +)*,
551				{
552					f(unsafe { #item_ident::all_erased(#self_arg) })
553				}
554
555				/// Execute a closure on shared borrows of the prefix fields and a mutable borrow of the suffix field of the struct.
556				///
557				/// The closure may return any value not bounded by one of the special rental lifetimes of the struct.
558				pub fn rent_all_mut<__F, __R>(#self_mut_param, f: __F) -> __R where
559					__F: for<#(#struct_rlt_args,)*> __rental_prelude::FnOnce(#borrow_mut_ident<#(#struct_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*>) -> __R,
560					__R: #(#struct_lt_args +)*,
561				{
562					f(unsafe { #item_ident::all_mut_erased(#self_arg) })
563				}
564
565				/// Return a mutable reference from shared borrows of the prefix fields and a mutable borrow of the suffix field of the struct.
566				///
567				/// This is a subtle variation of `rent_all_mut` where it is legal to return a reference bounded by a rental lifetime, because that lifetime is reborrowed away before it is returned to you.
568				pub fn ref_rent_all_mut<__F, __R>(#self_mut_param, f: __F) -> &mut __R where
569					__F: for<#(#struct_rlt_args,)*> __rental_prelude::FnOnce(#borrow_mut_ident<#(#struct_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*>) -> &#last_rlt_arg mut __R,
570					__R: ?Sized //#(#struct_lt_args +)*,
571				{
572					f(unsafe { #item_ident::all_mut_erased(#self_arg) })
573				}
574
575				/// Optionally return a mutable reference from shared borrows of the prefix fields and a mutable borrow of the suffix field of the struct.
576				///
577				/// This is a subtle variation of `rent_all_mut` where it is legal to return a reference bounded by a rental lifetime, because that lifetime is reborrowed away before it is returned to you.
578				pub fn maybe_ref_rent_all_mut<__F, __R>(#self_mut_param, f: __F) -> __rental_prelude::Option<&mut __R> where
579					__F: for<#(#struct_rlt_args,)*> __rental_prelude::FnOnce(#borrow_mut_ident<#(#struct_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*>) -> __rental_prelude::Option<&#last_rlt_arg mut __R>,
580					__R: ?Sized //#(#struct_lt_args +)*,
581				{
582					f(unsafe { #item_ident::all_mut_erased(#self_arg) })
583				}
584
585				/// Try to return a mutable reference from shared borrows of the prefix fields and a mutable borrow of the suffix field of the struct, or an error on failure.
586				///
587				/// This is a subtle variation of `rent_all_mut` where it is legal to return a reference bounded by a rental lifetime, because that lifetime is reborrowed away before it is returned to you.
588				pub fn try_ref_rent_all_mut<__F, __R, __E>(#self_mut_param, f: __F) -> __rental_prelude::Result<&mut __R, __E> where
589					__F: for<#(#struct_rlt_args,)*> __rental_prelude::FnOnce(#borrow_mut_ident<#(#struct_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*>) -> __rental_prelude::Result<&#last_rlt_arg mut __R, __E>,
590					__R: ?Sized //#(#struct_lt_args +)*,
591				{
592					f(unsafe { #item_ident::all_mut_erased(#self_arg) })
593				}
594			}
595		).to_tokens(tokens);
596	}
597
598	if attribs.is_debug {
599		if attribs.is_rental_mut {
600			quote_spanned!(struct_info.ident.span()/*.resolved_at(def_site)*/ =>
601				impl #struct_impl_params __rental_prelude::fmt::Debug for #item_ident #struct_impl_args #struct_where_clause #where_extra #suffix_ty: __rental_prelude::fmt::Debug {
602					fn fmt(&self, f: &mut __rental_prelude::fmt::Formatter) -> __rental_prelude::fmt::Result {
603						f.debug_struct(#item_ident_str)
604							.field(#suffix_ident_str, &self.#suffix_ident)
605							.finish()
606					}
607				}
608			).to_tokens(tokens);
609		} else {
610			quote_spanned!(struct_info.ident.span()/*.resolved_at(def_site)*/ =>
611				impl #struct_impl_params __rental_prelude::fmt::Debug for #item_ident #struct_impl_args #struct_where_clause #where_extra #(#field_tys: __rental_prelude::fmt::Debug),* {
612					fn fmt(&self, f: &mut __rental_prelude::fmt::Formatter) -> __rental_prelude::fmt::Result {
613						f.debug_struct(#item_ident_str)
614							#(.field(#field_ident_strs, &self.#field_idents))*
615							.finish()
616					}
617				}
618			).to_tokens(tokens);
619		}
620	}
621
622	if attribs.is_clone {
623		quote_spanned!(struct_info.ident.span()/*.resolved_at(def_site)*/ =>
624			impl #struct_impl_params __rental_prelude::Clone for #item_ident #struct_impl_args #struct_where_clause #where_extra #(#prefix_tys: #prefix_clone_traits,)* #suffix_ty: __rental_prelude::Clone {
625				fn clone(&self) -> Self {
626					#item_ident {
627						#(#local_idents: __rental_prelude::Clone::clone(&self.#field_idents),)*
628					}
629				}
630			}
631		).to_tokens(tokens);
632	}
633
634//	if fields[fields.len() - 1].subrental.is_some() {
635//		quote_spanned!(struct_span =>
636//			impl<#(#borrow_lt_params,)* #(#struct_nonlt_params),*> __rental_prelude::IntoSuffix for #borrow_ident<#(#struct_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*> #struct_where_clause {
637//				type Suffix = <#borrow_suffix_ty as __rental_prelude::IntoSuffix>::Suffix;
638//
639//				#[allow(non_shorthand_field_patterns)]
640//				fn into_suffix(self) -> <Self as __rental_prelude::IntoSuffix>::Suffix {
641//					let #borrow_ident{#suffix_ident: suffix, ..};
642//					suffix.into_suffix()
643//				}
644//			}
645//		).to_tokens(tokens);
646//
647//		quote_spanned!(struct_span =>
648//			impl<#(#borrow_lt_params,)* #(#struct_nonlt_params),*> __rental_prelude::IntoSuffix for #borrow_mut_ident<#(#struct_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*> #struct_where_clause {
649//				type Suffix = <#borrow_mut_suffix_ty as __rental_prelude::IntoSuffix>::Suffix;
650//
651//				#[allow(non_shorthand_field_patterns)]
652//				fn into_suffix(self) -> <Self as __rental_prelude::IntoSuffix>::Suffix {
653//					let #borrow_mut_ident{#suffix_ident: suffix, ..};
654//					suffix.into_suffix()
655//				}
656//			}
657//		).to_tokens(tokens);
658//
659//		if attribs.is_deref_suffix {
660//			quote_spanned!(suffix_ty_span =>
661//				impl #struct_impl_params __rental_prelude::Deref for #item_ident #struct_impl_args #struct_where_clause {
662//					type Target = <#suffix_ty as __rental_prelude::Deref>::Target;
663//
664//					fn deref(&self) -> &<Self as __rental_prelude::Deref>::Target {
665//						#item_ident::ref_rent(self, |suffix| &**__rental_prelude::IntoSuffix::into_suffix(suffix))
666//					}
667//				}
668//			).to_tokens(tokens);
669//		}
670//
671//		if attribs.is_deref_mut_suffix {
672//			quote_spanned!(suffix_ty_span =>
673//				impl #struct_impl_params __rental_prelude::DerefMut for #item_ident #struct_impl_args #struct_where_clause {
674//					fn deref_mut(&mut self) -> &mut <Self as __rental_prelude::Deref>::Target {
675//						#item_ident.ref_rent_mut(self, |suffix| &mut **__rental_prelude::IntoSuffix::into_suffix(suffix))
676//					}
677//				}
678//			).to_tokens(tokens);
679//		}
680//	} else {
681		quote_spanned!(struct_span =>
682			impl<#(#borrow_lt_params,)* #(#struct_nonlt_params),*> __rental_prelude::IntoSuffix for #borrow_ident<#(#struct_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*> #struct_where_clause {
683				type Suffix = #borrow_suffix_ty;
684
685				#[allow(non_shorthand_field_patterns)]
686				fn into_suffix(self) -> <Self as __rental_prelude::IntoSuffix>::Suffix {
687					let #borrow_ident{#suffix_ident: suffix, ..} = self;
688					suffix
689				}
690			}
691		).to_tokens(tokens);
692
693		quote_spanned!(struct_span =>
694			impl<#(#borrow_lt_params,)* #(#struct_nonlt_params),*> __rental_prelude::IntoSuffix for #borrow_mut_ident<#(#struct_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*> #struct_where_clause {
695				type Suffix = #borrow_mut_suffix_ty;
696
697				#[allow(non_shorthand_field_patterns)]
698				fn into_suffix(self) -> <Self as __rental_prelude::IntoSuffix>::Suffix {
699					let #borrow_mut_ident{#suffix_ident: suffix, ..} = self;
700					suffix
701				}
702			}
703		).to_tokens(tokens);
704
705		if attribs.is_deref_suffix {
706			quote_spanned!(suffix_ty_span =>
707				impl #struct_impl_params __rental_prelude::Deref for #item_ident #struct_impl_args #struct_where_clause #where_extra {
708					type Target = <#suffix_ty as __rental_prelude::Deref>::Target;
709
710					fn deref(&self) -> &<Self as __rental_prelude::Deref>::Target {
711						#item_ident::ref_rent(self, |suffix| &**suffix)
712					}
713				}
714			).to_tokens(tokens);
715		}
716
717		if attribs.is_deref_mut_suffix {
718			quote_spanned!(suffix_ty_span =>
719				impl #struct_impl_params __rental_prelude::DerefMut for #item_ident #struct_impl_args #struct_where_clause {
720					fn deref_mut(&mut self) -> &mut <Self as __rental_prelude::Deref>::Target {
721						#item_ident::ref_rent_mut(self, |suffix| &mut **suffix)
722					}
723				}
724			).to_tokens(tokens);
725		}
726//	}
727
728	if attribs.is_deref_suffix {
729		quote_spanned!(suffix_ty_span =>
730			impl #struct_impl_params __rental_prelude::AsRef<<Self as __rental_prelude::Deref>::Target> for #item_ident #struct_impl_args #struct_where_clause {
731				fn as_ref(&self) -> &<Self as __rental_prelude::Deref>::Target {
732					&**self
733				}
734			}
735		).to_tokens(tokens);
736	}
737
738	if attribs.is_deref_mut_suffix {
739		quote_spanned!(suffix_ty_span =>
740			impl #struct_impl_params __rental_prelude::AsMut<<Self as __rental_prelude::Deref>::Target> for #item_ident #struct_impl_args #struct_where_clause {
741				fn as_mut(&mut self) -> &mut <Self as __rental_prelude::Deref>::Target {
742					&mut **self
743				}
744			}
745		).to_tokens(tokens);
746	}
747
748	if attribs.is_covariant {
749		quote_spanned!(struct_info.ident.span()/*.resolved_at(def_site)*/ =>
750			#[allow(dead_code)]
751			impl #struct_impl_params #item_ident #struct_impl_args #struct_where_clause {
752				/// Borrow all fields of the struct by reborrowing away the rental lifetimes.
753				///
754				/// This is safe because the lifetimes are verified to be covariant first.
755				pub fn all<'__s>(#self_lt_ref_param) -> <Self as __rental_prelude::#rental_trait_ident>::Borrow {
756					unsafe {
757						let _covariant = __rental_prelude::PhantomData::<#borrow_ident<#(#static_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*>>;
758						let _covariant: __rental_prelude::PhantomData<#borrow_ident<#(#self_rlt_args,)* #(#struct_lt_args,)* #(#struct_nonlt_args),*>> = _covariant; 
759
760						#item_ident::all_erased(#self_arg)
761					}
762				}
763
764				/// Borrow the suffix field of the struct by reborrowing away the rental lifetimes.
765				///
766				/// This is safe because the lifetimes are verified to be covariant first.
767				pub fn suffix(#self_ref_param) -> <<Self as __rental_prelude::#rental_trait_ident>::Borrow as __rental_prelude::IntoSuffix>::Suffix {
768					&#self_arg.#suffix_ident
769				}
770			}
771		).to_tokens(tokens);
772	}
773
774	if let Some(ref map_suffix_param) = attribs.map_suffix_param {
775		let mut replacer = MapTyParamReplacer{
776			ty_param: map_suffix_param,
777		};
778
779		let mapped_suffix_param = replacer.fold_type_param(map_suffix_param.clone());
780		let mapped_ty = replacer.fold_path(parse_quote!(#item_ident #struct_impl_args));
781		let mapped_suffix_ty = replacer.fold_type(suffix_orig_ty.clone());
782
783		let mut map_where_clause = syn::WhereClause{
784			where_token: Default::default(),
785			predicates: syn::punctuated::Punctuated::from_iter(
786				struct_generics.type_params().filter(|p| p.ident != map_suffix_param.ident).filter_map(|p| {
787					let mut mapped_param = p.clone();
788					mapped_param.bounds = syn::punctuated::Punctuated::new();
789
790					for mapped_bound in p.bounds.iter().filter(|b| {
791						let mut finder = MapTyParamFinder {
792							ty_param: map_suffix_param,
793							found: false,
794						};
795						finder.visit_type_param_bound(b);
796						finder.found
797					}).map(|b| {
798						let mut replacer = MapTyParamReplacer{
799							ty_param: map_suffix_param,
800						};
801
802						replacer.fold_type_param_bound(b.clone())
803					}) {
804						mapped_param.bounds.push(mapped_bound)
805					}
806
807					if mapped_param.bounds.len() > 0 {
808						Some(syn::punctuated::Pair::Punctuated(parse_quote!(#mapped_param), Default::default()))
809					} else {
810						None
811					}
812				}).chain(
813					struct_where_clause.iter().flat_map(|w| w.predicates.iter()).filter(|p| {
814						let mut finder = MapTyParamFinder {
815							ty_param: map_suffix_param,
816							found: false,
817						};
818						finder.visit_where_predicate(p);
819						finder.found
820					}).map(|p| {
821						let mut replacer = MapTyParamReplacer{
822							ty_param: map_suffix_param,
823						};
824
825						syn::punctuated::Pair::Punctuated(replacer.fold_where_predicate(p.clone()), Default::default())
826					})
827				)
828			)
829		};
830
831		let mut try_map_where_clause = map_where_clause.clone();
832		map_where_clause.predicates.push(parse_quote!(
833			__F: for<#(#suffix_rlt_args),*> __rental_prelude::FnOnce(#suffix_orig_ty) -> #mapped_suffix_ty
834		));
835		try_map_where_clause.predicates.push(parse_quote!(
836			__F: for<#(#suffix_rlt_args),*> __rental_prelude::FnOnce(#suffix_orig_ty) -> __rental_prelude::Result<#mapped_suffix_ty, __E>
837		));
838
839		quote_spanned!(struct_span =>
840			#[allow(dead_code)]
841			impl #struct_impl_params #item_ident #struct_impl_args #struct_where_clause {
842				/// Maps the suffix field of the rental struct to a different type.
843				///
844				/// Consumes the rental struct and applies the closure to the suffix field. A new rental struct is then constructed with the original prefix and new suffix.
845				pub fn map<#mapped_suffix_param, __F>(#self_move_param, __f: __F) -> #mapped_ty #map_where_clause {
846					let #item_ident{ #(#field_idents,)* } = #self_arg;
847
848					let #suffix_ident = __f(#suffix_ident);
849
850					#item_ident{ #(#field_idents: #local_idents,)* }
851				}
852
853				/// Try to map the suffix field of the rental struct to a different type.
854				///
855				/// As `map`, but the closure may fail. Upon failure, the tail is dropped, and the error is returned to you along with the head.
856				pub fn try_map<#mapped_suffix_param, __F, __E>(#self_move_param, __f: __F) -> __rental_prelude::RentalResult<#mapped_ty, __E, #head_ty> #try_map_where_clause {
857					let #item_ident{ #(#field_idents,)* } = #self_arg;
858
859					match __f(#suffix_ident) {
860						__rental_prelude::Result::Ok(#suffix_ident) => __rental_prelude::Result::Ok(#item_ident { #(#field_idents: #local_idents,)* }),
861						__rental_prelude::Result::Err(__e) => __rental_prelude::Result::Err(__rental_prelude::RentalError(__e, #head_ident)),
862					}
863				}
864
865				/// Try to map the suffix field of the rental struct to a different type.
866				///
867				/// As `map`, but the closure may fail. Upon failure, the struct is dropped and the error is returned.
868				pub fn try_map_or_drop<#mapped_suffix_param, __F, __E>(#self_move_param, __f: __F) -> __rental_prelude::Result<#mapped_ty, __E> #try_map_where_clause {
869					let #item_ident{ #(#field_idents,)* } = #self_arg;
870
871					let #suffix_ident = __f(#suffix_ident)?;
872
873					Ok(#item_ident{ #(#field_idents: #local_idents,)* })
874				}
875			}
876		).to_tokens(tokens);
877	}
878}
879
880
881fn get_struct_attribs(struct_info: &syn::ItemStruct) -> RentalStructAttribs
882{
883	let mut rattribs = struct_info.attrs.clone();
884
885	let mut is_rental_mut = false;
886	let mut is_debug = false;
887	let mut is_clone = false;
888	let mut is_deref_suffix = false;
889	let mut is_deref_mut_suffix = false;
890	let mut is_covariant = false;
891	let mut map_suffix_param = None;
892
893	if let Some(rental_pos) = rattribs.iter()/*.filter(|attr| !attr.is_sugared_doc)*/.position(|attr| match attr.parse_meta().expect(&format!("Struct `{}` Attribute `{}` is not properly formatted.", struct_info.ident, attr.path.clone().into_token_stream())) {
894		syn::Meta::Path(ref attr_ident) => {
895			is_rental_mut = match attr_ident.segments.first().map(|s| s.ident.to_string()).as_ref().map(String::as_str) {
896				Some("rental") => false,
897				Some("rental_mut") => true,
898				_ => return false,
899			};
900
901			true
902		},
903		syn::Meta::List(ref list) => {
904			is_rental_mut = match list.path.segments.first().map(|s| s.ident.to_string()).as_ref().map(String::as_str) {
905				Some("rental") => false,
906				Some("rental_mut") => true,
907				_ => return false,
908			};
909
910			let leftover = list.nested.iter().filter(|nested| {
911				if let syn::NestedMeta::Meta(ref meta) = **nested {
912					match *meta {
913						syn::Meta::Path(ref ident) => {
914							match ident.segments.first().map(|s| s.ident.to_string()).as_ref().map(String::as_str) {
915								Some("debug") => {
916									is_debug = true;
917									false
918								},
919								Some("clone") => {
920									is_clone = true;
921									false
922								},
923								Some("deref_suffix") => {
924									is_deref_suffix = true;
925									false
926								},
927								Some("deref_mut_suffix") => {
928									is_deref_suffix = true;
929									is_deref_mut_suffix = true;
930									false
931								},
932								Some("covariant") => {
933									is_covariant = true;
934									false
935								},
936								Some("map_suffix") => {
937									panic!("Struct `{}` `map_suffix` flag expects ` = \"T\"`.", struct_info.ident);
938								},
939								_ => true,
940							}
941						},
942						syn::Meta::NameValue(ref name_value) => {
943							match name_value.path.segments.first().map(|s| s.ident.to_string()).as_ref().map(String::as_str) {
944								Some("map_suffix") => {
945									if let syn::Lit::Str(ref ty_param_str) = name_value.lit {
946										let ty_param_str = ty_param_str.value();
947										let ty_param = struct_info.generics.type_params().find(|ty_param| {
948											if ty_param.ident.to_string() == ty_param_str {
949												return true;
950											}
951
952											false
953										}).unwrap_or_else(|| {
954											panic!("Struct `{}` `map_suffix` param `{}` does not name a type parameter.", struct_info.ident, ty_param_str);
955										});
956
957										let mut finder = MapTyParamFinder{
958											ty_param: &ty_param,
959											found: false,
960										};
961
962										if struct_info.fields.iter().take(struct_info.fields.iter().count() - 1).any(|f| {
963											finder.found = false;
964											finder.visit_field(f);
965											finder.found
966										}) {
967											panic!("Struct `{}` `map_suffix` type param `{}` appears in a prefix field.", struct_info.ident, ty_param_str);
968										}
969
970										finder.found = false;
971										finder.visit_field(struct_info.fields.iter().last().unwrap());
972										if !finder.found {
973											panic!("Struct `{}` `map_suffix` type param `{}` does not appear in the suffix field.", struct_info.ident, ty_param_str);
974										}
975
976										map_suffix_param = Some(ty_param.clone());
977										false
978									} else {
979										panic!("Struct `{}` `map_suffix` flag expects ` = \"T\"`.", struct_info.ident);
980									}
981								},
982								_ => true,
983							}
984						},
985						_ => true,
986					}
987				} else {
988					true
989				}
990			}).count();
991
992			if leftover > 0 {
993				panic!("Struct `{}` rental attribute takes optional arguments: `debug`, `clone`, `deref_suffix`, `deref_mut_suffix`, `covariant`, and `map_suffix = \"T\"`.", struct_info.ident);
994			}
995
996			true
997		},
998		_ => false,
999	}) {
1000		rattribs.remove(rental_pos);
1001	} else {
1002		panic!("Struct `{}` must have a `rental` or `rental_mut` attribute.", struct_info.ident);
1003	}
1004
1005	if rattribs.iter().any(|attr| attr.path != syn::parse_str::<syn::Path>("doc").unwrap()) {
1006		panic!("Struct `{}` must not have attributes other than one `rental` or `rental_mut`.", struct_info.ident);
1007	}
1008
1009	if is_rental_mut && is_clone {
1010		panic!("Struct `{}` cannot be both `rental_mut` and `clone`.", struct_info.ident);
1011	}
1012
1013	RentalStructAttribs{
1014		doc: rattribs,
1015		is_rental_mut: is_rental_mut,
1016		is_debug: is_debug,
1017		is_clone: is_clone,
1018		is_deref_suffix: is_deref_suffix,
1019		is_deref_mut_suffix: is_deref_mut_suffix,
1020		is_covariant: is_covariant,
1021		map_suffix_param: map_suffix_param,
1022	}
1023}
1024
1025
1026fn prepare_fields(struct_info: &syn::ItemStruct) -> (Vec<RentalField>, syn::token::Brace) {
1027	let def_site: Span = Span::call_site(); // FIXME: hygiene
1028	let call_site: Span = Span::call_site();
1029
1030	let (fields, fields_brace) = match struct_info.fields {
1031		syn::Fields::Named(ref fields) => (&fields.named, fields.brace_token),
1032		syn::Fields::Unnamed(..) => panic!("Struct `{}` must not be a tuple struct.", struct_info.ident),
1033		_ => panic!("Struct `{}` must have at least 2 fields.", struct_info.ident),
1034	};
1035
1036	if fields.len() < 2 {
1037		panic!("Struct `{}` must have at least 2 fields.", struct_info.ident);
1038	}
1039
1040	let mut rfields = Vec::with_capacity(fields.len());
1041	for (field_idx, field) in fields.iter().enumerate() {
1042		if field.vis != syn::Visibility::Inherited {
1043			panic!(
1044				"Struct `{}` field `{}` must be private.",
1045				struct_info.ident,
1046				field.ident.as_ref().map(|ident| ident.to_string()).unwrap_or_else(|| field_idx.to_string())
1047			);
1048		}
1049
1050		let mut rfattribs = field.attrs.clone();
1051		let mut subrental = None;
1052		let mut target_ty_hack = None;
1053
1054		if let Some(sr_pos) = rfattribs.iter().position(|attr| match attr.parse_meta() {
1055			Ok(syn::Meta::List(ref list)) if list.path.segments.first().map(|s| s.ident.to_string()).as_ref().map(String::as_str) == Some("subrental") => {
1056				panic!(
1057					"`subrental` attribute on struct `{}` field `{}` expects ` = arity`.",
1058					struct_info.ident,
1059					field.ident.as_ref().map(|ident| ident.to_string()).unwrap_or_else(|| field_idx.to_string())
1060				);
1061			},
1062			Ok(syn::Meta::Path(ref word)) if word.segments.first().map(|s| s.ident.to_string()).as_ref().map(String::as_str) == Some("subrental") => {
1063				panic!(
1064					"`subrental` attribute on struct `{}` field `{}` expects ` = arity`.",
1065					struct_info.ident,
1066					field.ident.as_ref().map(|ident| ident.to_string()).unwrap_or_else(|| field_idx.to_string())
1067				);
1068			},
1069			Ok(syn::Meta::NameValue(ref name_value)) if name_value.path.segments.first().map(|s| s.ident.to_string()).as_ref().map(String::as_str) == Some("subrental") => {
1070				match name_value.lit {
1071					syn::Lit::Int(ref arity) => {
1072						subrental = Some(Subrental{
1073							arity: arity.base10_parse::<usize>().unwrap(),
1074							rental_trait_ident: syn::Ident::new(&format!("Rental{}", arity.base10_parse::<usize>().unwrap()), def_site),
1075						})
1076					},
1077					_ => panic!(
1078						"`subrental` attribute on struct `{}` field `{}` expects ` = arity`.",
1079						struct_info.ident,
1080						field.ident.as_ref().map(|ident| ident.to_string()).unwrap_or_else(|| field_idx.to_string())
1081					),
1082				}
1083
1084				true
1085			},
1086			_ => false,
1087		}) {
1088			rfattribs.remove(sr_pos);
1089		}
1090
1091		if subrental.is_some() && field_idx == fields.len() - 1 {
1092			panic!(
1093				"struct `{}` field `{}` cannot be a subrental because it is the suffix field.",
1094				struct_info.ident,
1095				field.ident.as_ref().map(|ident| ident.to_string()).unwrap_or_else(|| field_idx.to_string())
1096			);
1097		}
1098
1099		if let Some(tth_pos) = rfattribs.iter().position(|a|
1100			match a.parse_meta() {
1101				Ok(syn::Meta::NameValue(syn::MetaNameValue{ref path, lit: syn::Lit::Str(ref ty_str), ..})) if path.segments.first().map(|s| s.ident.to_string()).as_ref().map(String::as_str) == Some("target_ty") => {
1102					if let Ok(ty) = syn::parse_str::<syn::Type>(&ty_str.value()) {
1103						target_ty_hack = Some(ty);
1104
1105						true
1106					} else {
1107						panic!(
1108							"`target_ty` attribute on struct `{}` field `{}` has an invalid ty string.",
1109							struct_info.ident,
1110							field.ident.as_ref().map(|ident| ident.to_string()).unwrap_or_else(|| field_idx.to_string())
1111						);
1112					}
1113				},
1114				_ => false,
1115			}
1116		) {
1117			rfattribs.remove(tth_pos);
1118		}
1119
1120		if field_idx == fields.len() - 1 && target_ty_hack.is_some() {
1121			panic!(
1122				"Struct `{}` field `{}` cannot have `target_ty` attribute because it is the suffix field.",
1123				struct_info.ident,
1124				field.ident.as_ref().map(|ident| ident.to_string()).unwrap_or_else(|| field_idx.to_string())
1125			);
1126		}
1127
1128		let target_ty_hack = target_ty_hack.as_ref().map(|ty| (*ty).clone()).or_else(|| if field_idx < fields.len() - 1 {
1129			let guess = if let syn::Type::Path(ref ty_path) = field.ty {
1130				match ty_path.path.segments[ty_path.path.segments.len() - 1] {
1131					syn::PathSegment{ref ident, arguments: syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments{ref args, ..})} => {
1132						if let Some(&syn::GenericArgument::Type(ref ty)) = args.first() {
1133							if ident == "Vec" {
1134								Some(syn::Type::Slice(syn::TypeSlice{bracket_token: Default::default(), elem: Box::new(ty.clone())}))
1135							} else {
1136								Some(ty.clone())
1137							}
1138						} else {
1139							None
1140						}
1141					},
1142					syn::PathSegment{ref ident, arguments: syn::PathArguments::None} => {
1143						if ident == "String" {
1144							Some(parse_quote!(str))
1145						} else {
1146							None
1147						}
1148					},
1149					_ => {
1150						None
1151					},
1152				}
1153			} else if let syn::Type::Reference(syn::TypeReference{elem: ref box_ty, ..}) = field.ty {
1154				Some((**box_ty).clone())
1155			} else {
1156				None
1157			};
1158
1159			let guess = guess.or_else(|| if field_idx == 0 {
1160				let field_ty = &field.ty;
1161				Some(parse_quote!(<#field_ty as __rental_prelude::Deref>::Target))
1162			} else {
1163				None
1164			});
1165
1166			if guess.is_none() {
1167				panic!("Struct `{}` field `{}` must be a type path with 1 type param, `String`, or a reference.", struct_info.ident, field.ident.as_ref().unwrap())
1168			}
1169
1170			guess
1171		} else {
1172			None
1173		});
1174
1175		if subrental.is_some() {
1176			if match target_ty_hack {
1177				Some(syn::Type::Path(ref ty_path)) => ty_path.qself.is_some(),
1178				Some(_) => true,
1179				_ => false,
1180			} {
1181				panic!(
1182					"Struct `{}` field `{}` must have an unqualified path for its `target_ty` to be a valid subrental.",
1183					struct_info.ident,
1184					field.ident.as_ref().map(|ident| ident.to_string()).unwrap_or_else(|| field_idx.to_string())
1185				);
1186			}
1187		}
1188
1189		let target_ty_hack_erased = target_ty_hack.as_ref().map(|tth| {
1190			let mut eraser = RentalLifetimeEraser{
1191				fields: &rfields,
1192				used_rlt_args: &mut Vec::new(),
1193			};
1194
1195			eraser.fold_type(tth.clone())
1196		});
1197
1198		let mut self_rlt_args = Vec::new();
1199		if let Some(Subrental{arity: sr_arity, ..}) = subrental {
1200			let field_ident = field.ident.as_ref().unwrap();
1201			for sr_idx in 0 .. sr_arity {
1202				self_rlt_args.push(syn::Lifetime::new(&format!("'{}_{}", field_ident, sr_idx), call_site));
1203			}
1204		} else {
1205			let field_ident = field.ident.as_ref().unwrap();
1206			self_rlt_args.push(syn::Lifetime::new(&format!("'{}", field_ident), call_site));
1207		}
1208
1209		let mut used_rlt_args = Vec::new();
1210		let rty = {
1211			let mut eraser = RentalLifetimeEraser{
1212				fields: &rfields,
1213				used_rlt_args: &mut used_rlt_args,
1214			};
1215
1216			eraser.fold_type(field.ty.clone())
1217		};
1218
1219		if rfattribs.iter().any(|attr| match attr.parse_meta() { Ok(syn::Meta::NameValue(syn::MetaNameValue{ref path, ..})) if path.segments.first().map(|s| s.ident.to_string()).as_ref().map(String::as_str) == Some("doc") => false, _ => true }) {
1220			panic!(
1221				"Struct `{}` field `{}` must not have attributes other than one `subrental` and `target_ty`.",
1222				struct_info.ident,
1223				field.ident.as_ref().map(|ident| ident.to_string()).unwrap_or_else(|| field_idx.to_string())
1224			);
1225		}
1226
1227		rfields.push(RentalField{
1228			name: field.ident.as_ref().unwrap().clone(),
1229			orig_ty: field.ty.clone(),
1230			erased: syn::Field{
1231				colon_token: field.colon_token,
1232				ident: field.ident.clone(),
1233				vis: field.vis.clone(),
1234				attrs: rfattribs,
1235				ty: rty,
1236			},
1237			subrental: subrental,
1238			self_rlt_args: self_rlt_args,
1239			used_rlt_args: used_rlt_args,
1240			target_ty_hack: target_ty_hack,
1241			target_ty_hack_erased: target_ty_hack_erased,
1242		});
1243	}
1244
1245	(rfields, fields_brace)
1246}
1247
1248
1249fn make_borrow_quotes(self_arg: &proc_macro2::TokenStream, fields: &[RentalField], is_rental_mut: bool) -> Vec<BorrowQuotes> {
1250	let call_site: Span = Span::call_site();
1251
1252	(0 .. fields.len()).map(|idx| {
1253		let (field_ty, deref) = if idx == fields.len() - 1 {
1254			let orig_ty = &fields[idx].orig_ty;
1255			(
1256				quote!(#orig_ty),
1257				quote!()
1258			)
1259		} else {
1260			let orig_ty = &fields[idx].orig_ty;
1261			(
1262				quote!(<#orig_ty as __rental_prelude::Deref>::Target),
1263				quote!(*)
1264			)
1265		};
1266
1267		let field_ty_hack = fields[idx].target_ty_hack.as_ref().unwrap_or(&fields[idx].orig_ty);
1268		let field_ty_hack_erased = fields[idx].target_ty_hack_erased.as_ref().unwrap_or(&fields[idx].erased.ty);
1269
1270		if let Some(ref subrental) = fields[idx].subrental {
1271			let field_ident = &fields[idx].name;
1272			let rental_trait_ident = &subrental.rental_trait_ident;
1273			let field_rlt_args = &fields[idx].self_rlt_args;
1274
1275			let (ref borrow_ty_hack, ref borrow_mut_ty_hack, ref field_args) = if let syn::Type::Path(syn::TypePath{ref qself, path: ref ty_path}) = *field_ty_hack {
1276				let seg_idx = ty_path.segments.len() - 1;
1277				let ty_name = &ty_path.segments[seg_idx].ident.to_string();
1278
1279				let mut borrow_ty_path = ty_path.clone();
1280				borrow_ty_path.segments[seg_idx].ident = syn::Ident::new(&format!("{}_Borrow", ty_name), call_site);
1281				borrow_ty_path.segments[seg_idx].arguments = syn::PathArguments::None;
1282
1283				let mut borrow_mut_ty_path = ty_path.clone();
1284				borrow_mut_ty_path.segments[seg_idx].ident = syn::Ident::new(&format!("{}_BorrowMut", ty_name), call_site);
1285				borrow_mut_ty_path.segments[seg_idx].arguments = syn::PathArguments::None;
1286
1287				match ty_path.segments[seg_idx].arguments {
1288					syn::PathArguments::AngleBracketed(ref args) => {
1289						(
1290							syn::Type::Path(syn::TypePath{qself: qself.clone(), path: borrow_ty_path}),
1291							syn::Type::Path(syn::TypePath{qself: qself.clone(), path: borrow_mut_ty_path}),
1292							args.args.iter().collect::<Vec<_>>(),
1293						)
1294					},
1295					syn::PathArguments::None => {
1296						(
1297							syn::Type::Path(syn::TypePath{qself: qself.clone(), path: borrow_ty_path}),
1298							syn::Type::Path(syn::TypePath{qself: qself.clone(), path: borrow_mut_ty_path}),
1299							Vec::with_capacity(0),
1300						)
1301					},
1302					_ => panic!("Field `{}` must have angle-bracketed args.", fields[idx].name),
1303				}
1304			} else {
1305				panic!("Field `{}` must be a type path.", fields[idx].name)
1306			};
1307
1308			BorrowQuotes {
1309				ty: if idx == fields.len() - 1 || !is_rental_mut {
1310					quote!(<#field_ty as __rental_prelude::#rental_trait_ident<#(#field_rlt_args),*>>::Borrow)
1311				} else {
1312					quote!(__rental_prelude::PhantomData<<#field_ty as __rental_prelude::#rental_trait_ident<#(#field_rlt_args),*>>::Borrow>)
1313				},
1314				ty_hack: if idx == fields.len() - 1 || !is_rental_mut {
1315					quote!(#borrow_ty_hack<#(#field_rlt_args,)* #(#field_args),*>)
1316				} else {
1317					quote!(__rental_prelude::PhantomData<#borrow_ty_hack<#(#field_rlt_args,)* #(#field_args),*>>)
1318				},
1319				expr: if idx == fields.len() - 1 || !is_rental_mut {
1320					quote!(unsafe { <#field_ty_hack_erased>::all_erased(&#deref #self_arg.#field_ident) })
1321				} else {
1322					quote!(__rental_prelude::PhantomData::<()>)
1323				},
1324
1325				mut_ty: if idx == fields.len() - 1 {
1326					quote!(<#field_ty as __rental_prelude::#rental_trait_ident<#(#field_rlt_args),*>>::BorrowMut)
1327				} else if !is_rental_mut {
1328					quote!(<#field_ty as __rental_prelude::#rental_trait_ident<#(#field_rlt_args),*>>::Borrow)
1329				} else {
1330					quote!(__rental_prelude::PhantomData<<#field_ty as __rental_prelude::#rental_trait_ident<#(#field_rlt_args),*>>::BorrowMut>)
1331				},
1332				mut_ty_hack: if idx == fields.len() - 1 {
1333					quote!(#borrow_mut_ty_hack<#(#field_rlt_args,)* #(#field_args),*>)
1334				} else if !is_rental_mut {
1335					quote!(#borrow_ty_hack<#(#field_rlt_args,)* #(#field_args),*>)
1336				} else {
1337					quote!(__rental_prelude::PhantomData<#borrow_mut_ty_hack<#(#field_rlt_args,)* #(#field_args),*>>)
1338				},
1339				mut_expr: if idx == fields.len() - 1 {
1340					quote!(unsafe { <#field_ty_hack_erased>::all_mut_erased(&mut #deref #self_arg.#field_ident) })
1341				} else if !is_rental_mut {
1342					quote!(unsafe { <#field_ty_hack_erased>::all_erased(&#deref #self_arg.#field_ident) })
1343				} else {
1344					quote!(__rental_prelude::PhantomData::<()>)
1345				},
1346
1347				new_ty: if !is_rental_mut  {
1348					//quote!(<#field_ty as __rental_prelude::#rental_trait_ident<#(#field_rlt_args),*>>::Borrow)
1349					quote!(#borrow_ty_hack<#(#field_rlt_args,)* #(#field_args),*>)
1350				} else {
1351					//quote!(<#field_ty as __rental_prelude::#rental_trait_ident<#(#field_rlt_args),*>>::BorrowMut)
1352					quote!(#borrow_mut_ty_hack<#(#field_rlt_args,)* #(#field_args),*>)
1353				},
1354				new_expr: if !is_rental_mut {
1355					quote!(unsafe { <#field_ty_hack_erased>::all_erased(&#deref #field_ident) })
1356				} else {
1357					quote!(unsafe { <#field_ty_hack_erased>::all_mut_erased(&mut #deref #field_ident) })
1358				},
1359			}
1360		} else {
1361			let field_ident = &fields[idx].name;
1362			let field_rlt_arg = &fields[idx].self_rlt_args[0];
1363
1364			BorrowQuotes {
1365				ty: if idx == fields.len() - 1 || !is_rental_mut {
1366					quote!(&#field_rlt_arg (#field_ty))
1367				} else {
1368					quote!(__rental_prelude::PhantomData<&#field_rlt_arg #field_ty>)
1369				},
1370				ty_hack: if idx == fields.len() - 1 || !is_rental_mut {
1371					quote!(&#field_rlt_arg (#field_ty_hack))
1372				} else {
1373					quote!(__rental_prelude::PhantomData<&#field_rlt_arg #field_ty_hack>)
1374				},
1375				expr: if idx == fields.len() - 1 || !is_rental_mut {
1376					quote!(&#deref #self_arg.#field_ident)
1377				} else {
1378					quote!(__rental_prelude::PhantomData::<()>)
1379				},
1380
1381				mut_ty: if idx == fields.len() - 1 {
1382					quote!(&#field_rlt_arg mut (#field_ty))
1383				} else if !is_rental_mut {
1384					quote!(&#field_rlt_arg (#field_ty))
1385				} else {
1386					quote!(__rental_prelude::PhantomData<&#field_rlt_arg mut #field_ty>)
1387				},
1388				mut_ty_hack: if idx == fields.len() - 1 {
1389					quote!(&#field_rlt_arg mut (#field_ty_hack))
1390				} else if !is_rental_mut {
1391					quote!(&#field_rlt_arg (#field_ty_hack))
1392				} else {
1393					quote!(__rental_prelude::PhantomData<&#field_rlt_arg mut #field_ty_hack>)
1394				},
1395				mut_expr: if idx == fields.len() - 1 {
1396					quote!(&mut #deref #self_arg.#field_ident)
1397				} else if !is_rental_mut {
1398					quote!(&#deref #self_arg.#field_ident)
1399				} else {
1400					quote!(__rental_prelude::PhantomData::<()>)
1401				},
1402
1403				new_ty: if !is_rental_mut {
1404					//quote!(&#field_rlt_arg #field_ty)
1405					quote!(&#field_rlt_arg (#field_ty_hack))
1406				} else {
1407					//quote!(&#field_rlt_arg mut #field_ty)
1408					quote!(&#field_rlt_arg mut (#field_ty_hack))
1409				},
1410				new_expr: if !is_rental_mut {
1411					quote!(& #deref #field_ident)
1412				} else {
1413					quote!(&mut #deref #field_ident)
1414				},
1415			}
1416		}
1417	}).collect()
1418}
1419
1420
1421fn make_tail_closure_quotes(fields: &[RentalField], borrows: &[BorrowQuotes], is_rental_mut: bool) -> Vec<ClosureQuotes> {
1422	(1 .. fields.len()).map(|idx| {
1423		let local_name = &fields[idx].name;
1424		let field_ty = &fields[idx].orig_ty;
1425
1426		if !is_rental_mut {
1427			let prev_new_tys_reverse = &borrows[0 .. idx].iter().map(|b| &b.new_ty).rev().collect::<Vec<_>>();
1428			let prev_new_exprs_reverse = &borrows[0 .. idx].iter().map(|b| &b.new_expr).rev().collect::<Vec<_>>();;
1429			let mut prev_rlt_args = Vec::<syn::Lifetime>::new();
1430			for prev_field in &fields[0 .. idx] {
1431				prev_rlt_args.extend(prev_field.self_rlt_args.iter().cloned());
1432			}
1433			let prev_rlt_args = &prev_rlt_args;
1434
1435			ClosureQuotes {
1436				bound: quote!(for<#(#prev_rlt_args),*> __rental_prelude::FnOnce(#(#prev_new_tys_reverse),*) -> #field_ty),
1437				expr: quote!(#local_name(#(#prev_new_exprs_reverse),*)),
1438				try_bound: quote!(for<#(#prev_rlt_args),*> __rental_prelude::FnOnce(#(#prev_new_tys_reverse),*) -> __rental_prelude::Result<#field_ty, __E>),
1439				try_expr: quote!(#local_name(#(#prev_new_exprs_reverse),*)),
1440			}
1441		} else {
1442			let prev_new_ty = &borrows[idx - 1].new_ty;
1443			let prev_new_expr = &borrows[idx - 1].new_expr;
1444			let prev_rlt_args = &fields[idx - 1].self_rlt_args.iter().chain(&fields[idx - 1].used_rlt_args).collect::<Vec<_>>();
1445
1446			ClosureQuotes {
1447				bound: quote!(for<#(#prev_rlt_args),*> __rental_prelude::FnOnce(#prev_new_ty) -> #field_ty),
1448				expr: quote!(#local_name(#prev_new_expr)),
1449				try_bound: quote!(for<#(#prev_rlt_args),*> __rental_prelude::FnOnce(#prev_new_ty) -> __rental_prelude::Result<#field_ty, __E>),
1450				try_expr: quote!(#local_name(#prev_new_expr)),
1451			}
1452		}
1453	}).collect()
1454}
1455
1456
1457struct RentalStructAttribs {
1458	pub doc: Vec<syn::Attribute>,
1459	pub is_rental_mut: bool,
1460	pub is_debug: bool,
1461	pub is_clone: bool,
1462	pub is_deref_suffix: bool,
1463	pub is_deref_mut_suffix: bool,
1464	pub is_covariant: bool,
1465	pub map_suffix_param: Option<syn::TypeParam>,
1466}
1467
1468
1469struct RentalField {
1470	pub name: syn::Ident,
1471	pub orig_ty: syn::Type,
1472	pub erased: syn::Field,
1473	pub subrental: Option<Subrental>,
1474	pub self_rlt_args: Vec<syn::Lifetime>,
1475	pub used_rlt_args: Vec<syn::Lifetime>,
1476	pub target_ty_hack: Option<syn::Type>,
1477	pub target_ty_hack_erased: Option<syn::Type>,
1478}
1479
1480
1481struct Subrental {
1482	arity: usize,
1483	rental_trait_ident: syn::Ident,
1484}
1485
1486
1487struct BorrowQuotes {
1488	pub ty: proc_macro2::TokenStream,
1489	pub ty_hack: proc_macro2::TokenStream,
1490	pub expr: proc_macro2::TokenStream,
1491	pub mut_ty: proc_macro2::TokenStream,
1492	pub mut_ty_hack: proc_macro2::TokenStream,
1493	pub mut_expr: proc_macro2::TokenStream,
1494	pub new_ty: proc_macro2::TokenStream,
1495	pub new_expr: proc_macro2::TokenStream,
1496}
1497
1498
1499struct ClosureQuotes {
1500	pub bound: proc_macro2::TokenStream,
1501	pub expr: proc_macro2::TokenStream,
1502	pub try_bound: proc_macro2::TokenStream,
1503	pub try_expr: proc_macro2::TokenStream,
1504}
1505
1506
1507struct RentalLifetimeEraser<'a> {
1508	pub fields: &'a [RentalField],
1509	pub used_rlt_args: &'a mut Vec<syn::Lifetime>,
1510}
1511
1512
1513impl<'a> syn::fold::Fold for RentalLifetimeEraser<'a> {
1514	fn fold_lifetime(&mut self, lifetime: syn::Lifetime) -> syn::Lifetime {
1515		let def_site: Span = Span::call_site(); // FIXME: hygiene
1516
1517		if self.fields.iter().any(|field| field.self_rlt_args.contains(&lifetime)) {
1518			if !self.used_rlt_args.contains(&lifetime) {
1519				self.used_rlt_args.push(lifetime.clone());
1520			}
1521
1522			syn::Lifetime::new("'static", def_site)
1523		} else {
1524			lifetime
1525		}
1526	}
1527}
1528
1529
1530struct MapTyParamFinder<'p> {
1531	pub ty_param: &'p syn::TypeParam,
1532	pub found: bool,
1533}
1534
1535
1536impl<'p, 'ast> syn::visit::Visit<'ast> for MapTyParamFinder<'p> {
1537	fn visit_path(&mut self, path: &'ast syn::Path) {
1538		if path.leading_colon.is_none() && path.segments.len() == 1 && path.segments[0].ident == self.ty_param.ident && path.segments[0].arguments == syn::PathArguments::None {
1539			self.found = true;
1540		} else {
1541			for seg in &path.segments {
1542				self.visit_path_segment(seg)
1543			};
1544		}
1545	}
1546}
1547
1548
1549struct MapTyParamReplacer<'p> {
1550	pub ty_param: &'p syn::TypeParam,
1551}
1552
1553
1554impl<'p> syn::fold::Fold for MapTyParamReplacer<'p> {
1555	fn fold_path(&mut self, path: syn::Path) -> syn::Path {
1556		if path.leading_colon.is_none() && path.segments.len() == 1 && path.segments[0].ident == self.ty_param.ident && path.segments[0].arguments == syn::PathArguments::None {
1557			let def_site: Span = Span::call_site(); // FIXME: hygiene
1558
1559			syn::Path{
1560				leading_colon: None,
1561				segments: syn::punctuated::Punctuated::from_iter(Some(
1562					syn::punctuated::Pair::End(syn::PathSegment{ident: syn::Ident::new("__U", def_site), arguments: syn::PathArguments::None})
1563				)),
1564			}
1565		} else {
1566			let syn::Path{
1567				leading_colon,
1568				segments,
1569			} = path;
1570
1571			syn::Path{
1572				leading_colon: leading_colon,
1573				segments: syn::punctuated::Punctuated::from_iter(segments.into_pairs().map(|p| match p {
1574					syn::punctuated::Pair::Punctuated(seg, punc) => syn::punctuated::Pair::Punctuated(self.fold_path_segment(seg), punc),
1575					syn::punctuated::Pair::End(seg) => syn::punctuated::Pair::End(self.fold_path_segment(seg)),
1576				}))
1577			}
1578		}
1579	}
1580
1581
1582	fn fold_type_param(&mut self, mut ty_param: syn::TypeParam) -> syn::TypeParam {
1583		if ty_param.ident == self.ty_param.ident {
1584			let def_site: Span = Span::call_site(); // FIXME: hygiene
1585			ty_param.ident = syn::Ident::new("__U", def_site);
1586		}
1587
1588		let bounds = syn::punctuated::Punctuated::from_iter(ty_param.bounds.iter().map(|b| self.fold_type_param_bound(b.clone())));
1589		ty_param.bounds = bounds;
1590
1591		ty_param
1592	}
1593}
1594
1595