From 2c1e53b8e4fce3d9b762296bf371f433651c2cc8 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Tue, 15 Jun 2021 20:39:46 +0000 Subject: [PATCH] Bug 1716518 - Upgrade anyhow to v1.0.41. r=emilio Differential Revision: https://phabricator.services.mozilla.com/D117755 --- Cargo.lock | 4 +- third_party/rust/anyhow/.cargo-checksum.json | 2 +- third_party/rust/anyhow/Cargo.toml | 9 +- third_party/rust/anyhow/README.md | 10 +- third_party/rust/anyhow/build.rs | 39 +- third_party/rust/anyhow/src/backtrace.rs | 379 +++++++++++++++- third_party/rust/anyhow/src/context.rs | 2 +- third_party/rust/anyhow/src/error.rs | 416 ++++++++++++------ third_party/rust/anyhow/src/fmt.rs | 26 +- third_party/rust/anyhow/src/kind.rs | 3 - third_party/rust/anyhow/src/lib.rs | 68 ++- third_party/rust/anyhow/src/macros.rs | 42 +- third_party/rust/anyhow/src/ptr.rs | 199 +++++++++ third_party/rust/anyhow/tests/compiletest.rs | 1 + third_party/rust/anyhow/tests/drop/mod.rs | 2 + third_party/rust/anyhow/tests/test_convert.rs | 2 + .../rust/anyhow/tests/test_downcast.rs | 8 + third_party/rust/anyhow/tests/test_ffi.rs | 18 + third_party/rust/anyhow/tests/test_macros.rs | 11 + .../rust/anyhow/tests/ui/no-impl.stderr | 22 +- .../rust/anyhow/tests/ui/temporary-value.rs | 5 + .../anyhow/tests/ui/temporary-value.stderr | 8 + 22 files changed, 1083 insertions(+), 193 deletions(-) create mode 100644 third_party/rust/anyhow/src/ptr.rs create mode 100644 third_party/rust/anyhow/tests/test_ffi.rs create mode 100644 third_party/rust/anyhow/tests/ui/temporary-value.rs create mode 100644 third_party/rust/anyhow/tests/ui/temporary-value.stderr diff --git a/Cargo.lock b/Cargo.lock index 0d136f84bf2d..71663fa1a45f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,9 +35,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.30" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2494382e9ba43995f3c56359e518641f450f5c36feeb4632a75cde2ec297c867" +checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61" [[package]] name = "app_services_logger" diff --git a/third_party/rust/anyhow/.cargo-checksum.json b/third_party/rust/anyhow/.cargo-checksum.json index 015dd54c4a0b..e3841923b769 100644 --- a/third_party/rust/anyhow/.cargo-checksum.json +++ b/third_party/rust/anyhow/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"76e6e0a729a4038b0d8bcdd36a054e96f3e93dc1922813f512d28cdf8d21e516","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"0d9c5facc3db17123752af8c3dbcdb9bb3785c8ed046b27de26669e4e87f131c","build.rs":"d8b58acc2cd88d627763135b3b25b46f276e2672ef740efb7fb5b1404fb230d8","src/backtrace.rs":"a82a8ffae2c68ee385dc78d8ec8cb6f3351234f0ad6af7e87df2371593e0f6aa","src/chain.rs":"1627608ce95c3484d26e1742a1b8b533b74c6159916b717bacffae3ae53731f9","src/context.rs":"f2be36af9588c924ed087bcb7bd681d330889e54b8f98cdc2aba93512a28762e","src/error.rs":"2c6a51880c7379265f7f7b6557e7bed808ff0f3267337a0c77dbbc1d2c4662e7","src/fmt.rs":"079d7b4faaa23f42423e0bb6b4e8a80d7d6d45c38c0d46bebd7d647c8679469f","src/kind.rs":"8481a8b7835eebb3859a8c32c217bf9c73543cfc62e3916b98d39af8b063125c","src/lib.rs":"119a39d1062a4b99a9f888a9f595a48fabacba6c8f2c3c59361ce2065d938ef6","src/macros.rs":"77722190b58a6106b21aefd3b5d4f136a076afcdbc0fae21562d99e2c22912e1","src/wrapper.rs":"1229beca67dbd95ca77c9ecce282272acc55276c267c58cb73a75388b4693dda","tests/common/mod.rs":"f9088c2d7afafa64ff730b629272045b776bfafc2f5957508242da630635f2e1","tests/compiletest.rs":"0a52a44786aea1c299c695bf948b2ed2081e4cc344e5c2cadceab4eb03d0010d","tests/drop/mod.rs":"464bc1ddeae307eac906928286ec3edb77057c5c1302e02150d3649e2b861f1a","tests/test_autotrait.rs":"981e792db353be2f14c7a1cabe43b5f1329c168cb7679077cc2be786a0920d48","tests/test_backtrace.rs":"0e50edbb33b6bd07ba89ff3db72fb7c688ba2a4371fccdbbb20309ab02948b6a","tests/test_boxed.rs":"98a45325b1e86d4c5d3094ab99cd1ada1f771c505d2d7322f0afcbe7bdb71cfa","tests/test_chain.rs":"f28efeae7395d1c395e6f1a647b4199c25a00410ade45248c145c6fcf2fb448a","tests/test_context.rs":"f82c915b182df1a604a4cd558a03b1a821414983d6f6af6822398104cea70676","tests/test_convert.rs":"62840be1ee8022ba5e8c0d3fc1752a1526b2c47d4cceecff2b86790524c3b3ea","tests/test_downcast.rs":"253d6f54e554965023b378b037827ec6289c4779a7a7c12706e19c2731d219fe","tests/test_fmt.rs":"17572596f257aac9aa2ec4620e292ca6a954128b94772bb948399fab53832e70","tests/test_macros.rs":"c7d3d5e0b756f59d4858035025fb341d031369c88486fd9f961ee16bae6c78bf","tests/test_repr.rs":"dbb9b04ddbe1ab31eb5331ea69f05bb3a147299da2275a3d4dcc92947b5591b9","tests/test_source.rs":"b80723cf635a4f8c4df21891b34bfab9ed2b2aa407e7a2f826d24e334cd5f88e","tests/ui/no-impl.rs":"fab6cbf2f6ea510b86f567dfb3b7c31250a9fd71ae5d110dbb9188be569ec593","tests/ui/no-impl.stderr":"7c2c3f46c266a437300591f10be330f937ac6a0a2213ed5030a9fbc895e2d100"},"package":"2494382e9ba43995f3c56359e518641f450f5c36feeb4632a75cde2ec297c867"} \ No newline at end of file +{"files":{"Cargo.toml":"05c1bbd8a9f36fba15398f0dc3634198aca3c3f6887b085b9812d21f4f33c450","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"4a58a26808c92aae6265a60e21745bb2891a60cf1d69985fc05d26b77c2b9a79","build.rs":"afa03584629443ec723ca4e99bd087d5f07602d8640772f6f57c8e3847f75ae6","src/backtrace.rs":"a1a52f9874f0aa1382fb404f029c6fa88e53afe38fb2417877d5711f1f2b90c9","src/chain.rs":"1627608ce95c3484d26e1742a1b8b533b74c6159916b717bacffae3ae53731f9","src/context.rs":"559478ae785ce913523aa21358cc1561ef4b0b95c5c87675a77890364c0162fe","src/error.rs":"2aa93ec95f16980037c244e94fa8ac75f8b20ac22530fe45a24550d1878eb0b5","src/fmt.rs":"c2d4aad6ce20625a70a7c091e3087b6a2c19a4a87c7a12edb4c98978307245ea","src/kind.rs":"ccf5d8075d44b03cc69c0478ee5e5b3a02d4f2e7cecb37588b30043d3fcdf65f","src/lib.rs":"c0a0f94d85f5cc4aed37048ca12d8652da85b50f0999d998903ccd3ebf043eec","src/macros.rs":"88daf58370b2fcc93c43ebd5b9c1659bf5460c972681b63d89d51132126e5560","src/ptr.rs":"f1ece995b5be064773ee3d516710b4948b0bee3c237786d9988c7d2acc52c95c","src/wrapper.rs":"1229beca67dbd95ca77c9ecce282272acc55276c267c58cb73a75388b4693dda","tests/common/mod.rs":"f9088c2d7afafa64ff730b629272045b776bfafc2f5957508242da630635f2e1","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/drop/mod.rs":"382956f4bd3dcd1f6036efb8f11193595a7c60e0a5dbf5f2da149f1f25183abf","tests/test_autotrait.rs":"981e792db353be2f14c7a1cabe43b5f1329c168cb7679077cc2be786a0920d48","tests/test_backtrace.rs":"0e50edbb33b6bd07ba89ff3db72fb7c688ba2a4371fccdbbb20309ab02948b6a","tests/test_boxed.rs":"98a45325b1e86d4c5d3094ab99cd1ada1f771c505d2d7322f0afcbe7bdb71cfa","tests/test_chain.rs":"f28efeae7395d1c395e6f1a647b4199c25a00410ade45248c145c6fcf2fb448a","tests/test_context.rs":"f82c915b182df1a604a4cd558a03b1a821414983d6f6af6822398104cea70676","tests/test_convert.rs":"cae1c941727f2371b2439ff95b2628f810cfb2f77431a0807de32db84c5844e1","tests/test_downcast.rs":"e9dc236dad1cbb8b7ad74a0d87d328f23a585fbb55670b8fe55a9a2644041c5c","tests/test_ffi.rs":"d0cb4c1d6d9154090982dee72ae3ebe05a5981f976058c3250f1c9da5a45edef","tests/test_fmt.rs":"17572596f257aac9aa2ec4620e292ca6a954128b94772bb948399fab53832e70","tests/test_macros.rs":"0288c879c4735a8d317560baa3d4a6efbf1435d8ec350c5cb12cc1ba7c484080","tests/test_repr.rs":"dbb9b04ddbe1ab31eb5331ea69f05bb3a147299da2275a3d4dcc92947b5591b9","tests/test_source.rs":"b80723cf635a4f8c4df21891b34bfab9ed2b2aa407e7a2f826d24e334cd5f88e","tests/ui/no-impl.rs":"fab6cbf2f6ea510b86f567dfb3b7c31250a9fd71ae5d110dbb9188be569ec593","tests/ui/no-impl.stderr":"7dd1b84a267c83121d9f85a9c1aadc072a863ec324e170af4d7d19516f0f526c","tests/ui/temporary-value.rs":"4dcc96271b2403e6372cf4cfc813445e5ce4365fc6e156b6bc38274098499a70","tests/ui/temporary-value.stderr":"4b0cceae9e9b27fe2594e6c02bb3e3fd9965ed04498738e5877934dab807b50f"},"package":"15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61"} \ No newline at end of file diff --git a/third_party/rust/anyhow/Cargo.toml b/third_party/rust/anyhow/Cargo.toml index 5ae385777fdf..bf9b18f92b03 100644 --- a/third_party/rust/anyhow/Cargo.toml +++ b/third_party/rust/anyhow/Cargo.toml @@ -13,7 +13,7 @@ [package] edition = "2018" name = "anyhow" -version = "1.0.30" +version = "1.0.41" authors = ["David Tolnay "] description = "Flexible concrete Error type built on std::error::Error" documentation = "https://docs.rs/anyhow" @@ -24,6 +24,9 @@ repository = "https://github.com/dtolnay/anyhow" [package.metadata.docs.rs] rustdoc-args = ["--cfg", "doc_cfg"] targets = ["x86_64-unknown-linux-gnu"] +[dependencies.backtrace] +version = "0.3.51" +optional = true [dev-dependencies.futures] version = "0.3" default-features = false @@ -31,6 +34,10 @@ default-features = false [dev-dependencies.rustversion] version = "1.0" +[dev-dependencies.syn] +version = "1.0" +features = ["full"] + [dev-dependencies.thiserror] version = "1.0" diff --git a/third_party/rust/anyhow/README.md b/third_party/rust/anyhow/README.md index 87b41d795826..c6eb0f1a1d03 100644 --- a/third_party/rust/anyhow/README.md +++ b/third_party/rust/anyhow/README.md @@ -1,5 +1,5 @@ -Anyhow ¯\\\_(ツ)\_/¯ -========================= +Anyhow ¯\\\_(°ペ)\_/¯ +========================== [github](https://github.com/dtolnay/anyhow) [crates.io](https://crates.io/crates/anyhow) @@ -118,6 +118,12 @@ anyhow = "1.0" return Err(anyhow!("Missing attribute: {}", missing)); ``` + A `bail!` macro is provided as a shorthand for the same early return. + + ```rust + bail!("Missing attribute: {}", missing); + ``` +
## No-std support diff --git a/third_party/rust/anyhow/build.rs b/third_party/rust/anyhow/build.rs index d20b0721dba7..df2e73bd82a4 100644 --- a/third_party/rust/anyhow/build.rs +++ b/third_party/rust/anyhow/build.rs @@ -2,6 +2,12 @@ use std::env; use std::fs; use std::path::Path; use std::process::{Command, ExitStatus, Stdio}; +use std::str; + +#[cfg(all(feature = "backtrace", not(feature = "std")))] +compile_error! { + "`backtrace` feature without `std` feature is not supported" +} // This code exercises the surface area that we expect of the std Backtrace // type. If the current toolchain is able to compile it, we go ahead and use @@ -35,12 +41,24 @@ const PROBE: &str = r#" "#; fn main() { - if !cfg!(feature = "std") { - return; + if cfg!(feature = "std") { + match compile_probe() { + Some(status) if status.success() => println!("cargo:rustc-cfg=backtrace"), + _ => {} + } } - match compile_probe() { - Some(status) if status.success() => println!("cargo:rustc-cfg=backtrace"), - _ => {} + + let rustc = match rustc_minor_version() { + Some(rustc) => rustc, + None => return, + }; + + if rustc < 38 { + println!("cargo:rustc-cfg=anyhow_no_macro_reexport"); + } + + if rustc < 51 { + println!("cargo:rustc-cfg=anyhow_no_ptr_addr_of"); } } @@ -61,3 +79,14 @@ fn compile_probe() -> Option { .status() .ok() } + +fn rustc_minor_version() -> Option { + let rustc = env::var_os("RUSTC")?; + let output = Command::new(rustc).arg("--version").output().ok()?; + let version = str::from_utf8(&output.stdout).ok()?; + let mut pieces = version.split('.'); + if pieces.next() != Some("rustc 1") { + return None; + } + pieces.next()?.parse().ok() +} diff --git a/third_party/rust/anyhow/src/backtrace.rs b/third_party/rust/anyhow/src/backtrace.rs index 01e33cb2379a..1fa20a6a12a2 100644 --- a/third_party/rust/anyhow/src/backtrace.rs +++ b/third_party/rust/anyhow/src/backtrace.rs @@ -1,17 +1,34 @@ #[cfg(backtrace)] -pub(crate) use std::backtrace::Backtrace; +pub(crate) use std::backtrace::{Backtrace, BacktraceStatus}; -#[cfg(not(backtrace))] +#[cfg(all(not(backtrace), feature = "backtrace"))] +pub(crate) use self::capture::{Backtrace, BacktraceStatus}; + +#[cfg(not(any(backtrace, feature = "backtrace")))] pub(crate) enum Backtrace {} #[cfg(backtrace)] -macro_rules! backtrace { +macro_rules! impl_backtrace { () => { - Some(Backtrace::capture()) + std::backtrace::Backtrace }; } -#[cfg(not(backtrace))] +#[cfg(all(not(backtrace), feature = "backtrace"))] +macro_rules! impl_backtrace { + () => { + impl core::fmt::Debug + core::fmt::Display + }; +} + +#[cfg(any(backtrace, feature = "backtrace"))] +macro_rules! backtrace { + () => { + Some(crate::backtrace::Backtrace::capture()) + }; +} + +#[cfg(not(any(backtrace, feature = "backtrace")))] macro_rules! backtrace { () => { None @@ -23,14 +40,362 @@ macro_rules! backtrace_if_absent { ($err:expr) => { match $err.backtrace() { Some(_) => None, - None => Some(Backtrace::capture()), + None => backtrace!(), } }; } -#[cfg(all(feature = "std", not(backtrace)))] +#[cfg(all(feature = "std", not(backtrace), feature = "backtrace"))] +macro_rules! backtrace_if_absent { + ($err:expr) => { + backtrace!() + }; +} + +#[cfg(all(feature = "std", not(backtrace), not(feature = "backtrace")))] macro_rules! backtrace_if_absent { ($err:expr) => { None }; } + +#[cfg(all(not(backtrace), feature = "backtrace"))] +mod capture { + use backtrace::{BacktraceFmt, BytesOrWideString, Frame, PrintFmt, SymbolName}; + use core::cell::UnsafeCell; + use core::fmt::{self, Debug, Display}; + use core::sync::atomic::{AtomicUsize, Ordering}; + use std::borrow::Cow; + use std::env; + use std::path::{self, Path, PathBuf}; + use std::sync::Once; + + pub(crate) struct Backtrace { + inner: Inner, + } + + pub(crate) enum BacktraceStatus { + Unsupported, + Disabled, + Captured, + } + + enum Inner { + Unsupported, + Disabled, + Captured(LazilyResolvedCapture), + } + + struct Capture { + actual_start: usize, + resolved: bool, + frames: Vec, + } + + struct BacktraceFrame { + frame: Frame, + symbols: Vec, + } + + struct BacktraceSymbol { + name: Option>, + filename: Option, + lineno: Option, + colno: Option, + } + + enum BytesOrWide { + Bytes(Vec), + Wide(Vec), + } + + impl Debug for Backtrace { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let capture = match &self.inner { + Inner::Unsupported => return fmt.write_str(""), + Inner::Disabled => return fmt.write_str(""), + Inner::Captured(c) => c.force(), + }; + + let frames = &capture.frames[capture.actual_start..]; + + write!(fmt, "Backtrace ")?; + + let mut dbg = fmt.debug_list(); + + for frame in frames { + if frame.frame.ip().is_null() { + continue; + } + + dbg.entries(&frame.symbols); + } + + dbg.finish() + } + } + + impl Debug for BacktraceFrame { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let mut dbg = fmt.debug_list(); + dbg.entries(&self.symbols); + dbg.finish() + } + } + + impl Debug for BacktraceSymbol { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{{ ")?; + + if let Some(fn_name) = self.name.as_ref().map(|b| SymbolName::new(b)) { + write!(fmt, "fn: \"{:#}\"", fn_name)?; + } else { + write!(fmt, "fn: ")?; + } + + if let Some(fname) = self.filename.as_ref() { + write!(fmt, ", file: \"{:?}\"", fname)?; + } + + if let Some(line) = self.lineno { + write!(fmt, ", line: {:?}", line)?; + } + + write!(fmt, " }}") + } + } + + impl Debug for BytesOrWide { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + output_filename( + fmt, + match self { + BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w), + BytesOrWide::Wide(w) => BytesOrWideString::Wide(w), + }, + PrintFmt::Short, + env::current_dir().as_ref().ok(), + ) + } + } + + impl Backtrace { + fn enabled() -> bool { + static ENABLED: AtomicUsize = AtomicUsize::new(0); + match ENABLED.load(Ordering::SeqCst) { + 0 => {} + 1 => return false, + _ => return true, + } + let enabled = match env::var_os("RUST_LIB_BACKTRACE") { + Some(s) => s != "0", + None => match env::var_os("RUST_BACKTRACE") { + Some(s) => s != "0", + None => false, + }, + }; + ENABLED.store(enabled as usize + 1, Ordering::SeqCst); + enabled + } + + #[inline(never)] // want to make sure there's a frame here to remove + pub(crate) fn capture() -> Backtrace { + if Backtrace::enabled() { + Backtrace::create(Backtrace::capture as usize) + } else { + let inner = Inner::Disabled; + Backtrace { inner } + } + } + + // Capture a backtrace which starts just before the function addressed + // by `ip` + fn create(ip: usize) -> Backtrace { + let mut frames = Vec::new(); + let mut actual_start = None; + backtrace::trace(|frame| { + frames.push(BacktraceFrame { + frame: frame.clone(), + symbols: Vec::new(), + }); + if frame.symbol_address() as usize == ip && actual_start.is_none() { + actual_start = Some(frames.len() + 1); + } + true + }); + + // If no frames came out assume that this is an unsupported platform + // since `backtrace` doesn't provide a way of learning this right + // now, and this should be a good enough approximation. + let inner = if frames.is_empty() { + Inner::Unsupported + } else { + Inner::Captured(LazilyResolvedCapture::new(Capture { + actual_start: actual_start.unwrap_or(0), + frames, + resolved: false, + })) + }; + + Backtrace { inner } + } + + pub(crate) fn status(&self) -> BacktraceStatus { + match self.inner { + Inner::Unsupported => BacktraceStatus::Unsupported, + Inner::Disabled => BacktraceStatus::Disabled, + Inner::Captured(_) => BacktraceStatus::Captured, + } + } + } + + impl Display for Backtrace { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + let capture = match &self.inner { + Inner::Unsupported => return fmt.write_str("unsupported backtrace"), + Inner::Disabled => return fmt.write_str("disabled backtrace"), + Inner::Captured(c) => c.force(), + }; + + let full = fmt.alternate(); + let (frames, style) = if full { + (&capture.frames[..], PrintFmt::Full) + } else { + (&capture.frames[capture.actual_start..], PrintFmt::Short) + }; + + // When printing paths we try to strip the cwd if it exists, + // otherwise we just print the path as-is. Note that we also only do + // this for the short format, because if it's full we presumably + // want to print everything. + let cwd = env::current_dir(); + let mut print_path = move |fmt: &mut fmt::Formatter, path: BytesOrWideString| { + output_filename(fmt, path, style, cwd.as_ref().ok()) + }; + + let mut f = BacktraceFmt::new(fmt, style, &mut print_path); + f.add_context()?; + for frame in frames { + let mut f = f.frame(); + if frame.symbols.is_empty() { + f.print_raw(frame.frame.ip(), None, None, None)?; + } else { + for symbol in frame.symbols.iter() { + f.print_raw_with_column( + frame.frame.ip(), + symbol.name.as_ref().map(|b| SymbolName::new(b)), + symbol.filename.as_ref().map(|b| match b { + BytesOrWide::Bytes(w) => BytesOrWideString::Bytes(w), + BytesOrWide::Wide(w) => BytesOrWideString::Wide(w), + }), + symbol.lineno, + symbol.colno, + )?; + } + } + } + f.finish()?; + Ok(()) + } + } + + struct LazilyResolvedCapture { + sync: Once, + capture: UnsafeCell, + } + + impl LazilyResolvedCapture { + fn new(capture: Capture) -> Self { + LazilyResolvedCapture { + sync: Once::new(), + capture: UnsafeCell::new(capture), + } + } + + fn force(&self) -> &Capture { + self.sync.call_once(|| { + // Safety: This exclusive reference can't overlap with any + // others. `Once` guarantees callers will block until this + // closure returns. `Once` also guarantees only a single caller + // will enter this closure. + unsafe { &mut *self.capture.get() }.resolve(); + }); + + // Safety: This shared reference can't overlap with the exclusive + // reference above. + unsafe { &*self.capture.get() } + } + } + + // Safety: Access to the inner value is synchronized using a thread-safe + // `Once`. So long as `Capture` is `Sync`, `LazilyResolvedCapture` is too + unsafe impl Sync for LazilyResolvedCapture where Capture: Sync {} + + impl Capture { + fn resolve(&mut self) { + // If we're already resolved, nothing to do! + if self.resolved { + return; + } + self.resolved = true; + + for frame in self.frames.iter_mut() { + let symbols = &mut frame.symbols; + let frame = &frame.frame; + backtrace::resolve_frame(frame, |symbol| { + symbols.push(BacktraceSymbol { + name: symbol.name().map(|m| m.as_bytes().to_vec()), + filename: symbol.filename_raw().map(|b| match b { + BytesOrWideString::Bytes(b) => BytesOrWide::Bytes(b.to_owned()), + BytesOrWideString::Wide(b) => BytesOrWide::Wide(b.to_owned()), + }), + lineno: symbol.lineno(), + colno: symbol.colno(), + }); + }); + } + } + } + + // Prints the filename of the backtrace frame. + fn output_filename( + fmt: &mut fmt::Formatter, + bows: BytesOrWideString, + print_fmt: PrintFmt, + cwd: Option<&PathBuf>, + ) -> fmt::Result { + let file: Cow = match bows { + #[cfg(unix)] + BytesOrWideString::Bytes(bytes) => { + use std::os::unix::ffi::OsStrExt; + Path::new(std::ffi::OsStr::from_bytes(bytes)).into() + } + #[cfg(not(unix))] + BytesOrWideString::Bytes(bytes) => { + Path::new(std::str::from_utf8(bytes).unwrap_or("")).into() + } + #[cfg(windows)] + BytesOrWideString::Wide(wide) => { + use std::os::windows::ffi::OsStringExt; + Cow::Owned(std::ffi::OsString::from_wide(wide).into()) + } + #[cfg(not(windows))] + BytesOrWideString::Wide(_wide) => Path::new("").into(), + }; + if print_fmt == PrintFmt::Short && file.is_absolute() { + if let Some(cwd) = cwd { + if let Ok(stripped) = file.strip_prefix(&cwd) { + if let Some(s) = stripped.to_str() { + return write!(fmt, ".{}{}", path::MAIN_SEPARATOR, s); + } + } + } + } + Display::fmt(&file.display(), fmt) + } +} + +fn _assert_send_sync() { + fn _assert() {} + _assert::(); +} diff --git a/third_party/rust/anyhow/src/context.rs b/third_party/rust/anyhow/src/context.rs index 25d34114c111..c2284130fbac 100644 --- a/third_party/rust/anyhow/src/context.rs +++ b/third_party/rust/anyhow/src/context.rs @@ -143,7 +143,7 @@ where } fn source(&self) -> Option<&(dyn StdError + 'static)> { - Some(self.error.inner.error()) + Some(unsafe { crate::ErrorImpl::error(self.error.inner.by_ref()) }) } } diff --git a/third_party/rust/anyhow/src/error.rs b/third_party/rust/anyhow/src/error.rs index 80d879f84e30..92bb63de0ae5 100644 --- a/third_party/rust/anyhow/src/error.rs +++ b/third_party/rust/anyhow/src/error.rs @@ -1,11 +1,16 @@ use crate::alloc::Box; use crate::backtrace::Backtrace; use crate::chain::Chain; +#[cfg(any(feature = "std", anyhow_no_ptr_addr_of))] +use crate::ptr::Mut; +use crate::ptr::{Own, Ref}; use crate::{Error, StdError}; use core::any::TypeId; use core::fmt::{self, Debug, Display}; -use core::mem::{self, ManuallyDrop}; -use core::ptr::{self, NonNull}; +use core::mem::ManuallyDrop; +#[cfg(not(anyhow_no_ptr_addr_of))] +use core::ptr; +use core::ptr::NonNull; #[cfg(feature = "std")] use core::ops::{Deref, DerefMut}; @@ -80,11 +85,15 @@ impl Error { let vtable = &ErrorVTable { object_drop: object_drop::, object_ref: object_ref::, - #[cfg(feature = "std")] + #[cfg(anyhow_no_ptr_addr_of)] object_mut: object_mut::, object_boxed: object_boxed::, object_downcast: object_downcast::, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: object_downcast_mut::, object_drop_rest: object_drop_front::, + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: no_backtrace, }; // Safety: passing vtable that operates on the right type E. @@ -100,11 +109,15 @@ impl Error { let vtable = &ErrorVTable { object_drop: object_drop::>, object_ref: object_ref::>, - #[cfg(feature = "std")] + #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] object_mut: object_mut::>, object_boxed: object_boxed::>, object_downcast: object_downcast::, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: object_downcast_mut::, object_drop_rest: object_drop_front::, + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: no_backtrace, }; // Safety: MessageError is repr(transparent) so it is okay for the @@ -121,11 +134,15 @@ impl Error { let vtable = &ErrorVTable { object_drop: object_drop::>, object_ref: object_ref::>, - #[cfg(feature = "std")] + #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] object_mut: object_mut::>, object_boxed: object_boxed::>, object_downcast: object_downcast::, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: object_downcast_mut::, object_drop_rest: object_drop_front::, + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: no_backtrace, }; // Safety: DisplayError is repr(transparent) so it is okay for the @@ -144,11 +161,15 @@ impl Error { let vtable = &ErrorVTable { object_drop: object_drop::>, object_ref: object_ref::>, - #[cfg(feature = "std")] + #[cfg(anyhow_no_ptr_addr_of)] object_mut: object_mut::>, object_boxed: object_boxed::>, object_downcast: context_downcast::, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: context_downcast_mut::, object_drop_rest: context_drop_rest::, + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: no_backtrace, }; // Safety: passing vtable that operates on the right type. @@ -165,11 +186,15 @@ impl Error { let vtable = &ErrorVTable { object_drop: object_drop::, object_ref: object_ref::, - #[cfg(feature = "std")] + #[cfg(anyhow_no_ptr_addr_of)] object_mut: object_mut::, object_boxed: object_boxed::, object_downcast: object_downcast::>, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: object_downcast_mut::>, object_drop_rest: object_drop_front::>, + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: no_backtrace, }; // Safety: BoxedError is repr(transparent) so it is okay for the vtable @@ -190,19 +215,18 @@ impl Error { where E: StdError + Send + Sync + 'static, { - let inner = Box::new(ErrorImpl { + let inner: Box> = Box::new(ErrorImpl { vtable, backtrace, _object: error, }); // Erase the concrete type of E from the compile-time type system. This - // is equivalent to the safe unsize coersion from Box> to + // is equivalent to the safe unsize coercion from Box> to // Box> except that the // result is a thin pointer. The necessary behavior for manipulating the // underlying ErrorImpl is preserved in the vtable provided by the // caller rather than a builtin fat pointer vtable. - let erased = mem::transmute::>, Box>>(inner); - let inner = ManuallyDrop::new(erased); + let inner = Own::new(inner).cast::(); Error { inner } } @@ -272,11 +296,15 @@ impl Error { let vtable = &ErrorVTable { object_drop: object_drop::>, object_ref: object_ref::>, - #[cfg(feature = "std")] + #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] object_mut: object_mut::>, object_boxed: object_boxed::>, object_downcast: context_chain_downcast::, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: context_chain_downcast_mut::, object_drop_rest: context_chain_drop_rest::, + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: context_backtrace::, }; // As the cause is anyhow::Error, we already have a backtrace for it. @@ -288,9 +316,6 @@ impl Error { /// Get the backtrace for this Error. /// - /// Backtraces are only available on the nightly channel. Tracking issue: - /// [rust-lang/rust#53487][tracking]. - /// /// In order for the backtrace to be meaningful, one of the two environment /// variables `RUST_LIB_BACKTRACE=1` or `RUST_BACKTRACE=1` must be defined /// and `RUST_LIB_BACKTRACE` must not be `0`. Backtraces are somewhat @@ -304,10 +329,25 @@ impl Error { /// - If you want only panics to have backtraces, set `RUST_BACKTRACE=1` and /// `RUST_LIB_BACKTRACE=0`. /// + /// # Stability + /// + /// Standard library backtraces are only available on the nightly channel. + /// Tracking issue: [rust-lang/rust#53487][tracking]. + /// + /// On stable compilers, this function is only available if the crate's + /// "backtrace" feature is enabled, and will use the `backtrace` crate as + /// the underlying backtrace implementation. + /// + /// ```toml + /// [dependencies] + /// anyhow = { version = "1.0", features = ["backtrace"] } + /// ``` + /// /// [tracking]: https://github.com/rust-lang/rust/issues/53487 - #[cfg(backtrace)] - pub fn backtrace(&self) -> &Backtrace { - self.inner.backtrace() + #[cfg(any(backtrace, feature = "backtrace"))] + #[cfg_attr(doc_cfg, doc(cfg(any(nightly, feature = "backtrace"))))] + pub fn backtrace(&self) -> &impl_backtrace!() { + unsafe { ErrorImpl::backtrace(self.inner.by_ref()) } } /// An iterator of the chain of source errors contained by this Error. @@ -332,8 +372,9 @@ impl Error { /// } /// ``` #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] pub fn chain(&self) -> Chain { - self.inner.chain() + unsafe { ErrorImpl::chain(self.inner.by_ref()) } } /// The lowest level cause of this error — this error's cause's @@ -342,13 +383,9 @@ impl Error { /// The root cause is the last error in the iterator produced by /// [`chain()`][Error::chain]. #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] pub fn root_cause(&self) -> &(dyn StdError + 'static) { - let mut chain = self.chain(); - let mut root_cause = chain.next().unwrap(); - for cause in chain { - root_cause = cause; - } - root_cause + self.chain().last().unwrap() } /// Returns true if `E` is the type held by this error object. @@ -367,16 +404,23 @@ impl Error { } /// Attempt to downcast the error object to a concrete type. - pub fn downcast(self) -> Result + pub fn downcast(mut self) -> Result where E: Display + Debug + Send + Sync + 'static, { let target = TypeId::of::(); + let inner = self.inner.by_mut(); unsafe { // Use vtable to find NonNull<()> which points to a value of type E // somewhere inside the data structure. - let addr = match (self.inner.vtable.object_downcast)(&self.inner, target) { - Some(addr) => addr, + #[cfg(not(anyhow_no_ptr_addr_of))] + let addr = match (vtable(inner.ptr).object_downcast)(inner.by_ref(), target) { + Some(addr) => addr.by_mut().extend(), + None => return Err(self), + }; + #[cfg(anyhow_no_ptr_addr_of)] + let addr = match (vtable(inner.ptr).object_downcast_mut)(inner, target) { + Some(addr) => addr.extend(), None => return Err(self), }; @@ -385,15 +429,10 @@ impl Error { let outer = ManuallyDrop::new(self); // Read E from where the vtable found it. - let error = ptr::read(addr.cast::().as_ptr()); - - // Read Box> from self. Can't move it out because - // Error has a Drop impl which we want to not run. - let inner = ptr::read(&outer.inner); - let erased = ManuallyDrop::into_inner(inner); + let error = addr.cast::().read(); // Drop rest of the data structure outside of E. - (erased.vtable.object_drop_rest)(erased, target); + (vtable(outer.inner.ptr).object_drop_rest)(outer.inner, target); Ok(error) } @@ -443,8 +482,8 @@ impl Error { unsafe { // Use vtable to find NonNull<()> which points to a value of type E // somewhere inside the data structure. - let addr = (self.inner.vtable.object_downcast)(&self.inner, target)?; - Some(&*addr.cast::().as_ptr()) + let addr = (vtable(self.inner.ptr).object_downcast)(self.inner.by_ref(), target)?; + Some(addr.cast::().deref()) } } @@ -457,13 +496,21 @@ impl Error { unsafe { // Use vtable to find NonNull<()> which points to a value of type E // somewhere inside the data structure. - let addr = (self.inner.vtable.object_downcast)(&self.inner, target)?; - Some(&mut *addr.cast::().as_ptr()) + + #[cfg(not(anyhow_no_ptr_addr_of))] + let addr = + (vtable(self.inner.ptr).object_downcast)(self.inner.by_ref(), target)?.by_mut(); + + #[cfg(anyhow_no_ptr_addr_of)] + let addr = (vtable(self.inner.ptr).object_downcast_mut)(self.inner.by_mut(), target)?; + + Some(addr.cast::().deref_mut()) } } } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl From for Error where E: StdError + Send + Sync + 'static, @@ -475,133 +522,193 @@ where } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl Deref for Error { type Target = dyn StdError + Send + Sync + 'static; fn deref(&self) -> &Self::Target { - self.inner.error() + unsafe { ErrorImpl::error(self.inner.by_ref()) } } } #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] impl DerefMut for Error { fn deref_mut(&mut self) -> &mut Self::Target { - self.inner.error_mut() + unsafe { ErrorImpl::error_mut(self.inner.by_mut()) } } } impl Display for Error { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - self.inner.display(formatter) + unsafe { ErrorImpl::display(self.inner.by_ref(), formatter) } } } impl Debug for Error { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - self.inner.debug(formatter) + unsafe { ErrorImpl::debug(self.inner.by_ref(), formatter) } } } impl Drop for Error { fn drop(&mut self) { unsafe { - // Read Box> from self. - let inner = ptr::read(&self.inner); - let erased = ManuallyDrop::into_inner(inner); - // Invoke the vtable's drop behavior. - (erased.vtable.object_drop)(erased); + (vtable(self.inner.ptr).object_drop)(self.inner); } } } struct ErrorVTable { - object_drop: unsafe fn(Box>), - object_ref: unsafe fn(&ErrorImpl<()>) -> &(dyn StdError + Send + Sync + 'static), - #[cfg(feature = "std")] - object_mut: unsafe fn(&mut ErrorImpl<()>) -> &mut (dyn StdError + Send + Sync + 'static), - object_boxed: unsafe fn(Box>) -> Box, - object_downcast: unsafe fn(&ErrorImpl<()>, TypeId) -> Option>, - object_drop_rest: unsafe fn(Box>, TypeId), + object_drop: unsafe fn(Own), + object_ref: unsafe fn(Ref) -> Ref, + #[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] + object_mut: unsafe fn(Mut) -> &mut (dyn StdError + Send + Sync + 'static), + object_boxed: unsafe fn(Own) -> Box, + object_downcast: unsafe fn(Ref, TypeId) -> Option>, + #[cfg(anyhow_no_ptr_addr_of)] + object_downcast_mut: unsafe fn(Mut, TypeId) -> Option>, + object_drop_rest: unsafe fn(Own, TypeId), + #[cfg(all(not(backtrace), feature = "backtrace"))] + object_backtrace: unsafe fn(Ref) -> Option<&Backtrace>, } // Safety: requires layout of *e to match ErrorImpl. -unsafe fn object_drop(e: Box>) { +unsafe fn object_drop(e: Own) { // Cast back to ErrorImpl so that the allocator receives the correct // Layout to deallocate the Box's memory. - let unerased = mem::transmute::>, Box>>(e); + let unerased = e.cast::>().boxed(); drop(unerased); } // Safety: requires layout of *e to match ErrorImpl. -unsafe fn object_drop_front(e: Box>, target: TypeId) { +unsafe fn object_drop_front(e: Own, target: TypeId) { // Drop the fields of ErrorImpl other than E as well as the Box allocation, // without dropping E itself. This is used by downcast after doing a // ptr::read to take ownership of the E. let _ = target; - let unerased = mem::transmute::>, Box>>>(e); + let unerased = e.cast::>>().boxed(); drop(unerased); } // Safety: requires layout of *e to match ErrorImpl. -unsafe fn object_ref(e: &ErrorImpl<()>) -> &(dyn StdError + Send + Sync + 'static) +unsafe fn object_ref(e: Ref) -> Ref where E: StdError + Send + Sync + 'static, { // Attach E's native StdError vtable onto a pointer to self._object. - &(*(e as *const ErrorImpl<()> as *const ErrorImpl))._object + + let unerased = e.cast::>(); + + #[cfg(not(anyhow_no_ptr_addr_of))] + return Ref::from_raw(NonNull::new_unchecked( + ptr::addr_of!((*unerased.as_ptr())._object) as *mut E, + )); + + #[cfg(anyhow_no_ptr_addr_of)] + return Ref::new(&unerased.deref()._object); } -// Safety: requires layout of *e to match ErrorImpl. -#[cfg(feature = "std")] -unsafe fn object_mut(e: &mut ErrorImpl<()>) -> &mut (dyn StdError + Send + Sync + 'static) +// Safety: requires layout of *e to match ErrorImpl, and for `e` to be derived +// from a `&mut` +#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] +unsafe fn object_mut(e: Mut) -> &mut (dyn StdError + Send + Sync + 'static) where E: StdError + Send + Sync + 'static, { // Attach E's native StdError vtable onto a pointer to self._object. - &mut (*(e as *mut ErrorImpl<()> as *mut ErrorImpl))._object + &mut e.cast::>().deref_mut()._object } // Safety: requires layout of *e to match ErrorImpl. -unsafe fn object_boxed(e: Box>) -> Box +unsafe fn object_boxed(e: Own) -> Box where E: StdError + Send + Sync + 'static, { // Attach ErrorImpl's native StdError vtable. The StdError impl is below. - mem::transmute::>, Box>>(e) + e.cast::>().boxed() } // Safety: requires layout of *e to match ErrorImpl. -unsafe fn object_downcast(e: &ErrorImpl<()>, target: TypeId) -> Option> +unsafe fn object_downcast(e: Ref, target: TypeId) -> Option> where E: 'static, { if TypeId::of::() == target { // Caller is looking for an E pointer and e is ErrorImpl, take a // pointer to its E field. - let unerased = e as *const ErrorImpl<()> as *const ErrorImpl; - let addr = &(*unerased)._object as *const E as *mut (); - Some(NonNull::new_unchecked(addr)) + + let unerased = e.cast::>(); + + #[cfg(not(anyhow_no_ptr_addr_of))] + return Some( + Ref::from_raw(NonNull::new_unchecked( + ptr::addr_of!((*unerased.as_ptr())._object) as *mut E, + )) + .cast::<()>(), + ); + + #[cfg(anyhow_no_ptr_addr_of)] + return Some(Ref::new(&unerased.deref()._object).cast::<()>()); } else { None } } +// Safety: requires layout of *e to match ErrorImpl. +#[cfg(anyhow_no_ptr_addr_of)] +unsafe fn object_downcast_mut(e: Mut, target: TypeId) -> Option> +where + E: 'static, +{ + if TypeId::of::() == target { + // Caller is looking for an E pointer and e is ErrorImpl, take a + // pointer to its E field. + let unerased = e.cast::>().deref_mut(); + Some(Mut::new(&mut unerased._object).cast::<()>()) + } else { + None + } +} + +#[cfg(all(not(backtrace), feature = "backtrace"))] +fn no_backtrace(e: Ref) -> Option<&Backtrace> { + let _ = e; + None +} + // Safety: requires layout of *e to match ErrorImpl>. #[cfg(feature = "std")] -unsafe fn context_downcast(e: &ErrorImpl<()>, target: TypeId) -> Option> +unsafe fn context_downcast(e: Ref, target: TypeId) -> Option> where C: 'static, E: 'static, { if TypeId::of::() == target { - let unerased = e as *const ErrorImpl<()> as *const ErrorImpl>; - let addr = &(*unerased)._object.context as *const C as *mut (); - Some(NonNull::new_unchecked(addr)) + let unerased = e.cast::>>().deref(); + Some(Ref::new(&unerased._object.context).cast::<()>()) } else if TypeId::of::() == target { - let unerased = e as *const ErrorImpl<()> as *const ErrorImpl>; - let addr = &(*unerased)._object.error as *const E as *mut (); - Some(NonNull::new_unchecked(addr)) + let unerased = e.cast::>>().deref(); + Some(Ref::new(&unerased._object.error).cast::<()>()) + } else { + None + } +} + +// Safety: requires layout of *e to match ErrorImpl>. +#[cfg(all(feature = "std", anyhow_no_ptr_addr_of))] +unsafe fn context_downcast_mut(e: Mut, target: TypeId) -> Option> +where + C: 'static, + E: 'static, +{ + if TypeId::of::() == target { + let unerased = e.cast::>>().deref_mut(); + Some(Mut::new(&mut unerased._object.context).cast::<()>()) + } else if TypeId::of::() == target { + let unerased = e.cast::>>().deref_mut(); + Some(Mut::new(&mut unerased._object.error).cast::<()>()) } else { None } @@ -609,7 +716,7 @@ where // Safety: requires layout of *e to match ErrorImpl>. #[cfg(feature = "std")] -unsafe fn context_drop_rest(e: Box>, target: TypeId) +unsafe fn context_drop_rest(e: Own, target: TypeId) where C: 'static, E: 'static, @@ -617,68 +724,92 @@ where // Called after downcasting by value to either the C or the E and doing a // ptr::read to take ownership of that value. if TypeId::of::() == target { - let unerased = mem::transmute::< - Box>, - Box, E>>>, - >(e); + let unerased = e + .cast::, E>>>() + .boxed(); drop(unerased); } else { - let unerased = mem::transmute::< - Box>, - Box>>>, - >(e); + let unerased = e + .cast::>>>() + .boxed(); drop(unerased); } } // Safety: requires layout of *e to match ErrorImpl>. -unsafe fn context_chain_downcast(e: &ErrorImpl<()>, target: TypeId) -> Option> +unsafe fn context_chain_downcast(e: Ref, target: TypeId) -> Option> where C: 'static, { + let unerased = e.cast::>>().deref(); if TypeId::of::() == target { - let unerased = e as *const ErrorImpl<()> as *const ErrorImpl>; - let addr = &(*unerased)._object.context as *const C as *mut (); - Some(NonNull::new_unchecked(addr)) + Some(Ref::new(&unerased._object.context).cast::<()>()) } else { // Recurse down the context chain per the inner error's vtable. - let unerased = e as *const ErrorImpl<()> as *const ErrorImpl>; - let source = &(*unerased)._object.error; - (source.inner.vtable.object_downcast)(&source.inner, target) + let source = &unerased._object.error; + (vtable(source.inner.ptr).object_downcast)(source.inner.by_ref(), target) } } // Safety: requires layout of *e to match ErrorImpl>. -unsafe fn context_chain_drop_rest(e: Box>, target: TypeId) +#[cfg(anyhow_no_ptr_addr_of)] +unsafe fn context_chain_downcast_mut(e: Mut, target: TypeId) -> Option> +where + C: 'static, +{ + let unerased = e.cast::>>().deref_mut(); + if TypeId::of::() == target { + Some(Mut::new(&mut unerased._object.context).cast::<()>()) + } else { + // Recurse down the context chain per the inner error's vtable. + let source = &mut unerased._object.error; + (vtable(source.inner.ptr).object_downcast_mut)(source.inner.by_mut(), target) + } +} + +// Safety: requires layout of *e to match ErrorImpl>. +unsafe fn context_chain_drop_rest(e: Own, target: TypeId) where C: 'static, { // Called after downcasting by value to either the C or one of the causes // and doing a ptr::read to take ownership of that value. if TypeId::of::() == target { - let unerased = mem::transmute::< - Box>, - Box, Error>>>, - >(e); + let unerased = e + .cast::, Error>>>() + .boxed(); // Drop the entire rest of the data structure rooted in the next Error. drop(unerased); } else { - let unerased = mem::transmute::< - Box>, - Box>>>, - >(e); - // Read out a ManuallyDrop>> from the next error. - let inner = ptr::read(&unerased._object.error.inner); + let unerased = e + .cast::>>>() + .boxed(); + // Read the Own from the next error. + let inner = unerased._object.error.inner; drop(unerased); - let erased = ManuallyDrop::into_inner(inner); + let vtable = vtable(inner.ptr); // Recursively drop the next error using the same target typeid. - (erased.vtable.object_drop_rest)(erased, target); + (vtable.object_drop_rest)(inner, target); } } +// Safety: requires layout of *e to match ErrorImpl>. +#[cfg(all(not(backtrace), feature = "backtrace"))] +#[allow(clippy::unnecessary_wraps)] +unsafe fn context_backtrace(e: Ref) -> Option<&Backtrace> +where + C: 'static, +{ + let unerased = e.cast::>>().deref(); + let backtrace = ErrorImpl::backtrace(unerased._object.error.inner.by_ref()); + Some(backtrace) +} + +// NOTE: If working with `ErrorImpl<()>`, references should be avoided in favor +// of raw pointers and `NonNull`. // repr C to ensure that E remains in the final position. #[repr(C)] -pub(crate) struct ErrorImpl { +pub(crate) struct ErrorImpl { vtable: &'static ErrorVTable, backtrace: Option, // NOTE: Don't use directly. Use only through vtable. Erased type may have @@ -686,6 +817,13 @@ pub(crate) struct ErrorImpl { _object: E, } +// Reads the vtable out of `p`. This is the same as `p.as_ref().vtable`, but +// avoids converting `p` into a reference. +unsafe fn vtable(p: NonNull) -> &'static ErrorVTable { + // NOTE: This assumes that `ErrorVTable` is the first field of ErrorImpl. + *(p.as_ptr() as *const &'static ErrorVTable) +} + // repr C to ensure that ContextError has the same layout as // ContextError, E> and ContextError>. #[repr(C)] @@ -695,41 +833,54 @@ pub(crate) struct ContextError { } impl ErrorImpl { - fn erase(&self) -> &ErrorImpl<()> { + fn erase(&self) -> Ref { // Erase the concrete type of E but preserve the vtable in self.vtable // for manipulating the resulting thin pointer. This is analogous to an - // unsize coersion. - unsafe { &*(self as *const ErrorImpl as *const ErrorImpl<()>) } + // unsize coercion. + Ref::new(self).cast::() } } -impl ErrorImpl<()> { - pub(crate) fn error(&self) -> &(dyn StdError + Send + Sync + 'static) { +impl ErrorImpl { + pub(crate) unsafe fn error(this: Ref) -> &(dyn StdError + Send + Sync + 'static) { // Use vtable to attach E's native StdError vtable for the right // original type E. - unsafe { &*(self.vtable.object_ref)(self) } + (vtable(this.ptr).object_ref)(this).deref() } #[cfg(feature = "std")] - pub(crate) fn error_mut(&mut self) -> &mut (dyn StdError + Send + Sync + 'static) { + pub(crate) unsafe fn error_mut(this: Mut) -> &mut (dyn StdError + Send + Sync + 'static) { // Use vtable to attach E's native StdError vtable for the right // original type E. - unsafe { &mut *(self.vtable.object_mut)(self) } + + #[cfg(not(anyhow_no_ptr_addr_of))] + return (vtable(this.ptr).object_ref)(this.by_ref()) + .by_mut() + .deref_mut(); + + #[cfg(anyhow_no_ptr_addr_of)] + return (vtable(this.ptr).object_mut)(this); } - #[cfg(backtrace)] - pub(crate) fn backtrace(&self) -> &Backtrace { + #[cfg(any(backtrace, feature = "backtrace"))] + pub(crate) unsafe fn backtrace(this: Ref) -> &Backtrace { // This unwrap can only panic if the underlying error's backtrace method // is nondeterministic, which would only happen in maliciously // constructed code. - self.backtrace + this.deref() + .backtrace .as_ref() - .or_else(|| self.error().backtrace()) + .or_else(|| { + #[cfg(backtrace)] + return Self::error(this).backtrace(); + #[cfg(all(not(backtrace), feature = "backtrace"))] + return (vtable(this.ptr).object_backtrace)(this); + }) .expect("backtrace capture failed") } - pub(crate) fn chain(&self) -> Chain { - Chain::new(self.error()) + pub(crate) unsafe fn chain(this: Ref) -> Chain { + Chain::new(Self::error(this)) } } @@ -739,11 +890,11 @@ where { #[cfg(backtrace)] fn backtrace(&self) -> Option<&Backtrace> { - Some(self.erase().backtrace()) + Some(unsafe { ErrorImpl::backtrace(self.erase()) }) } fn source(&self) -> Option<&(dyn StdError + 'static)> { - self.erase().error().source() + unsafe { ErrorImpl::error(self.erase()).source() } } } @@ -752,7 +903,7 @@ where E: Debug, { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - self.erase().debug(formatter) + unsafe { ErrorImpl::debug(self.erase(), formatter) } } } @@ -761,7 +912,7 @@ where E: Display, { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - Display::fmt(&self.erase().error(), formatter) + unsafe { Display::fmt(ErrorImpl::error(self.erase()), formatter) } } } @@ -769,18 +920,19 @@ impl From for Box { fn from(error: Error) -> Self { let outer = ManuallyDrop::new(error); unsafe { - // Read Box> from error. Can't move it out because - // Error has a Drop impl which we want to not run. - let inner = ptr::read(&outer.inner); - let erased = ManuallyDrop::into_inner(inner); - // Use vtable to attach ErrorImpl's native StdError vtable for // the right original type E. - (erased.vtable.object_boxed)(erased) + (vtable(outer.inner.ptr).object_boxed)(outer.inner) } } } +impl From for Box { + fn from(error: Error) -> Self { + Box::::from(error) + } +} + impl From for Box { fn from(error: Error) -> Self { Box::::from(error) diff --git a/third_party/rust/anyhow/src/fmt.rs b/third_party/rust/anyhow/src/fmt.rs index 16a82ba8d8d1..03d8fd3940e5 100644 --- a/third_party/rust/anyhow/src/fmt.rs +++ b/third_party/rust/anyhow/src/fmt.rs @@ -1,13 +1,14 @@ use crate::chain::Chain; use crate::error::ErrorImpl; +use crate::ptr::Ref; use core::fmt::{self, Debug, Write}; -impl ErrorImpl<()> { - pub(crate) fn display(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.error())?; +impl ErrorImpl { + pub(crate) unsafe fn display(this: Ref, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", Self::error(this))?; if f.alternate() { - for cause in self.chain().skip(1) { + for cause in Self::chain(this).skip(1) { write!(f, ": {}", cause)?; } } @@ -15,8 +16,8 @@ impl ErrorImpl<()> { Ok(()) } - pub(crate) fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result { - let error = self.error(); + pub(crate) unsafe fn debug(this: Ref, f: &mut fmt::Formatter) -> fmt::Result { + let error = Self::error(this); if f.alternate() { return Debug::fmt(error, f); @@ -38,19 +39,24 @@ impl ErrorImpl<()> { } } - #[cfg(backtrace)] + #[cfg(any(backtrace, feature = "backtrace"))] { - use std::backtrace::BacktraceStatus; + use crate::backtrace::BacktraceStatus; - let backtrace = self.backtrace(); + let backtrace = Self::backtrace(this); if let BacktraceStatus::Captured = backtrace.status() { let mut backtrace = backtrace.to_string(); + write!(f, "\n\n")?; if backtrace.starts_with("stack backtrace:") { // Capitalize to match "Caused by:" backtrace.replace_range(0..1, "S"); + } else { + // "stack backtrace:" prefix was removed in + // https://github.com/rust-lang/backtrace-rs/pull/286 + writeln!(f, "Stack backtrace:")?; } backtrace.truncate(backtrace.trim_end().len()); - write!(f, "\n\n{}", backtrace)?; + write!(f, "{}", backtrace)?; } } diff --git a/third_party/rust/anyhow/src/kind.rs b/third_party/rust/anyhow/src/kind.rs index fdeb060ad871..eb8d604462f2 100644 --- a/third_party/rust/anyhow/src/kind.rs +++ b/third_party/rust/anyhow/src/kind.rs @@ -50,9 +50,6 @@ use core::fmt::{Debug, Display}; #[cfg(feature = "std")] use crate::StdError; -#[cfg(backtrace)] -use std::backtrace::Backtrace; - pub struct Adhoc; pub trait AdhocKind: Sized { diff --git a/third_party/rust/anyhow/src/lib.rs b/third_party/rust/anyhow/src/lib.rs index 91d4c4652e21..5ff891c06045 100644 --- a/third_party/rust/anyhow/src/lib.rs +++ b/third_party/rust/anyhow/src/lib.rs @@ -179,6 +179,18 @@ //! # } //! ``` //! +//! A `bail!` macro is provided as a shorthand for the same early return. +//! +//! ``` +//! # use anyhow::{bail, Result}; +//! # +//! # fn demo() -> Result<()> { +//! # let missing = "..."; +//! bail!("Missing attribute: {}", missing); +//! # Ok(()) +//! # } +//! ``` +//! //!
//! //! # No-std support @@ -197,13 +209,24 @@ //! will require an explicit `.map_err(Error::msg)` when working with a //! non-Anyhow error type inside a function that returns Anyhow's error type. -#![doc(html_root_url = "https://docs.rs/anyhow/1.0.30")] +#![doc(html_root_url = "https://docs.rs/anyhow/1.0.41")] #![cfg_attr(backtrace, feature(backtrace))] #![cfg_attr(doc_cfg, feature(doc_cfg))] #![cfg_attr(not(feature = "std"), no_std)] +#![deny(dead_code, unused_imports, unused_mut)] #![allow( + clippy::doc_markdown, + clippy::enum_glob_use, + clippy::missing_errors_doc, + clippy::missing_panics_doc, + clippy::module_name_repetitions, + clippy::must_use_candidate, clippy::needless_doctest_main, clippy::new_ret_no_self, + clippy::redundant_else, + clippy::unused_self, + clippy::used_underscore_binding, + clippy::wildcard_imports, clippy::wrong_self_convention )] @@ -226,12 +249,12 @@ mod error; mod fmt; mod kind; mod macros; +mod ptr; mod wrapper; -use crate::alloc::Box; use crate::error::ErrorImpl; +use crate::ptr::Own; use core::fmt::Display; -use core::mem::ManuallyDrop; #[cfg(not(feature = "std"))] use core::fmt::Debug; @@ -288,6 +311,15 @@ pub use anyhow as format_err; /// /// Caused by: /// No such file or directory (os error 2) +/// ``` +/// +/// and if there is a backtrace available: +/// +/// ```console +/// Error: Failed to read instrs from ./path/to/instrs.json +/// +/// Caused by: +/// No such file or directory (os error 2) /// /// Stack backtrace: /// 0: ::ext_context @@ -340,8 +372,9 @@ pub use anyhow as format_err; /// # Ok(()) /// } /// ``` +#[repr(transparent)] pub struct Error { - inner: ManuallyDrop>>, + inner: Own, } /// Iterator of a chain of source errors. @@ -364,6 +397,7 @@ pub struct Error { /// } /// ``` #[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] #[derive(Clone)] pub struct Chain<'a> { state: crate::chain::ChainState<'a>, @@ -581,9 +615,6 @@ pub mod private { use crate::Error; use core::fmt::{Debug, Display}; - #[cfg(backtrace)] - use std::backtrace::Backtrace; - pub use core::result::Result::Err; #[doc(hidden)] @@ -600,4 +631,27 @@ pub mod private { { Error::from_adhoc(message, backtrace!()) } + + #[cfg(anyhow_no_macro_reexport)] + pub use crate::{__anyhow_concat as concat, __anyhow_stringify as stringify}; + #[cfg(not(anyhow_no_macro_reexport))] + pub use core::{concat, stringify}; + + #[cfg(anyhow_no_macro_reexport)] + #[doc(hidden)] + #[macro_export] + macro_rules! __anyhow_concat { + ($($tt:tt)*) => { + concat!($($tt)*) + }; + } + + #[cfg(anyhow_no_macro_reexport)] + #[doc(hidden)] + #[macro_export] + macro_rules! __anyhow_stringify { + ($($tt:tt)*) => { + stringify!($($tt)*) + }; + } } diff --git a/third_party/rust/anyhow/src/macros.rs b/third_party/rust/anyhow/src/macros.rs index 15a920810cf3..a0f4cae46926 100644 --- a/third_party/rust/anyhow/src/macros.rs +++ b/third_party/rust/anyhow/src/macros.rs @@ -1,6 +1,9 @@ /// Return early with an error. /// -/// This macro is equivalent to `return Err(From::from($err))`. +/// This macro is equivalent to `return Err(`[`anyhow!($args...)`][anyhow!]`)`. +/// +/// The surrounding function's or closure's return value is required to be +/// `Result<_,`[`anyhow::Error`][crate::Error]`>`. /// /// # Example /// @@ -50,19 +53,23 @@ #[macro_export] macro_rules! bail { ($msg:literal $(,)?) => { - return $crate::private::Err($crate::anyhow!($msg)); + return $crate::private::Err($crate::anyhow!($msg)) }; ($err:expr $(,)?) => { - return $crate::private::Err($crate::anyhow!($err)); + return $crate::private::Err($crate::anyhow!($err)) }; ($fmt:expr, $($arg:tt)*) => { - return $crate::private::Err($crate::anyhow!($fmt, $($arg)*)); + return $crate::private::Err($crate::anyhow!($fmt, $($arg)*)) }; } /// Return early with an error if a condition is not satisfied. /// -/// This macro is equivalent to `if !$cond { return Err(From::from($err)); }`. +/// This macro is equivalent to `if !$cond { return +/// Err(`[`anyhow!($args...)`][anyhow!]`); }`. +/// +/// The surrounding function's or closure's return value is required to be +/// `Result<_,`[`anyhow::Error`][crate::Error]`>`. /// /// Analogously to `assert!`, `ensure!` takes a condition and exits the function /// if the condition fails. Unlike `assert!`, `ensure!` returns an `Error` @@ -106,6 +113,12 @@ macro_rules! bail { /// ``` #[macro_export] macro_rules! ensure { + ($cond:expr $(,)?) => { + $crate::ensure!( + $cond, + $crate::private::concat!("Condition failed: `", $crate::private::stringify!($cond), "`"), + ) + }; ($cond:expr, $msg:literal $(,)?) => { if !$cond { return $crate::private::Err($crate::anyhow!($msg)); @@ -123,11 +136,17 @@ macro_rules! ensure { }; } -/// Construct an ad-hoc error from a string. +/// Construct an ad-hoc error from a string or existing non-`anyhow` error +/// value. /// -/// This evaluates to an `Error`. It can take either just a string, or a format -/// string with arguments. It also can take any custom type which implements -/// `Debug` and `Display`. +/// This evaluates to an [`Error`][crate::Error]. It can take either just a +/// string, or a format string with arguments. It also can take any custom type +/// which implements `Debug` and `Display`. +/// +/// If called with a single argument whose type implements `std::error::Error` +/// (in addition to `Debug` and `Display`, which are always required), then that +/// Error impl's `source` is preserved as the `source` of the resulting +/// `anyhow::Error`. /// /// # Example /// @@ -154,8 +173,9 @@ macro_rules! anyhow { }; ($err:expr $(,)?) => ({ use $crate::private::kind::*; - let error = $err; - (&error).anyhow_kind().new(error) + match $err { + error => (&error).anyhow_kind().new(error), + } }); ($fmt:expr, $($arg:tt)*) => { $crate::private::new_adhoc(format!($fmt, $($arg)*)) diff --git a/third_party/rust/anyhow/src/ptr.rs b/third_party/rust/anyhow/src/ptr.rs new file mode 100644 index 000000000000..684083389664 --- /dev/null +++ b/third_party/rust/anyhow/src/ptr.rs @@ -0,0 +1,199 @@ +use crate::alloc::Box; +use core::marker::PhantomData; +use core::ptr::NonNull; + +#[repr(transparent)] +pub struct Own +where + T: ?Sized, +{ + pub ptr: NonNull, +} + +unsafe impl Send for Own where T: ?Sized {} + +unsafe impl Sync for Own where T: ?Sized {} + +impl Copy for Own where T: ?Sized {} + +impl Clone for Own +where + T: ?Sized, +{ + fn clone(&self) -> Self { + *self + } +} + +impl Own +where + T: ?Sized, +{ + pub fn new(ptr: Box) -> Self { + Own { + ptr: unsafe { NonNull::new_unchecked(Box::into_raw(ptr)) }, + } + } + + pub fn cast(self) -> Own { + Own { + ptr: self.ptr.cast(), + } + } + + pub unsafe fn boxed(self) -> Box { + Box::from_raw(self.ptr.as_ptr()) + } + + pub fn by_ref(&self) -> Ref { + Ref { + ptr: self.ptr, + lifetime: PhantomData, + } + } + + pub fn by_mut(&mut self) -> Mut { + Mut { + ptr: self.ptr, + lifetime: PhantomData, + } + } +} + +#[repr(transparent)] +pub struct Ref<'a, T> +where + T: ?Sized, +{ + pub ptr: NonNull, + lifetime: PhantomData<&'a T>, +} + +impl<'a, T> Copy for Ref<'a, T> where T: ?Sized {} + +impl<'a, T> Clone for Ref<'a, T> +where + T: ?Sized, +{ + fn clone(&self) -> Self { + *self + } +} + +impl<'a, T> Ref<'a, T> +where + T: ?Sized, +{ + pub fn new(ptr: &'a T) -> Self { + Ref { + ptr: NonNull::from(ptr), + lifetime: PhantomData, + } + } + + #[cfg(not(anyhow_no_ptr_addr_of))] + pub fn from_raw(ptr: NonNull) -> Self { + Ref { + ptr, + lifetime: PhantomData, + } + } + + pub fn cast(self) -> Ref<'a, U::Target> { + Ref { + ptr: self.ptr.cast(), + lifetime: PhantomData, + } + } + + #[cfg(not(anyhow_no_ptr_addr_of))] + pub fn by_mut(self) -> Mut<'a, T> { + Mut { + ptr: self.ptr, + lifetime: PhantomData, + } + } + + #[cfg(not(anyhow_no_ptr_addr_of))] + pub fn as_ptr(self) -> *const T { + self.ptr.as_ptr() as *const T + } + + pub unsafe fn deref(self) -> &'a T { + &*self.ptr.as_ptr() + } +} + +#[repr(transparent)] +pub struct Mut<'a, T> +where + T: ?Sized, +{ + pub ptr: NonNull, + lifetime: PhantomData<&'a mut T>, +} + +impl<'a, T> Copy for Mut<'a, T> where T: ?Sized {} + +impl<'a, T> Clone for Mut<'a, T> +where + T: ?Sized, +{ + fn clone(&self) -> Self { + *self + } +} + +impl<'a, T> Mut<'a, T> +where + T: ?Sized, +{ + #[cfg(anyhow_no_ptr_addr_of)] + pub fn new(ptr: &'a mut T) -> Self { + Mut { + ptr: NonNull::from(ptr), + lifetime: PhantomData, + } + } + + pub fn cast(self) -> Mut<'a, U::Target> { + Mut { + ptr: self.ptr.cast(), + lifetime: PhantomData, + } + } + + #[cfg(not(anyhow_no_ptr_addr_of))] + pub fn by_ref(self) -> Ref<'a, T> { + Ref { + ptr: self.ptr, + lifetime: PhantomData, + } + } + + pub fn extend<'b>(self) -> Mut<'b, T> { + Mut { + ptr: self.ptr, + lifetime: PhantomData, + } + } + + pub unsafe fn deref_mut(self) -> &'a mut T { + &mut *self.ptr.as_ptr() + } +} + +impl<'a, T> Mut<'a, T> { + pub unsafe fn read(self) -> T { + self.ptr.as_ptr().read() + } +} + +// Force turbofish on all calls of `.cast::()`. +pub trait CastTo { + type Target; +} + +impl CastTo for T { + type Target = T; +} diff --git a/third_party/rust/anyhow/tests/compiletest.rs b/third_party/rust/anyhow/tests/compiletest.rs index f9aea23b5154..7974a6249e43 100644 --- a/third_party/rust/anyhow/tests/compiletest.rs +++ b/third_party/rust/anyhow/tests/compiletest.rs @@ -1,4 +1,5 @@ #[rustversion::attr(not(nightly), ignore)] +#[cfg_attr(miri, ignore)] #[test] fn ui() { let t = trybuild::TestCases::new(); diff --git a/third_party/rust/anyhow/tests/drop/mod.rs b/third_party/rust/anyhow/tests/drop/mod.rs index c9d71444794a..ba2cc5ed68c4 100644 --- a/third_party/rust/anyhow/tests/drop/mod.rs +++ b/third_party/rust/anyhow/tests/drop/mod.rs @@ -1,3 +1,5 @@ +#![allow(clippy::module_name_repetitions)] + use std::error::Error as StdError; use std::fmt::{self, Display}; use std::sync::atomic::AtomicBool; diff --git a/third_party/rust/anyhow/tests/test_convert.rs b/third_party/rust/anyhow/tests/test_convert.rs index 72da020be692..aff64e2fc7f2 100644 --- a/third_party/rust/anyhow/tests/test_convert.rs +++ b/third_party/rust/anyhow/tests/test_convert.rs @@ -1,3 +1,5 @@ +#![allow(clippy::unnecessary_wraps)] + mod drop; use self::drop::{DetectDrop, Flag}; diff --git a/third_party/rust/anyhow/tests/test_downcast.rs b/third_party/rust/anyhow/tests/test_downcast.rs index c2c3e129ff20..6b937107cb20 100644 --- a/third_party/rust/anyhow/tests/test_downcast.rs +++ b/third_party/rust/anyhow/tests/test_downcast.rs @@ -1,3 +1,5 @@ +#![allow(clippy::wildcard_imports)] + mod common; mod drop; @@ -66,6 +68,12 @@ fn test_downcast_mut() { .unwrap() .to_string(), ); + + let mut bailed = bail_fmt().unwrap_err(); + *bailed.downcast_mut::().unwrap() = "clobber".to_string(); + assert_eq!(bailed.downcast_ref::().unwrap(), "clobber"); + assert_eq!(bailed.downcast_mut::().unwrap(), "clobber"); + assert_eq!(bailed.downcast::().unwrap(), "clobber"); } #[test] diff --git a/third_party/rust/anyhow/tests/test_ffi.rs b/third_party/rust/anyhow/tests/test_ffi.rs new file mode 100644 index 000000000000..0321fc1b0581 --- /dev/null +++ b/third_party/rust/anyhow/tests/test_ffi.rs @@ -0,0 +1,18 @@ +#![deny(improper_ctypes, improper_ctypes_definitions)] + +use anyhow::anyhow; + +#[no_mangle] +pub extern "C" fn anyhow1(err: anyhow::Error) { + println!("{:?}", err); +} + +#[no_mangle] +pub extern "C" fn anyhow2(err: &mut Option) { + *err = Some(anyhow!("ffi error")); +} + +#[no_mangle] +pub extern "C" fn anyhow3() -> Option { + Some(anyhow!("ffi error")) +} diff --git a/third_party/rust/anyhow/tests/test_macros.rs b/third_party/rust/anyhow/tests/test_macros.rs index c6888b6b6347..cd75d50f3cf2 100644 --- a/third_party/rust/anyhow/tests/test_macros.rs +++ b/third_party/rust/anyhow/tests/test_macros.rs @@ -1,3 +1,5 @@ +#![allow(clippy::eq_op, clippy::shadow_unrelated, clippy::wildcard_imports)] + mod common; use self::common::*; @@ -30,4 +32,13 @@ fn test_ensure() { Ok(()) }; assert!(f().is_err()); + + let f = || { + ensure!(v + v == 1); + Ok(()) + }; + assert_eq!( + f().unwrap_err().to_string(), + "Condition failed: `v + v == 1`", + ); } diff --git a/third_party/rust/anyhow/tests/ui/no-impl.stderr b/third_party/rust/anyhow/tests/ui/no-impl.stderr index be957370d3f5..976b62c7bcce 100644 --- a/third_party/rust/anyhow/tests/ui/no-impl.stderr +++ b/third_party/rust/anyhow/tests/ui/no-impl.stderr @@ -1,21 +1,21 @@ -error[E0599]: no method named `anyhow_kind` found for reference `&Error` in the current scope +error[E0599]: the method `anyhow_kind` exists for reference `&Error`, but its trait bounds were not satisfied --> $DIR/no-impl.rs:7:13 | 4 | struct Error; | ------------- | | - | doesn't satisfy `Error: anyhow::kind::TraitKind` - | doesn't satisfy `Error: std::convert::Into` + | doesn't satisfy `Error: Into` + | doesn't satisfy `Error: anyhow::private::kind::TraitKind` | doesn't satisfy `Error: std::fmt::Display` ... 7 | let _ = anyhow!(Error); - | ^^^^^^^^^^^^^^ method not found in `&Error` + | ^^^^^^^^^^^^^^ method cannot be called on `&Error` due to unsatisfied trait bounds | - = note: the method `anyhow_kind` exists but the following trait bounds were not satisfied: - `Error: std::convert::Into` - which is required by `Error: anyhow::kind::TraitKind` + = note: the following trait bounds were not satisfied: + `Error: Into` + which is required by `Error: anyhow::private::kind::TraitKind` `Error: std::fmt::Display` - which is required by `&Error: anyhow::kind::AdhocKind` - `&Error: std::convert::Into` - which is required by `&Error: anyhow::kind::TraitKind` - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + which is required by `&Error: anyhow::private::kind::AdhocKind` + `&Error: Into` + which is required by `&Error: anyhow::private::kind::TraitKind` + = note: this error originates in the macro `anyhow` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/third_party/rust/anyhow/tests/ui/temporary-value.rs b/third_party/rust/anyhow/tests/ui/temporary-value.rs new file mode 100644 index 000000000000..803809b238f0 --- /dev/null +++ b/third_party/rust/anyhow/tests/ui/temporary-value.rs @@ -0,0 +1,5 @@ +use anyhow::anyhow; + +fn main() { + let _ = anyhow!(&String::new()); +} diff --git a/third_party/rust/anyhow/tests/ui/temporary-value.stderr b/third_party/rust/anyhow/tests/ui/temporary-value.stderr new file mode 100644 index 000000000000..fa753d2e7885 --- /dev/null +++ b/third_party/rust/anyhow/tests/ui/temporary-value.stderr @@ -0,0 +1,8 @@ +error[E0716]: temporary value dropped while borrowed + --> $DIR/temporary-value.rs:4:22 + | +4 | let _ = anyhow!(&String::new()); + | ---------^^^^^^^^^^^^^-- temporary value is freed at the end of this statement + | | | + | | creates a temporary which is freed while still in use + | argument requires that borrow lasts for `'static`