diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d9979825e..e55d307dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -132,6 +132,7 @@ jobs: timeout-minutes: 45 steps: - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable - uses: dtolnay/install@cargo-outdated - run: cargo outdated --exit-code 1 - run: cargo outdated --manifest-path fuzz/Cargo.toml --exit-code 1 diff --git a/Cargo.toml b/Cargo.toml index d4ea3c8d2..4863c56d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "serde_json" -version = "1.0.111" +version = "1.0.117" authors = ["Erick Tryzelaar ", "David Tolnay "] categories = ["encoding", "parser-implementations", "no-std"] description = "A JSON serialization file format" @@ -12,7 +12,7 @@ repository = "https://github.com/serde-rs/json" rust-version = "1.56" [dependencies] -indexmap = { version = "2", optional = true } +indexmap = { version = "2.2.1", optional = true } itoa = "1.0" ryu = "1.0" serde = { version = "1.0.194", default-features = false } @@ -32,9 +32,9 @@ trybuild = { version = "1.0.81", features = ["diff"] } doc-scrape-examples = false [package.metadata.docs.rs] -features = ["raw_value", "unbounded_depth"] +features = ["preserve_order", "raw_value", "unbounded_depth"] targets = ["x86_64-unknown-linux-gnu"] -rustdoc-args = ["--cfg", "docsrs", "--generate-link-to-definition"] +rustdoc-args = ["--generate-link-to-definition"] [package.metadata.playground] features = ["raw_value"] diff --git a/README.md b/README.md index a3ba288f1..be70b7b06 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ enum Value { A string of JSON data can be parsed into a `serde_json::Value` by the [`serde_json::from_str`][from_str] function. There is also -[`from_slice`][from_slice] for parsing from a byte slice &\[u8\] and +[`from_slice`][from_slice] for parsing from a byte slice `&[u8]` and [`from_reader`][from_reader] for parsing from any `io::Read` like a File or a TCP stream. diff --git a/build.rs b/build.rs index dd09e62a3..f2124b43f 100644 --- a/build.rs +++ b/build.rs @@ -3,6 +3,9 @@ use std::env; fn main() { println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rustc-check-cfg=cfg(limb_width_32)"); + println!("cargo:rustc-check-cfg=cfg(limb_width_64)"); + // Decide ideal limb width for arithmetic in the float parser. Refer to // src/lexical/math.rs for where this has an effect. let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); diff --git a/src/de.rs b/src/de.rs index e5221bf51..c815250e1 100644 --- a/src/de.rs +++ b/src/de.rs @@ -510,7 +510,7 @@ impl<'de, R: Read<'de>> Deserializer { // try to keep the number as a `u64` until we grow // too large. At that point, switch to parsing the // value as a `f64`. - if overflow!(significand * 10 + digit, u64::max_value()) { + if overflow!(significand * 10 + digit, u64::MAX) { return Ok(ParserNumber::F64(tri!( self.parse_long_integer(positive, significand), ))); @@ -562,7 +562,7 @@ impl<'de, R: Read<'de>> Deserializer { while let c @ b'0'..=b'9' = tri!(self.peek_or_null()) { let digit = (c - b'0') as u64; - if overflow!(significand * 10 + digit, u64::max_value()) { + if overflow!(significand * 10 + digit, u64::MAX) { let exponent = exponent_before_decimal_point + exponent_after_decimal_point; return self.parse_decimal_overflow(positive, significand, exponent); } @@ -626,7 +626,7 @@ impl<'de, R: Read<'de>> Deserializer { self.eat_char(); let digit = (c - b'0') as i32; - if overflow!(exp * 10 + digit, i32::max_value()) { + if overflow!(exp * 10 + digit, i32::MAX) { let zero_significand = significand == 0; return self.parse_exponent_overflow(positive, zero_significand, positive_exp); } @@ -818,7 +818,7 @@ impl<'de, R: Read<'de>> Deserializer { self.eat_char(); let digit = (c - b'0') as i32; - if overflow!(exp * 10 + digit, i32::max_value()) { + if overflow!(exp * 10 + digit, i32::MAX) { let zero_significand = self.scratch.iter().all(|&digit| digit == b'0'); return self.parse_exponent_overflow(positive, zero_significand, positive_exp); } diff --git a/src/error.rs b/src/error.rs index 74d2e2e2c..78e48e079 100644 --- a/src/error.rs +++ b/src/error.rs @@ -435,11 +435,20 @@ impl de::Error for Error { #[cold] fn invalid_type(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self { - if let de::Unexpected::Unit = unexp { - Error::custom(format_args!("invalid type: null, expected {}", exp)) - } else { - Error::custom(format_args!("invalid type: {}, expected {}", unexp, exp)) - } + Error::custom(format_args!( + "invalid type: {}, expected {}", + JsonUnexpected(unexp), + exp, + )) + } + + #[cold] + fn invalid_value(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self { + Error::custom(format_args!( + "invalid value: {}, expected {}", + JsonUnexpected(unexp), + exp, + )) } } @@ -450,6 +459,22 @@ impl ser::Error for Error { } } +struct JsonUnexpected<'a>(de::Unexpected<'a>); + +impl<'a> Display for JsonUnexpected<'a> { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + de::Unexpected::Unit => formatter.write_str("null"), + de::Unexpected::Float(value) => write!( + formatter, + "floating point `{}`", + ryu::Buffer::new().format(value), + ), + unexp => Display::fmt(&unexp, formatter), + } + } +} + // Parse our own error message that looks like "{} at line {} column {}" to work // around erased-serde round-tripping the error through de::Error::custom. fn make_error(mut msg: String) -> Error { diff --git a/src/features_check/error.rs b/src/features_check/error.rs deleted file mode 100644 index 22e58235c..000000000 --- a/src/features_check/error.rs +++ /dev/null @@ -1 +0,0 @@ -"serde_json requires that either `std` (default) or `alloc` feature is enabled" diff --git a/src/features_check/mod.rs b/src/features_check/mod.rs deleted file mode 100644 index d12032cef..000000000 --- a/src/features_check/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! Shows a user-friendly compiler error on incompatible selected features. - -#[allow(unused_macros)] -macro_rules! hide_from_rustfmt { - ($mod:item) => { - $mod - }; -} - -#[cfg(not(any(feature = "std", feature = "alloc")))] -hide_from_rustfmt! { - mod error; -} diff --git a/src/lexical/bignum.rs b/src/lexical/bignum.rs index f9551f534..4fa7eed6d 100644 --- a/src/lexical/bignum.rs +++ b/src/lexical/bignum.rs @@ -3,6 +3,7 @@ //! Big integer type definition. use super::math::*; +#[allow(unused_imports)] use alloc::vec::Vec; /// Storage for a big integer type. diff --git a/src/lexical/exponent.rs b/src/lexical/exponent.rs index 6fc51977e..5e27de893 100644 --- a/src/lexical/exponent.rs +++ b/src/lexical/exponent.rs @@ -8,8 +8,8 @@ /// the mantissa we do not overflow for comically-long exponents. #[inline] fn into_i32(value: usize) -> i32 { - if value > i32::max_value() as usize { - i32::max_value() + if value > i32::MAX as usize { + i32::MAX } else { value as i32 } diff --git a/src/lexical/large_powers32.rs b/src/lexical/large_powers32.rs index 799119726..eb8582f5f 100644 --- a/src/lexical/large_powers32.rs +++ b/src/lexical/large_powers32.rs @@ -2,7 +2,7 @@ //! Precalculated large powers for 32-bit limbs. -/// Large powers (&[u32]) for base5 operations. +/// Large powers (`&[u32]`) for base5 operations. const POW5_1: [u32; 1] = [5]; const POW5_2: [u32; 1] = [25]; const POW5_3: [u32; 1] = [625]; diff --git a/src/lexical/large_powers64.rs b/src/lexical/large_powers64.rs index ee3656108..96554eac1 100644 --- a/src/lexical/large_powers64.rs +++ b/src/lexical/large_powers64.rs @@ -2,7 +2,7 @@ //! Precalculated large powers for 64-bit limbs. -/// Large powers (&[u64]) for base5 operations. +/// Large powers (`&[u64]`) for base5 operations. const POW5_1: [u64; 1] = [5]; const POW5_2: [u64; 1] = [25]; const POW5_3: [u64; 1] = [625]; diff --git a/src/lexical/num.rs b/src/lexical/num.rs index e47e00341..75eee01b8 100644 --- a/src/lexical/num.rs +++ b/src/lexical/num.rs @@ -223,7 +223,7 @@ pub trait Float: Number { const NEGATIVE_INFINITY_BITS: Self::Unsigned; /// Size of the significand (mantissa) without hidden bit. const MANTISSA_SIZE: i32; - /// Bias of the exponet + /// Bias of the exponent const EXPONENT_BIAS: i32; /// Exponent portion of a denormal float. const DENORMAL_EXPONENT: i32; @@ -248,7 +248,6 @@ pub trait Float: Number { fn from_bits(u: Self::Unsigned) -> Self; fn to_bits(self) -> Self::Unsigned; fn is_sign_positive(self) -> bool; - fn is_sign_negative(self) -> bool; /// Returns true if the float is a denormal. #[inline] @@ -368,11 +367,6 @@ impl Float for f32 { fn is_sign_positive(self) -> bool { f32::is_sign_positive(self) } - - #[inline] - fn is_sign_negative(self) -> bool { - f32::is_sign_negative(self) - } } impl Float for f64 { @@ -432,9 +426,4 @@ impl Float for f64 { fn is_sign_positive(self) -> bool { f64::is_sign_positive(self) } - - #[inline] - fn is_sign_negative(self) -> bool { - f64::is_sign_negative(self) - } } diff --git a/src/lexical/rounding.rs b/src/lexical/rounding.rs index 6ec1292aa..634487522 100644 --- a/src/lexical/rounding.rs +++ b/src/lexical/rounding.rs @@ -25,7 +25,7 @@ pub(crate) fn lower_n_mask(n: u64) -> u64 { debug_assert!(n <= bits, "lower_n_mask() overflow in shl."); if n == bits { - u64::max_value() + u64::MAX } else { (1 << n) - 1 } diff --git a/src/lib.rs b/src/lib.rs index 3cdbd3ae3..475cd4475 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,7 +56,7 @@ //! //! A string of JSON data can be parsed into a `serde_json::Value` by the //! [`serde_json::from_str`][from_str] function. There is also [`from_slice`] -//! for parsing from a byte slice &\[u8\] and [`from_reader`] for parsing from +//! for parsing from a byte slice `&[u8]` and [`from_reader`] for parsing from //! any `io::Read` like a File or a TCP stream. //! //! ``` @@ -299,7 +299,7 @@ //! [macro]: crate::json //! [`serde-json-core`]: https://github.com/rust-embedded-community/serde-json-core -#![doc(html_root_url = "https://docs.rs/serde_json/1.0.111")] +#![doc(html_root_url = "https://docs.rs/serde_json/1.0.117")] // Ignored clippy lints #![allow( clippy::collapsible_else_if, @@ -316,6 +316,7 @@ clippy::needless_late_init, clippy::return_self_not_must_use, clippy::transmute_ptr_to_ptr, + clippy::unconditional_recursion, // https://github.com/rust-lang/rust-clippy/issues/12133 clippy::unnecessary_wraps )] // Ignored clippy_pedantic lints @@ -359,11 +360,19 @@ #![deny(clippy::question_mark_used)] #![allow(non_upper_case_globals)] #![deny(missing_docs)] -#![cfg_attr(not(feature = "std"), no_std)] +#![no_std] #![cfg_attr(docsrs, feature(doc_cfg))] +#[cfg(not(any(feature = "std", feature = "alloc")))] +compile_error! { + "serde_json requires that either `std` (default) or `alloc` feature is enabled" +} + extern crate alloc; +#[cfg(feature = "std")] +extern crate std; + #[cfg(feature = "std")] #[cfg_attr(docsrs, doc(cfg(feature = "std")))] #[doc(inline)] @@ -405,8 +414,6 @@ pub mod ser; mod ser; pub mod value; -mod features_check; - mod io; #[cfg(feature = "std")] mod iter; diff --git a/src/map.rs b/src/map.rs index 675058ba1..520cd6cf5 100644 --- a/src/map.rs +++ b/src/map.rs @@ -20,7 +20,7 @@ use serde::de; #[cfg(not(feature = "preserve_order"))] use alloc::collections::{btree_map, BTreeMap}; #[cfg(feature = "preserve_order")] -use indexmap::{self, IndexMap}; +use indexmap::IndexMap; /// Represents a JSON key/value type. pub struct Map { @@ -130,6 +130,12 @@ impl Map { /// /// The key may be any borrowed form of the map's key type, but the ordering /// on the borrowed form *must* match the ordering on the key type. + /// + /// If serde_json's "preserve_order" is enabled, `.remove(key)` is + /// equivalent to [`.swap_remove(key)`][Self::swap_remove], replacing this + /// entry's position with the last element. If you need to preserve the + /// relative order of the keys in the map, use + /// [`.shift_remove(key)`][Self::shift_remove] instead. #[inline] pub fn remove(&mut self, key: &Q) -> Option where @@ -137,7 +143,7 @@ impl Map { Q: ?Sized + Ord + Eq + Hash, { #[cfg(feature = "preserve_order")] - return self.map.swap_remove(key); + return self.swap_remove(key); #[cfg(not(feature = "preserve_order"))] return self.map.remove(key); } @@ -147,12 +153,94 @@ impl Map { /// /// The key may be any borrowed form of the map's key type, but the ordering /// on the borrowed form *must* match the ordering on the key type. + /// + /// If serde_json's "preserve_order" is enabled, `.remove_entry(key)` is + /// equivalent to [`.swap_remove_entry(key)`][Self::swap_remove_entry], + /// replacing this entry's position with the last element. If you need to + /// preserve the relative order of the keys in the map, use + /// [`.shift_remove_entry(key)`][Self::shift_remove_entry] instead. + #[inline] pub fn remove_entry(&mut self, key: &Q) -> Option<(String, Value)> where String: Borrow, Q: ?Sized + Ord + Eq + Hash, { - self.map.remove_entry(key) + #[cfg(feature = "preserve_order")] + return self.swap_remove_entry(key); + #[cfg(not(feature = "preserve_order"))] + return self.map.remove_entry(key); + } + + /// Removes and returns the value corresponding to the key from the map. + /// + /// Like [`Vec::swap_remove`], the entry is removed by swapping it with the + /// last element of the map and popping it off. This perturbs the position + /// of what used to be the last element! + /// + /// [`Vec::swap_remove`]: std::vec::Vec::swap_remove + #[cfg(feature = "preserve_order")] + #[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))] + #[inline] + pub fn swap_remove(&mut self, key: &Q) -> Option + where + String: Borrow, + Q: ?Sized + Ord + Eq + Hash, + { + self.map.swap_remove(key) + } + + /// Remove and return the key-value pair. + /// + /// Like [`Vec::swap_remove`], the entry is removed by swapping it with the + /// last element of the map and popping it off. This perturbs the position + /// of what used to be the last element! + /// + /// [`Vec::swap_remove`]: std::vec::Vec::swap_remove + #[cfg(feature = "preserve_order")] + #[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))] + #[inline] + pub fn swap_remove_entry(&mut self, key: &Q) -> Option<(String, Value)> + where + String: Borrow, + Q: ?Sized + Ord + Eq + Hash, + { + self.map.swap_remove_entry(key) + } + + /// Removes and returns the value corresponding to the key from the map. + /// + /// Like [`Vec::remove`], the entry is removed by shifting all of the + /// elements that follow it, preserving their relative order. This perturbs + /// the index of all of those elements! + /// + /// [`Vec::remove`]: std::vec::Vec::remove + #[cfg(feature = "preserve_order")] + #[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))] + #[inline] + pub fn shift_remove(&mut self, key: &Q) -> Option + where + String: Borrow, + Q: ?Sized + Ord + Eq + Hash, + { + self.map.shift_remove(key) + } + + /// Remove and return the key-value pair. + /// + /// Like [`Vec::remove`], the entry is removed by shifting all of the + /// elements that follow it, preserving their relative order. This perturbs + /// the index of all of those elements! + /// + /// [`Vec::remove`]: std::vec::Vec::remove + #[cfg(feature = "preserve_order")] + #[cfg_attr(docsrs, doc(cfg(feature = "preserve_order")))] + #[inline] + pub fn shift_remove_entry(&mut self, key: &Q) -> Option<(String, Value)> + where + String: Borrow, + Q: ?Sized + Ord + Eq + Hash, + { + self.map.shift_remove_entry(key) } /// Moves all elements from other into self, leaving other empty. diff --git a/src/number.rs b/src/number.rs index b0231a87b..878a3dcb2 100644 --- a/src/number.rs +++ b/src/number.rs @@ -82,7 +82,7 @@ impl Number { /// ``` /// # use serde_json::json; /// # - /// let big = i64::max_value() as u64 + 10; + /// let big = i64::MAX as u64 + 10; /// let v = json!({ "a": 64, "b": big, "c": 256.0 }); /// /// assert!(v["a"].is_i64()); @@ -97,7 +97,7 @@ impl Number { pub fn is_i64(&self) -> bool { #[cfg(not(feature = "arbitrary_precision"))] match self.n { - N::PosInt(v) => v <= i64::max_value() as u64, + N::PosInt(v) => v <= i64::MAX as u64, N::NegInt(_) => true, N::Float(_) => false, } @@ -177,7 +177,7 @@ impl Number { /// ``` /// # use serde_json::json; /// # - /// let big = i64::max_value() as u64 + 10; + /// let big = i64::MAX as u64 + 10; /// let v = json!({ "a": 64, "b": big, "c": 256.0 }); /// /// assert_eq!(v["a"].as_i64(), Some(64)); @@ -189,7 +189,7 @@ impl Number { #[cfg(not(feature = "arbitrary_precision"))] match self.n { N::PosInt(n) => { - if n <= i64::max_value() as u64 { + if n <= i64::MAX as u64 { Some(n as i64) } else { None diff --git a/src/raw.rs b/src/raw.rs index a2bf0ecbb..22d14441e 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -112,8 +112,8 @@ use serde::ser::{Serialize, SerializeStruct, Serializer}; /// raw_value: Box, /// } /// ``` -#[cfg_attr(not(doc), repr(transparent))] #[cfg_attr(docsrs, doc(cfg(feature = "raw_value")))] +#[repr(transparent)] pub struct RawValue { json: str, } diff --git a/src/read.rs b/src/read.rs index 7446f28b9..a426911c7 100644 --- a/src/read.rs +++ b/src/read.rs @@ -14,11 +14,13 @@ use crate::iter::LineColIterator; use crate::raw::BorrowedRawDeserializer; #[cfg(all(feature = "raw_value", feature = "std"))] use crate::raw::OwnedRawDeserializer; +#[cfg(all(feature = "raw_value", feature = "std"))] +use alloc::string::String; #[cfg(feature = "raw_value")] use serde::de::Visitor; /// Trait used by the deserializer for iterating over input. This is manually -/// "specialized" for iterating over &[u8]. Once feature(specialization) is +/// "specialized" for iterating over `&[u8]`. Once feature(specialization) is /// stable we can use actual specialization. /// /// This trait is sealed and cannot be implemented for types outside of diff --git a/src/value/de.rs b/src/value/de.rs index 1e8b5acbb..936725635 100644 --- a/src/value/de.rs +++ b/src/value/de.rs @@ -219,6 +219,8 @@ impl<'de> serde::Deserializer<'de> for Value { Value::Number(n) => n.deserialize_any(visitor), #[cfg(any(feature = "std", feature = "alloc"))] Value::String(v) => visitor.visit_string(v), + #[cfg(not(any(feature = "std", feature = "alloc")))] + Value::String(_) => unreachable!(), Value::Array(v) => visit_array(v, visitor), Value::Object(v) => visit_object(v, visitor), } @@ -1339,6 +1341,8 @@ impl<'de> de::Deserializer<'de> for BorrowedCowStrDeserializer<'de> { Cow::Borrowed(string) => visitor.visit_borrowed_str(string), #[cfg(any(feature = "std", feature = "alloc"))] Cow::Owned(string) => visitor.visit_string(string), + #[cfg(not(any(feature = "std", feature = "alloc")))] + Cow::Owned(_) => unreachable!(), } } diff --git a/src/value/ser.rs b/src/value/ser.rs index 835fa9080..e869ae160 100644 --- a/src/value/ser.rs +++ b/src/value/ser.rs @@ -29,6 +29,8 @@ impl Serialize for Value { } map.end() } + #[cfg(not(any(feature = "std", feature = "alloc")))] + Value::Object(_) => unreachable!(), } } } diff --git a/tests/lexical/exponent.rs b/tests/lexical/exponent.rs index f7a847be3..c109ff07d 100644 --- a/tests/lexical/exponent.rs +++ b/tests/lexical/exponent.rs @@ -17,38 +17,20 @@ fn scientific_exponent_test() { assert_eq!(scientific_exponent(-10, 2, 20), -9); // Underflow - assert_eq!( - scientific_exponent(i32::min_value(), 0, 0), - i32::min_value() - ); - assert_eq!( - scientific_exponent(i32::min_value(), 0, 5), - i32::min_value() - ); + assert_eq!(scientific_exponent(i32::MIN, 0, 0), i32::MIN); + assert_eq!(scientific_exponent(i32::MIN, 0, 5), i32::MIN); // Overflow - assert_eq!( - scientific_exponent(i32::max_value(), 0, 0), - i32::max_value() - 1 - ); - assert_eq!( - scientific_exponent(i32::max_value(), 5, 0), - i32::max_value() - ); + assert_eq!(scientific_exponent(i32::MAX, 0, 0), i32::MAX - 1); + assert_eq!(scientific_exponent(i32::MAX, 5, 0), i32::MAX); } #[test] fn mantissa_exponent_test() { assert_eq!(mantissa_exponent(10, 5, 0), 5); assert_eq!(mantissa_exponent(0, 5, 0), -5); - assert_eq!( - mantissa_exponent(i32::max_value(), 5, 0), - i32::max_value() - 5 - ); - assert_eq!(mantissa_exponent(i32::max_value(), 0, 5), i32::max_value()); - assert_eq!(mantissa_exponent(i32::min_value(), 5, 0), i32::min_value()); - assert_eq!( - mantissa_exponent(i32::min_value(), 0, 5), - i32::min_value() + 5 - ); + assert_eq!(mantissa_exponent(i32::MAX, 5, 0), i32::MAX - 5); + assert_eq!(mantissa_exponent(i32::MAX, 0, 5), i32::MAX); + assert_eq!(mantissa_exponent(i32::MIN, 5, 0), i32::MIN); + assert_eq!(mantissa_exponent(i32::MIN, 0, 5), i32::MIN + 5); } diff --git a/tests/regression/issue520.rs b/tests/regression/issue520.rs index 9ed367731..730ecc60a 100644 --- a/tests/regression/issue520.rs +++ b/tests/regression/issue520.rs @@ -1,6 +1,6 @@ #![allow(clippy::float_cmp)] -use serde_derive::{Serialize, Deserialize}; +use serde_derive::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] #[serde(tag = "type", content = "data")] diff --git a/tests/regression/issue795.rs b/tests/regression/issue795.rs index bb82852c5..411e8af5d 100644 --- a/tests/regression/issue795.rs +++ b/tests/regression/issue795.rs @@ -8,7 +8,10 @@ use std::fmt; #[derive(Debug)] pub enum Enum { - Variant { x: u8 }, + Variant { + #[allow(dead_code)] + x: u8, + }, } impl<'de> Deserialize<'de> for Enum { diff --git a/tests/regression/issue845.rs b/tests/regression/issue845.rs index e8b0c0fd0..7b6564dad 100644 --- a/tests/regression/issue845.rs +++ b/tests/regression/issue845.rs @@ -60,6 +60,7 @@ where #[derive(Deserialize, Debug)] pub struct Struct { #[serde(deserialize_with = "deserialize_integer_or_string")] + #[allow(dead_code)] pub i: i64, } diff --git a/tests/test.rs b/tests/test.rs index 05b7f86fc..8c9af6b32 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -5,6 +5,7 @@ clippy::derive_partial_eq_without_eq, clippy::excessive_precision, clippy::float_cmp, + clippy::incompatible_msrv, // https://github.com/rust-lang/rust-clippy/issues/12257 clippy::items_after_statements, clippy::let_underscore_untyped, clippy::shadow_unrelated, @@ -42,10 +43,7 @@ use std::iter; use std::marker::PhantomData; use std::mem; use std::str::FromStr; -use std::string::ToString; use std::{f32, f64}; -use std::{i16, i32, i64, i8}; -use std::{u16, u32, u64, u8}; macro_rules! treemap { () => { @@ -158,28 +156,28 @@ fn test_write_f64() { #[test] fn test_encode_nonfinite_float_yields_null() { - let v = to_value(::std::f64::NAN.copysign(1.0)).unwrap(); + let v = to_value(f64::NAN.copysign(1.0)).unwrap(); assert!(v.is_null()); - let v = to_value(::std::f64::NAN.copysign(-1.0)).unwrap(); + let v = to_value(f64::NAN.copysign(-1.0)).unwrap(); assert!(v.is_null()); - let v = to_value(::std::f64::INFINITY).unwrap(); + let v = to_value(f64::INFINITY).unwrap(); assert!(v.is_null()); - let v = to_value(-::std::f64::INFINITY).unwrap(); + let v = to_value(-f64::INFINITY).unwrap(); assert!(v.is_null()); - let v = to_value(::std::f32::NAN.copysign(1.0)).unwrap(); + let v = to_value(f32::NAN.copysign(1.0)).unwrap(); assert!(v.is_null()); - let v = to_value(::std::f32::NAN.copysign(-1.0)).unwrap(); + let v = to_value(f32::NAN.copysign(-1.0)).unwrap(); assert!(v.is_null()); - let v = to_value(::std::f32::INFINITY).unwrap(); + let v = to_value(f32::INFINITY).unwrap(); assert!(v.is_null()); - let v = to_value(-::std::f32::INFINITY).unwrap(); + let v = to_value(-f32::INFINITY).unwrap(); assert!(v.is_null()); } @@ -2102,20 +2100,20 @@ fn issue_220() { assert_eq!(from_str::(r#"{"V": 0}"#).unwrap(), E::V(0)); } -macro_rules! number_partialeq_ok { - ($($n:expr)*) => { - $( - let value = to_value($n).unwrap(); - let s = $n.to_string(); - assert_eq!(value, $n); - assert_eq!($n, value); - assert_ne!(value, s); - )* - } -} - #[test] fn test_partialeq_number() { + macro_rules! number_partialeq_ok { + ($($n:expr)*) => { + $( + let value = to_value($n).unwrap(); + let s = $n.to_string(); + assert_eq!(value, $n); + assert_eq!($n, value); + assert_ne!(value, s); + )* + }; + } + number_partialeq_ok!(0 1 100 i8::MIN i8::MAX i16::MIN i16::MAX i32::MIN i32::MAX i64::MIN i64::MAX u8::MIN u8::MAX u16::MIN u16::MAX u32::MIN u32::MAX u64::MIN u64::MAX @@ -2126,13 +2124,6 @@ fn test_partialeq_number() { ); } -#[test] -#[cfg(integer128)] -#[cfg(feature = "arbitrary_precision")] -fn test_partialeq_integer128() { - number_partialeq_ok!(i128::MIN i128::MAX u128::MIN u128::MAX) -} - #[test] fn test_partialeq_string() { let v = to_value("42").unwrap(); @@ -2240,8 +2231,8 @@ fn null_invalid_type() { #[test] fn test_integer128() { - let signed = &[i128::min_value(), -1, 0, 1, i128::max_value()]; - let unsigned = &[0, 1, u128::max_value()]; + let signed = &[i128::MIN, -1, 0, 1, i128::MAX]; + let unsigned = &[0, 1, u128::MAX]; for integer128 in signed { let expected = integer128.to_string(); @@ -2277,8 +2268,8 @@ fn test_integer128() { #[test] fn test_integer128_to_value() { - let signed = &[i128::from(i64::min_value()), i128::from(u64::max_value())]; - let unsigned = &[0, u128::from(u64::max_value())]; + let signed = &[i128::from(i64::MIN), i128::from(u64::MAX)]; + let unsigned = &[0, u128::from(u64::MAX)]; for integer128 in signed { let expected = integer128.to_string(); @@ -2291,7 +2282,7 @@ fn test_integer128_to_value() { } if !cfg!(feature = "arbitrary_precision") { - let err = to_value(u128::from(u64::max_value()) + 1).unwrap_err(); + let err = to_value(u128::from(u64::MAX) + 1).unwrap_err(); assert_eq!(err.to_string(), "number out of range"); } } @@ -2335,6 +2326,8 @@ fn test_raw_value_in_map_key() { #[repr(transparent)] struct RawMapKey(RawValue); + #[allow(unknown_lints)] + #[allow(non_local_definitions)] // false positive: https://github.com/rust-lang/rust/issues/121621 impl<'de> Deserialize<'de> for &'de RawMapKey { fn deserialize(deserializer: D) -> Result where