From 5a05eaeed4c6699576fc5a31cf98124b8873bb9a Mon Sep 17 00:00:00 2001 From: "Adam H. Leventhal" Date: Sat, 19 Sep 2026 14:11:43 -0700 Subject: [PATCH] emit the error module only when something references it The ConversionError type went into every output whether or not any conversion impl existed. It now goes in only when an emitted item names it, so output with no fallible conversions carries no error module. --- cargo-typify/tests/outputs/attr.rs | 26 -------------- cargo-typify/tests/outputs/derive.rs | 26 -------------- cargo-typify/tests/outputs/multi_derive.rs | 26 -------------- cargo-typify/tests/outputs/no-builder.rs | 26 -------------- typify-impl/src/convert.rs | 2 +- typify-impl/src/lib.rs | 36 +++++++++++-------- typify-impl/src/output.rs | 7 ++++ typify/tests/schemas/arrays-and-tuples.rs | 26 -------------- typify/tests/schemas/maps.rs | 26 -------------- typify/tests/schemas/maps_custom.rs | 26 -------------- .../tests/schemas/multiple-instance-types.rs | 26 -------------- 11 files changed, 30 insertions(+), 223 deletions(-) diff --git a/cargo-typify/tests/outputs/attr.rs b/cargo-typify/tests/outputs/attr.rs index f57017f0..9ec11e1e 100644 --- a/cargo-typify/tests/outputs/attr.rs +++ b/cargo-typify/tests/outputs/attr.rs @@ -68,29 +68,3 @@ pub struct Veggies { #[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")] pub vegetables: ::std::vec::Vec, } -#[doc = " Error types."] -pub mod error { - #[doc = r" Error from a `TryFrom` or `FromStr` implementation."] - pub struct ConversionError(::std::borrow::Cow<'static, str>); - impl ::std::error::Error for ConversionError {} - impl ::std::fmt::Display for ConversionError { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Display::fmt(&self.0, f) - } - } - impl ::std::fmt::Debug for ConversionError { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Debug::fmt(&self.0, f) - } - } - impl From<&'static str> for ConversionError { - fn from(value: &'static str) -> Self { - Self(value.into()) - } - } - impl From for ConversionError { - fn from(value: String) -> Self { - Self(value.into()) - } - } -} diff --git a/cargo-typify/tests/outputs/derive.rs b/cargo-typify/tests/outputs/derive.rs index 6106e88a..e77b9b9b 100644 --- a/cargo-typify/tests/outputs/derive.rs +++ b/cargo-typify/tests/outputs/derive.rs @@ -64,29 +64,3 @@ pub struct Veggies { #[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")] pub vegetables: ::std::vec::Vec, } -#[doc = " Error types."] -pub mod error { - #[doc = r" Error from a `TryFrom` or `FromStr` implementation."] - pub struct ConversionError(::std::borrow::Cow<'static, str>); - impl ::std::error::Error for ConversionError {} - impl ::std::fmt::Display for ConversionError { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Display::fmt(&self.0, f) - } - } - impl ::std::fmt::Debug for ConversionError { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Debug::fmt(&self.0, f) - } - } - impl From<&'static str> for ConversionError { - fn from(value: &'static str) -> Self { - Self(value.into()) - } - } - impl From for ConversionError { - fn from(value: String) -> Self { - Self(value.into()) - } - } -} diff --git a/cargo-typify/tests/outputs/multi_derive.rs b/cargo-typify/tests/outputs/multi_derive.rs index 09cc5ed6..d818e398 100644 --- a/cargo-typify/tests/outputs/multi_derive.rs +++ b/cargo-typify/tests/outputs/multi_derive.rs @@ -78,29 +78,3 @@ pub struct Veggies { #[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")] pub vegetables: ::std::vec::Vec, } -#[doc = " Error types."] -pub mod error { - #[doc = r" Error from a `TryFrom` or `FromStr` implementation."] - pub struct ConversionError(::std::borrow::Cow<'static, str>); - impl ::std::error::Error for ConversionError {} - impl ::std::fmt::Display for ConversionError { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Display::fmt(&self.0, f) - } - } - impl ::std::fmt::Debug for ConversionError { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Debug::fmt(&self.0, f) - } - } - impl From<&'static str> for ConversionError { - fn from(value: &'static str) -> Self { - Self(value.into()) - } - } - impl From for ConversionError { - fn from(value: String) -> Self { - Self(value.into()) - } - } -} diff --git a/cargo-typify/tests/outputs/no-builder.rs b/cargo-typify/tests/outputs/no-builder.rs index c98c84b9..2e1fe68a 100644 --- a/cargo-typify/tests/outputs/no-builder.rs +++ b/cargo-typify/tests/outputs/no-builder.rs @@ -64,29 +64,3 @@ pub struct Veggies { #[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")] pub vegetables: ::std::vec::Vec, } -#[doc = " Error types."] -pub mod error { - #[doc = r" Error from a `TryFrom` or `FromStr` implementation."] - pub struct ConversionError(::std::borrow::Cow<'static, str>); - impl ::std::error::Error for ConversionError {} - impl ::std::fmt::Display for ConversionError { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Display::fmt(&self.0, f) - } - } - impl ::std::fmt::Debug for ConversionError { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Debug::fmt(&self.0, f) - } - } - impl From<&'static str> for ConversionError { - fn from(value: &'static str) -> Self { - Self(value.into()) - } - } - impl From for ConversionError { - fn from(value: String) -> Self { - Self(value.into()) - } - } -} diff --git a/typify-impl/src/convert.rs b/typify-impl/src/convert.rs index 8eecb994..7c1716e7 100644 --- a/typify-impl/src/convert.rs +++ b/typify-impl/src/convert.rs @@ -2299,7 +2299,7 @@ mod tests { let actual = type_space.to_stream(); let file = syn::parse2::(actual).expect("type space should emit a valid file"); match file.items.as_slice() { - [syn::Item::Mod(error)] if error.ident == "error" => {} + [] => {} _ => panic!("unexpected file contents {}", file.to_token_stream()), } } diff --git a/typify-impl/src/lib.rs b/typify-impl/src/lib.rs index 4785c7b1..462e30e2 100644 --- a/typify-impl/src/lib.rs +++ b/typify-impl/src/lib.rs @@ -902,8 +902,28 @@ impl TypeSpace { pub fn to_stream(&self) -> TokenStream { let mut output = OutputSpace::default(); - // Add the error type we use for conversions; it's fine if this is - // unused. + // Add all types. + self.id_to_entry + .values() + .for_each(|type_entry| type_entry.output(self, &mut output)); + + // Add all shared default functions. + self.defaults + .iter() + .for_each(|x| output.add_item(output::OutputSpaceMod::Defaults, "", x.into())); + + // Add the error type conversions use, but only when some emitted item + // references it. This is kind of gross that we're groveling around + // through output to decide, but it will--I hope--be short-lived. + if output.contains("ConversionError") { + self.add_error_item(&mut output); + } + + output.into_stream() + } + + /// The error type generated `TryFrom` and `FromStr` impls report. + fn add_error_item(&self, output: &mut OutputSpace) { output.add_item( output::OutputSpaceMod::Error, "", @@ -939,18 +959,6 @@ impl TypeSpace { } }, ); - - // Add all types. - self.id_to_entry - .values() - .for_each(|type_entry| type_entry.output(self, &mut output)); - - // Add all shared default functions. - self.defaults - .iter() - .for_each(|x| output.add_item(output::OutputSpaceMod::Defaults, "", x.into())); - - output.into_stream() } /// Allocated the next TypeId. diff --git a/typify-impl/src/output.rs b/typify-impl/src/output.rs index d33406a3..7220cbb8 100644 --- a/typify-impl/src/output.rs +++ b/typify-impl/src/output.rs @@ -31,6 +31,13 @@ impl OutputSpace { .extend(stream); } + /// Whether any accumulated item's tokens contain `needle`. + pub fn contains(&self, needle: &str) -> bool { + self.items + .values() + .any(|stream| stream.to_string().contains(needle)) + } + pub fn into_stream(self) -> TokenStream { let mods = self .items diff --git a/typify/tests/schemas/arrays-and-tuples.rs b/typify/tests/schemas/arrays-and-tuples.rs index c8ffe924..c71da4cd 100644 --- a/typify/tests/schemas/arrays-and-tuples.rs +++ b/typify/tests/schemas/arrays-and-tuples.rs @@ -139,30 +139,4 @@ impl ::std::convert::From<[::serde_json::Value; 2usize]> for YoloTwoArray { Self(value) } } -#[doc = " Error types."] -pub mod error { - #[doc = r" Error from a `TryFrom` or `FromStr` implementation."] - pub struct ConversionError(::std::borrow::Cow<'static, str>); - impl ::std::error::Error for ConversionError {} - impl ::std::fmt::Display for ConversionError { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Display::fmt(&self.0, f) - } - } - impl ::std::fmt::Debug for ConversionError { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Debug::fmt(&self.0, f) - } - } - impl From<&'static str> for ConversionError { - fn from(value: &'static str) -> Self { - Self(value.into()) - } - } - impl From for ConversionError { - fn from(value: String) -> Self { - Self(value.into()) - } - } -} fn main() {} diff --git a/typify/tests/schemas/maps.rs b/typify/tests/schemas/maps.rs index 5388bbe8..a46ef2a8 100644 --- a/typify/tests/schemas/maps.rs +++ b/typify/tests/schemas/maps.rs @@ -181,30 +181,4 @@ impl ::std::str::FromStr for Value { Ok(Self(value.to_string())) } } -#[doc = " Error types."] -pub mod error { - #[doc = r" Error from a `TryFrom` or `FromStr` implementation."] - pub struct ConversionError(::std::borrow::Cow<'static, str>); - impl ::std::error::Error for ConversionError {} - impl ::std::fmt::Display for ConversionError { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Display::fmt(&self.0, f) - } - } - impl ::std::fmt::Debug for ConversionError { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Debug::fmt(&self.0, f) - } - } - impl From<&'static str> for ConversionError { - fn from(value: &'static str) -> Self { - Self(value.into()) - } - } - impl From for ConversionError { - fn from(value: String) -> Self { - Self(value.into()) - } - } -} fn main() {} diff --git a/typify/tests/schemas/maps_custom.rs b/typify/tests/schemas/maps_custom.rs index 8843c9a2..407603e1 100644 --- a/typify/tests/schemas/maps_custom.rs +++ b/typify/tests/schemas/maps_custom.rs @@ -181,30 +181,4 @@ impl ::std::str::FromStr for Value { Ok(Self(value.to_string())) } } -#[doc = " Error types."] -pub mod error { - #[doc = r" Error from a `TryFrom` or `FromStr` implementation."] - pub struct ConversionError(::std::borrow::Cow<'static, str>); - impl ::std::error::Error for ConversionError {} - impl ::std::fmt::Display for ConversionError { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Display::fmt(&self.0, f) - } - } - impl ::std::fmt::Debug for ConversionError { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Debug::fmt(&self.0, f) - } - } - impl From<&'static str> for ConversionError { - fn from(value: &'static str) -> Self { - Self(value.into()) - } - } - impl From for ConversionError { - fn from(value: String) -> Self { - Self(value.into()) - } - } -} fn main() {} diff --git a/typify/tests/schemas/multiple-instance-types.rs b/typify/tests/schemas/multiple-instance-types.rs index 6f8d9c89..e3e17392 100644 --- a/typify/tests/schemas/multiple-instance-types.rs +++ b/typify/tests/schemas/multiple-instance-types.rs @@ -107,30 +107,4 @@ impl ::std::convert::From for YesNoMaybe { Self::Boolean(value) } } -#[doc = " Error types."] -pub mod error { - #[doc = r" Error from a `TryFrom` or `FromStr` implementation."] - pub struct ConversionError(::std::borrow::Cow<'static, str>); - impl ::std::error::Error for ConversionError {} - impl ::std::fmt::Display for ConversionError { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Display::fmt(&self.0, f) - } - } - impl ::std::fmt::Debug for ConversionError { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Debug::fmt(&self.0, f) - } - } - impl From<&'static str> for ConversionError { - fn from(value: &'static str) -> Self { - Self(value.into()) - } - } - impl From for ConversionError { - fn from(value: String) -> Self { - Self(value.into()) - } - } -} fn main() {}