diff --git a/serde_macros/src/lib.rs b/serde_macros/src/lib.rs index 1ad3b613..d1ac9696 100644 --- a/serde_macros/src/lib.rs +++ b/serde_macros/src/lib.rs @@ -615,6 +615,16 @@ fn deserialize_substructure( .strip_bounds() .build(); + let visitor_ty = builder.ty().path() + .segment("__Visitor").with_generics(trait_generics.clone()).build() + .build(); + + // Build `__Visitor(PhantomData, PhantomData, ...)` + let (visitor_item, visitor_expr) = deserialize_visitor( + &builder, + &trait_generics + ); + match *substr.fields { StaticStruct(ref struct_def, ref fields) => { deserialize_struct( @@ -628,7 +638,9 @@ fn deserialize_substructure( state, struct_def, &trait_generics, - &type_generics, + visitor_item, + visitor_ty, + visitor_expr, ) } StaticEnum(ref enum_def, ref fields) => { @@ -647,6 +659,38 @@ fn deserialize_substructure( } } +// Build `__Visitor(PhantomData, PhantomData, ...)` +fn deserialize_visitor( + builder: &aster::AstBuilder, + trait_generics: &ast::Generics, +) -> (P, P) { + if trait_generics.ty_params.is_empty() { + ( + builder.item().tuple_struct("__Visitor") + .build(), + builder.expr().id("__Visitor"), + ) + } else { + ( + builder.item().tuple_struct("__Visitor") + .generics().with(trait_generics.clone()).build() + .with_tys( + trait_generics.ty_params.iter().map(|ty_param| { + builder.ty().phantom_data().id(ty_param.ident) + }) + ) + .build(), + builder.expr().call().id("__Visitor") + .with_args( + trait_generics.ty_params.iter().map(|_| { + builder.expr().phantom_data() + }) + ) + .build(), + ) + } +} + fn deserialize_struct( cx: &ExtCtxt, span: Span, @@ -658,12 +702,10 @@ fn deserialize_struct( state: P, struct_def: &StructDef, trait_generics: &ast::Generics, - impl_generics: &ast::Generics, + visitor_item: P, + visitor_ty: P, + visitor_expr: P, ) -> P { - let visitor_ty = builder.ty().path() - .segment("__Visitor").with_generics(trait_generics.clone()).build() - .build(); - match *fields { Unnamed(ref fields) => { if fields.is_empty() { @@ -684,7 +726,9 @@ fn deserialize_struct( &fields, state, trait_generics, + visitor_item, visitor_ty, + visitor_expr, ) } } @@ -700,7 +744,9 @@ fn deserialize_struct( state, struct_def, trait_generics, + visitor_item, visitor_ty, + visitor_expr, ) } } @@ -764,7 +810,9 @@ fn deserialize_struct_unnamed_fields( fields: &[Span], state: P, trait_generics: &ast::Generics, + visitor_item: P, visitor_ty: P, + visitor_expr: P, ) -> P { let where_clause = &trait_generics.where_clause; @@ -779,12 +827,6 @@ fn deserialize_struct_unnamed_fields( &field_names, ); - // Build `__Visitor(PhantomData, PhantomData, ...)` - let (visitor_struct, visitor_expr) = deserialize_struct_field_visitor( - builder, - trait_generics - ); - let struct_name = builder.expr().str(struct_ident); let value_ty = builder.ty().path() @@ -792,7 +834,7 @@ fn deserialize_struct_unnamed_fields( .build(); quote_expr!(cx, { - $visitor_struct + $visitor_item impl $trait_generics ::serde::de::Visitor for $visitor_ty $where_clause { type Value = $value_ty; @@ -864,7 +906,9 @@ fn deserialize_struct_named_fields( state: P, struct_def: &StructDef, trait_generics: &ast::Generics, + visitor_item: P, visitor_ty: P, + visitor_expr: P, ) -> P { let where_clause = &trait_generics.where_clause; @@ -873,33 +917,6 @@ fn deserialize_struct_named_fields( .map(|i| token::str_to_ident(&format!("__field{}", i))) .collect(); - // Build `__Visitor(PhantomData, PhantomData, ...)` - let (visitor_struct, visitor_expr) = if trait_generics.ty_params.is_empty() { - ( - builder.item().tuple_struct("__Visitor") - .build(), - builder.expr().id("__Visitor"), - ) - } else { - ( - builder.item().tuple_struct("__Visitor") - .generics().with(trait_generics.clone()).build() - .with_tys( - trait_generics.ty_params.iter().map(|ty_param| { - builder.ty().phantom_data().id(ty_param.ident) - }) - ) - .build(), - builder.expr().call().id("__Visitor") - .with_args( - trait_generics.ty_params.iter().map(|_| { - builder.expr().phantom_data() - }) - ) - .build(), - ) - }; - let struct_name = builder.expr().str(struct_ident); let value_ty = builder.ty().path() @@ -927,7 +944,7 @@ fn deserialize_struct_named_fields( quote_expr!(cx, { $field_devisitor - $visitor_struct; + $visitor_item impl $trait_generics ::serde::de::Visitor for $visitor_ty $where_clause { type Value = $value_ty; @@ -1174,7 +1191,7 @@ fn deserialize_enum( ) -> P { let where_clause = &trait_generics.where_clause; - let (visitor_struct, visitor_expr) = deserialize_struct_field_visitor( + let (visitor_struct, visitor_expr) = deserialize_visitor( builder, trait_generics, ); @@ -1243,38 +1260,6 @@ fn deserialize_enum( }) } -// Build `__Visitor(PhantomData, PhantomData, ...)` -fn deserialize_struct_field_visitor( - builder: &aster::AstBuilder, - trait_generics: &ast::Generics, -) -> (P, P) { - if trait_generics.ty_params.is_empty() { - ( - builder.item().tuple_struct("__Visitor") - .build(), - builder.expr().id("__Visitor"), - ) - } else { - ( - builder.item().tuple_struct("__Visitor") - .generics().with(trait_generics.clone()).build() - .with_tys( - trait_generics.ty_params.iter().map(|ty_param| { - builder.ty().phantom_data().id(ty_param.ident) - }) - ) - .build(), - builder.expr().call().id("__Visitor") - .with_args( - trait_generics.ty_params.iter().map(|_| { - builder.expr().phantom_data() - }) - ) - .build(), - ) - } -} - fn deserialize_enum_variant( cx: &ExtCtxt, span: Span, @@ -1354,7 +1339,7 @@ fn deserialize_enum_variant_seq( &field_names, ); - let (visitor_struct, visitor_expr) = deserialize_struct_field_visitor( + let (visitor_struct, visitor_expr) = deserialize_visitor( builder, trait_generics, ); @@ -1420,7 +1405,7 @@ fn deserialize_enum_variant_map( }, ); - let (visitor_struct, visitor_expr) = deserialize_struct_field_visitor( + let (visitor_struct, visitor_expr) = deserialize_visitor( builder, trait_generics );