From 338fb6785316d7c2c446e179266a98639bf03af9 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 3 Jun 2018 00:02:29 -0700 Subject: [PATCH 1/3] Implement traits for `!` --- serde/src/de/impls.rs | 10 ++++++++++ serde/src/de/mod.rs | 1 + serde/src/lib.rs | 2 +- serde/src/ser/impls.rs | 10 ++++++++++ serde/src/ser/mod.rs | 1 + 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/serde/src/de/impls.rs b/serde/src/de/impls.rs index 342ca3be..579ee594 100644 --- a/serde/src/de/impls.rs +++ b/serde/src/de/impls.rs @@ -49,6 +49,16 @@ impl<'de> Deserialize<'de> for () { } } +#[cfg(feature = "unstable")] +impl<'de> Deserialize<'de> for ! { + fn deserialize(_deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Err(Error::custom("cannot deserialize `!`")) + } +} + //////////////////////////////////////////////////////////////////////////////// struct BoolVisitor; diff --git a/serde/src/de/mod.rs b/serde/src/de/mod.rs index 10427156..ec1ed5e8 100644 --- a/serde/src/de/mod.rs +++ b/serde/src/de/mod.rs @@ -98,6 +98,7 @@ //! - PathBuf //! - Range\ //! - num::NonZero* +//! - `!` *(unstable)* //! - **Net types**: //! - IpAddr //! - Ipv4Addr diff --git a/serde/src/lib.rs b/serde/src/lib.rs index 9c1535a3..148e1ac4 100644 --- a/serde/src/lib.rs +++ b/serde/src/lib.rs @@ -89,7 +89,7 @@ // discussion of these features please refer to this issue: // // https://github.com/serde-rs/serde/issues/812 -#![cfg_attr(feature = "unstable", feature(specialization))] +#![cfg_attr(feature = "unstable", feature(specialization, never_type))] #![cfg_attr(feature = "alloc", feature(alloc))] #![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))] // Whitelisted clippy lints diff --git a/serde/src/ser/impls.rs b/serde/src/ser/impls.rs index be07d061..3a4a4efe 100644 --- a/serde/src/ser/impls.rs +++ b/serde/src/ser/impls.rs @@ -247,6 +247,16 @@ impl Serialize for () { } } +#[cfg(feature = "unstable")] +impl Serialize for ! { + fn serialize(&self, _serializer: S) -> Result + where + S: Serializer, + { + *self + } +} + //////////////////////////////////////////////////////////////////////////////// macro_rules! tuple_impls { diff --git a/serde/src/ser/mod.rs b/serde/src/ser/mod.rs index c5c9c423..d1d4bd7f 100644 --- a/serde/src/ser/mod.rs +++ b/serde/src/ser/mod.rs @@ -93,6 +93,7 @@ //! - PathBuf //! - Range\ //! - num::NonZero* +//! - `!` *(unstable)* //! - **Net types**: //! - IpAddr //! - Ipv4Addr From fd6178cad63280a63b50b74811813f920c11e9ad Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 3 Jun 2018 00:12:02 -0700 Subject: [PATCH 2/3] IntoDeserializer for `!` --- serde/src/de/value.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/serde/src/de/value.rs b/serde/src/de/value.rs index 56ed7c57..fe097042 100644 --- a/serde/src/de/value.rs +++ b/serde/src/de/value.rs @@ -176,6 +176,48 @@ where //////////////////////////////////////////////////////////////////////////////// +/// A deserializer that cannot be instantiated. +#[cfg(feature = "unstable")] +pub struct NeverDeserializer { + never: !, + marker: PhantomData, +} + +#[cfg(feature = "unstable")] +impl<'de, E> IntoDeserializer<'de, E> for ! +where + E: de::Error, +{ + type Deserializer = NeverDeserializer; + + fn into_deserializer(self) -> Self::Deserializer { + self + } +} + +#[cfg(feature = "unstable")] +impl<'de, E> de::Deserializer<'de> for NeverDeserializer +where + E: de::Error, +{ + type Error = E; + + fn deserialize_any(self, _visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.never + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any + } +} + +//////////////////////////////////////////////////////////////////////////////// + macro_rules! primitive_deserializer { ($ty:ty, $doc:tt, $name:ident, $method:ident $($cast:tt)*) => { #[doc = "A deserializer holding"] From 22b1af7eb3f7ca8765849a342c474027c5119249 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 3 Jun 2018 00:15:05 -0700 Subject: [PATCH 3/3] Test never_type --- test_suite/tests/test_de.rs | 25 +++++++++++++++++++++++++ test_suite/tests/test_ser.rs | 12 ++++++++++++ 2 files changed, 37 insertions(+) diff --git a/test_suite/tests/test_de.rs b/test_suite/tests/test_de.rs index 6c1f3d82..b4ca2e19 100644 --- a/test_suite/tests/test_de.rs +++ b/test_suite/tests/test_de.rs @@ -7,6 +7,7 @@ // except according to those terms. #![cfg_attr(feature = "cargo-clippy", allow(decimal_literal_representation))] +#![cfg_attr(feature = "unstable", feature(never_type))] #[macro_use] extern crate serde_derive; @@ -984,6 +985,16 @@ declare_tests! { } } +#[cfg(feature = "unstable")] +declare_tests! { + test_never_result { + Ok::(0) => &[ + Token::NewtypeVariant { name: "Result", variant: "Ok" }, + Token::U8(0), + ], + } +} + #[cfg(unix)] #[test] fn test_osstring() { @@ -1051,6 +1062,20 @@ fn test_cstr_internal_null_end() { ); } +#[cfg(feature = "unstable")] +#[test] +fn test_never_type() { + assert_de_tokens_error::(&[], "cannot deserialize `!`"); + + assert_de_tokens_error::>( + &[Token::NewtypeVariant { + name: "Result", + variant: "Err", + }], + "cannot deserialize `!`", + ); +} + declare_error_tests! { test_unknown_field { &[ diff --git a/test_suite/tests/test_ser.rs b/test_suite/tests/test_ser.rs index 21c641a7..0d4a35de 100644 --- a/test_suite/tests/test_ser.rs +++ b/test_suite/tests/test_ser.rs @@ -6,6 +6,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![cfg_attr(feature = "unstable", feature(never_type))] + #[macro_use] extern crate serde_derive; @@ -548,6 +550,16 @@ declare_tests! { } } +#[cfg(feature = "unstable")] +declare_tests! { + test_never_result { + Ok::(0) => &[ + Token::NewtypeVariant { name: "Result", variant: "Ok" }, + Token::U8(0), + ], + } +} + #[test] #[cfg(unix)] fn test_cannot_serialize_paths() {