diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index ec8c6ccd..8c74e119 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -55,10 +55,7 @@ pub fn expand_derive_serialize( &builder, &item, &impl_generics, - builder.ty() - .ref_() - .lifetime("'__a") - .build_ty(ty.clone()), + ty.clone(), ); let where_clause = &impl_generics.where_clause; @@ -184,7 +181,10 @@ fn serialize_tuple_struct( cx, builder, ty.clone(), - ty, + builder.ty() + .ref_() + .lifetime("'__a") + .build_ty(ty.clone()), fields, impl_generics, ); @@ -197,7 +197,7 @@ fn serialize_tuple_struct( serializer.visit_tuple_struct($type_name, Visitor { value: self, state: 0, - _structure_ty: ::std::marker::PhantomData, + _structure_ty: ::std::marker::PhantomData::<&$ty>, }) }) } @@ -215,7 +215,10 @@ fn serialize_struct( cx, builder, ty.clone(), - ty, + builder.ty() + .ref_() + .lifetime("'__a") + .build_ty(ty.clone()), struct_def, impl_generics, fields.iter().map(|field| quote_expr!(cx, &self.value.$field)), @@ -229,7 +232,7 @@ fn serialize_struct( serializer.visit_struct($type_name, Visitor { value: self, state: 0, - _structure_ty: ::std::marker::PhantomData, + _structure_ty: ::std::marker::PhantomData::<&$ty>, }) }) } @@ -383,7 +386,7 @@ fn serialize_tuple_variant( let (visitor_struct, visitor_impl) = serialize_tuple_struct_visitor( cx, builder, - structure_ty, + structure_ty.clone(), variant_ty, args.len(), generics, @@ -392,9 +395,7 @@ fn serialize_tuple_variant( let value_expr = builder.expr().tuple() .with_exprs( fields.iter().map(|field| { - builder.expr() - .addr_of() - .id(field) + builder.expr().id(field) }) ) .build(); @@ -405,7 +406,7 @@ fn serialize_tuple_variant( serializer.visit_enum_seq($type_name, $variant_index, $variant_name, Visitor { value: $value_expr, state: 0, - _structure_ty: ::std::marker::PhantomData, + _structure_ty: ::std::marker::PhantomData::<&$structure_ty>, }) }) } @@ -435,9 +436,7 @@ fn serialize_struct_variant( let value_expr = builder.expr().tuple() .with_exprs( fields.iter().map(|field| { - builder.expr() - .addr_of() - .id(field) + builder.expr().id(field) }) ) .build(); @@ -445,7 +444,7 @@ fn serialize_struct_variant( let (visitor_struct, visitor_impl) = serialize_struct_visitor( cx, builder, - structure_ty, + structure_ty.clone(), value_ty, struct_def, generics, @@ -462,7 +461,7 @@ fn serialize_struct_variant( serializer.visit_enum_map($type_name, $variant_index, $variant_name, Visitor { value: $value_expr, state: 0, - _structure_ty: ::std::marker::PhantomData, + _structure_ty: ::std::marker::PhantomData::<&$structure_ty>, }) }) } @@ -502,19 +501,12 @@ fn serialize_tuple_struct_visitor( .strip_bounds() .build(); - // Variants don't necessarily reference all generic lifetimes and type parameters, - // so to avoid a compilation failure, we'll just add a phantom type to capture these - // unused values. - let structure_ty = builder.ty() - .phantom_data() - .build(structure_ty); - ( quote_item!(cx, struct Visitor $visitor_impl_generics $where_clause { state: usize, value: $variant_ty, - _structure_ty: $structure_ty, + _structure_ty: ::std::marker::PhantomData<&'__a $structure_ty>, } ).unwrap(), @@ -590,19 +582,12 @@ fn serialize_struct_visitor( .strip_bounds() .build(); - // Variants don't necessarily reference all generic lifetimes and type parameters, - // so to avoid a compilation failure, we'll just add a phantom type to capture these - // unused values. - let structure_ty = builder.ty() - .phantom_data() - .build(structure_ty); - ( quote_item!(cx, struct Visitor $visitor_impl_generics $where_clause { state: usize, value: $variant_ty, - _structure_ty: $structure_ty, + _structure_ty: ::std::marker::PhantomData<&'__a $structure_ty>, } ).unwrap(), diff --git a/serde_tests/tests/test_macros.rs b/serde_tests/tests/test_macros.rs index d7af9855..3c41ca4c 100644 --- a/serde_tests/tests/test_macros.rs +++ b/serde_tests/tests/test_macros.rs @@ -131,6 +131,26 @@ enum Lifetimes<'a> { NoLifetimeMap { a: i32 }, } +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct GenericStruct { + x: T, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct GenericTupleStruct(T); + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub enum GenericEnumSeq { + Ok(T), + Err(E), +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub enum GenericEnumMap { + Ok { x: T }, + Err { x: E }, +} + #[test] fn test_named_unit() { let named_unit = NamedUnit; @@ -475,3 +495,29 @@ fn test_lifetimes() { "{\"NoLifetimeMap\":{\"a\":5}}" ); } + +#[test] +fn test_generic() { + macro_rules! declare_tests { + ($($ty:ty : $value:expr => $str:expr,)+) => { + $({ + let value: $ty = $value; + + let string = serde_json::to_string(&value).unwrap(); + assert_eq!(string, $str); + + let expected: $ty = serde_json::from_str(&string).unwrap(); + assert_eq!(value, expected); + })+ + } + } + + declare_tests!( + GenericStruct : GenericStruct { x: 5 } => "{\"x\":5}", + GenericTupleStruct : GenericTupleStruct(5) => "[5]", + GenericEnumSeq : GenericEnumSeq::Ok(5) => "{\"Ok\":[5]}", + GenericEnumSeq : GenericEnumSeq::Err(5) => "{\"Err\":[5]}", + GenericEnumMap : GenericEnumMap::Ok { x: 5 } => "{\"Ok\":{\"x\":5}}", + GenericEnumMap : GenericEnumMap::Err { x: 5 } => "{\"Err\":{\"x\":5}}", + ); +}