diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3f5988fbd..249cc08eb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -35,11 +35,10 @@ jobs: rust: stable-x86_64-pc-windows-gnu steps: - uses: actions/checkout@v4 - - name: Install toolchain - run: | - rustup update ${{ matrix.rust }} --no-self-update - rustup default ${{ matrix.rust }} - cargo +stable install cargo-hack --locked + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + - uses: taiki-e/install-action@cargo-hack - run: cargo hack test --feature-powerset --exclude-features max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release @@ -49,11 +48,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Install toolchain - run: | - rustup update stable --no-self-update - rustup default stable - rustup component add clippy rustfmt + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy - run: cargo fmt -- --check - run: cargo fmt --manifest-path test_max_level_features/Cargo.toml -- --check - run: cargo clippy --verbose @@ -64,25 +61,18 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Install toolchain - run: | - rustup update stable --no-self-update - rustup default stable - rustup component add rust-docs + - uses: dtolnay/rust-toolchain@stable - name: Run rustdoc env: RUSTDOCFLAGS: "-D warnings" - run: cargo doc --verbose --features std,serde,sval,sval_ref,value-bag,kv,kv_std,kv_sval,kv_serde + run: cargo doc --verbose --features std,kv,kv_std,kv_sval,kv_serde features: name: Feature check runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Install toolchain - run: | - rustup update nightly --no-self-update - rustup default nightly + - uses: dtolnay/rust-toolchain@nightly - run: cargo build --verbose -Z avoid-dev-deps --features kv - run: cargo build --verbose -Z avoid-dev-deps --features "kv std" - run: cargo build --verbose -Z avoid-dev-deps --features "kv kv_sval" @@ -95,10 +85,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Install toolchain - run: | - rustup update nightly --no-self-update - rustup default nightly + - uses: dtolnay/rust-toolchain@nightly - run: cargo build --verbose -Z minimal-versions --features kv - run: cargo build --verbose -Z minimal-versions --features "kv std" - run: cargo build --verbose -Z minimal-versions --features "kv kv_sval" @@ -111,11 +98,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Install toolchain - run: | - rustup update 1.61.0 --no-self-update - rustup default 1.61.0 - cargo +stable install cargo-hack --locked + - uses: dtolnay/rust-toolchain@1.68.0 + with: + components: clippy + - uses: taiki-e/install-action@cargo-hack - run: cargo hack test --feature-powerset --exclude-features max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release @@ -125,10 +111,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Install toolchain - run: | - rustup update stable --no-self-update - rustup default stable + - uses: dtolnay/rust-toolchain@stable - run: rustup target add thumbv6m-none-eabi riscv32imc-unknown-none-elf - run: cargo build --verbose --target=thumbv6m-none-eabi - run: cargo build --verbose --target=riscv32imc-unknown-none-elf diff --git a/CHANGELOG.md b/CHANGELOG.md index 48f669334..ff039887f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ ## [Unreleased] +## [0.4.29] - 2025-12-02 + +## What's Changed +* perf: reduce llvm-lines of FromStr for `Level` and `LevelFilter` by @dishmaker in https://github.com/rust-lang/log/pull/709 +* Replace serde with serde_core by @Thomasdezeeuw in https://github.com/rust-lang/log/pull/712 + +## New Contributors +* @AldaronLau made their first contribution in https://github.com/rust-lang/log/pull/703 +* @dishmaker made their first contribution in https://github.com/rust-lang/log/pull/709 + +**Full Changelog**: https://github.com/rust-lang/log/compare/0.4.28...0.4.29 + ## [0.4.28] - 2025-09-02 ## What's Changed @@ -377,7 +389,8 @@ version using log 0.4.x to avoid losing module and file information. Look at the [release tags] for information about older releases. -[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.28...HEAD +[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.29...HEAD +[0.4.29]: https://github.com/rust-lang/log/compare/0.4.28...0.4.29 [0.4.28]: https://github.com/rust-lang/log/compare/0.4.27...0.4.28 [0.4.27]: https://github.com/rust-lang/log/compare/0.4.26...0.4.27 [0.4.26]: https://github.com/rust-lang/log/compare/0.4.25...0.4.26 diff --git a/Cargo.toml b/Cargo.toml index 47b847133..964b887e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.4.28" # remember to update html_root_url +version = "0.4.29" # remember to update html_root_url authors = ["The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" @@ -13,7 +13,7 @@ A lightweight logging facade for Rust categories = ["development-tools::debugging"] keywords = ["logging"] exclude = ["rfcs/**/*"] -rust-version = "1.61.0" +rust-version = "1.68.0" edition = "2021" [package.metadata.docs.rs] @@ -41,6 +41,11 @@ kv_sval = ["kv", "value-bag/sval", "sval", "sval_ref"] kv_std = ["std", "kv", "value-bag/error"] kv_serde = ["kv_std", "value-bag/serde", "serde"] +# This is here to not break backwards compatibility with the implicit feature +# that enables support for serde based on the dependency name. Since we're now +# using serde_core, the implicit feature was renamed, this adds back an alias. +serde = ["serde_core"] + # Deprecated: use `kv_*` instead # These `*_unstable` features will be removed in a future release kv_unstable = ["kv", "value-bag"] @@ -49,18 +54,18 @@ kv_unstable_std = ["kv_std", "kv_unstable"] kv_unstable_serde = ["kv_serde", "kv_unstable_std"] [dependencies] -serde = { version = "1.0", optional = true, default-features = false } -sval = { version = "2.14.1", optional = true, default-features = false } -sval_ref = { version = "2.1", optional = true, default-features = false } -value-bag = { version = "1.7", optional = true, default-features = false, features = ["inline-i128"] } +serde_core = { version = "1.0", optional = true, default-features = false } +sval = { version = "2.16", optional = true, default-features = false } +sval_ref = { version = "2.16", optional = true, default-features = false } +value-bag = { version = "1.12", optional = true, default-features = false, features = ["inline-i128"] } [dev-dependencies] serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0" } serde_test = { version = "1.0" } -sval = { version = "2.1" } -sval_derive = { version = "2.1" } -value-bag = { version = "1.7", features = ["test"] } +sval = { version = "2.16" } +sval_derive = { version = "2.16" } +value-bag = { version = "1.12", features = ["test"] } # NOTE: log doesn't actually depend on this crate. However, our dependencies, # serde and sval, dependent on version 1.0 of the crate, which has problem fixed diff --git a/src/__private_api.rs b/src/__private_api.rs index 58d4c0fab..8d4446727 100644 --- a/src/__private_api.rs +++ b/src/__private_api.rs @@ -142,7 +142,7 @@ mod kv_support { } #[cfg(feature = "kv_serde")] - pub fn capture_serde<'a, V: serde::Serialize + ?Sized>(v: &'a &'a V) -> Value<'a> { + pub fn capture_serde<'a, V: serde_core::Serialize + ?Sized>(v: &'a &'a V) -> Value<'a> { Value::from_serde(v) } } diff --git a/src/kv/key.rs b/src/kv/key.rs index 6e00a2ca8..f0557d0cf 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -6,26 +6,26 @@ use std::fmt; /// A type that can be converted into a [`Key`](struct.Key.html). pub trait ToKey { /// Perform the conversion. - fn to_key(&self) -> Key; + fn to_key(&self) -> Key<'_>; } -impl<'a, T> ToKey for &'a T +impl ToKey for &T where T: ToKey + ?Sized, { - fn to_key(&self) -> Key { + fn to_key(&self) -> Key<'_> { (**self).to_key() } } impl<'k> ToKey for Key<'k> { - fn to_key(&self) -> Key { + fn to_key(&self) -> Key<'_> { Key { key: self.key } } } impl ToKey for str { - fn to_key(&self) -> Key { + fn to_key(&self) -> Key<'_> { Key::from_str(self) } } @@ -41,6 +41,7 @@ pub struct Key<'k> { impl<'k> Key<'k> { /// Get a key from a borrowed string. + #[allow(clippy::should_implement_trait)] // Part of the public API now. pub fn from_str(key: &'k str) -> Self { Key { key } } @@ -96,13 +97,13 @@ mod std_support { use std::borrow::Cow; impl ToKey for String { - fn to_key(&self) -> Key { + fn to_key(&self) -> Key<'_> { Key::from_str(self) } } impl<'a> ToKey for Cow<'a, str> { - fn to_key(&self) -> Key { + fn to_key(&self) -> Key<'_> { Key::from_str(self) } } @@ -135,7 +136,7 @@ mod sval_support { mod serde_support { use super::*; - use serde::{Serialize, Serializer}; + use serde_core::{Serialize, Serializer}; impl<'a> Serialize for Key<'a> { fn serialize(&self, serializer: S) -> Result diff --git a/src/kv/mod.rs b/src/kv/mod.rs index 34e61c3ae..dff2179e0 100644 --- a/src/kv/mod.rs +++ b/src/kv/mod.rs @@ -191,7 +191,7 @@ //! //! ``` //! # fn main() -> Result<(), Box> { -//! # #[cfg(feature = "serde")] +//! # #[cfg(feature = "kv_serde")] //! # { //! # use log::kv::Key; //! #[derive(serde::Serialize)] diff --git a/src/kv/source.rs b/src/kv/source.rs index f463e6d2b..a9c6b437b 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -127,7 +127,7 @@ fn count_default(source: impl Source) -> usize { count.0 } -impl<'a, T> Source for &'a T +impl Source for &T where T: Source + ?Sized, { @@ -237,6 +237,7 @@ pub trait VisitSource<'kvs> { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error>; } +#[allow(clippy::needless_lifetimes)] // Not needless. impl<'a, 'kvs, T> VisitSource<'kvs> for &'a mut T where T: VisitSource<'kvs> + ?Sized, diff --git a/src/kv/value.rs b/src/kv/value.rs index e604c806c..5e79bb816 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -10,20 +10,20 @@ pub use crate::kv::Error; /// A type that can be converted into a [`Value`](struct.Value.html). pub trait ToValue { /// Perform the conversion. - fn to_value(&self) -> Value; + fn to_value(&self) -> Value<'_>; } -impl<'a, T> ToValue for &'a T +impl ToValue for &T where T: ToValue + ?Sized, { - fn to_value(&self) -> Value { + fn to_value(&self) -> Value<'_> { (**self).to_value() } } impl<'v> ToValue for Value<'v> { - fn to_value(&self) -> Value { + fn to_value(&self) -> Value<'_> { Value { inner: self.inner.clone(), } @@ -153,7 +153,7 @@ impl<'v> Value<'v> { #[cfg(feature = "kv_serde")] pub fn from_serde(value: &'v T) -> Self where - T: serde::Serialize, + T: serde_core::Serialize, { Value { inner: inner::Inner::from_serde1(value), @@ -232,10 +232,10 @@ impl<'v> fmt::Display for Value<'v> { } #[cfg(feature = "kv_serde")] -impl<'v> serde::Serialize for Value<'v> { +impl<'v> serde_core::Serialize for Value<'v> { fn serialize(&self, s: S) -> Result where - S: serde::Serializer, + S: serde_core::Serializer, { self.inner.serialize(s) } @@ -256,7 +256,7 @@ impl<'v> sval_ref::ValueRef<'v> for Value<'v> { } impl ToValue for str { - fn to_value(&self) -> Value { + fn to_value(&self) -> Value<'_> { Value::from(self) } } @@ -268,7 +268,7 @@ impl<'v> From<&'v str> for Value<'v> { } impl ToValue for () { - fn to_value(&self) -> Value { + fn to_value(&self) -> Value<'_> { Value::from_inner(()) } } @@ -277,7 +277,7 @@ impl ToValue for Option where T: ToValue, { - fn to_value(&self) -> Value { + fn to_value(&self) -> Value<'_> { match *self { Some(ref value) => value.to_value(), None => Value::from_inner(()), @@ -289,7 +289,7 @@ macro_rules! impl_to_value_primitive { ($($into_ty:ty,)*) => { $( impl ToValue for $into_ty { - fn to_value(&self) -> Value { + fn to_value(&self) -> Value<'_> { Value::from(*self) } } @@ -313,7 +313,7 @@ macro_rules! impl_to_value_nonzero_primitive { ($($into_ty:ident,)*) => { $( impl ToValue for std::num::$into_ty { - fn to_value(&self) -> Value { + fn to_value(&self) -> Value<'_> { Value::from(self.get()) } } @@ -398,7 +398,7 @@ mod std_support { where T: ToValue + ?Sized, { - fn to_value(&self) -> Value { + fn to_value(&self) -> Value<'_> { (**self).to_value() } } @@ -407,7 +407,7 @@ mod std_support { where T: ToValue + ?Sized, { - fn to_value(&self) -> Value { + fn to_value(&self) -> Value<'_> { (**self).to_value() } } @@ -416,19 +416,19 @@ mod std_support { where T: ToValue + ?Sized, { - fn to_value(&self) -> Value { + fn to_value(&self) -> Value<'_> { (**self).to_value() } } impl ToValue for String { - fn to_value(&self) -> Value { + fn to_value(&self) -> Value<'_> { Value::from(&**self) } } impl<'v> ToValue for Cow<'v, str> { - fn to_value(&self) -> Value { + fn to_value(&self) -> Value<'_> { Value::from(&**self) } } @@ -535,6 +535,7 @@ pub trait VisitValue<'v> { } } +#[allow(clippy::needless_lifetimes)] // Not needless. impl<'a, 'v, T: ?Sized> VisitValue<'v> for &'a mut T where T: VisitValue<'v>, @@ -1083,7 +1084,7 @@ impl<'v> Value<'v> { #[deprecated(note = "use `from_serde` instead")] pub fn capture_serde(value: &'v T) -> Self where - T: serde::Serialize + 'static, + T: serde_core::Serialize + 'static, { Value::from_serde(value) } diff --git a/src/lib.rs b/src/lib.rs index 47f2cf132..0ad1b3d41 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -142,6 +142,7 @@ //! * [stderrlog] //! * [flexi_logger] //! * [call_logger] +//! * [std-logger] //! * [structured-logger] //! * [clang_log] //! * [ftail] @@ -166,6 +167,7 @@ //! * Utilities: //! * [log_err] //! * [log-reload] +//! * [alterable_logger] //! //! # Implementing a Logger //! @@ -322,6 +324,7 @@ //! [stderrlog]: https://docs.rs/stderrlog/*/stderrlog/ //! [flexi_logger]: https://docs.rs/flexi_logger/*/flexi_logger/ //! [call_logger]: https://docs.rs/call_logger/*/call_logger/ +//! [std-logger]: https://docs.rs/std-logger/*/std_logger/ //! [syslog]: https://docs.rs/syslog/*/syslog/ //! [slog-stdlog]: https://docs.rs/slog-stdlog/*/slog_stdlog/ //! [log4rs]: https://docs.rs/log4rs/*/log4rs/ @@ -338,13 +341,14 @@ //! [logcontrol-log]: https://docs.rs/logcontrol-log/*/logcontrol_log/ //! [log_err]: https://docs.rs/log_err/*/log_err/ //! [log-reload]: https://docs.rs/log-reload/*/log_reload/ +//! [alterable_logger]: https://docs.rs/alterable_logger/*/alterable_logger //! [clang_log]: https://docs.rs/clang_log/latest/clang_log //! [ftail]: https://docs.rs/ftail/latest/ftail #![doc( - html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.28" + html_logo_url = "https://prev.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", + html_favicon_url = "https://prev.rust-lang.org/favicon.ico", + html_root_url = "https://docs.rs/log/0.4.29" )] #![warn(missing_docs)] #![deny(missing_debug_implementations, unconditional_recursion)] @@ -511,14 +515,13 @@ impl PartialOrd for Level { impl FromStr for Level { type Err = ParseLevelError; fn from_str(level: &str) -> Result { - LOG_LEVEL_NAMES - .iter() - .position(|&name| name.eq_ignore_ascii_case(level)) - .into_iter() - .filter(|&idx| idx != 0) - .map(|idx| Level::from_usize(idx).unwrap()) - .next() - .ok_or(ParseLevelError(())) + // iterate from 1, excluding "OFF" + for idx in 1..LOG_LEVEL_NAMES.len() { + if LOG_LEVEL_NAMES[idx].eq_ignore_ascii_case(level) { + return Ok(Level::from_usize(idx).unwrap()); + } + } + Err(ParseLevelError(())) } } @@ -662,11 +665,13 @@ impl PartialOrd for LevelFilter { impl FromStr for LevelFilter { type Err = ParseLevelError; fn from_str(level: &str) -> Result { - LOG_LEVEL_NAMES - .iter() - .position(|&name| name.eq_ignore_ascii_case(level)) - .map(|p| LevelFilter::from_usize(p).unwrap()) - .ok_or(ParseLevelError(())) + // iterate from 0, including "OFF" + for idx in 0..LOG_LEVEL_NAMES.len() { + if LOG_LEVEL_NAMES[idx].eq_ignore_ascii_case(level) { + return Ok(LevelFilter::from_usize(idx).unwrap()); + } + } + Err(ParseLevelError(())) } } @@ -938,7 +943,7 @@ impl<'a> Record<'a> { /// Create a new [`RecordBuilder`](struct.RecordBuilder.html) based on this record. #[cfg(feature = "kv")] #[inline] - pub fn to_builder(&self) -> RecordBuilder { + pub fn to_builder(&self) -> RecordBuilder<'_> { RecordBuilder { record: Record { metadata: Metadata { diff --git a/src/serde.rs b/src/serde.rs index db732395b..f664756f3 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -1,10 +1,10 @@ -#![cfg(feature = "serde")] +#![cfg(feature = "serde_core")] -use serde::de::{ +use serde_core::de::{ Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error, Unexpected, VariantAccess, Visitor, }; -use serde::ser::{Serialize, Serializer}; +use serde_core::ser::{Serialize, Serializer}; use crate::{Level, LevelFilter, LOG_LEVEL_NAMES};