From 5d3c563d469ef36ce5a01f1612f53883fee20db5 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 25 May 2024 10:02:21 -0700 Subject: [PATCH 1/2] Document tuple impls as fake variadic --- serde/src/de/impls.rs | 31 ++++++++++++++++++++++++++----- serde/src/lib.rs | 3 ++- serde/src/ser/impls.rs | 26 ++++++++++++++++++++++---- 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index f26b20d46..4f71a20e5 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -1393,7 +1393,19 @@ array_impls! { macro_rules! tuple_impls { ($($len:tt => ($($n:tt $name:ident)+))+) => { $( - impl<'de, $($name: Deserialize<'de>),+> Deserialize<'de> for ($($name,)+) { + #[cfg_attr(docsrs, doc(hidden))] + impl<'de, $($name),+> Deserialize<'de> for ($($name,)+) + where + $($name: Deserialize<'de>,)+ + { + tuple_impl_body!($len => ($($n $name)+)); + } + )+ + }; +} + +macro_rules! tuple_impl_body { + ($len:tt => ($($n:tt $name:ident)+)) => { #[inline] fn deserialize(deserializer: D) -> Result where @@ -1462,13 +1474,22 @@ macro_rules! tuple_impls { deserializer.deserialize_tuple($len, TupleInPlaceVisitor(place)) } - } - )+ - } + }; +} + +#[cfg_attr(docsrs, doc(fake_variadic))] +#[cfg_attr( + docsrs, + doc = "This trait is implemented for tuples up to 16 items long." +)] +impl<'de, T> Deserialize<'de> for (T,) +where + T: Deserialize<'de>, +{ + tuple_impl_body!(1 => (0 T)); } tuple_impls! { - 1 => (0 T0) 2 => (0 T0 1 T1) 3 => (0 T0 1 T1 2 T2) 4 => (0 T0 1 T1 2 T2 3 T3) diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 3185d340e..d2eeca162 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -99,7 +99,8 @@ // Support using Serde without the standard library! #![cfg_attr(not(feature = "std"), no_std)] // Show which crate feature enables conditionally compiled APIs in documentation. -#![cfg_attr(docsrs, feature(doc_cfg))] +#![cfg_attr(docsrs, feature(doc_cfg, rustdoc_internals))] +#![cfg_attr(docsrs, allow(internal_features))] // Unstable functionality only if the user asks for it. For tracking and // discussion of these features please refer to this issue: // diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index 70711afd4..c3a6215ad 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -386,10 +386,19 @@ impl Serialize for ! { macro_rules! tuple_impls { ($($len:expr => ($($n:tt $name:ident)+))+) => { $( + #[cfg_attr(docsrs, doc(hidden))] impl<$($name),+> Serialize for ($($name,)+) where $($name: Serialize,)+ { + tuple_impl_body!($len => ($($n)+)); + } + )+ + }; +} + +macro_rules! tuple_impl_body { + ($len:expr => ($($n:tt)+)) => { #[inline] fn serialize(&self, serializer: S) -> Result where @@ -401,13 +410,22 @@ macro_rules! tuple_impls { )+ tuple.end() } - } - )+ - } + }; +} + +#[cfg_attr(docsrs, doc(fake_variadic))] +#[cfg_attr( + docsrs, + doc = "This trait is implemented for tuples up to 16 items long." +)] +impl Serialize for (T,) +where + T: Serialize, +{ + tuple_impl_body!(1 => (0)); } tuple_impls! { - 1 => (0 T0) 2 => (0 T0 1 T1) 3 => (0 T0 1 T1 2 T2) 4 => (0 T0 1 T1 2 T2 3 T3) From b7b97dda7333baf6474517e3646754be54e3796b Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 25 May 2024 10:11:45 -0700 Subject: [PATCH 2/2] Unindent implementation inside tuple_impl_body macro --- serde/src/de/impls.rs | 104 ++++++++++++++++++++--------------------- serde/src/ser/impls.rs | 22 ++++----- 2 files changed, 63 insertions(+), 63 deletions(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 4f71a20e5..02591d982 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -1406,74 +1406,74 @@ macro_rules! tuple_impls { macro_rules! tuple_impl_body { ($len:tt => ($($n:tt $name:ident)+)) => { + #[inline] + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct TupleVisitor<$($name,)+> { + marker: PhantomData<($($name,)+)>, + } + + impl<'de, $($name: Deserialize<'de>),+> Visitor<'de> for TupleVisitor<$($name,)+> { + type Value = ($($name,)+); + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(concat!("a tuple of size ", $len)) + } + #[inline] - fn deserialize(deserializer: D) -> Result + #[allow(non_snake_case)] + fn visit_seq(self, mut seq: A) -> Result where - D: Deserializer<'de>, + A: SeqAccess<'de>, { - struct TupleVisitor<$($name,)+> { - marker: PhantomData<($($name,)+)>, - } + $( + let $name = match tri!(seq.next_element()) { + Some(value) => value, + None => return Err(Error::invalid_length($n, &self)), + }; + )+ - impl<'de, $($name: Deserialize<'de>),+> Visitor<'de> for TupleVisitor<$($name,)+> { - type Value = ($($name,)+); + Ok(($($name,)+)) + } + } - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str(concat!("a tuple of size ", $len)) - } + deserializer.deserialize_tuple($len, TupleVisitor { marker: PhantomData }) + } - #[inline] - #[allow(non_snake_case)] - fn visit_seq(self, mut seq: A) -> Result - where - A: SeqAccess<'de>, - { - $( - let $name = match tri!(seq.next_element()) { - Some(value) => value, - None => return Err(Error::invalid_length($n, &self)), - }; - )+ + #[inline] + fn deserialize_in_place(deserializer: D, place: &mut Self) -> Result<(), D::Error> + where + D: Deserializer<'de>, + { + struct TupleInPlaceVisitor<'a, $($name: 'a,)+>(&'a mut ($($name,)+)); - Ok(($($name,)+)) - } - } + impl<'a, 'de, $($name: Deserialize<'de>),+> Visitor<'de> for TupleInPlaceVisitor<'a, $($name,)+> { + type Value = (); - deserializer.deserialize_tuple($len, TupleVisitor { marker: PhantomData }) + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(concat!("a tuple of size ", $len)) } #[inline] - fn deserialize_in_place(deserializer: D, place: &mut Self) -> Result<(), D::Error> + #[allow(non_snake_case)] + fn visit_seq(self, mut seq: A) -> Result where - D: Deserializer<'de>, + A: SeqAccess<'de>, { - struct TupleInPlaceVisitor<'a, $($name: 'a,)+>(&'a mut ($($name,)+)); - - impl<'a, 'de, $($name: Deserialize<'de>),+> Visitor<'de> for TupleInPlaceVisitor<'a, $($name,)+> { - type Value = (); - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str(concat!("a tuple of size ", $len)) - } - - #[inline] - #[allow(non_snake_case)] - fn visit_seq(self, mut seq: A) -> Result - where - A: SeqAccess<'de>, - { - $( - if tri!(seq.next_element_seed(InPlaceSeed(&mut (self.0).$n))).is_none() { - return Err(Error::invalid_length($n, &self)); - } - )+ - - Ok(()) + $( + if tri!(seq.next_element_seed(InPlaceSeed(&mut (self.0).$n))).is_none() { + return Err(Error::invalid_length($n, &self)); } - } + )+ - deserializer.deserialize_tuple($len, TupleInPlaceVisitor(place)) + Ok(()) } + } + + deserializer.deserialize_tuple($len, TupleInPlaceVisitor(place)) + } }; } diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index c3a6215ad..557b6aa12 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -399,17 +399,17 @@ macro_rules! tuple_impls { macro_rules! tuple_impl_body { ($len:expr => ($($n:tt)+)) => { - #[inline] - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let mut tuple = tri!(serializer.serialize_tuple($len)); - $( - tri!(tuple.serialize_element(&self.$n)); - )+ - tuple.end() - } + #[inline] + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut tuple = tri!(serializer.serialize_tuple($len)); + $( + tri!(tuple.serialize_element(&self.$n)); + )+ + tuple.end() + } }; }