diff --git a/serde_codegen/src/bound.rs b/serde_codegen/src/bound.rs index db7c5a79..ad973302 100644 --- a/serde_codegen/src/bound.rs +++ b/serde_codegen/src/bound.rs @@ -7,6 +7,20 @@ use syntax::ext::base::ExtCtxt; use syntax::ptr::P; use syntax::visit; +// Remove the default from every type parameter because in the generated impls +// they look like associated types: "error: associated type bindings are not +// allowed here". +pub fn without_defaults(generics: &ast::Generics) -> ast::Generics { + ast::Generics { + ty_params: generics.ty_params.map(|ty_param| { + ast::TyParam { + default: None, + .. ty_param.clone() + }}), + .. generics.clone() + } +} + pub fn with_bound( cx: &ExtCtxt, builder: &AstBuilder, diff --git a/serde_codegen/src/de.rs b/serde_codegen/src/de.rs index dd649841..b9dd70ed 100644 --- a/serde_codegen/src/de.rs +++ b/serde_codegen/src/de.rs @@ -85,7 +85,8 @@ fn build_impl_generics( item: &Item, generics: &ast::Generics, ) -> ast::Generics { - let generics = bound::with_bound(cx, builder, item, generics, + let generics = bound::without_defaults(generics); + let generics = bound::with_bound(cx, builder, item, &generics, &deserialized_by_us, &["serde", "de", "Deserialize"]); let generics = bound::with_bound(cx, builder, item, &generics, diff --git a/serde_codegen/src/ser.rs b/serde_codegen/src/ser.rs index ed79b542..7766cbfb 100644 --- a/serde_codegen/src/ser.rs +++ b/serde_codegen/src/ser.rs @@ -93,9 +93,11 @@ fn build_impl_generics( item: &Item, generics: &ast::Generics, ) -> ast::Generics { - bound::with_bound(cx, builder, item, generics, + let generics = bound::without_defaults(generics); + let generics = bound::with_bound(cx, builder, item, &generics, &serialized_by_us, - &["serde", "ser", "Serialize"]) + &["serde", "ser", "Serialize"]); + generics } // Fields with a `skip_serializing` or `serialize_with` attribute are not diff --git a/serde_tests/tests/test_macros.rs b/serde_tests/tests/test_macros.rs index ad472395..491acca2 100644 --- a/serde_tests/tests/test_macros.rs +++ b/serde_tests/tests/test_macros.rs @@ -1,3 +1,4 @@ +use std::marker::PhantomData; use token::{Token, assert_tokens, assert_ser_tokens, assert_de_tokens}; /* @@ -143,6 +144,19 @@ pub enum GenericEnum { Map { x: T, y: U }, } +trait AssociatedType { + type X; +} + +impl AssociatedType for i32 { + type X = i32; +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +struct DefaultTyParam = i32> { + phantom: PhantomData +} + #[test] fn test_named_unit() { assert_tokens( @@ -601,3 +615,19 @@ fn test_generic_enum_map() { ] ); } + +#[test] +fn test_default_ty_param() { + assert_tokens( + &DefaultTyParam:: { phantom: PhantomData }, + vec![ + Token::StructStart("DefaultTyParam", Some(1)), + + Token::StructSep, + Token::Str("phantom"), + Token::UnitStruct("PhantomData"), + + Token::StructEnd, + ] + ); +}