1 #![recursion_limit = "512"]
2 
3 extern crate proc_macro;
4 extern crate proc_macro2;
5 #[macro_use]
6 extern crate syn;
7 #[macro_use]
8 extern crate quote;
9 
10 use std::iter::{self, FromIterator};
11 use syn::spanned::Spanned;
12 use syn::visit::Visit;
13 use syn::fold::Fold;
14 use quote::ToTokens;
15 use proc_macro2::Span;
16 
17 
18 /// From `procedural_masquerade` crate
19 #[doc(hidden)]
_extract_input(derive_input: &str) -> &str20 fn _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)]
__rental_traits(input: proc_macro::TokenStream) -> proc_macro::TokenStream43 pub 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)]
__rental_structs_and_impls(input: proc_macro::TokenStream) -> proc_macro::TokenStream56 pub 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 
write_rental_traits(tokens: &mut proc_macro2::TokenStream, max_arity: usize)78 fn 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 
write_rental_struct_and_impls(tokens: &mut proc_macro2::TokenStream, struct_info: &syn::ItemStruct)101 fn 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 
get_struct_attribs(struct_info: &syn::ItemStruct) -> RentalStructAttribs881 fn 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 
prepare_fields(struct_info: &syn::ItemStruct) -> (Vec<RentalField>, syn::token::Brace)1026 fn 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 
make_borrow_quotes(self_arg: &proc_macro2::TokenStream, fields: &[RentalField], is_rental_mut: bool) -> Vec<BorrowQuotes>1249 fn 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 
make_tail_closure_quotes(fields: &[RentalField], borrows: &[BorrowQuotes], is_rental_mut: bool) -> Vec<ClosureQuotes>1421 fn 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 
1457 struct 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 
1469 struct 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 
1481 struct Subrental {
1482 	arity: usize,
1483 	rental_trait_ident: syn::Ident,
1484 }
1485 
1486 
1487 struct 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 
1499 struct 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 
1507 struct RentalLifetimeEraser<'a> {
1508 	pub fields: &'a [RentalField],
1509 	pub used_rlt_args: &'a mut Vec<syn::Lifetime>,
1510 }
1511 
1512 
1513 impl<'a> syn::fold::Fold for RentalLifetimeEraser<'a> {
fold_lifetime(&mut self, lifetime: syn::Lifetime) -> syn::Lifetime1514 	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 
1530 struct MapTyParamFinder<'p> {
1531 	pub ty_param: &'p syn::TypeParam,
1532 	pub found: bool,
1533 }
1534 
1535 
1536 impl<'p, 'ast> syn::visit::Visit<'ast> for MapTyParamFinder<'p> {
visit_path(&mut self, path: &'ast syn::Path)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 
1549 struct MapTyParamReplacer<'p> {
1550 	pub ty_param: &'p syn::TypeParam,
1551 }
1552 
1553 
1554 impl<'p> syn::fold::Fold for MapTyParamReplacer<'p> {
fold_path(&mut self, path: syn::Path) -> syn::Path1555 	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 
fold_type_param(&mut self, mut ty_param: syn::TypeParam) -> syn::TypeParam1582 	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 
1596