diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 554873e3..f682c34d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,10 +24,10 @@ jobs: strategy: fail-fast: false matrix: - rust: [nightly, beta, stable, 1.81.0, 1.70.0] + rust: [nightly, beta, stable, 1.81.0, 1.76.0] timeout-minutes: 45 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{matrix.rust}} @@ -40,7 +40,7 @@ jobs: if: matrix.rust == 'nightly' - run: cargo test --workspace --exclude thiserror_no_std_test - run: cargo test --manifest-path tests/no-std/Cargo.toml - if: matrix.rust != '1.70.0' + if: matrix.rust != '1.76.0' - run: cargo test --no-default-features - uses: actions/upload-artifact@v4 if: matrix.rust == 'nightly' && always() @@ -56,7 +56,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 45 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@1.61.0 with: components: rust-src @@ -69,7 +69,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 45 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@nightly - run: cargo generate-lockfile -Z minimal-versions - run: cargo check --locked @@ -83,7 +83,7 @@ jobs: env: RUSTDOCFLAGS: -Dwarnings steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@nightly with: components: rust-src @@ -96,7 +96,7 @@ jobs: if: github.event_name != 'pull_request' timeout-minutes: 45 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@nightly with: components: clippy, rust-src @@ -109,7 +109,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 45 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@miri - run: cargo miri setup - run: cargo miri test @@ -122,7 +122,7 @@ jobs: if: github.event_name != 'pull_request' timeout-minutes: 45 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@stable - uses: dtolnay/install@cargo-outdated - run: cargo outdated --workspace --exit-code 1 diff --git a/Cargo.toml b/Cargo.toml index 455b950c..28718d7f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "thiserror" -version = "2.0.12" +version = "2.0.17" authors = ["David Tolnay "] -categories = ["rust-patterns"] +categories = ["rust-patterns", "no-std"] description = "derive(Error)" documentation = "https://docs.rs/thiserror" edition = "2021" @@ -28,13 +28,13 @@ default = ["std"] std = [] [dependencies] -thiserror-impl = { version = "=2.0.12", path = "impl" } +thiserror-impl = { version = "=2.0.17", path = "impl" } [dev-dependencies] anyhow = "1.0.73" ref-cast = "1.0.18" rustversion = "1.0.13" -trybuild = { version = "1.0.81", features = ["diff"] } +trybuild = { version = "1.0.108", features = ["diff"] } [workspace] members = ["impl", "tests/no-std"] @@ -43,6 +43,7 @@ members = ["impl", "tests/no-std"] targets = ["x86_64-unknown-linux-gnu"] rustdoc-args = [ "--generate-link-to-definition", + "--generate-macro-expansion", "--extern-html-root-url=core=https://doc.rust-lang.org", "--extern-html-root-url=alloc=https://doc.rust-lang.org", "--extern-html-root-url=std=https://doc.rust-lang.org", diff --git a/build.rs b/build.rs index 5d795e40..3b9fb329 100644 --- a/build.rs +++ b/build.rs @@ -3,10 +3,18 @@ use std::ffi::OsString; use std::fs; use std::io::ErrorKind; use std::iter; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::process::{self, Command, Stdio}; use std::str; +const PRIVATE: &str = "\ +#[doc(hidden)] +pub mod __private$$ { + #[doc(hidden)] + pub use crate::private::*; +} +"; + fn main() { println!("cargo:rerun-if-changed=build/probe.rs"); @@ -14,6 +22,11 @@ fn main() { println!("cargo:rustc-check-cfg=cfg(thiserror_nightly_testing)"); println!("cargo:rustc-check-cfg=cfg(thiserror_no_backtrace_type)"); + let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let patch_version = env::var("CARGO_PKG_VERSION_PATCH").unwrap(); + let module = PRIVATE.replace("$$", &patch_version); + fs::write(out_dir.join("private.rs"), module).unwrap(); + let error_generic_member_access; let consider_rustc_bootstrap; if compile_probe(false) { @@ -146,7 +159,16 @@ fn compile_probe(rustc_bootstrap: bool) -> bool { // file in OUT_DIR, which causes nonreproducible builds in build systems // that treat the entire OUT_DIR as an artifact. if let Err(err) = fs::remove_dir_all(&out_subdir) { - if err.kind() != ErrorKind::NotFound { + // libc::ENOTEMPTY + // Some filesystems (NFSv3) have timing issues under load where '.nfs*' + // dummy files can continue to get created for a short period after the + // probe command completes, breaking remove_dir_all. + // To be replaced with ErrorKind::DirectoryNotEmpty (Rust 1.83+). + const ENOTEMPTY: i32 = 39; + + if !(err.kind() == ErrorKind::NotFound + || (cfg!(target_os = "linux") && err.raw_os_error() == Some(ENOTEMPTY))) + { eprintln!("Failed to clean up {}: {}", out_subdir.display(), err); process::exit(1); } diff --git a/impl/Cargo.toml b/impl/Cargo.toml index 9166114d..0e95d32f 100644 --- a/impl/Cargo.toml +++ b/impl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.17" authors = ["David Tolnay "] description = "Implementation detail of the `thiserror` crate" edition = "2021" @@ -20,6 +20,7 @@ syn = "2.0.87" targets = ["x86_64-unknown-linux-gnu"] rustdoc-args = [ "--generate-link-to-definition", + "--generate-macro-expansion", "--extern-html-root-url=core=https://doc.rust-lang.org", "--extern-html-root-url=alloc=https://doc.rust-lang.org", "--extern-html-root-url=std=https://doc.rust-lang.org", diff --git a/impl/src/expand.rs b/impl/src/expand.rs index c6939214..97466ddc 100644 --- a/impl/src/expand.rs +++ b/impl/src/expand.rs @@ -2,6 +2,7 @@ use crate::ast::{Enum, Field, Input, Struct}; use crate::attr::Trait; use crate::fallback; use crate::generics::InferredBounds; +use crate::private; use crate::unraw::MemberUnraw; use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote, quote_spanned, ToTokens}; @@ -35,17 +36,17 @@ fn impl_struct(input: Struct) -> TokenStream { let source_body = if let Some(transparent_attr) = &input.attrs.transparent { let only_field = &input.fields[0]; if only_field.contains_generic { - error_inferred_bounds.insert(only_field.ty, quote!(::thiserror::__private::Error)); + error_inferred_bounds.insert(only_field.ty, quote!(::thiserror::#private::Error)); } let member = &only_field.member; Some(quote_spanned! {transparent_attr.span=> - ::thiserror::__private::Error::source(self.#member.as_dyn_error()) + ::thiserror::#private::Error::source(self.#member.as_dyn_error()) }) } else if let Some(source_field) = input.source_field() { let source = &source_field.member; if source_field.contains_generic { let ty = unoptional_type(source_field.ty); - error_inferred_bounds.insert(ty, quote!(::thiserror::__private::Error + 'static)); + error_inferred_bounds.insert(ty, quote!(::thiserror::#private::Error + 'static)); } let asref = if type_is_option(source_field.ty) { Some(quote_spanned!(source.span()=> .as_ref()?)) @@ -63,8 +64,8 @@ fn impl_struct(input: Struct) -> TokenStream { }; let source_method = source_body.map(|body| { quote! { - fn source(&self) -> ::core::option::Option<&(dyn ::thiserror::__private::Error + 'static)> { - use ::thiserror::__private::AsDynError as _; + fn source(&self) -> ::core::option::Option<&(dyn ::thiserror::#private::Error + 'static)> { + use ::thiserror::#private::AsDynError as _; #body } } @@ -91,28 +92,28 @@ fn impl_struct(input: Struct) -> TokenStream { } else if type_is_option(backtrace_field.ty) { Some(quote! { if let ::core::option::Option::Some(backtrace) = &self.#backtrace { - #request.provide_ref::<::thiserror::__private::Backtrace>(backtrace); + #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace); } }) } else { Some(quote! { - #request.provide_ref::<::thiserror::__private::Backtrace>(&self.#backtrace); + #request.provide_ref::<::thiserror::#private::Backtrace>(&self.#backtrace); }) }; quote! { - use ::thiserror::__private::ThiserrorProvide as _; + use ::thiserror::#private::ThiserrorProvide as _; #source_provide #self_provide } } else if type_is_option(backtrace_field.ty) { quote! { if let ::core::option::Option::Some(backtrace) = &self.#backtrace { - #request.provide_ref::<::thiserror::__private::Backtrace>(backtrace); + #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace); } } } else { quote! { - #request.provide_ref::<::thiserror::__private::Backtrace>(&self.#backtrace); + #request.provide_ref::<::thiserror::#private::Backtrace>(&self.#backtrace); } }; quote! { @@ -201,7 +202,7 @@ fn impl_struct(input: Struct) -> TokenStream { quote! { #[allow(unused_qualifications)] #[automatically_derived] - impl #impl_generics ::thiserror::__private::Error for #ty #ty_generics #error_where_clause { + impl #impl_generics ::thiserror::#private::Error for #ty #ty_generics #error_where_clause { #source_method #provide_method } @@ -221,11 +222,11 @@ fn impl_enum(input: Enum) -> TokenStream { if let Some(transparent_attr) = &variant.attrs.transparent { let only_field = &variant.fields[0]; if only_field.contains_generic { - error_inferred_bounds.insert(only_field.ty, quote!(::thiserror::__private::Error)); + error_inferred_bounds.insert(only_field.ty, quote!(::thiserror::#private::Error)); } let member = &only_field.member; let source = quote_spanned! {transparent_attr.span=> - ::thiserror::__private::Error::source(transparent.as_dyn_error()) + ::thiserror::#private::Error::source(transparent.as_dyn_error()) }; quote! { #ty::#ident {#member: transparent} => #source, @@ -234,7 +235,7 @@ fn impl_enum(input: Enum) -> TokenStream { let source = &source_field.member; if source_field.contains_generic { let ty = unoptional_type(source_field.ty); - error_inferred_bounds.insert(ty, quote!(::thiserror::__private::Error + 'static)); + error_inferred_bounds.insert(ty, quote!(::thiserror::#private::Error + 'static)); } let asref = if type_is_option(source_field.ty) { Some(quote_spanned!(source.span()=> .as_ref()?)) @@ -255,8 +256,8 @@ fn impl_enum(input: Enum) -> TokenStream { } }); Some(quote! { - fn source(&self) -> ::core::option::Option<&(dyn ::thiserror::__private::Error + 'static)> { - use ::thiserror::__private::AsDynError as _; + fn source(&self) -> ::core::option::Option<&(dyn ::thiserror::#private::Error + 'static)> { + use ::thiserror::#private::AsDynError as _; #[allow(deprecated)] match self { #(#arms)* @@ -292,12 +293,12 @@ fn impl_enum(input: Enum) -> TokenStream { let self_provide = if type_is_option(backtrace_field.ty) { quote! { if let ::core::option::Option::Some(backtrace) = backtrace { - #request.provide_ref::<::thiserror::__private::Backtrace>(backtrace); + #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace); } } } else { quote! { - #request.provide_ref::<::thiserror::__private::Backtrace>(backtrace); + #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace); } }; quote! { @@ -306,7 +307,7 @@ fn impl_enum(input: Enum) -> TokenStream { #source: #varsource, .. } => { - use ::thiserror::__private::ThiserrorProvide as _; + use ::thiserror::#private::ThiserrorProvide as _; #source_provide #self_provide } @@ -330,7 +331,7 @@ fn impl_enum(input: Enum) -> TokenStream { }; quote! { #ty::#ident {#backtrace: #varsource, ..} => { - use ::thiserror::__private::ThiserrorProvide as _; + use ::thiserror::#private::ThiserrorProvide as _; #source_provide } } @@ -340,12 +341,12 @@ fn impl_enum(input: Enum) -> TokenStream { let body = if type_is_option(backtrace_field.ty) { quote! { if let ::core::option::Option::Some(backtrace) = backtrace { - #request.provide_ref::<::thiserror::__private::Backtrace>(backtrace); + #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace); } } } else { quote! { - #request.provide_ref::<::thiserror::__private::Backtrace>(backtrace); + #request.provide_ref::<::thiserror::#private::Backtrace>(backtrace); } }; quote! { @@ -476,7 +477,7 @@ fn impl_enum(input: Enum) -> TokenStream { quote! { #[allow(unused_qualifications)] #[automatically_derived] - impl #impl_generics ::thiserror::__private::Error for #ty #ty_generics #error_where_clause { + impl #impl_generics ::thiserror::#private::Error for #ty #ty_generics #error_where_clause { #source_method #provide_method } @@ -511,7 +512,7 @@ fn fields_pat(fields: &[Field]) -> TokenStream { fn use_as_display(needs_as_display: bool) -> Option { if needs_as_display { Some(quote! { - use ::thiserror::__private::AsDisplay as _; + use ::thiserror::#private::AsDisplay as _; }) } else { None @@ -533,11 +534,11 @@ fn from_initializer( let backtrace_member = &backtrace_field.member; if type_is_option(backtrace_field.ty) { quote! { - #backtrace_member: ::core::option::Option::Some(::thiserror::__private::Backtrace::capture()), + #backtrace_member: ::core::option::Option::Some(::thiserror::#private::Backtrace::capture()), } } else { quote! { - #backtrace_member: ::core::convert::From::from(::thiserror::__private::Backtrace::capture()), + #backtrace_member: ::core::convert::From::from(::thiserror::#private::Backtrace::capture()), } } }); diff --git a/impl/src/fallback.rs b/impl/src/fallback.rs index e9c429ba..9914aa5f 100644 --- a/impl/src/fallback.rs +++ b/impl/src/fallback.rs @@ -1,4 +1,5 @@ use crate::expand::call_site_ident; +use crate::private; use proc_macro2::TokenStream; use quote::quote; use syn::DeriveInput; @@ -14,7 +15,7 @@ pub(crate) fn expand(input: &DeriveInput, error: syn::Error) -> TokenStream { #[allow(unused_qualifications)] #[automatically_derived] - impl #impl_generics ::thiserror::__private::Error for #ty #ty_generics #where_clause + impl #impl_generics ::thiserror::#private::Error for #ty #ty_generics #where_clause where // Work around trivial bounds being unstable. // https://github.com/rust-lang/rust/issues/48214 diff --git a/impl/src/fmt.rs b/impl/src/fmt.rs index 1da28c19..2988ca37 100644 --- a/impl/src/fmt.rs +++ b/impl/src/fmt.rs @@ -1,5 +1,6 @@ use crate::ast::{ContainerKind, Field}; use crate::attr::{Display, Trait}; +use crate::private; use crate::scan_expr::scan_expr; use crate::unraw::{IdentUnraw, MemberUnraw}; use proc_macro2::{Delimiter, TokenStream, TokenTree}; @@ -145,7 +146,7 @@ impl Display<'_> { let wrapped_binding_value = if bonus_display { quote_spanned!(span=> #binding_value.as_display()) } else if bound == Trait::Pointer { - quote!(::thiserror::__private::Var(#binding_value)) + quote!(::thiserror::#private::Var(#binding_value)) } else { binding_value.into_token_stream() }; diff --git a/impl/src/lib.rs b/impl/src/lib.rs index 7f3767ef..ce34ad5b 100644 --- a/impl/src/lib.rs +++ b/impl/src/lib.rs @@ -15,6 +15,7 @@ clippy::too_many_lines, clippy::wrong_self_convention )] +#![allow(unknown_lints, mismatched_lifetime_syntaxes)] extern crate proc_macro; @@ -30,6 +31,8 @@ mod unraw; mod valid; use proc_macro::TokenStream; +use proc_macro2::{Ident, Span}; +use quote::{ToTokens, TokenStreamExt as _}; use syn::{parse_macro_input, DeriveInput}; #[proc_macro_derive(Error, attributes(backtrace, error, from, source))] @@ -37,3 +40,15 @@ pub fn derive_error(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); expand::derive(&input).into() } + +#[allow(non_camel_case_types)] +struct private; + +impl ToTokens for private { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + tokens.append(Ident::new( + concat!("__private", env!("CARGO_PKG_VERSION_PATCH")), + Span::call_site(), + )); + } +} diff --git a/src/display.rs b/src/display.rs index 7b2bf1cf..e544657b 100644 --- a/src/display.rs +++ b/src/display.rs @@ -60,6 +60,7 @@ mod placeholder { use super::{AsDisplay, Sealed}; use core::fmt::{self, Display}; + #[allow(dead_code)] pub struct Placeholder; impl<'a> AsDisplay<'a> for Placeholder { diff --git a/src/lib.rs b/src/lib.rs index fa90229f..155272de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,14 +38,14 @@ //! # Details //! //! - Thiserror deliberately does not appear in your public API. You get the -//! same thing as if you had written an implementation of `std::error::Error` -//! by hand, and switching from handwritten impls to thiserror or vice versa -//! is not a breaking change. +//! same thing as if you had written an implementation of +//! [`std::error::Error`] by hand, and switching from handwritten impls to +//! thiserror or vice versa is not a breaking change. //! //! - Errors may be enums, structs with named fields, tuple structs, or unit //! structs. //! -//! - A `Display` impl is generated for your error if you provide +//! - A [`Display`] impl is generated for your error if you provide //! `#[error("...")]` messages on the struct or each variant of your enum, as //! shown above in the example. //! @@ -96,7 +96,7 @@ //! } //! ``` //! -//! - A `From` impl is generated for each variant that contains a `#[from]` +//! - A [`From`] impl is generated for each variant that contains a `#[from]` //! attribute. //! //! The variant using `#[from]` must not contain any other fields beyond the @@ -128,7 +128,7 @@ //! # } //! ``` //! -//! - The Error trait's `source()` method is implemented to return whichever +//! - The Error trait's [`source()`] method is implemented to return whichever //! field has a `#[source]` attribute or is named `source`, if any. This is //! for identifying the underlying lower level error that caused your error. //! @@ -156,9 +156,9 @@ //! # } //! ``` //! -//! - The Error trait's `provide()` method is implemented to provide whichever +//! - The Error trait's [`provide()`] method is implemented to provide whichever //! field has a type named `Backtrace`, if any, as a -//! `std::backtrace::Backtrace`. Using `Backtrace` in errors requires a +//! [`std::backtrace::Backtrace`]. Using `Backtrace` in errors requires a //! nightly compiler with Rust version 1.73 or newer. //! //! ```rust @@ -175,8 +175,8 @@ //! //! - If a field is both a source (named `source`, or has `#[source]` or //! `#[from]` attribute) *and* is marked `#[backtrace]`, then the Error -//! trait's `provide()` method is forwarded to the source's `provide` so that -//! both layers of the error share the same backtrace. The `#[backtrace]` +//! trait's [`provide()`] method is forwarded to the source's `provide` so +//! that both layers of the error share the same backtrace. The `#[backtrace]` //! attribute requires a nightly compiler with Rust version 1.73 or newer. //! //! ```rust @@ -207,7 +207,7 @@ //! # }; //! ``` //! -//! - Errors may use `error(transparent)` to forward the source and Display +//! - Errors may use `error(transparent)` to forward the source and [`Display`] //! methods straight through to an underlying error without adding an //! additional message. This would be appropriate for enums that need an //! "anything else" variant. @@ -254,10 +254,13 @@ //! - See also the [`anyhow`] library for a convenient single error type to use //! in application code. //! -//! [`anyhow`]: https://github.com/dtolnay/anyhow +//! [`anyhow`]: https://github.com/dtolnay/anyhow +//! [`source()`]: std::error::Error::source +//! [`provide()`]: std::error::Error::provide +//! [`Display`]: std::fmt::Display #![no_std] -#![doc(html_root_url = "https://docs.rs/thiserror/2.0.12")] +#![doc(html_root_url = "https://docs.rs/thiserror/2.0.17")] #![allow( clippy::elidable_lifetime_names, clippy::module_name_repetitions, @@ -283,21 +286,6 @@ mod var; pub use thiserror_impl::*; -// Not public API. -#[doc(hidden)] -pub mod __private { - #[doc(hidden)] - pub use crate::aserror::AsDynError; - #[doc(hidden)] - pub use crate::display::AsDisplay; - #[cfg(error_generic_member_access)] - #[doc(hidden)] - pub use crate::provide::ThiserrorProvide; - #[doc(hidden)] - pub use crate::var::Var; - #[doc(hidden)] - pub use core::error::Error; - #[cfg(all(feature = "std", not(thiserror_no_backtrace_type)))] - #[doc(hidden)] - pub use std::backtrace::Backtrace; -} +mod private; + +include!(concat!(env!("OUT_DIR"), "/private.rs")); diff --git a/src/private.rs b/src/private.rs new file mode 100644 index 00000000..545aa8ee --- /dev/null +++ b/src/private.rs @@ -0,0 +1,14 @@ +#[doc(hidden)] +pub use crate::aserror::AsDynError; +#[doc(hidden)] +pub use crate::display::AsDisplay; +#[cfg(error_generic_member_access)] +#[doc(hidden)] +pub use crate::provide::ThiserrorProvide; +#[doc(hidden)] +pub use crate::var::Var; +#[doc(hidden)] +pub use core::error::Error; +#[cfg(all(feature = "std", not(thiserror_no_backtrace_type)))] +#[doc(hidden)] +pub use std::backtrace::Backtrace; diff --git a/tests/test_lints.rs b/tests/test_lints.rs index 5e2b8957..802ad50a 100644 --- a/tests/test_lints.rs +++ b/tests/test_lints.rs @@ -93,4 +93,6 @@ fn test_deprecated() { let _ = DeprecatedEnum::Variant; #[allow(deprecated)] let _ = DeprecatedVariant::Variant; + #[allow(deprecated)] + let _ = DeprecatedFrom::Variant(DeprecatedStruct); } diff --git a/tests/ui/concat-display.stderr b/tests/ui/concat-display.stderr index 9255488f..73718aee 100644 --- a/tests/ui/concat-display.stderr +++ b/tests/ui/concat-display.stderr @@ -1,7 +1,7 @@ error: expected one of: string literal, `transparent`, `fmt` --> tests/ui/concat-display.rs:8:17 | -8 | #[error(concat!("invalid ", $what))] + 8 | #[error(concat!("invalid ", $what))] | ^^^^^^ ... 13 | error_type!(Error, "foo"); diff --git a/tests/ui/expression-fallback.stderr b/tests/ui/expression-fallback.stderr index 5c9f2157..8d22c3a5 100644 --- a/tests/ui/expression-fallback.stderr +++ b/tests/ui/expression-fallback.stderr @@ -11,6 +11,11 @@ error: argument never used | -- ^^^^^^ argument never used | | | formatting specifier missing + | +help: format specifiers use curly braces, consider adding a format specifier + | +4 | #[error("{}".yellow)] + | ++ error[E0425]: cannot find value `yellow` in this scope --> tests/ui/expression-fallback.rs:4:12 diff --git a/tests/ui/missing-display.stderr b/tests/ui/missing-display.stderr index f7a044bd..fe7472ef 100644 --- a/tests/ui/missing-display.stderr +++ b/tests/ui/missing-display.stderr @@ -4,10 +4,13 @@ error[E0277]: `MyError` doesn't implement `std::fmt::Display` 3 | #[derive(Error, Debug)] | ----- in this derive macro expansion 4 | pub enum MyError { - | ^^^^^^^ `MyError` cannot be formatted with the default formatter + | ^^^^^^^ unsatisfied trait bound | - = help: the trait `std::fmt::Display` is not implemented for `MyError` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +help: the trait `std::fmt::Display` is not implemented for `MyError` + --> tests/ui/missing-display.rs:4:1 + | +4 | pub enum MyError { + | ^^^^^^^^^^^^^^^^ note: required by a bound in `std::error::Error` --> $RUST/core/src/error.rs | diff --git a/tests/ui/no-display.stderr b/tests/ui/no-display.stderr index 8f35b82b..97505826 100644 --- a/tests/ui/no-display.stderr +++ b/tests/ui/no-display.stderr @@ -13,8 +13,8 @@ error[E0599]: the method `as_display` exists for reference `&NoDisplay`, but its note: the trait `std::fmt::Display` must be implemented --> $RUST/core/src/fmt/mod.rs | - | pub trait Display { - | ^^^^^^^^^^^^^^^^^ + | pub trait Display: PointeeSized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `as_display`, perhaps you need to implement it: candidate #1: `AsDisplay` @@ -25,8 +25,13 @@ error[E0277]: the trait bound `NoDisplay: Octal` is not satisfied 12 | #[derive(Error, Debug)] | ----- in this derive macro expansion 13 | #[error("thread: {thread:o}")] - | ^^^^^^^^^^^^^^^^^^^^ the trait `Octal` is not implemented for `NoDisplay` + | ^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound | +help: the trait `Octal` is not implemented for `NoDisplay` + --> tests/ui/no-display.rs:4:1 + | + 4 | struct NoDisplay; + | ^^^^^^^^^^^^^^^^ = help: the following other types implement trait `Octal`: &T &mut T @@ -38,9 +43,4 @@ error[E0277]: the trait bound `NoDisplay: Octal` is not satisfied i32 and $N others = note: required for `&NoDisplay` to implement `Octal` -note: required by a bound in `core::fmt::rt::Argument::<'_>::new_octal` - --> $RUST/core/src/fmt/rt.rs - | - | pub fn new_octal(x: &T) -> Argument<'_> { - | ^^^^^ required by this bound in `Argument::<'_>::new_octal` = note: this error originates in the macro `$crate::format_args` which comes from the expansion of the derive macro `Error` (in Nightly builds, run with -Z macro-backtrace for more info)