@@ -58,8 +58,8 @@ fn derive_for_struct(
5858 fields : & Fields ,
5959) -> Result < TokenStream , syn:: Error > {
6060 let cardinality = tuple_cardinality ( fields) ;
61- let first = init_fields ( fields, Direction :: Forward ) ;
62- let last = init_fields ( fields, Direction :: Backward ) ;
61+ let first = init_value ( ty , None , fields, Direction :: Forward ) ;
62+ let last = init_value ( ty , None , fields, Direction :: Backward ) ;
6363 let next_body = advance_struct ( ty, fields, Direction :: Forward ) ;
6464 let previous_body = advance_struct ( ty, fields, Direction :: Backward ) ;
6565 let ( impl_generics, ty_generics, where_clause) = generics. split_for_impl ( ) ;
@@ -92,11 +92,11 @@ fn derive_for_struct(
9292 }
9393
9494 fn first( ) -> :: core:: option:: Option <Self > {
95- :: core :: option :: Option :: Some ( #ty { # first } )
95+ # first
9696 }
9797
9898 fn last( ) -> :: core:: option:: Option <Self > {
99- :: core :: option :: Option :: Some ( #ty { # last } )
99+ # last
100100 }
101101 }
102102 } ;
@@ -209,18 +209,25 @@ fn field_id(field: &Field, index: usize) -> Member {
209209 . map_or_else ( || Member :: from ( index) , Member :: from)
210210}
211211
212- fn init_fields ( fields : & Fields , direction : Direction ) -> TokenStream {
212+ fn init_value (
213+ ty : & Ident ,
214+ variant : Option < & Ident > ,
215+ fields : & Fields ,
216+ direction : Direction ,
217+ ) -> TokenStream {
213218 let reset = direction. reset ( ) ;
214- fields
215- . iter ( )
216- . enumerate ( )
217- . map ( |( i, field) | {
218- let id = field_id ( field, i) ;
219- quote ! {
220- #id: :: enum_iterator:: Sequence :: #reset( ) ?,
219+ let initialization = repeat ( quote ! { :: enum_iterator:: Sequence :: #reset( ) } ) . take ( fields. len ( ) ) ;
220+ let assignments = field_assignments ( fields) ;
221+ let bindings = bindings ( ) . take ( fields. len ( ) ) ;
222+ let id = variant. map_or_else ( || quote ! { #ty } , |v| quote ! { #ty:: #v } ) ;
223+ quote ! { {
224+ match ( #( #initialization, ) * ) {
225+ ( #( :: core:: option:: Option :: Some ( #bindings) , ) * ) => {
226+ :: core:: option:: Option :: Some ( #id { #assignments } )
221227 }
222- } )
223- . collect :: < TokenStream > ( )
228+ _ => :: core:: option:: Option :: None ,
229+ }
230+ } }
224231}
225232
226233fn next_variant (
@@ -241,17 +248,17 @@ fn next_variant(
241248 } ;
242249 let arms = variants. iter ( ) . enumerate ( ) . map ( |( i, v) | {
243250 let id = & v. ident ;
244- let init = init_fields ( & v. fields , direction) ;
251+ let init = init_value ( ty , Some ( id ) , & v. fields , direction) ;
245252 quote ! {
246- #i => :: core :: option :: Option :: Some ( #ty :: #id { # init } )
253+ #i => # init
247254 }
248255 } ) ;
249256 quote ! {
250257 loop {
251- let next = ( || match i {
258+ let next = match i {
252259 #( #arms, ) *
253260 _ => :: core:: option:: Option :: None ,
254- } ) ( ) ;
261+ } ;
255262 match next {
256263 :: core:: option:: Option :: Some ( _) => break next,
257264 :: core:: option:: Option :: None => #advance,
@@ -299,12 +306,12 @@ fn advance_enum(
299306fn advance_enum_arm ( ty : & Ident , direction : Direction , i : usize , variant : & Variant ) -> TokenStream {
300307 let next = match direction {
301308 Direction :: Forward => match i. checked_add ( 1 ) {
302- Some ( next_i) => quote ! { . or_else ( || next_variant( #next_i) ) } ,
303- None => quote ! { } ,
309+ Some ( next_i) => quote ! { next_variant( #next_i) } ,
310+ None => quote ! { :: core :: option :: Option :: None } ,
304311 } ,
305312 Direction :: Backward => match i. checked_sub ( 1 ) {
306- Some ( prev_i) => quote ! { . or_else ( || previous_variant( #prev_i) ) } ,
307- None => quote ! { } ,
313+ Some ( prev_i) => quote ! { previous_variant( #prev_i) } ,
314+ None => quote ! { :: core :: option :: Option :: None } ,
308315 } ,
309316 } ;
310317 let id = & variant. ident ;
@@ -314,9 +321,13 @@ fn advance_enum_arm(ty: &Ident, direction: Direction, i: usize, variant: &Varian
314321 let tuple = advance_tuple ( & bindings, direction) ;
315322 quote ! {
316323 #ty:: #id { #destructuring } => {
317- #tuple
318- . map( |( #( #bindings, ) * ) | #ty:: #id { #assignments } )
319- #next
324+ let y = #tuple;
325+ match y {
326+ :: core:: option:: Option :: Some ( ( #( #bindings, ) * ) ) => {
327+ :: core:: option:: Option :: Some ( #ty:: #id { #assignments } )
328+ }
329+ :: core:: option:: Option :: None => #next,
330+ }
320331 }
321332 }
322333}
@@ -332,8 +343,8 @@ fn advance_tuple(bindings: &[Ident], direction: Direction) -> TokenStream {
332343 let rev_binding_head = match rev_binding_head {
333344 Some ( head) => quote ! {
334345 let ( #head, carry) = match :: enum_iterator:: Sequence :: #advance( #head) {
335- :: core:: option:: Option :: Some ( #head) => ( #head, false ) ,
336- :: core:: option:: Option :: None => ( :: enum_iterator:: Sequence :: #reset( ) ? , true ) ,
346+ :: core:: option:: Option :: Some ( #head) => ( :: core :: option :: Option :: Some ( #head) , false ) ,
347+ :: core:: option:: Option :: None => ( :: enum_iterator:: Sequence :: #reset( ) , true ) ,
337348 } ;
338349 } ,
339350 None => quote ! {
@@ -345,17 +356,31 @@ fn advance_tuple(bindings: &[Ident], direction: Direction) -> TokenStream {
345356 #(
346357 let ( #rev_binding_tail, carry) = if carry {
347358 match :: enum_iterator:: Sequence :: #advance( #rev_binding_tail) {
348- :: core:: option:: Option :: Some ( #rev_binding_tail) => ( #rev_binding_tail, false ) ,
349- :: core:: option:: Option :: None => ( :: enum_iterator:: Sequence :: #reset( ) ?, true ) ,
359+ :: core:: option:: Option :: Some ( #rev_binding_tail) => {
360+ ( :: core:: option:: Option :: Some ( #rev_binding_tail) , false )
361+ }
362+ :: core:: option:: Option :: None => ( :: enum_iterator:: Sequence :: #reset( ) , true ) ,
350363 }
351364 } else {
352- ( :: core:: clone:: Clone :: clone( #rev_binding_tail) , false )
365+ (
366+ :: core:: option:: Option :: Some ( :: core:: clone:: Clone :: clone( #rev_binding_tail) ) ,
367+ false ,
368+ )
353369 } ;
354370 ) *
355- :: core:: option:: Option :: Some ( ( #( #bindings, ) * ) ) . filter( |_| !carry)
371+ if carry {
372+ :: core:: option:: Option :: None
373+ } else {
374+ match ( #( #bindings, ) * ) {
375+ ( #( :: core:: option:: Option :: Some ( #bindings) , ) * ) => {
376+ :: core:: option:: Option :: Some ( ( #( #bindings, ) * ) )
377+ }
378+ _ => :: core:: option:: Option :: None ,
379+ }
380+ }
356381 } ;
357382 quote ! {
358- ( || { #body } ) ( )
383+ { #body }
359384 }
360385}
361386
0 commit comments