diff --git a/src/build.rs b/src/build.rs index 32e9a125..43293211 100644 --- a/src/build.rs +++ b/src/build.rs @@ -264,11 +264,19 @@ impl FieldsBuilder { pub fn finalize(self) -> Vec> { self.fields } + + fn push_field(mut self, field: Field) -> Self { + // filter out fields of PhantomData + if !field.ty().is_phantom() { + self.fields.push(field); + } + self + } } impl FieldsBuilder { /// Add a named field constructed using the builder. - pub fn field(mut self, builder: F) -> Self + pub fn field(self, builder: F) -> Self where F: Fn( FieldBuilder, @@ -276,18 +284,13 @@ impl FieldsBuilder { -> FieldBuilder, { let builder = builder(FieldBuilder::new()); - let field = builder.finalize(); - // filter out fields of PhantomData - if !field.ty().is_phantom() { - self.fields.push(field); - } - self + self.push_field(builder.finalize()) } } impl FieldsBuilder { /// Add an unnamed field constructed using the builder. - pub fn field(mut self, builder: F) -> Self + pub fn field(self, builder: F) -> Self where F: Fn( FieldBuilder, @@ -295,8 +298,7 @@ impl FieldsBuilder { -> FieldBuilder, { let builder = builder(FieldBuilder::new()); - self.fields.push(builder.finalize()); - self + self.push_field(builder.finalize()) } } diff --git a/src/impls.rs b/src/impls.rs index 2b2afa3e..d917e249 100644 --- a/src/impls.rs +++ b/src/impls.rs @@ -329,7 +329,11 @@ impl TypeInfo for PhantomData { type Identity = PhantomIdentity; fn type_info() -> Type { - panic!("PhantomData type instances should be filtered out.") + // Fields of this type should be filtered out and never appear in the type graph. + Type::builder() + .path(Path::prelude("PhantomData")) + .docs(&["PhantomData placeholder, this type should be filtered out"]) + .composite(Fields::unit()) } } diff --git a/src/tests.rs b/src/tests.rs index 3146a961..b634205a 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -106,9 +106,14 @@ fn prelude_items() { } #[test] -#[should_panic] fn phantom_data() { - PhantomData::::type_info(); + assert_type!( + PhantomData, + Type::builder() + .path(Path::prelude("PhantomData")) + .docs(&["PhantomData placeholder, this type should be filtered out"]) + .composite(Fields::unit()) + ) } #[test] diff --git a/test_suite/tests/derive.rs b/test_suite/tests/derive.rs index 8df5932a..dbd9c355 100644 --- a/test_suite/tests/derive.rs +++ b/test_suite/tests/derive.rs @@ -108,15 +108,21 @@ fn phantom_data_field_is_erased() { let ty = Type::builder() .path(Path::new("P", "derive")) .type_params(named_type_params!((T, bool))) - .composite( - Fields::named() - .field(|f| f.ty::().name("a").type_name("u8")) - .field(|f| { - f.ty::>() - .name("m") - .type_name("PhantomData") - }), - ); + .composite(Fields::named().field(|f| f.ty::().name("a").type_name("u8"))); + + assert_type!(P, ty); +} + +#[test] +fn phantom_data_tuple_struct_field_is_erased() { + #[allow(unused)] + #[derive(TypeInfo)] + struct P(u8, PhantomData); + + let ty = Type::builder() + .path(Path::new("P", "derive")) + .type_params(named_type_params!((T, bool))) + .composite(Fields::unnamed().field(|f| f.ty::().type_name("u8"))); assert_type!(P, ty); }