From 3dd2760ed7b4eba417104794d9c562eced395b12 Mon Sep 17 00:00:00 2001 From: RA <70325462+RAprogramm@users.noreply.github.com> Date: Wed, 24 Sep 2025 11:18:43 +0700 Subject: [PATCH] Fix conversions for Rust 1.89 compatibility --- CHANGELOG.md | 12 ++++ Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 14 ++--- src/app_error.rs | 4 +- src/app_error/core.rs | 44 +++++++++++-- src/app_error/tests.rs | 19 +++--- src/convert/actix.rs | 8 +-- src/convert/config.rs | 3 + src/convert/redis.rs | 23 ++++--- src/convert/serde_json.rs | 15 ++++- src/convert/sqlx.rs | 29 +++++++-- src/convert/tonic.rs | 62 ++++++++----------- src/result_ext.rs | 19 +++--- .../fail/enum_missing_variant.stderr | 7 +-- tests/ui/app_error/fail/missing_code.stderr | 4 +- tests/ui/app_error/fail/missing_kind.stderr | 2 +- tests/ui/formatter/fail/duplicate_fmt.stderr | 2 +- .../fail/implicit_after_named.stderr | 1 - .../ui/formatter/fail/unsupported_flag.stderr | 4 +- .../fail/unsupported_formatter.stderr | 4 +- .../ui/formatter/fail/uppercase_binary.stderr | 4 +- .../formatter/fail/uppercase_pointer.stderr | 4 +- tests/ui/masterror/fail/duplicate_attr.stderr | 2 +- .../masterror/fail/duplicate_telemetry.stderr | 2 +- tests/ui/masterror/fail/empty_redact.stderr | 2 +- .../fail/enum_missing_variant.stderr | 7 +-- .../ui/masterror/fail/missing_category.stderr | 4 +- tests/ui/masterror/fail/missing_code.stderr | 4 +- tests/ui/masterror/fail/unknown_option.stderr | 2 +- 30 files changed, 181 insertions(+), 130 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d6eccd..9a0b0af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [0.20.2] - 2025-10-02 + +### Fixed +- Restored compatibility with Rust 1.89 by updating gRPC, Redis, SQLx and + serde_json integrations to avoid deprecated APIs, unsafe environment + mutations and Debug requirements that no longer hold. +- Added deterministic backtrace preference overrides for unit tests so + telemetry behavior remains covered without mutating global environment + variables. +- Ensured config error mapping gracefully handles new non-exhaustive variants + by falling back to a generic context that captures the formatted error. + ## [0.20.1] - 2025-10-01 ### Changed diff --git a/Cargo.lock b/Cargo.lock index 18742cd..bba324d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1727,7 +1727,7 @@ dependencies = [ [[package]] name = "masterror" -version = "0.20.1" +version = "0.20.2" dependencies = [ "actix-web", "axum 0.8.4", diff --git a/Cargo.toml b/Cargo.toml index b36f3aa..236991d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "masterror" -version = "0.20.1" +version = "0.20.2" rust-version = "1.90" edition = "2024" license = "MIT OR Apache-2.0" diff --git a/README.md b/README.md index b5cdc06..4bedfff 100644 --- a/README.md +++ b/README.md @@ -38,9 +38,9 @@ guides, comparisons with `thiserror`/`anyhow`, and troubleshooting recipes. ~~~toml [dependencies] -masterror = { version = "0.20.1", default-features = false } +masterror = { version = "0.20.2", default-features = false } # or with features: -# masterror = { version = "0.20.1", features = [ +# masterror = { version = "0.20.2", features = [ # "axum", "actix", "openapi", "serde_json", # "tracing", "metrics", "backtrace", "sqlx", # "sqlx-migrate", "reqwest", "redis", "validator", @@ -78,10 +78,10 @@ masterror = { version = "0.20.1", default-features = false } ~~~toml [dependencies] # lean core -masterror = { version = "0.20.1", default-features = false } +masterror = { version = "0.20.2", default-features = false } # with Axum/Actix + JSON + integrations -# masterror = { version = "0.20.1", features = [ +# masterror = { version = "0.20.2", features = [ # "axum", "actix", "openapi", "serde_json", # "tracing", "metrics", "backtrace", "sqlx", # "sqlx-migrate", "reqwest", "redis", "validator", @@ -720,13 +720,13 @@ assert_eq!(problem.grpc.expect("grpc").name, "UNAUTHENTICATED"); Minimal core: ~~~toml -masterror = { version = "0.20.1", default-features = false } +masterror = { version = "0.20.2", default-features = false } ~~~ API (Axum + JSON + deps): ~~~toml -masterror = { version = "0.20.1", features = [ +masterror = { version = "0.20.2", features = [ "axum", "serde_json", "openapi", "sqlx", "reqwest", "redis", "validator", "config", "tokio" ] } @@ -735,7 +735,7 @@ masterror = { version = "0.20.1", features = [ API (Actix + JSON + deps): ~~~toml -masterror = { version = "0.20.1", features = [ +masterror = { version = "0.20.2", features = [ "actix", "serde_json", "openapi", "sqlx", "reqwest", "redis", "validator", "config", "tokio" ] } diff --git a/src/app_error.rs b/src/app_error.rs index a154446..d952cc0 100644 --- a/src/app_error.rs +++ b/src/app_error.rs @@ -67,9 +67,9 @@ mod context; mod core; mod metadata; -#[cfg(all(test, feature = "backtrace"))] -pub(crate) use core::reset_backtrace_preference; pub use core::{AppError, AppResult, Error, MessageEditPolicy}; +#[cfg(all(test, feature = "backtrace"))] +pub(crate) use core::{reset_backtrace_preference, set_backtrace_preference_override}; pub use context::Context; pub use metadata::{Field, FieldRedaction, FieldValue, Metadata, field}; diff --git a/src/app_error/core.rs b/src/app_error/core.rs index 38cff1b..cf43ec8 100644 --- a/src/app_error/core.rs +++ b/src/app_error/core.rs @@ -95,6 +95,11 @@ fn should_capture_backtrace() -> bool { #[cfg(feature = "backtrace")] fn detect_backtrace_preference() -> bool { + #[cfg(all(test, feature = "backtrace"))] + if let Some(value) = test_backtrace_override::get() { + return value; + } + match env::var_os("RUST_BACKTRACE") { None => false, Some(value) => { @@ -112,6 +117,40 @@ fn detect_backtrace_preference() -> bool { #[cfg(all(test, feature = "backtrace"))] pub(crate) fn reset_backtrace_preference() { BACKTRACE_STATE.store(BACKTRACE_STATE_UNSET, AtomicOrdering::Release); + test_backtrace_override::set(None); +} + +#[cfg(all(test, feature = "backtrace"))] +pub(crate) fn set_backtrace_preference_override(value: Option) { + test_backtrace_override::set(value); +} + +#[cfg(all(test, feature = "backtrace"))] +mod test_backtrace_override { + use std::sync::atomic::{AtomicI8, Ordering}; + + const OVERRIDE_UNSET: i8 = -1; + const OVERRIDE_DISABLED: i8 = 0; + const OVERRIDE_ENABLED: i8 = 1; + + static OVERRIDE_STATE: AtomicI8 = AtomicI8::new(OVERRIDE_UNSET); + + pub(super) fn set(value: Option) { + let state = match value { + Some(true) => OVERRIDE_ENABLED, + Some(false) => OVERRIDE_DISABLED, + None => OVERRIDE_UNSET + }; + OVERRIDE_STATE.store(state, Ordering::Release); + } + + pub(super) fn get() -> Option { + match OVERRIDE_STATE.load(Ordering::Acquire) { + OVERRIDE_ENABLED => Some(true), + OVERRIDE_DISABLED => Some(false), + _ => None + } + } } /// Rich application error preserving domain code, taxonomy and metadata. @@ -151,11 +190,6 @@ impl StdError for Error { .as_deref() .map(|source| source as &(dyn StdError + 'static)) } - - #[cfg(feature = "backtrace")] - fn backtrace(&self) -> Option<&Backtrace> { - self.capture_backtrace() - } } /// Conventional result alias for application code. diff --git a/src/app_error/tests.rs b/src/app_error/tests.rs index d1d33d0..69be3b7 100644 --- a/src/app_error/tests.rs +++ b/src/app_error/tests.rs @@ -1,9 +1,9 @@ -use std::{borrow::Cow, error::Error as StdError, fmt::Display, sync::Arc}; #[cfg(feature = "backtrace")] -use std::{env, sync::Mutex}; +use std::sync::Mutex; +use std::{borrow::Cow, error::Error as StdError, fmt::Display, sync::Arc}; #[cfg(feature = "backtrace")] -use super::core::reset_backtrace_preference; +use super::core::{reset_backtrace_preference, set_backtrace_preference_override}; #[cfg(feature = "backtrace")] static BACKTRACE_ENV_GUARD: Mutex<()> = Mutex::new(()); @@ -270,22 +270,19 @@ fn error_chain_is_preserved() { } #[cfg(feature = "backtrace")] -fn with_backtrace_env(value: Option<&str>, test: F) { +fn with_backtrace_preference(value: Option, test: F) { let _guard = BACKTRACE_ENV_GUARD.lock().expect("env guard"); reset_backtrace_preference(); - match value { - Some(val) => env::set_var("RUST_BACKTRACE", val), - None => env::remove_var("RUST_BACKTRACE") - } + set_backtrace_preference_override(value); test(); - env::remove_var("RUST_BACKTRACE"); + set_backtrace_preference_override(None); reset_backtrace_preference(); } #[cfg(feature = "backtrace")] #[test] fn backtrace_respects_disabled_env() { - with_backtrace_env(Some("0"), || { + with_backtrace_preference(Some(false), || { let err = AppError::internal("boom"); assert!(err.backtrace().is_none()); }); @@ -294,7 +291,7 @@ fn backtrace_respects_disabled_env() { #[cfg(feature = "backtrace")] #[test] fn backtrace_enabled_when_env_requests() { - with_backtrace_env(Some("1"), || { + with_backtrace_preference(Some(true), || { let err = AppError::internal("boom"); assert!(err.backtrace().is_some()); }); diff --git a/src/convert/actix.rs b/src/convert/actix.rs index b58108a..f4abbb0 100644 --- a/src/convert/actix.rs +++ b/src/convert/actix.rs @@ -72,13 +72,7 @@ //! See also: Axum integration in [`convert::axum`]. #[cfg(feature = "actix")] -use actix_web::{ - HttpResponse, ResponseError, - http::{ - StatusCode as ActixStatus, - header::{RETRY_AFTER, WWW_AUTHENTICATE} - } -}; +use actix_web::{HttpResponse, ResponseError, http::StatusCode as ActixStatus}; #[cfg(feature = "actix")] use crate::response::actix_impl::respond_with_problem_json; diff --git a/src/convert/config.rs b/src/convert/config.rs index 44e7650..c8c1913 100644 --- a/src/convert/config.rs +++ b/src/convert/config.rs @@ -88,6 +88,9 @@ fn build_context(error: &ConfigError) -> Context { ConfigError::Foreign(_) => { Context::new(AppErrorKind::Config).with(field::str("config.phase", "foreign")) } + other => Context::new(AppErrorKind::Config) + .with(field::str("config.phase", "unclassified")) + .with(field::str("config.debug", other.to_string())) } } diff --git a/src/convert/redis.rs b/src/convert/redis.rs index a0fc969..919de00 100644 --- a/src/convert/redis.rs +++ b/src/convert/redis.rs @@ -94,12 +94,8 @@ fn build_context(err: &RedisError) -> (Context, Option) { .with(field::u64("redis.redirect_slot", u64::from(slot))); } - let retry_method = err.retry_method(); - let retry_after = retry_after_hint(retry_method); - context = context.with(field::str( - "redis.retry_method", - format!("{:?}", retry_method) - )); + let (retry_method_label, retry_after) = retry_method_details(err.retry_method()); + context = context.with(field::str("redis.retry_method", retry_method_label)); if let Some(secs) = retry_after { context = context.with(field::u64("redis.retry_after_hint_secs", secs)); @@ -109,14 +105,17 @@ fn build_context(err: &RedisError) -> (Context, Option) { } #[cfg(feature = "redis")] -const fn retry_after_hint(method: RetryMethod) -> Option { +const fn retry_method_details(method: RetryMethod) -> (&'static str, Option) { match method { - RetryMethod::NoRetry => None, - RetryMethod::RetryImmediately | RetryMethod::AskRedirect | RetryMethod::MovedRedirect => { - Some(0) + RetryMethod::NoRetry => ("NoRetry", None), + RetryMethod::RetryImmediately => ("RetryImmediately", Some(0)), + RetryMethod::AskRedirect => ("AskRedirect", Some(0)), + RetryMethod::MovedRedirect => ("MovedRedirect", Some(0)), + RetryMethod::Reconnect => ("Reconnect", Some(1)), + RetryMethod::ReconnectFromInitialConnections => { + ("ReconnectFromInitialConnections", Some(1)) } - RetryMethod::Reconnect | RetryMethod::ReconnectFromInitialConnections => Some(1), - RetryMethod::WaitAndRetry => Some(2) + RetryMethod::WaitAndRetry => ("WaitAndRetry", Some(2)) } } diff --git a/src/convert/serde_json.rs b/src/convert/serde_json.rs index b24ba10..a47b854 100644 --- a/src/convert/serde_json.rs +++ b/src/convert/serde_json.rs @@ -30,6 +30,9 @@ //! assert!(matches!(app_err.kind, AppErrorKind::Deserialization)); //! ``` +#[cfg(feature = "serde_json")] +use std::convert::TryFrom; + #[cfg(feature = "serde_json")] use serde_json::{Error as SjError, error::Category}; @@ -62,11 +65,19 @@ fn build_context(err: &SjError) -> Context { let line = err.line(); if line != 0 { - context = context.with(field::u64("serde_json.line", u64::from(line))); + let value = match u64::try_from(line) { + Ok(converted) => converted, + Err(_) => u64::MAX + }; + context = context.with(field::u64("serde_json.line", value)); } let column = err.column(); if column != 0 { - context = context.with(field::u64("serde_json.column", u64::from(column))); + let value = match u64::try_from(column) { + Ok(converted) => converted, + Err(_) => u64::MAX + }; + context = context.with(field::u64("serde_json.column", value)); } if line != 0 && column != 0 { context = context.with(field::str( diff --git a/src/convert/sqlx.rs b/src/convert/sqlx.rs index 9710414..b8a377a 100644 --- a/src/convert/sqlx.rs +++ b/src/convert/sqlx.rs @@ -255,6 +255,11 @@ fn classify_database_error(error: &(dyn DatabaseError + 'static)) -> (Context, O #[cfg(feature = "sqlx-migrate")] fn build_migrate_context(err: &MigrateError) -> Context { + if is_invalid_mix(err) { + return Context::new(AppErrorKind::Database) + .with(field::str("migration.phase", "invalid_mix")); + } + match err { MigrateError::Execute(inner) => Context::new(AppErrorKind::Database) .with(field::str("migration.phase", "execute")) @@ -285,12 +290,20 @@ fn build_migrate_context(err: &MigrateError) -> Context { .with(field::i64("migration.latest", *latest)), MigrateError::ForceNotSupported => Context::new(AppErrorKind::Database) .with(field::str("migration.phase", "force_not_supported")), - MigrateError::InvalidMixReversibleAndSimple => { - Context::new(AppErrorKind::Database).with(field::str("migration.phase", "invalid_mix")) - } MigrateError::Dirty(version) => Context::new(AppErrorKind::Database) .with(field::str("migration.phase", "dirty")) - .with(field::i64("migration.version", *version)) + .with(field::i64("migration.version", *version)), + _ => Context::new(AppErrorKind::Database) + .with(field::str("migration.phase", "unclassified")) + .with(field::str("migration.detail", err.to_string())) + } +} + +#[cfg(feature = "sqlx-migrate")] +fn is_invalid_mix(err: &MigrateError) -> bool { + #[allow(deprecated)] + { + matches!(err, MigrateError::InvalidMixReversibleAndSimple) } } @@ -402,7 +415,13 @@ mod tests_sqlx { } fn kind(&self) -> SqlxErrorKind { - self.kind + match self.kind { + SqlxErrorKind::UniqueViolation => SqlxErrorKind::UniqueViolation, + SqlxErrorKind::ForeignKeyViolation => SqlxErrorKind::ForeignKeyViolation, + SqlxErrorKind::NotNullViolation => SqlxErrorKind::NotNullViolation, + SqlxErrorKind::CheckViolation => SqlxErrorKind::CheckViolation, + SqlxErrorKind::Other => SqlxErrorKind::Other + } } } } diff --git a/src/convert/tonic.rs b/src/convert/tonic.rs index e56c68e..8a567bf 100644 --- a/src/convert/tonic.rs +++ b/src/convert/tonic.rs @@ -18,9 +18,6 @@ //! assert_eq!(status.code(), tonic::Code::NotFound); //! ``` -#![cfg(feature = "tonic")] -#![cfg_attr(docsrs, doc(cfg(feature = "tonic")))] - use std::{borrow::Cow, convert::Infallible}; use tonic::{ @@ -39,29 +36,19 @@ impl TryFrom for Status { type Error = Infallible; fn try_from(error: Error) -> Result { - Ok(status_from_error(error)) + Ok(status_from_error(&error)) } } -fn status_from_error(error: Error) -> Status { +fn status_from_error(error: &Error) -> Status { error.emit_telemetry(); - let Error { - code, - kind, - message, - metadata, - edit_policy, - retry, - www_authenticate, - .. - } = error; - - let mapping = mapping_for_code(code); + + let mapping = mapping_for_code(error.code); let grpc_code = Code::from_i32(mapping.grpc().value); - let detail = sanitize_detail(message, kind, edit_policy); + let detail = sanitize_detail(error.message.as_ref(), error.kind, error.edit_policy); let mut meta = MetadataMap::new(); - insert_ascii(&mut meta, "app-code", code.as_str()); + insert_ascii(&mut meta, "app-code", error.code.as_str()); insert_ascii( &mut meta, "app-http-status", @@ -69,24 +56,24 @@ fn status_from_error(error: Error) -> Status { ); insert_ascii(&mut meta, "app-problem-type", mapping.problem_type()); - if let Some(advice) = retry { + if let Some(advice) = error.retry { insert_retry(&mut meta, advice); } - if let Some(challenge) = www_authenticate { - if is_ascii_metadata_value(&challenge) { + if let Some(challenge) = error.www_authenticate.as_deref() { + if is_ascii_metadata_value(challenge) { insert_ascii(&mut meta, "www-authenticate", challenge); } } - if !matches!(edit_policy, MessageEditPolicy::Redact) { - attach_metadata(&mut meta, metadata); + if !matches!(error.edit_policy, MessageEditPolicy::Redact) { + attach_metadata(&mut meta, error.metadata()); } Status::with_metadata(grpc_code, detail, meta) } fn sanitize_detail( - message: Option>, + message: Option<&Cow<'static, str>>, kind: AppErrorKind, policy: MessageEditPolicy ) -> String { @@ -94,16 +81,15 @@ fn sanitize_detail( return kind.to_string(); } - message.map_or_else(|| kind.to_string(), Cow::into_owned) + message.map_or_else(|| kind.to_string(), |msg| msg.as_ref().to_owned()) } fn insert_retry(meta: &mut MetadataMap, retry: RetryAdvice) { insert_ascii(meta, "retry-after", retry.after_seconds.to_string()); } -fn attach_metadata(meta: &mut MetadataMap, metadata: Metadata) { - for field in metadata { - let (name, value, redaction) = field.into_parts(); +fn attach_metadata(meta: &mut MetadataMap, metadata: &Metadata) { + for (name, value, redaction) in metadata.iter_with_redaction() { if !matches!(redaction, FieldRedaction::None) { continue; } @@ -124,21 +110,23 @@ fn insert_ascii(meta: &mut MetadataMap, key: &'static str, value: impl AsRef Option { +fn metadata_value_to_ascii(value: &FieldValue) -> Option> { match value { FieldValue::Str(value) => { - let owned = value.into_owned(); - is_ascii_metadata_value(&owned).then_some(owned) + let text = value.as_ref(); + is_ascii_metadata_value(text).then(|| Cow::Borrowed(text)) } - FieldValue::I64(value) => Some(value.to_string()), - FieldValue::U64(value) => Some(value.to_string()), - FieldValue::Bool(value) => Some(if value { "true" } else { "false" }.to_string()), - FieldValue::Uuid(value) => Some(value.to_string()) + FieldValue::I64(value) => Some(Cow::Owned(value.to_string())), + FieldValue::U64(value) => Some(Cow::Owned(value.to_string())), + FieldValue::Bool(value) => Some(Cow::Owned( + if *value { "true" } else { "false" }.to_string() + )), + FieldValue::Uuid(value) => Some(Cow::Owned(value.to_string())) } } diff --git a/src/result_ext.rs b/src/result_ext.rs index 60ec0e9..31d5f6c 100644 --- a/src/result_ext.rs +++ b/src/result_ext.rs @@ -45,18 +45,18 @@ impl ResultExt for Result { #[cfg(test)] mod tests { + #[cfg(feature = "backtrace")] + use std::sync::Mutex; use std::{ borrow::Cow, error::Error as StdError, fmt::{Display, Formatter, Result as FmtResult}, sync::Arc }; - #[cfg(feature = "backtrace")] - use std::{env, sync::Mutex}; use super::ResultExt; #[cfg(feature = "backtrace")] - use crate::app_error::reset_backtrace_preference; + use crate::app_error::{reset_backtrace_preference, set_backtrace_preference_override}; use crate::{ AppCode, AppErrorKind, app_error::{Context, FieldValue, MessageEditPolicy}, @@ -189,29 +189,26 @@ mod tests { } #[cfg(feature = "backtrace")] - fn with_backtrace_env(value: Option<&str>, test: impl FnOnce()) { + fn with_backtrace_preference(value: Option, test: impl FnOnce()) { let _guard = BACKTRACE_ENV_GUARD.lock().expect("env guard"); reset_backtrace_preference(); - match value { - Some(value) => env::set_var("RUST_BACKTRACE", value), - None => env::remove_var("RUST_BACKTRACE") - } + set_backtrace_preference_override(value); test(); - env::remove_var("RUST_BACKTRACE"); + set_backtrace_preference_override(None); reset_backtrace_preference(); } #[cfg(feature = "backtrace")] #[test] fn ctx_respects_backtrace_environment() { - with_backtrace_env(Some("0"), || { + with_backtrace_preference(Some(false), || { let err = Result::<(), DummyError>::Err(DummyError) .ctx(|| Context::new(AppErrorKind::Internal)) .expect_err("err"); assert!(err.backtrace().is_none()); }); - with_backtrace_env(Some("1"), || { + with_backtrace_preference(Some(true), || { let err = Result::<(), DummyError>::Err(DummyError) .ctx(|| Context::new(AppErrorKind::Internal)) .expect_err("err"); diff --git a/tests/ui/app_error/fail/enum_missing_variant.stderr b/tests/ui/app_error/fail/enum_missing_variant.stderr index bbc297c..d000de1 100644 --- a/tests/ui/app_error/fail/enum_missing_variant.stderr +++ b/tests/ui/app_error/fail/enum_missing_variant.stderr @@ -1,9 +1,8 @@ error: all variants must use #[app_error(...)] to derive AppError conversion --> tests/ui/app_error/fail/enum_missing_variant.rs:8:5 | -8 | / #[error("without")] -9 | | Without, - | |___________^ +8 | #[error("without")] + | ^ warning: unused import: `AppErrorKind` --> tests/ui/app_error/fail/enum_missing_variant.rs:1:17 @@ -11,4 +10,4 @@ warning: unused import: `AppErrorKind` 1 | use masterror::{AppErrorKind, Error}; | ^^^^^^^^^^^^ | - = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default + = note: `#[warn(unused_imports)]` on by default diff --git a/tests/ui/app_error/fail/missing_code.stderr b/tests/ui/app_error/fail/missing_code.stderr index 4f02301..70ccade 100644 --- a/tests/ui/app_error/fail/missing_code.stderr +++ b/tests/ui/app_error/fail/missing_code.stderr @@ -2,7 +2,7 @@ error: AppCode conversion requires `code = ...` in #[app_error(...)] --> tests/ui/app_error/fail/missing_code.rs:9:5 | 9 | #[app_error(kind = AppErrorKind::Service)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ warning: unused imports: `AppCode` and `AppErrorKind` --> tests/ui/app_error/fail/missing_code.rs:1:17 @@ -10,4 +10,4 @@ warning: unused imports: `AppCode` and `AppErrorKind` 1 | use masterror::{AppCode, AppErrorKind, Error}; | ^^^^^^^ ^^^^^^^^^^^^ | - = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default + = note: `#[warn(unused_imports)]` on by default diff --git a/tests/ui/app_error/fail/missing_kind.stderr b/tests/ui/app_error/fail/missing_kind.stderr index 021c135..c615e98 100644 --- a/tests/ui/app_error/fail/missing_kind.stderr +++ b/tests/ui/app_error/fail/missing_kind.stderr @@ -2,4 +2,4 @@ error: missing `kind = ...` in #[app_error(...)] --> tests/ui/app_error/fail/missing_kind.rs:5:1 | 5 | #[app_error(message)] - | ^^^^^^^^^^^^^^^^^^^^^ + | ^ diff --git a/tests/ui/formatter/fail/duplicate_fmt.stderr b/tests/ui/formatter/fail/duplicate_fmt.stderr index 5b8f363..5b08225 100644 --- a/tests/ui/formatter/fail/duplicate_fmt.stderr +++ b/tests/ui/formatter/fail/duplicate_fmt.stderr @@ -2,4 +2,4 @@ error: duplicate `fmt` handler specified --> tests/ui/formatter/fail/duplicate_fmt.rs:4:36 | 4 | #[error(fmt = crate::format_error, fmt = crate::format_error)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^ diff --git a/tests/ui/formatter/fail/implicit_after_named.stderr b/tests/ui/formatter/fail/implicit_after_named.stderr index be76742..d416399 100644 --- a/tests/ui/formatter/fail/implicit_after_named.stderr +++ b/tests/ui/formatter/fail/implicit_after_named.stderr @@ -8,5 +8,4 @@ error: multiple unused formatting arguments | argument never used | argument never used | - = note: consider adding 2 format specifiers = note: this error originates in the derive macro `Error` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/formatter/fail/unsupported_flag.stderr b/tests/ui/formatter/fail/unsupported_flag.stderr index b8bf229..d7acdb1 100644 --- a/tests/ui/formatter/fail/unsupported_flag.stderr +++ b/tests/ui/formatter/fail/unsupported_flag.stderr @@ -1,5 +1,5 @@ error: placeholder spanning bytes 0..11 uses an unsupported formatter - --> tests/ui/formatter/fail/unsupported_flag.rs:4:10 + --> tests/ui/formatter/fail/unsupported_flag.rs:4:9 | 4 | #[error("{value:##x}")] - | ^^^^^^^^^^^ + | ^^^^^^^^^^^^^ diff --git a/tests/ui/formatter/fail/unsupported_formatter.stderr b/tests/ui/formatter/fail/unsupported_formatter.stderr index a6a40c2..5869420 100644 --- a/tests/ui/formatter/fail/unsupported_formatter.stderr +++ b/tests/ui/formatter/fail/unsupported_formatter.stderr @@ -1,5 +1,5 @@ error: placeholder spanning bytes 0..9 uses an unsupported formatter - --> tests/ui/formatter/fail/unsupported_formatter.rs:4:10 + --> tests/ui/formatter/fail/unsupported_formatter.rs:4:9 | 4 | #[error("{value:y}")] - | ^^^^^^^^^ + | ^^^^^^^^^^^ diff --git a/tests/ui/formatter/fail/uppercase_binary.stderr b/tests/ui/formatter/fail/uppercase_binary.stderr index 3d332c7..bbe04b4 100644 --- a/tests/ui/formatter/fail/uppercase_binary.stderr +++ b/tests/ui/formatter/fail/uppercase_binary.stderr @@ -1,5 +1,5 @@ error: placeholder spanning bytes 0..9 uses an unsupported formatter - --> tests/ui/formatter/fail/uppercase_binary.rs:4:10 + --> tests/ui/formatter/fail/uppercase_binary.rs:4:9 | 4 | #[error("{value:B}")] - | ^^^^^^^^^ + | ^^^^^^^^^^^ diff --git a/tests/ui/formatter/fail/uppercase_pointer.stderr b/tests/ui/formatter/fail/uppercase_pointer.stderr index 0bd10fa..2c30e71 100644 --- a/tests/ui/formatter/fail/uppercase_pointer.stderr +++ b/tests/ui/formatter/fail/uppercase_pointer.stderr @@ -1,5 +1,5 @@ error: placeholder spanning bytes 0..9 uses an unsupported formatter - --> tests/ui/formatter/fail/uppercase_pointer.rs:4:10 + --> tests/ui/formatter/fail/uppercase_pointer.rs:4:9 | 4 | #[error("{value:P}")] - | ^^^^^^^^^ + | ^^^^^^^^^^^ diff --git a/tests/ui/masterror/fail/duplicate_attr.stderr b/tests/ui/masterror/fail/duplicate_attr.stderr index 113a10d..c3fb86b 100644 --- a/tests/ui/masterror/fail/duplicate_attr.stderr +++ b/tests/ui/masterror/fail/duplicate_attr.stderr @@ -10,4 +10,4 @@ warning: unused imports: `AppCode` and `AppErrorKind` 1 | use masterror::{AppCode, AppErrorKind, Masterror}; | ^^^^^^^ ^^^^^^^^^^^^ | - = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default + = note: `#[warn(unused_imports)]` on by default diff --git a/tests/ui/masterror/fail/duplicate_telemetry.stderr b/tests/ui/masterror/fail/duplicate_telemetry.stderr index 9ada290..b331baa 100644 --- a/tests/ui/masterror/fail/duplicate_telemetry.stderr +++ b/tests/ui/masterror/fail/duplicate_telemetry.stderr @@ -10,4 +10,4 @@ warning: unused imports: `AppCode` and `AppErrorKind` 1 | use masterror::{AppCode, AppErrorKind, Masterror}; | ^^^^^^^ ^^^^^^^^^^^^ | - = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default + = note: `#[warn(unused_imports)]` on by default diff --git a/tests/ui/masterror/fail/empty_redact.stderr b/tests/ui/masterror/fail/empty_redact.stderr index fd151cc..b2658a1 100644 --- a/tests/ui/masterror/fail/empty_redact.stderr +++ b/tests/ui/masterror/fail/empty_redact.stderr @@ -10,4 +10,4 @@ warning: unused imports: `AppCode` and `AppErrorKind` 1 | use masterror::{AppCode, AppErrorKind, Masterror}; | ^^^^^^^ ^^^^^^^^^^^^ | - = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default + = note: `#[warn(unused_imports)]` on by default diff --git a/tests/ui/masterror/fail/enum_missing_variant.stderr b/tests/ui/masterror/fail/enum_missing_variant.stderr index 5a25e12..83d517f 100644 --- a/tests/ui/masterror/fail/enum_missing_variant.stderr +++ b/tests/ui/masterror/fail/enum_missing_variant.stderr @@ -1,9 +1,8 @@ error: all variants must use #[masterror(...)] to derive masterror::Error conversion --> tests/ui/masterror/fail/enum_missing_variant.rs:8:5 | -8 | / #[error("missing")] -9 | | Missing - | |___________^ +8 | #[error("missing")] + | ^ warning: unused imports: `AppCode` and `AppErrorKind` --> tests/ui/masterror/fail/enum_missing_variant.rs:1:17 @@ -11,4 +10,4 @@ warning: unused imports: `AppCode` and `AppErrorKind` 1 | use masterror::{AppCode, AppErrorKind, Masterror}; | ^^^^^^^ ^^^^^^^^^^^^ | - = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default + = note: `#[warn(unused_imports)]` on by default diff --git a/tests/ui/masterror/fail/missing_category.stderr b/tests/ui/masterror/fail/missing_category.stderr index bdadf45..f929951 100644 --- a/tests/ui/masterror/fail/missing_category.stderr +++ b/tests/ui/masterror/fail/missing_category.stderr @@ -2,7 +2,7 @@ error: missing `category = ...` in #[masterror(...)] --> tests/ui/masterror/fail/missing_category.rs:5:1 | 5 | #[masterror(code = AppCode::Internal)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ warning: unused import: `AppCode` --> tests/ui/masterror/fail/missing_category.rs:1:17 @@ -10,4 +10,4 @@ warning: unused import: `AppCode` 1 | use masterror::{AppCode, Masterror}; | ^^^^^^^ | - = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default + = note: `#[warn(unused_imports)]` on by default diff --git a/tests/ui/masterror/fail/missing_code.stderr b/tests/ui/masterror/fail/missing_code.stderr index 037fac8..34abc91 100644 --- a/tests/ui/masterror/fail/missing_code.stderr +++ b/tests/ui/masterror/fail/missing_code.stderr @@ -2,7 +2,7 @@ error: missing `code = ...` in #[masterror(...)] --> tests/ui/masterror/fail/missing_code.rs:5:1 | 5 | #[masterror(category = AppErrorKind::Internal)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ warning: unused import: `AppErrorKind` --> tests/ui/masterror/fail/missing_code.rs:1:17 @@ -10,4 +10,4 @@ warning: unused import: `AppErrorKind` 1 | use masterror::{AppErrorKind, Masterror}; | ^^^^^^^^^^^^ | - = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default + = note: `#[warn(unused_imports)]` on by default diff --git a/tests/ui/masterror/fail/unknown_option.stderr b/tests/ui/masterror/fail/unknown_option.stderr index 1822edf..d579838 100644 --- a/tests/ui/masterror/fail/unknown_option.stderr +++ b/tests/ui/masterror/fail/unknown_option.stderr @@ -10,4 +10,4 @@ warning: unused imports: `AppCode` and `AppErrorKind` 1 | use masterror::{AppCode, AppErrorKind, Masterror}; | ^^^^^^^ ^^^^^^^^^^^^ | - = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default + = note: `#[warn(unused_imports)]` on by default