fix(codegen): Discard type defaults from impl generics

This commit is contained in:
David Tolnay 2016-04-13 23:51:04 -07:00
parent 808b06940e
commit fd3c15fb68
4 changed files with 50 additions and 3 deletions

View File

@ -7,6 +7,20 @@ use syntax::ext::base::ExtCtxt;
use syntax::ptr::P; use syntax::ptr::P;
use syntax::visit; 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( pub fn with_bound(
cx: &ExtCtxt, cx: &ExtCtxt,
builder: &AstBuilder, builder: &AstBuilder,

View File

@ -85,7 +85,8 @@ fn build_impl_generics(
item: &Item, item: &Item,
generics: &ast::Generics, generics: &ast::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, &deserialized_by_us,
&["serde", "de", "Deserialize"]); &["serde", "de", "Deserialize"]);
let generics = bound::with_bound(cx, builder, item, &generics, let generics = bound::with_bound(cx, builder, item, &generics,

View File

@ -93,9 +93,11 @@ fn build_impl_generics(
item: &Item, item: &Item,
generics: &ast::Generics, generics: &ast::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, &serialized_by_us,
&["serde", "ser", "Serialize"]) &["serde", "ser", "Serialize"]);
generics
} }
// Fields with a `skip_serializing` or `serialize_with` attribute are not // Fields with a `skip_serializing` or `serialize_with` attribute are not

View File

@ -1,3 +1,4 @@
use std::marker::PhantomData;
use token::{Token, assert_tokens, assert_ser_tokens, assert_de_tokens}; use token::{Token, assert_tokens, assert_ser_tokens, assert_de_tokens};
/* /*
@ -143,6 +144,19 @@ pub enum GenericEnum<T, U> {
Map { x: T, y: U }, Map { x: T, y: U },
} }
trait AssociatedType {
type X;
}
impl AssociatedType for i32 {
type X = i32;
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct DefaultTyParam<T: AssociatedType<X=i32> = i32> {
phantom: PhantomData<T>
}
#[test] #[test]
fn test_named_unit() { fn test_named_unit() {
assert_tokens( assert_tokens(
@ -601,3 +615,19 @@ fn test_generic_enum_map() {
] ]
); );
} }
#[test]
fn test_default_ty_param() {
assert_tokens(
&DefaultTyParam::<i32> { phantom: PhantomData },
vec![
Token::StructStart("DefaultTyParam", Some(1)),
Token::StructSep,
Token::Str("phantom"),
Token::UnitStruct("PhantomData"),
Token::StructEnd,
]
);
}