Vendor things

This commit is contained in:
John Doty 2024-03-08 11:03:01 -08:00
parent 5deceec006
commit 977e3c17e5
19434 changed files with 10682014 additions and 0 deletions

View file

@ -0,0 +1 @@
{"files":{"CHANGELOG.md":"b980ff14aa7e728c69b6966f68ade64cd6259b89d6b61a099bfd0dd47960990b","Cargo.lock":"4e4e145371cef95fe347e7b14731fbf8f8aef366f45eb45f37760892a966e35b","Cargo.toml":"ad05a3833cfb3693e44c8341e23a85bd88d9578833193341b1b016cdbf99b8fd","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"d6083c077bb087914386be267b52b98bca521f9af5b40b7fd82960d3ae2d2e3a","build.rs":"fbd0d04cc64884da6b65ad460084ad49e56f8a14fba24a256e161cb18b15441c","examples/custom_handler.rs":"33fa83c1ac4a6af8511796cc3b4818d4d4a50fa5eac5b9533a91acd695337169","examples/eyre-usage.rs":"3380d5176d433209eadeb355c2884fd0d46dc6a636b7402fab8fae17f79fa6c0","src/backtrace.rs":"02e509dd794ee2814b1342879414373935bcc33b433e45a58193297e52f95db7","src/chain.rs":"342161434eaa3db018541a24e01531135b471dfac44f7d25c84875c4dc5692d1","src/context.rs":"97f5c3fbe0679db8203ba5983817124df0d888d39e4fc8a55f33f568b4c536e0","src/error.rs":"b2395cb008713ec5112d332c81d0edc293a71bb992dc0d1a42db67ec5301dc10","src/error/pyo3_compat.rs":"6a3b48211b5496944aac8e058cbca85d37f379b3fc18b57c5e00ce56832d47bc","src/fmt.rs":"101f0fc55eba79900dafe04874f2b8f144d5da884b2087b77cda9fc1588d4d8c","src/kind.rs":"12aa656231f87f33367ac1db011dee70f87adff119305cf9d40faf3140234436","src/lib.rs":"32812e58622ad0d0fcc862163fda9c0f13497bc38df5cdd214f04d78a6d069e6","src/macros.rs":"22f30ae6fa6c130db4fa15913caf690cb33429e69cbf9f6371db586f1e0a5002","src/option.rs":"06271311605414d5f850efdf61a8c6976730f90cb03dc0712faa53f051a34509","src/ptr.rs":"81c21f61e9063db1eea3152ced7f01dd02d78ec64d09bf7f8ea0936e1d9772ad","src/wrapper.rs":"1d92365de5b679cc8bd328895724e6f7283e48ebf826bdbfac594813b2f96243","tests/common/mod.rs":"8094c30a551b8d4b04b474e5d4094bfd56f714fd51a8e2f4636eb823c5d08b1c","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/drop/mod.rs":"bd6d59b699a2901de2bda3c40c899af4ee82e4e98617516ea41c327b99af51e1","tests/test_autotrait.rs":"18b0c73026e9bbbc5272e8ed832ccb2522a606b64d50c80316495013f6acc808","tests/test_boxed.rs":"badf6e661aa3076ca644f6c0275991c8d26c5d3684bb2cb260ca2f58482594e8","tests/test_chain.rs":"8c7a75e38d241e9931a3530b30fab80ef87488daeecf87c84f72069d34650188","tests/test_context.rs":"816bdfa55f2fda0abde014817e46227a2da3effa0f697cfa5d2ca218650b946e","tests/test_context_access.rs":"dc490cfc031ac3907314a578c9bb9dfa51be95b041a62f771e39b79d66b763d3","tests/test_convert.rs":"300644b4ebf0cb94b542f6e306779199bc7fce7cc7bec956a1156767d847ae44","tests/test_downcast.rs":"4172648f5f48d489fe5b2e0e962dc2c35624eef5f907192db63f11493a396008","tests/test_fmt.rs":"a1ed4b79bea5f04006868d5145980ea6936d2eb4feee4b87e2c675d4f0b465ff","tests/test_location.rs":"79725e31e961df162b6e1f1194e7a0e5f45740bbeb7700293c2880360050ae28","tests/test_macros.rs":"bd1577f801a24abfb2870de9af9a9224a49025cbc8227a3b237bc73669592ba7","tests/test_no_install.rs":"9b4d695d9c699d5c39c7c4fd178b30fe472e96efbf2e8e4448ce72d6f2b3101b","tests/test_option.rs":"ae49e0b486f35bcd485765b1f6ebd0e02173b574b11c279c5597caf2f84f8c71","tests/test_pyo3.rs":"a1006f46d317e9e7a0c7c57f3502b9af594b62cb717269fee220f175d9ba5f17","tests/test_repr.rs":"a105eba1500a0bd7e36895bf03d43e2c9dbb6c573a0051c80f7ea7bdac103f78","tests/test_source.rs":"7d3cc674b802e46f84230db2e72b9a66b3bff39ae8d0246ab31607a8e6c01f27","tests/test_toolchain.rs":"96f9aacc8d9fe33d6e1d90a8f329d54d7ad5880348c64a87894ca916321c8c10"},"package":"7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec"}

91
third-party/vendor/eyre/CHANGELOG.md vendored Normal file
View file

@ -0,0 +1,91 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
<!-- next-header -->
## [Unreleased] - ReleaseDate
## [0.6.12] - 2024-01-31
### Fixed
- Unsound cast to invalid type during Report downcast [by ten3roberts](https://github.com/eyre-rs/eyre/pull/143)
## [0.6.11] - 2023-12-13
### Fixed
- stale references to `Error` in docstrings [by birkenfeld](https://github.com/eyre-rs/eyre/pull/87)
### Added
- one-argument ensure!($expr) [by sharnoff](https://github.com/eyre-rs/eyre/pull/86)
- documentation on the performance characteristics of `wrap_err` vs `wrap_err_with` [by akshayknarayan](https://github.com/eyre-rs/eyre/pull/93)
- tl;dr: `wrap_err_with` is faster unless the constructed error object already exists
- ~~automated conversion to external errors for ensure! and bail! [by j-baker](https://github.com/eyre-rs/eyre/pull/95)~~ breaking change: shelved for next major release
- eyre::Ok for generating eyre::Ok() without fully specifying the type [by kylewlacy](https://github.com/eyre-rs/eyre/pull/91)
- `OptionExt::ok_or_eyre` for yielding static `Report`s from `None` [by LeoniePhiline](https://github.com/eyre-rs/eyre/pull/125)
### New Contributors
- @sharnoff made their first contribution in https://github.com/eyre-rs/eyre/pull/86
- @akshayknarayan made their first contribution in https://github.com/eyre-rs/eyre/pull/93
- @j-baker made their first contribution in https://github.com/eyre-rs/eyre/pull/95
- @kylewlacy made their first contribution in https://github.com/eyre-rs/eyre/pull/91
- @LeoniePhiline made their first contribution in https://github.com/eyre-rs/eyre/pull/129
~~## [0.6.10] - 2023-12-07~~ Yanked
## [0.6.9] - 2023-11-17
### Fixed
- stacked borrows when dropping [by TimDiekmann](https://github.com/eyre-rs/eyre/pull/81)
- miri validation errors through now stricter provenance [by ten3roberts](https://github.com/eyre-rs/eyre/pull/103)
- documentation on no_std support [by thenorili](https://github.com/eyre-rs/eyre/pull/111)
### Added
- monorepo for eyre-related crates [by pksunkara](https://github.com/eyre-rs/eyre/pull/104), [[2]](https://github.com/eyre-rs/eyre/pull/105)[[3]](https://github.com/eyre-rs/eyre/pull/107)
- CONTRIBUTING.md [by yaahc](https://github.com/eyre-rs/eyre/pull/99)
## [0.6.8] - 2022-04-04
### Added
- `#[must_use]` to `Report`
- `must-install` feature to help reduce binary sizes when using a custom `EyreHandler`
## [0.6.7] - 2022-02-24
### Fixed
- missing track_caller annotation to new format arg capture constructor
## [0.6.6] - 2022-01-19
### Added
- support for format arguments capture on 1.58 and later
## [0.6.5] - 2021-01-05
### Added
- optional support for converting into `pyo3` exceptions
## [0.6.4] - 2021-01-04
### Fixed
- missing track_caller annotations to `wrap_err` related trait methods
## [0.6.3] - 2020-11-10
### Fixed
- missing track_caller annotation to autoref specialization functions
## [0.6.2] - 2020-10-27
### Fixed
- missing track_caller annotation to new_adhoc function
## [0.6.1] - 2020-09-28
### Added
- support for track_caller on rust versions where it is available
<!-- next-url -->
[Unreleased]: https://github.com/eyre-rs/eyre/compare/v0.6.11...HEAD
[0.6.11]: https://github.com/eyre-rs/eyre/compare/v0.6.9...v0.6.11
[0.6.9]: https://github.com/eyre-rs/eyre/compare/v0.6.8...v0.6.9
[0.6.8]: https://github.com/eyre-rs/eyre/compare/v0.6.7...v0.6.8
[0.6.7]: https://github.com/eyre-rs/eyre/compare/v0.6.6...v0.6.7
[0.6.6]: https://github.com/eyre-rs/eyre/compare/v0.6.5...v0.6.6
[0.6.5]: https://github.com/eyre-rs/eyre/compare/v0.6.4...v0.6.5
[0.6.4]: https://github.com/eyre-rs/eyre/compare/v0.6.3...v0.6.4
[0.6.3]: https://github.com/eyre-rs/eyre/compare/v0.6.2...v0.6.3
[0.6.2]: https://github.com/eyre-rs/eyre/compare/v0.6.1...v0.6.2
[0.6.1]: https://github.com/eyre-rs/eyre/releases/tag/v0.6.1

504
third-party/vendor/eyre/Cargo.lock generated vendored Normal file
View file

@ -0,0 +1,504 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "anyhow"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "basic-toml"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f2139706359229bfa8f19142ac1155b4b80beafb7a60471ac5dd109d4a19778"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"libc",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "dissimilar"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86e3bdc80eee6e16b2b6b0f87fbc98c04bee3455e35174c0de1a125d0688c632"
[[package]]
name = "eyre"
version = "0.6.12"
dependencies = [
"anyhow",
"backtrace",
"futures",
"indenter",
"once_cell",
"pyo3",
"rustversion",
"syn",
"thiserror",
"trybuild",
]
[[package]]
name = "futures"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
[[package]]
name = "futures-io"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
[[package]]
name = "futures-sink"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
[[package]]
name = "futures-task"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
[[package]]
name = "futures-util"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
dependencies = [
"futures-core",
"futures-sink",
"futures-task",
"pin-project-lite",
"pin-utils",
]
[[package]]
name = "gimli"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "indenter"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]]
name = "itoa"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "libc"
version = "0.2.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
[[package]]
name = "lock_api"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "memchr"
version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
[[package]]
name = "memoffset"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
dependencies = [
"autocfg",
]
[[package]]
name = "miniz_oxide"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
dependencies = [
"adler",
]
[[package]]
name = "object"
version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "parking_lot"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [
"instant",
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
dependencies = [
"cfg-if",
"instant",
"libc",
"redox_syscall",
"smallvec",
"winapi",
]
[[package]]
name = "pin-project-lite"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "proc-macro2"
version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
dependencies = [
"unicode-ident",
]
[[package]]
name = "pyo3"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04e8453b658fe480c3e70c8ed4e3d3ec33eb74988bd186561b0cc66b85c3bc4b"
dependencies = [
"cfg-if",
"libc",
"memoffset",
"parking_lot",
"pyo3-build-config",
"pyo3-ffi",
]
[[package]]
name = "pyo3-build-config"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a96fe70b176a89cff78f2fa7b3c930081e163d5379b4dcdf993e3ae29ca662e5"
dependencies = [
"once_cell",
"target-lexicon",
]
[[package]]
name = "pyo3-ffi"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "214929900fd25e6604661ed9cf349727c8920d47deff196c4e28165a6ef2a96b"
dependencies = [
"libc",
"pyo3-build-config",
]
[[package]]
name = "quote"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags",
]
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustversion"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
[[package]]
name = "ryu"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "smallvec"
version = "1.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
[[package]]
name = "syn"
version = "2.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "target-lexicon"
version = "0.12.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a"
[[package]]
name = "termcolor"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449"
dependencies = [
"winapi-util",
]
[[package]]
name = "thiserror"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "trybuild"
version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "196a58260a906cedb9bf6d8034b6379d0c11f552416960452f267402ceeddff1"
dependencies = [
"basic-toml",
"dissimilar",
"glob",
"once_cell",
"serde",
"serde_derive",
"serde_json",
"termcolor",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

84
third-party/vendor/eyre/Cargo.toml vendored Normal file
View file

@ -0,0 +1,84 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
rust-version = "1.65.0"
name = "eyre"
version = "0.6.12"
authors = [
"David Tolnay <dtolnay@gmail.com>",
"Jane Lusby <jlusby42@gmail.com>",
]
description = "Flexible concrete Error Reporting type built on std::error::Error with customizable Reports"
documentation = "https://docs.rs/eyre"
readme = "README.md"
categories = ["rust-patterns"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/eyre-rs/eyre"
[package.metadata.docs.rs]
rustdoc-args = [
"--cfg",
"doc_cfg",
]
targets = ["x86_64-unknown-linux-gnu"]
[package.metadata.workspaces]
independent = true
[dependencies.indenter]
version = "0.3.0"
[dependencies.once_cell]
version = "1.18.0"
[dependencies.pyo3]
version = "0.20"
optional = true
default-features = false
[dev-dependencies.anyhow]
version = "1.0.28"
[dev-dependencies.backtrace]
version = "0.3.46"
[dev-dependencies.futures]
version = "0.3"
default-features = false
[dev-dependencies.pyo3]
version = "0.20"
features = ["auto-initialize"]
default-features = false
[dev-dependencies.rustversion]
version = "1.0"
[dev-dependencies.syn]
version = "2.0"
features = ["full"]
[dev-dependencies.thiserror]
version = "1.0"
[dev-dependencies.trybuild]
version = "1.0.19"
features = ["diff"]
[features]
auto-install = []
default = [
"auto-install",
"track-caller",
]
track-caller = []

201
third-party/vendor/eyre/LICENSE-APACHE vendored Normal file
View file

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

23
third-party/vendor/eyre/LICENSE-MIT vendored Normal file
View file

@ -0,0 +1,23 @@
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

269
third-party/vendor/eyre/README.md vendored Normal file
View file

@ -0,0 +1,269 @@
eyre
====
[![Build Status][actions-badge]][actions-url]
[![Latest Version](https://img.shields.io/crates/v/eyre.svg)](https://crates.io/crates/eyre)
[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/eyre)
[![Discord chat][discord-badge]][discord-url]
[actions-badge]: https://github.com/eyre-rs/eyre/workflows/Continuous%20integration/badge.svg
[actions-url]: https://github.com/eyre-rs/eyre/actions?query=workflow%3A%22Continuous+integration%22
[discord-badge]: https://img.shields.io/discord/960645145018110012?label=eyre%20community%20discord
[discord-url]: https://discord.gg/z94RqmUTKB
This library provides [`eyre::Report`][Report], a trait object based
error handling type for easy idiomatic error handling and reporting in Rust
applications.
This crate is a fork of [`anyhow`] with support for customized
error reports. For more details on customization checkout the docs on
[`eyre::EyreHandler`].
## Custom Report Handlers
The heart of this crate is its ability to swap out the Handler type to change
what information is carried alongside errors and how the end report is
formatted. This crate is meant to be used alongside companion crates that
customize its behavior. Below is a list of known crates that export report
handlers for eyre and short summaries of what features they provide.
- [`stable-eyre`]: Switches the backtrace type from `std`'s to `backtrace-rs`'s
so that it can be captured on stable. The report format is identical to
`DefaultHandler`'s report format.
- [`color-eyre`]: Captures a `backtrace::Backtrace` and a
`tracing_error::SpanTrace`. Provides a `Help` trait for attaching warnings
and suggestions to error reports. The end report is then pretty printed with
the help of [`color-backtrace`], [`color-spantrace`], and `ansi_term`. Check
out the README on [`color-eyre`] for details on the report format.
- [`simple-eyre`]: A minimal `EyreHandler` that captures no additional
information, for when you do not wish to capture `Backtrace`s with errors.
- [`jane-eyre`]: A report handler crate that exists purely for the pun of it.
Currently just re-exports `color-eyre`.
## Usage Recommendations and Stability Considerations
**We recommend users do not re-export types from this library as part their own
public API for libraries with external users.** The main reason for this is
that it will make your library API break if we ever bump the major version
number on eyre and your users upgrade the eyre version they use in their
application code before you upgrade your own eyre dep version[^1].
However, even beyond this API stability hazard, there are other good reasons to
avoid using `eyre::Report` as your public error type.
- You export an undocumented error interface that is otherwise still accessible
via downcast, making it hard for users to react to specific errors while not
preventing them from depending on details you didn't mean to make part of
your public API.
- This in turn makes the error types of all libraries you use a part of your
public API as well, and makes changing any of those libraries into an
undetectable runtime breakage.
- If many of your errors are constructed from strings you encourage your users
to use string comparision for reacting to specific errors which is brittle
and turns updating error messages into a potentially undetectable runtime
breakage.
## Details
- Use `Result<T, eyre::Report>`, or equivalently `eyre::Result<T>`, as the
return type of any fallible function.
Within the function, use `?` to easily propagate any error that implements the
`std::error::Error` trait.
```rust
use eyre::Result;
fn get_cluster_info() -> Result<ClusterMap> {
let config = std::fs::read_to_string("cluster.json")?;
let map: ClusterMap = serde_json::from_str(&config)?;
Ok(map)
}
```
- Wrap a lower level error with a new error created from a message to help the
person troubleshooting understand the chain of failures that occurred. A
low-level error like "No such file or directory" can be annoying to debug
without more information about what higher level step the application was in
the middle of.
```rust
use eyre::{WrapErr, Result};
fn main() -> Result<()> {
...
it.detach().wrap_err("Failed to detach the important thing")?;
let content = std::fs::read(path)
.wrap_err_with(|| format!("Failed to read instrs from {}", path))?;
...
}
```
```console
Error: Failed to read instrs from ./path/to/instrs.json
Caused by:
No such file or directory (os error 2)
```
- Downcasting is supported and can be by value, by shared reference, or by
mutable reference as needed.
```rust
// If the error was caused by redaction, then return a
// tombstone instead of the content.
match root_cause.downcast_ref::<DataStoreError>() {
Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
None => Err(error),
}
```
- If using the nightly channel, a backtrace is captured and printed with the
error if the underlying error type does not already provide its own. In order
to see backtraces, they must be enabled through the environment variables
described in [`std::backtrace`]:
- If you want panics and errors to both have backtraces, set
`RUST_BACKTRACE=1`;
- If you want only errors to have backtraces, set `RUST_LIB_BACKTRACE=1`;
- If you want only panics to have backtraces, set `RUST_BACKTRACE=1` and
`RUST_LIB_BACKTRACE=0`.
The tracking issue for this feature is [rust-lang/rust#53487].
[`std::backtrace`]: https://doc.rust-lang.org/std/backtrace/index.html#environment-variables
[rust-lang/rust#53487]: https://github.com/rust-lang/rust/issues/53487
- Eyre works with any error type that has an impl of `std::error::Error`,
including ones defined in your crate. We do not bundle a `derive(Error)` macro
but you can write the impls yourself or use a standalone macro like
[thiserror].
```rust
use thiserror::Error;
#[derive(Error, Debug)]
pub enum FormatError {
#[error("Invalid header (expected {expected:?}, got {found:?})")]
InvalidHeader {
expected: String,
found: String,
},
#[error("Missing attribute: {0}")]
MissingAttribute(String),
}
```
- One-off error messages can be constructed using the `eyre!` macro, which
supports string interpolation and produces an `eyre::Report`.
```rust
return Err(eyre!("Missing attribute: {}", missing));
```
- On newer versions of the compiler (e.g. 1.58 and later) this macro also
supports format args captures.
```rust
return Err(eyre!("Missing attribute: {missing}"));
```
## No-std support
No-std support was removed in 2020 in [commit 608a16a] due to unaddressed upstream breakages.
[commit 608a16a]:
https://github.com/eyre-rs/eyre/pull/29/commits/608a16aa2c2c27eca6c88001cc94c6973c18f1d5
## Comparison to failure
The `eyre::Report` type works something like `failure::Error`, but unlike
failure ours is built around the standard library's `std::error::Error` trait
rather than a separate trait `failure::Fail`. The standard library has adopted
the necessary improvements for this to be possible as part of [RFC 2504].
[RFC 2504]: https://github.com/rust-lang/rfcs/blob/master/text/2504-fix-error.md
## Comparison to thiserror
Use `eyre` if you don't think you'll do anything with an error other than
report it. This is common in application code. Use `thiserror` if you think
you need an error type that can be handled via match or reported. This is
common in library crates where you don't know how your users will handle
your errors.
[thiserror]: https://github.com/dtolnay/thiserror
## Compatibility with `anyhow`
This crate does its best to be usable as a drop in replacement of `anyhow` and
vice-versa by `re-exporting` all of the renamed APIs with the names used in
`anyhow`, though there are some differences still.
#### `Context` and `Option`
As part of renaming `Context` to `WrapErr` we also intentionally do not
implement `WrapErr` for `Option`. This decision was made because `wrap_err`
implies that you're creating a new error that saves the old error as its
`source`. With `Option` there is no source error to wrap, so `wrap_err` ends up
being somewhat meaningless.
Instead `eyre` offers [`OptionExt::ok_or_eyre`] to yield _static_ errors from `None`,
and intends for users to use the combinator functions provided by
`std`, converting `Option`s to `Result`s, for _dynamic_ errors.
So where you would write this with
anyhow:
[`OptionExt::ok_or_eyre`]: https://docs.rs/eyre/latest/eyre/trait.OptionExt.html#tymethod.ok_or_eyre
```rust
use anyhow::Context;
let opt: Option<()> = None;
let result_static = opt.context("static error message");
let result_dynamic = opt.with_context(|| format!("{} error message", "dynamic"));
```
With `eyre` we want users to write:
```rust
use eyre::{eyre, OptionExt, Result};
let opt: Option<()> = None;
let result_static: Result<()> = opt.ok_or_eyre("static error message");
let result_dynamic: Result<()> = opt.ok_or_else(|| eyre!("{} error message", "dynamic"));
```
**NOTE**: However, to help with porting we do provide a `ContextCompat` trait which
implements `context` for options which you can import to make existing
`.context` calls compile.
[Report]: https://docs.rs/eyre/*/eyre/struct.Report.html
[`eyre::EyreHandler`]: https://docs.rs/eyre/*/eyre/trait.EyreHandler.html
[`eyre::WrapErr`]: https://docs.rs/eyre/*/eyre/trait.WrapErr.html
[`anyhow::Context`]: https://docs.rs/anyhow/*/anyhow/trait.Context.html
[`anyhow`]: https://github.com/dtolnay/anyhow
[`tracing_error::SpanTrace`]: https://docs.rs/tracing-error/*/tracing_error/struct.SpanTrace.html
[`stable-eyre`]: https://github.com/eyre-rs/stable-eyre
[`color-eyre`]: https://github.com/eyre-rs/color-eyre
[`jane-eyre`]: https://github.com/yaahc/jane-eyre
[`simple-eyre`]: https://github.com/eyre-rs/simple-eyre
[`color-spantrace`]: https://github.com/eyre-rs/color-spantrace
[`color-backtrace`]: https://github.com/athre0z/color-backtrace
[^1]: example and explanation of breakage https://github.com/eyre-rs/eyre/issues/30#issuecomment-647650361
#### License
<sup>
Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
</sup>
<br>
<sub>
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions.
</sub>

132
third-party/vendor/eyre/build.rs vendored Normal file
View file

@ -0,0 +1,132 @@
use std::env;
use std::ffi::OsString;
use std::fs;
use std::path::Path;
use std::process::{Command, ExitStatus};
use std::str;
// 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
// backtrace in eyre.
const BACKTRACE_PROBE: &str = r#"
#![feature(backtrace)]
#![allow(dead_code)]
use std::backtrace::{Backtrace, BacktraceStatus};
use std::error::Error;
use std::fmt::{self, Display};
#[derive(Debug)]
struct E;
impl Display for E {
fn fmt(&self, _formatter: &mut fmt::Formatter) -> fmt::Result {
unimplemented!()
}
}
impl Error for E {
fn backtrace(&self) -> Option<&Backtrace> {
let backtrace = Backtrace::capture();
match backtrace.status() {
BacktraceStatus::Captured | BacktraceStatus::Disabled | _ => {}
}
unimplemented!()
}
}
"#;
const TRACK_CALLER_PROBE: &str = r#"
#![allow(dead_code)]
#[track_caller]
fn foo() {
let _location = std::panic::Location::caller();
}
"#;
fn main() {
match compile_probe(BACKTRACE_PROBE) {
Some(status) if status.success() => println!("cargo:rustc-cfg=backtrace"),
_ => {}
}
match compile_probe(TRACK_CALLER_PROBE) {
Some(status) if status.success() => println!("cargo:rustc-cfg=track_caller"),
_ => {}
}
let version = match rustc_version_info() {
Some(version) => version,
None => return,
};
version.toolchain.set_feature();
if version.minor < 52 {
println!("cargo:rustc-cfg=eyre_no_fmt_arguments_as_str");
}
if version.minor < 58 {
println!("cargo:rustc-cfg=eyre_no_fmt_args_capture");
}
}
fn compile_probe(probe: &str) -> Option<ExitStatus> {
let rustc = env::var_os("RUSTC")?;
let out_dir = env::var_os("OUT_DIR")?;
let probefile = Path::new(&out_dir).join("probe.rs");
fs::write(&probefile, probe).ok()?;
Command::new(rustc)
.arg("--edition=2018")
.arg("--crate-name=eyre_build")
.arg("--crate-type=lib")
.arg("--emit=metadata")
.arg("--out-dir")
.arg(out_dir)
.arg(probefile)
.status()
.ok()
}
// TODO factor this toolchain parsing and related tests into its own file
#[derive(PartialEq)]
enum Toolchain {
Stable,
Beta,
Nightly,
}
impl Toolchain {
fn set_feature(self) {
match self {
Toolchain::Nightly => println!("cargo:rustc-cfg=nightly"),
Toolchain::Beta => println!("cargo:rustc-cfg=beta"),
Toolchain::Stable => println!("cargo:rustc-cfg=stable"),
}
}
}
struct VersionInfo {
minor: u32,
toolchain: Toolchain,
}
fn rustc_version_info() -> Option<VersionInfo> {
let rustc = env::var_os("RUSTC").unwrap_or_else(|| OsString::from("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") {
return None;
}
let _major: u32 = pieces.next()?.parse().ok()?;
let minor = pieces.next()?.parse().ok()?;
let _patch: u32 = pieces.next()?.parse().ok()?;
let toolchain = match pieces.next() {
Some("beta") => Toolchain::Beta,
Some("nightly") => Toolchain::Nightly,
_ => Toolchain::Stable,
};
let version = VersionInfo { minor, toolchain };
Some(version)
}

View file

@ -0,0 +1,81 @@
use backtrace::Backtrace;
use eyre::EyreHandler;
use std::error::Error;
use std::{fmt, iter};
fn main() -> eyre::Result<()> {
// Install our custom eyre report hook for constructing our custom Handlers
install().unwrap();
// construct a report with, hopefully, our custom handler!
let mut report = eyre::eyre!("hello from custom error town!");
// manually set the custom msg for this report after it has been constructed
if let Some(handler) = report.handler_mut().downcast_mut::<Handler>() {
handler.custom_msg = Some("you're the best users, you know that right???");
}
// print that shit!!
Err(report)
}
// define a handler that captures backtraces unless told not to
fn install() -> Result<(), impl Error> {
let capture_backtrace = std::env::var("RUST_BACKWARDS_TRACE")
.map(|val| val != "0")
.unwrap_or(true);
let hook = Hook { capture_backtrace };
eyre::set_hook(Box::new(move |e| Box::new(hook.make_handler(e))))
}
struct Hook {
capture_backtrace: bool,
}
impl Hook {
fn make_handler(&self, _error: &(dyn Error + 'static)) -> Handler {
let backtrace = if self.capture_backtrace {
Some(Backtrace::new())
} else {
None
};
Handler {
backtrace,
custom_msg: None,
}
}
}
struct Handler {
// custom configured backtrace capture
backtrace: Option<Backtrace>,
// customizable message payload associated with reports
custom_msg: Option<&'static str>,
}
impl EyreHandler for Handler {
fn debug(&self, error: &(dyn Error + 'static), f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
return fmt::Debug::fmt(error, f);
}
let errors = iter::successors(Some(error), |error| (*error).source());
for (ind, error) in errors.enumerate() {
write!(f, "\n{:>4}: {}", ind, error)?;
}
if let Some(backtrace) = self.backtrace.as_ref() {
writeln!(f, "\n\nBacktrace:\n{:?}", backtrace)?;
}
if let Some(msg) = self.custom_msg.as_ref() {
writeln!(f, "\n\n{}", msg)?;
}
Ok(())
}
}

View file

@ -0,0 +1,7 @@
use eyre::{eyre, Report, WrapErr};
fn main() -> Result<(), Report> {
let e: Report = eyre!("oh no this program is just bad!");
Err(e).wrap_err("usage example successfully experienced a failure")
}

View file

@ -0,0 +1,22 @@
#[cfg(backtrace)]
pub(crate) use std::backtrace::Backtrace;
#[cfg(not(backtrace))]
pub(crate) enum Backtrace {}
#[cfg(backtrace)]
macro_rules! backtrace_if_absent {
($err:expr) => {
match $err.backtrace() {
Some(_) => None,
None => Some(Backtrace::capture()),
}
};
}
#[cfg(not(backtrace))]
macro_rules! backtrace_if_absent {
($err:expr) => {
None
};
}

109
third-party/vendor/eyre/src/chain.rs vendored Normal file
View file

@ -0,0 +1,109 @@
use self::ChainState::*;
use crate::StdError;
use std::vec;
pub(crate) use crate::Chain;
#[derive(Clone)]
pub(crate) enum ChainState<'a> {
Linked {
next: Option<&'a (dyn StdError + 'static)>,
},
Buffered {
rest: vec::IntoIter<&'a (dyn StdError + 'static)>,
},
}
impl<'a> Chain<'a> {
/// Construct an iterator over a chain of errors via the `source` method
///
/// # Example
///
/// ```rust
/// use std::error::Error;
/// use std::fmt::{self, Write};
/// use eyre::Chain;
/// use indenter::indented;
///
/// fn report(error: &(dyn Error + 'static), f: &mut fmt::Formatter<'_>) -> fmt::Result {
/// let mut errors = Chain::new(error).enumerate();
/// for (i, error) in errors {
/// writeln!(f)?;
/// write!(indented(f).ind(i), "{}", error)?;
/// }
///
/// Ok(())
/// }
/// ```
pub fn new(head: &'a (dyn StdError + 'static)) -> Self {
Chain {
state: ChainState::Linked { next: Some(head) },
}
}
}
impl<'a> Iterator for Chain<'a> {
type Item = &'a (dyn StdError + 'static);
fn next(&mut self) -> Option<Self::Item> {
match &mut self.state {
Linked { next } => {
let error = (*next)?;
*next = error.source();
Some(error)
}
Buffered { rest } => rest.next(),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
}
impl DoubleEndedIterator for Chain<'_> {
fn next_back(&mut self) -> Option<Self::Item> {
match &mut self.state {
Linked { mut next } => {
let mut rest = Vec::new();
while let Some(cause) = next {
next = cause.source();
rest.push(cause);
}
let mut rest = rest.into_iter();
let last = rest.next_back();
self.state = Buffered { rest };
last
}
Buffered { rest } => rest.next_back(),
}
}
}
impl ExactSizeIterator for Chain<'_> {
fn len(&self) -> usize {
match &self.state {
Linked { mut next } => {
let mut len = 0;
while let Some(cause) = next {
next = cause.source();
len += 1;
}
len
}
Buffered { rest } => rest.len(),
}
}
}
impl Default for Chain<'_> {
fn default() -> Self {
Chain {
state: ChainState::Buffered {
rest: Vec::new().into_iter(),
},
}
}
}

192
third-party/vendor/eyre/src/context.rs vendored Normal file
View file

@ -0,0 +1,192 @@
use crate::error::{ContextError, ErrorImpl};
use crate::{ContextCompat, Report, StdError, WrapErr};
use core::fmt::{self, Debug, Display, Write};
#[cfg(backtrace)]
use std::backtrace::Backtrace;
mod ext {
use super::*;
pub trait StdError {
#[cfg_attr(track_caller, track_caller)]
fn ext_report<D>(self, msg: D) -> Report
where
D: Display + Send + Sync + 'static;
}
impl<E> StdError for E
where
E: std::error::Error + Send + Sync + 'static,
{
fn ext_report<D>(self, msg: D) -> Report
where
D: Display + Send + Sync + 'static,
{
Report::from_msg(msg, self)
}
}
impl StdError for Report {
fn ext_report<D>(self, msg: D) -> Report
where
D: Display + Send + Sync + 'static,
{
self.wrap_err(msg)
}
}
}
impl<T, E> WrapErr<T, E> for Result<T, E>
where
E: ext::StdError + Send + Sync + 'static,
{
fn wrap_err<D>(self, msg: D) -> Result<T, Report>
where
D: Display + Send + Sync + 'static,
{
match self {
Ok(t) => Ok(t),
Err(e) => Err(e.ext_report(msg)),
}
}
fn wrap_err_with<D, F>(self, msg: F) -> Result<T, Report>
where
D: Display + Send + Sync + 'static,
F: FnOnce() -> D,
{
match self {
Ok(t) => Ok(t),
Err(e) => Err(e.ext_report(msg())),
}
}
fn context<D>(self, msg: D) -> Result<T, Report>
where
D: Display + Send + Sync + 'static,
{
self.wrap_err(msg)
}
fn with_context<D, F>(self, msg: F) -> Result<T, Report>
where
D: Display + Send + Sync + 'static,
F: FnOnce() -> D,
{
self.wrap_err_with(msg)
}
}
impl<T> ContextCompat<T> for Option<T> {
fn wrap_err<D>(self, msg: D) -> Result<T, Report>
where
D: Display + Send + Sync + 'static,
{
self.context(msg)
}
fn wrap_err_with<D, F>(self, msg: F) -> Result<T, Report>
where
D: Display + Send + Sync + 'static,
F: FnOnce() -> D,
{
self.with_context(msg)
}
fn context<D>(self, msg: D) -> Result<T, Report>
where
D: Display + Send + Sync + 'static,
{
match self {
Some(t) => Ok(t),
None => Err(Report::from_display(msg)),
}
}
fn with_context<D, F>(self, msg: F) -> Result<T, Report>
where
D: Display + Send + Sync + 'static,
F: FnOnce() -> D,
{
match self {
Some(t) => Ok(t),
None => Err(Report::from_display(msg())),
}
}
}
impl<D, E> Debug for ContextError<D, E>
where
D: Display,
E: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Error")
.field("msg", &Quoted(&self.msg))
.field("source", &self.error)
.finish()
}
}
impl<D, E> Display for ContextError<D, E>
where
D: Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.msg, f)
}
}
impl<D, E> StdError for ContextError<D, E>
where
D: Display,
E: StdError + 'static,
{
#[cfg(backtrace)]
fn backtrace(&self) -> Option<&Backtrace> {
self.error.backtrace()
}
fn source(&self) -> Option<&(dyn StdError + 'static)> {
Some(&self.error)
}
}
impl<D> StdError for ContextError<D, Report>
where
D: Display,
{
fn source(&self) -> Option<&(dyn StdError + 'static)> {
Some(ErrorImpl::error(self.error.inner.as_ref()))
}
}
struct Quoted<D>(D);
impl<D> Debug for Quoted<D>
where
D: Display,
{
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_char('"')?;
Quoted(&mut *formatter).write_fmt(format_args!("{}", self.0))?;
formatter.write_char('"')?;
Ok(())
}
}
impl Write for Quoted<&mut fmt::Formatter<'_>> {
fn write_str(&mut self, s: &str) -> fmt::Result {
Display::fmt(&s.escape_debug(), self.0)
}
}
pub(crate) mod private {
use super::*;
pub trait Sealed {}
impl<T, E> Sealed for Result<T, E> where E: ext::StdError {}
impl<T> Sealed for Option<T> {}
}

912
third-party/vendor/eyre/src/error.rs vendored Normal file
View file

@ -0,0 +1,912 @@
use crate::chain::Chain;
use crate::ptr::{MutPtr, OwnedPtr, RefPtr};
use crate::EyreHandler;
use crate::{Report, StdError};
use core::any::TypeId;
use core::fmt::{self, Debug, Display};
use core::mem::{self, ManuallyDrop};
use core::ptr::{self, NonNull};
use core::ops::{Deref, DerefMut};
impl Report {
/// Create a new error object from any error type.
///
/// The error type must be threadsafe and `'static`, so that the `Report`
/// will be as well.
///
/// If the error type does not provide a backtrace, a backtrace will be
/// created here to ensure that a backtrace exists.
#[cfg_attr(track_caller, track_caller)]
pub fn new<E>(error: E) -> Self
where
E: StdError + Send + Sync + 'static,
{
Report::from_std(error)
}
/// Create a new error object from a printable error message.
///
/// If the argument implements std::error::Error, prefer `Report::new`
/// instead which preserves the underlying error's cause chain and
/// backtrace. If the argument may or may not implement std::error::Error
/// now or in the future, use `eyre!(err)` which handles either way
/// correctly.
///
/// `Report::msg("...")` is equivalent to `eyre!("...")` but occasionally
/// convenient in places where a function is preferable over a macro, such
/// as iterator or stream combinators:
///
/// ```
/// # mod ffi {
/// # pub struct Input;
/// # pub struct Output;
/// # pub async fn do_some_work(_: Input) -> Result<Output, &'static str> {
/// # unimplemented!()
/// # }
/// # }
/// #
/// # use ffi::{Input, Output};
/// #
/// use eyre::{Report, Result};
/// use futures::stream::{Stream, StreamExt, TryStreamExt};
///
/// async fn demo<S>(stream: S) -> Result<Vec<Output>>
/// where
/// S: Stream<Item = Input>,
/// {
/// stream
/// .then(ffi::do_some_work) // returns Result<Output, &str>
/// .map_err(Report::msg)
/// .try_collect()
/// .await
/// }
/// ```
#[cfg_attr(track_caller, track_caller)]
pub fn msg<M>(message: M) -> Self
where
M: Display + Debug + Send + Sync + 'static,
{
Report::from_adhoc(message)
}
#[cfg_attr(track_caller, track_caller)]
/// Creates a new error from an implementor of [`std::error::Error`]
pub(crate) fn from_std<E>(error: E) -> Self
where
E: StdError + Send + Sync + 'static,
{
let vtable = &ErrorVTable {
object_drop: object_drop::<E>,
object_ref: object_ref::<E>,
object_mut: object_mut::<E>,
object_boxed: object_boxed::<E>,
object_downcast: object_downcast::<E>,
object_downcast_mut: object_downcast_mut::<E>,
object_drop_rest: object_drop_front::<E>,
};
// Safety: passing vtable that operates on the right type E.
let handler = Some(crate::capture_handler(&error));
unsafe { Report::construct(error, vtable, handler) }
}
#[cfg_attr(track_caller, track_caller)]
pub(crate) fn from_adhoc<M>(message: M) -> Self
where
M: Display + Debug + Send + Sync + 'static,
{
use crate::wrapper::MessageError;
let error: MessageError<M> = MessageError(message);
let vtable = &ErrorVTable {
object_drop: object_drop::<MessageError<M>>,
object_ref: object_ref::<MessageError<M>>,
object_mut: object_mut::<MessageError<M>>,
object_boxed: object_boxed::<MessageError<M>>,
object_downcast: object_downcast::<M>,
object_downcast_mut: object_downcast_mut::<M>,
object_drop_rest: object_drop_front::<M>,
};
// Safety: MessageError is repr(transparent) so it is okay for the
// vtable to allow casting the MessageError<M> to M.
let handler = Some(crate::capture_handler(&error));
unsafe { Report::construct(error, vtable, handler) }
}
#[cfg_attr(track_caller, track_caller)]
pub(crate) fn from_display<M>(message: M) -> Self
where
M: Display + Send + Sync + 'static,
{
use crate::wrapper::{DisplayError, NoneError};
let error: DisplayError<M> = DisplayError(message);
let vtable = &ErrorVTable {
object_drop: object_drop::<DisplayError<M>>,
object_ref: object_ref::<DisplayError<M>>,
object_mut: object_mut::<DisplayError<M>>,
object_boxed: object_boxed::<DisplayError<M>>,
object_downcast: object_downcast::<M>,
object_downcast_mut: object_downcast_mut::<M>,
object_drop_rest: object_drop_front::<M>,
};
// Safety: DisplayError is repr(transparent) so it is okay for the
// vtable to allow casting the DisplayError<M> to M.
let handler = Some(crate::capture_handler(&NoneError));
unsafe { Report::construct(error, vtable, handler) }
}
#[cfg_attr(track_caller, track_caller)]
pub(crate) fn from_msg<D, E>(msg: D, error: E) -> Self
where
D: Display + Send + Sync + 'static,
E: StdError + Send + Sync + 'static,
{
let error: ContextError<D, E> = ContextError { msg, error };
let vtable = &ErrorVTable {
object_drop: object_drop::<ContextError<D, E>>,
object_ref: object_ref::<ContextError<D, E>>,
object_mut: object_mut::<ContextError<D, E>>,
object_boxed: object_boxed::<ContextError<D, E>>,
object_downcast: context_downcast::<D, E>,
object_downcast_mut: context_downcast_mut::<D, E>,
object_drop_rest: context_drop_rest::<D, E>,
};
// Safety: passing vtable that operates on the right type.
let handler = Some(crate::capture_handler(&error));
unsafe { Report::construct(error, vtable, handler) }
}
#[cfg_attr(track_caller, track_caller)]
pub(crate) fn from_boxed(error: Box<dyn StdError + Send + Sync>) -> Self {
use crate::wrapper::BoxedError;
let error = BoxedError(error);
let handler = Some(crate::capture_handler(&error));
let vtable = &ErrorVTable {
object_drop: object_drop::<BoxedError>,
object_ref: object_ref::<BoxedError>,
object_mut: object_mut::<BoxedError>,
object_boxed: object_boxed::<BoxedError>,
object_downcast: object_downcast::<Box<dyn StdError + Send + Sync>>,
object_downcast_mut: object_downcast_mut::<Box<dyn StdError + Send + Sync>>,
object_drop_rest: object_drop_front::<Box<dyn StdError + Send + Sync>>,
};
// Safety: BoxedError is repr(transparent) so it is okay for the vtable
// to allow casting to Box<dyn StdError + Send + Sync>.
unsafe { Report::construct(error, vtable, handler) }
}
// Takes backtrace as argument rather than capturing it here so that the
// user sees one fewer layer of wrapping noise in the backtrace.
//
// Unsafe because the given vtable must have sensible behavior on the error
// value of type E.
unsafe fn construct<E>(
error: E,
vtable: &'static ErrorVTable,
handler: Option<Box<dyn EyreHandler>>,
) -> Self
where
E: StdError + Send + Sync + 'static,
{
let inner = ErrorImpl {
header: ErrorHeader { vtable, handler },
_object: error,
};
// Construct a new owned allocation through a raw pointer
//
// This does not keep the allocation around as a `Box` which would invalidate an
// references when moved
let ptr = OwnedPtr::<ErrorImpl<E>>::new(inner);
// Safety: the type
let ptr = ptr.cast::<ErrorImpl<()>>();
Report { inner: ptr }
}
/// Create a new error from an error message to wrap the existing error.
///
/// For attaching a higher level error message to a `Result` as it is propagated, the
/// [`WrapErr`][crate::WrapErr] extension trait may be more convenient than this function.
///
/// The primary reason to use `error.wrap_err(...)` instead of `result.wrap_err(...)` via the
/// `WrapErr` trait would be if the message needs to depend on some data held by the underlying
/// error:
///
/// ```
/// # use std::fmt::{self, Debug, Display};
/// #
/// # type T = ();
/// #
/// # impl std::error::Error for ParseError {}
/// # impl Debug for ParseError {
/// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
/// # unimplemented!()
/// # }
/// # }
/// # impl Display for ParseError {
/// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
/// # unimplemented!()
/// # }
/// # }
/// #
/// use eyre::Result;
/// use std::fs::File;
/// use std::path::Path;
///
/// struct ParseError {
/// line: usize,
/// column: usize,
/// }
///
/// fn parse_impl(file: File) -> Result<T, ParseError> {
/// # const IGNORE: &str = stringify! {
/// ...
/// # };
/// # unimplemented!()
/// }
///
/// pub fn parse(path: impl AsRef<Path>) -> Result<T> {
/// let file = File::open(&path)?;
/// parse_impl(file).map_err(|error| {
/// let message = format!(
/// "only the first {} lines of {} are valid",
/// error.line, path.as_ref().display(),
/// );
/// eyre::Report::new(error).wrap_err(message)
/// })
/// }
/// ```
pub fn wrap_err<D>(mut self, msg: D) -> Self
where
D: Display + Send + Sync + 'static,
{
// Safety: this access a `ErrorImpl<unknown>` as a valid reference to a `ErrorImpl<()>`
//
// As the generic is at the end of the struct and the struct is `repr(C)` this reference
// will be within bounds of the original pointer, and the field will have the same offset
let handler = header_mut(self.inner.as_mut()).handler.take();
let error: ContextError<D, Report> = ContextError { msg, error: self };
let vtable = &ErrorVTable {
object_drop: object_drop::<ContextError<D, Report>>,
object_ref: object_ref::<ContextError<D, Report>>,
object_mut: object_mut::<ContextError<D, Report>>,
object_boxed: object_boxed::<ContextError<D, Report>>,
object_downcast: context_chain_downcast::<D>,
object_downcast_mut: context_chain_downcast_mut::<D>,
object_drop_rest: context_chain_drop_rest::<D>,
};
// Safety: passing vtable that operates on the right type.
unsafe { Report::construct(error, vtable, handler) }
}
/// Access the vtable for the current error object.
fn vtable(&self) -> &'static ErrorVTable {
header(self.inner.as_ref()).vtable
}
/// An iterator of the chain of source errors contained by this Report.
///
/// This iterator will visit every error in the cause chain of this error
/// object, beginning with the error that this error object was created
/// from.
///
/// # Example
///
/// ```
/// use eyre::Report;
/// use std::io;
///
/// pub fn underlying_io_error_kind(error: &Report) -> Option<io::ErrorKind> {
/// for cause in error.chain() {
/// if let Some(io_error) = cause.downcast_ref::<io::Error>() {
/// return Some(io_error.kind());
/// }
/// }
/// None
/// }
/// ```
pub fn chain(&self) -> Chain<'_> {
ErrorImpl::chain(self.inner.as_ref())
}
/// The lowest level cause of this error &mdash; this error's cause's
/// cause's cause etc.
///
/// The root cause is the last error in the iterator produced by
/// [`chain()`][Report::chain].
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
}
/// Returns true if `E` is the type held by this error object.
///
/// For errors constructed from messages, this method returns true if `E` matches the type of
/// the message `D` **or** the type of the error on which the message has been attached. For
/// details about the interaction between message and downcasting, [see here].
///
/// [see here]: trait.WrapErr.html#effect-on-downcasting
pub fn is<E>(&self) -> bool
where
E: Display + Debug + Send + Sync + 'static,
{
self.downcast_ref::<E>().is_some()
}
/// Attempt to downcast the error object to a concrete type.
pub fn downcast<E>(self) -> Result<E, Self>
where
E: Display + Debug + Send + Sync + 'static,
{
let target = TypeId::of::<E>();
unsafe {
// Use vtable to find NonNull<()> which points to a value of type E
// somewhere inside the data structure.
let addr = match (self.vtable().object_downcast)(self.inner.as_ref(), target) {
Some(addr) => addr,
None => return Err(self),
};
// Prepare to read E out of the data structure. We'll drop the rest
// of the data structure separately so that E is not dropped.
let outer = ManuallyDrop::new(self);
// Read E from where the vtable found it.
let error = ptr::read(addr.cast::<E>().as_ptr());
// Read Box<ErrorImpl<()>> from self. Can't move it out because
// Report has a Drop impl which we want to not run.
let inner = ptr::read(&outer.inner);
// Drop rest of the data structure outside of E.
(outer.vtable().object_drop_rest)(inner, target);
Ok(error)
}
}
/// Downcast this error object by reference.
///
/// # Example
///
/// ```
/// # use eyre::{Report, eyre};
/// # use std::fmt::{self, Display};
/// # use std::task::Poll;
/// #
/// # #[derive(Debug)]
/// # enum DataStoreError {
/// # Censored(()),
/// # }
/// #
/// # impl Display for DataStoreError {
/// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
/// # unimplemented!()
/// # }
/// # }
/// #
/// # impl std::error::Error for DataStoreError {}
/// #
/// # const REDACTED_CONTENT: () = ();
/// #
/// # #[cfg(not(feature = "auto-install"))]
/// # eyre::set_hook(Box::new(eyre::DefaultHandler::default_with)).unwrap();
/// #
/// # let error: Report = eyre!("...");
/// # let root_cause = &error;
/// #
/// # let ret =
/// // If the error was caused by redaction, then return a tombstone instead
/// // of the content.
/// match root_cause.downcast_ref::<DataStoreError>() {
/// Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),
/// None => Err(error),
/// }
/// # ;
/// ```
pub fn downcast_ref<E>(&self) -> Option<&E>
where
E: Display + Debug + Send + Sync + 'static,
{
let target = TypeId::of::<E>();
unsafe {
// Use vtable to find NonNull<()> which points to a value of type E
// somewhere inside the data structure.
let addr = (self.vtable().object_downcast)(self.inner.as_ref(), target)?;
Some(addr.cast::<E>().as_ref())
}
}
/// Downcast this error object by mutable reference.
pub fn downcast_mut<E>(&mut self) -> Option<&mut E>
where
E: Display + Debug + Send + Sync + 'static,
{
let target = TypeId::of::<E>();
unsafe {
// Use vtable to find NonNull<()> which points to a value of type E
// somewhere inside the data structure.
let addr = (self.vtable().object_downcast_mut)(self.inner.as_mut(), target)?;
Some(addr.cast::<E>().as_mut())
}
}
/// Get a reference to the Handler for this Report.
pub fn handler(&self) -> &dyn EyreHandler {
header(self.inner.as_ref())
.handler
.as_ref()
.unwrap()
.as_ref()
}
/// Get a mutable reference to the Handler for this Report.
pub fn handler_mut(&mut self) -> &mut dyn EyreHandler {
header_mut(self.inner.as_mut())
.handler
.as_mut()
.unwrap()
.as_mut()
}
/// Get a reference to the Handler for this Report.
#[doc(hidden)]
pub fn context(&self) -> &dyn EyreHandler {
header(self.inner.as_ref())
.handler
.as_ref()
.unwrap()
.as_ref()
}
/// Get a mutable reference to the Handler for this Report.
#[doc(hidden)]
pub fn context_mut(&mut self) -> &mut dyn EyreHandler {
header_mut(self.inner.as_mut())
.handler
.as_mut()
.unwrap()
.as_mut()
}
}
impl<E> From<E> for Report
where
E: StdError + Send + Sync + 'static,
{
#[cfg_attr(track_caller, track_caller)]
fn from(error: E) -> Self {
Report::from_std(error)
}
}
impl Deref for Report {
type Target = dyn StdError + Send + Sync + 'static;
fn deref(&self) -> &Self::Target {
ErrorImpl::error(self.inner.as_ref())
}
}
impl DerefMut for Report {
fn deref_mut(&mut self) -> &mut Self::Target {
ErrorImpl::error_mut(self.inner.as_mut())
}
}
impl Display for Report {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
ErrorImpl::display(self.inner.as_ref(), formatter)
}
}
impl Debug for Report {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
ErrorImpl::debug(self.inner.as_ref(), formatter)
}
}
impl Drop for Report {
fn drop(&mut self) {
unsafe {
// Read Box<ErrorImpl<()>> from self.
(self.vtable().object_drop)(self.inner);
}
}
}
struct ErrorVTable {
object_drop: unsafe fn(OwnedPtr<ErrorImpl<()>>),
object_ref: unsafe fn(RefPtr<'_, ErrorImpl<()>>) -> &(dyn StdError + Send + Sync + 'static),
object_mut: unsafe fn(MutPtr<'_, ErrorImpl<()>>) -> &mut (dyn StdError + Send + Sync + 'static),
#[allow(clippy::type_complexity)]
object_boxed: unsafe fn(OwnedPtr<ErrorImpl<()>>) -> Box<dyn StdError + Send + Sync + 'static>,
object_downcast: unsafe fn(RefPtr<'_, ErrorImpl<()>>, TypeId) -> Option<NonNull<()>>,
object_downcast_mut: unsafe fn(MutPtr<'_, ErrorImpl<()>>, TypeId) -> Option<NonNull<()>>,
object_drop_rest: unsafe fn(OwnedPtr<ErrorImpl<()>>, TypeId),
}
/// # Safety
///
/// Requires layout of *e to match ErrorImpl<E>.
unsafe fn object_drop<E>(e: OwnedPtr<ErrorImpl<()>>) {
// Cast to a context type and drop the Box allocation.
let unerased = unsafe { e.cast::<ErrorImpl<E>>().into_box() };
drop(unerased);
}
/// # Safety
///
/// Requires layout of *e to match ErrorImpl<E>.
unsafe fn object_drop_front<E>(e: OwnedPtr<ErrorImpl<()>>, 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;
// Note: This must not use `mem::transmute` because it tries to reborrow the `Unique`
// contained in `Box`, which must not be done. In practice this probably won't make any
// difference by now, but technically it's unsound.
// see: https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.m
let unerased = unsafe { e.cast::<ErrorImpl<E>>().into_box() };
mem::forget(unerased._object)
}
/// # Safety
///
/// Requires layout of *e to match ErrorImpl<E>.
unsafe fn object_ref<E>(e: RefPtr<'_, ErrorImpl<()>>) -> &(dyn StdError + Send + Sync + 'static)
where
E: StdError + Send + Sync + 'static,
{
// Attach E's native StdError vtable onto a pointer to self._object.
&unsafe { e.cast::<ErrorImpl<E>>().as_ref() }._object
}
/// # Safety
///
/// Requires layout of *e to match ErrorImpl<E>.
unsafe fn object_mut<E>(e: MutPtr<'_, ErrorImpl<()>>) -> &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 unsafe { e.cast::<ErrorImpl<E>>().into_mut() }._object
}
/// # Safety
///
/// Requires layout of *e to match ErrorImpl<E>.
unsafe fn object_boxed<E>(e: OwnedPtr<ErrorImpl<()>>) -> Box<dyn StdError + Send + Sync + 'static>
where
E: StdError + Send + Sync + 'static,
{
// Attach ErrorImpl<E>'s native StdError vtable. The StdError impl is below.
unsafe { e.cast::<ErrorImpl<E>>().into_box() }
}
/// # Safety
///
/// Requires layout of *e to match ErrorImpl<E>.
unsafe fn object_downcast<E>(e: RefPtr<'_, ErrorImpl<()>>, target: TypeId) -> Option<NonNull<()>>
where
E: 'static,
{
if TypeId::of::<E>() == target {
// Caller is looking for an E pointer and e is ErrorImpl<E>, take a
// pointer to its E field.
let unerased = unsafe { e.cast::<ErrorImpl<E>>().as_ref() };
Some(NonNull::from(&(unerased._object)).cast::<()>())
} else {
None
}
}
/// # Safety
///
/// Requires layout of *e to match ErrorImpl<E>.
unsafe fn object_downcast_mut<E>(
e: MutPtr<'_, ErrorImpl<()>>,
target: TypeId,
) -> Option<NonNull<()>>
where
E: 'static,
{
if TypeId::of::<E>() == target {
// Caller is looking for an E pointer and e is ErrorImpl<E>, take a
// pointer to its E field.
let unerased = unsafe { e.cast::<ErrorImpl<E>>().into_mut() };
Some(NonNull::from(&mut (unerased._object)).cast::<()>())
} else {
None
}
}
/// # Safety
///
/// Requires layout of *e to match ErrorImpl<ContextError<D, E>>.
unsafe fn context_downcast<D, E>(
e: RefPtr<'_, ErrorImpl<()>>,
target: TypeId,
) -> Option<NonNull<()>>
where
D: 'static,
E: 'static,
{
if TypeId::of::<D>() == target {
let unerased = unsafe { e.cast::<ErrorImpl<ContextError<D, E>>>().as_ref() };
let addr = NonNull::from(&unerased._object.msg).cast::<()>();
Some(addr)
} else if TypeId::of::<E>() == target {
let unerased = unsafe { e.cast::<ErrorImpl<ContextError<D, E>>>().as_ref() };
let addr = NonNull::from(&unerased._object.error).cast::<()>();
Some(addr)
} else {
None
}
}
/// # Safety
///
/// Requires layout of *e to match ErrorImpl<ContextError<D, E>>.
unsafe fn context_downcast_mut<D, E>(
e: MutPtr<'_, ErrorImpl<()>>,
target: TypeId,
) -> Option<NonNull<()>>
where
D: 'static,
E: 'static,
{
if TypeId::of::<D>() == target {
let unerased = unsafe { e.cast::<ErrorImpl<ContextError<D, E>>>().into_mut() };
let addr = NonNull::from(&unerased._object.msg).cast::<()>();
Some(addr)
} else if TypeId::of::<E>() == target {
let unerased = unsafe { e.cast::<ErrorImpl<ContextError<D, E>>>().into_mut() };
let addr = NonNull::from(&mut unerased._object.error).cast::<()>();
Some(addr)
} else {
None
}
}
/// # Safety
///
/// Requires layout of *e to match ErrorImpl<ContextError<D, E>>.
unsafe fn context_drop_rest<D, E>(e: OwnedPtr<ErrorImpl<()>>, target: TypeId)
where
D: 'static,
E: 'static,
{
// Called after downcasting by value to either the D or the E and doing a
// ptr::read to take ownership of that value.
if TypeId::of::<D>() == target {
unsafe {
e.cast::<ErrorImpl<ContextError<ManuallyDrop<D>, E>>>()
.into_box()
};
} else {
debug_assert_eq!(TypeId::of::<E>(), target);
unsafe {
e.cast::<ErrorImpl<ContextError<D, ManuallyDrop<E>>>>()
.into_box()
};
}
}
/// # Safety
///
/// Requires layout of *e to match ErrorImpl<ContextError<D, Report>>.
unsafe fn context_chain_downcast<D>(
e: RefPtr<'_, ErrorImpl<()>>,
target: TypeId,
) -> Option<NonNull<()>>
where
D: 'static,
{
let unerased = unsafe { e.cast::<ErrorImpl<ContextError<D, Report>>>().as_ref() };
if TypeId::of::<D>() == target {
let addr = NonNull::from(&unerased._object.msg).cast::<()>();
Some(addr)
} else {
// Recurse down the context chain per the inner error's vtable.
let source = &unerased._object.error;
unsafe { (source.vtable().object_downcast)(source.inner.as_ref(), target) }
}
}
/// # Safety
///
/// Requires layout of *e to match ErrorImpl<ContextError<D, Report>>.
unsafe fn context_chain_downcast_mut<D>(
e: MutPtr<'_, ErrorImpl<()>>,
target: TypeId,
) -> Option<NonNull<()>>
where
D: 'static,
{
let unerased = unsafe { e.cast::<ErrorImpl<ContextError<D, Report>>>().into_mut() };
if TypeId::of::<D>() == target {
let addr = NonNull::from(&unerased._object.msg).cast::<()>();
Some(addr)
} else {
// Recurse down the context chain per the inner error's vtable.
let source = &mut unerased._object.error;
unsafe { (source.vtable().object_downcast_mut)(source.inner.as_mut(), target) }
}
}
/// # Safety
///
/// Requires layout of *e to match ErrorImpl<ContextError<D, Report>>.
unsafe fn context_chain_drop_rest<D>(e: OwnedPtr<ErrorImpl<()>>, target: TypeId)
where
D: 'static,
{
// Called after downcasting by value to either the D or one of the causes
// and doing a ptr::read to take ownership of that value.
if TypeId::of::<D>() == target {
let unerased = unsafe {
e.cast::<ErrorImpl<ContextError<ManuallyDrop<D>, Report>>>()
.into_box()
};
// Drop the entire rest of the data structure rooted in the next Report.
drop(unerased);
} else {
unsafe {
let unerased = e
.cast::<ErrorImpl<ContextError<D, ManuallyDrop<Report>>>>()
.into_box();
// Read out a ManuallyDrop<Box<ErrorImpl<()>>> from the next error.
let inner = ptr::read(&unerased.as_ref()._object.error.inner);
drop(unerased);
// Recursively drop the next error using the same target typeid.
(header(inner.as_ref()).vtable.object_drop_rest)(inner, target);
}
}
}
#[repr(C)]
pub(crate) struct ErrorHeader {
vtable: &'static ErrorVTable,
pub(crate) handler: Option<Box<dyn EyreHandler>>,
}
// repr C to ensure that E remains in the final position.
#[repr(C)]
pub(crate) struct ErrorImpl<E = ()> {
header: ErrorHeader,
// NOTE: Don't use directly. Use only through vtable. Erased type may have
// different alignment.
_object: E,
}
// repr C to ensure that ContextError<D, E> has the same layout as
// ContextError<ManuallyDrop<D>, E> and ContextError<D, ManuallyDrop<E>>.
#[repr(C)]
pub(crate) struct ContextError<D, E> {
pub(crate) msg: D,
pub(crate) error: E,
}
impl<E> ErrorImpl<E> {
/// Returns a type erased Error
fn erase(&self) -> RefPtr<'_, ErrorImpl<()>> {
// 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.
RefPtr::new(self).cast()
}
}
// Reads the header out of `p`. This is the same as `p.as_ref().header`, but
// avoids converting `p` into a reference of a shrunk provenance with a type different than the
// allocation.
fn header(p: RefPtr<'_, ErrorImpl<()>>) -> &'_ ErrorHeader {
// Safety: `ErrorHeader` is the first field of repr(C) `ErrorImpl`
unsafe { p.cast().as_ref() }
}
fn header_mut(p: MutPtr<'_, ErrorImpl<()>>) -> &mut ErrorHeader {
// Safety: `ErrorHeader` is the first field of repr(C) `ErrorImpl`
unsafe { p.cast().into_mut() }
}
impl ErrorImpl<()> {
pub(crate) fn error(this: RefPtr<'_, Self>) -> &(dyn StdError + Send + Sync + 'static) {
// Use vtable to attach E's native StdError vtable for the right
// original type E.
unsafe { (header(this).vtable.object_ref)(this) }
}
pub(crate) fn error_mut(this: MutPtr<'_, Self>) -> &mut (dyn StdError + Send + Sync + 'static) {
// Use vtable to attach E's native StdError vtable for the right
// original type E.
unsafe { (header_mut(this).vtable.object_mut)(this) }
}
pub(crate) fn chain(this: RefPtr<'_, Self>) -> Chain<'_> {
Chain::new(Self::error(this))
}
pub(crate) fn header(this: RefPtr<'_, ErrorImpl>) -> &ErrorHeader {
header(this)
}
}
impl<E> StdError for ErrorImpl<E>
where
E: StdError,
{
fn source(&self) -> Option<&(dyn StdError + 'static)> {
ErrorImpl::<()>::error(self.erase()).source()
}
}
impl<E> Debug for ErrorImpl<E>
where
E: Debug,
{
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
ErrorImpl::debug(self.erase(), formatter)
}
}
impl<E> Display for ErrorImpl<E>
where
E: Display,
{
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(ErrorImpl::error(self.erase()), formatter)
}
}
impl From<Report> for Box<dyn StdError + Send + Sync + 'static> {
fn from(error: Report) -> Self {
let outer = ManuallyDrop::new(error);
unsafe {
// Read Box<ErrorImpl<()>> from error. Can't move it out because
// Report has a Drop impl which we want to not run.
// Use vtable to attach ErrorImpl<E>'s native StdError vtable for
// the right original type E.
(header(outer.inner.as_ref()).vtable.object_boxed)(outer.inner)
}
}
}
impl From<Report> for Box<dyn StdError + 'static> {
fn from(error: Report) -> Self {
Box::<dyn StdError + Send + Sync>::from(error)
}
}
impl AsRef<dyn StdError + Send + Sync> for Report {
fn as_ref(&self) -> &(dyn StdError + Send + Sync + 'static) {
&**self
}
}
impl AsRef<dyn StdError> for Report {
fn as_ref(&self) -> &(dyn StdError + 'static) {
&**self
}
}
#[cfg(feature = "pyo3")]
mod pyo3_compat;

View file

@ -0,0 +1,7 @@
use crate::Report;
impl From<Report> for pyo3::PyErr {
fn from(error: Report) -> Self {
pyo3::exceptions::PyRuntimeError::new_err(format!("{:?}", error))
}
}

21
third-party/vendor/eyre/src/fmt.rs vendored Normal file
View file

@ -0,0 +1,21 @@
use crate::{error::ErrorImpl, ptr::RefPtr};
use core::fmt;
impl ErrorImpl<()> {
pub(crate) fn display(this: RefPtr<'_, Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
ErrorImpl::header(this)
.handler
.as_ref()
.map(|handler| handler.display(Self::error(this), f))
.unwrap_or_else(|| core::fmt::Display::fmt(Self::error(this), f))
}
/// Debug formats the error using the captured handler
pub(crate) fn debug(this: RefPtr<'_, Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
ErrorImpl::header(this)
.handler
.as_ref()
.map(|handler| handler.debug(Self::error(this), f))
.unwrap_or_else(|| core::fmt::Debug::fmt(Self::error(this), f))
}
}

111
third-party/vendor/eyre/src/kind.rs vendored Normal file
View file

@ -0,0 +1,111 @@
#![allow(missing_debug_implementations, missing_docs)]
// Tagged dispatch mechanism for resolving the behavior of `eyre!($expr)`.
//
// When eyre! is given a single expr argument to turn into eyre::Report, we
// want the resulting Report to pick up the input's implementation of source()
// and backtrace() if it has a std::error::Error impl, otherwise require nothing
// more than Display and Debug.
//
// Expressed in terms of specialization, we want something like:
//
// trait EyreNew {
// fn new(self) -> Report;
// }
//
// impl<T> EyreNew for T
// where
// T: Display + Debug + Send + Sync + 'static,
// {
// default fn new(self) -> Report {
// /* no std error impl */
// }
// }
//
// impl<T> EyreNew for T
// where
// T: std::error::Error + Send + Sync + 'static,
// {
// fn new(self) -> Report {
// /* use std error's source() and backtrace() */
// }
// }
//
// Since specialization is not stable yet, instead we rely on autoref behavior
// of method resolution to perform tagged dispatch. Here we have two traits
// AdhocKind and TraitKind that both have an eyre_kind() method. AdhocKind is
// implemented whether or not the caller's type has a std error impl, while
// TraitKind is implemented only when a std error impl does exist. The ambiguity
// is resolved by AdhocKind requiring an extra autoref so that it has lower
// precedence.
//
// The eyre! macro will set up the call in this form:
//
// #[allow(unused_imports)]
// use $crate::private::{AdhocKind, TraitKind};
// let error = $msg;
// (&error).eyre_kind().new(error)
use crate::Report;
use core::fmt::{Debug, Display};
use crate::StdError;
pub struct Adhoc;
pub trait AdhocKind: Sized {
#[inline]
fn eyre_kind(&self) -> Adhoc {
Adhoc
}
}
impl<T> AdhocKind for &T where T: ?Sized + Display + Debug + Send + Sync + 'static {}
impl Adhoc {
#[cfg_attr(track_caller, track_caller)]
pub fn new<M>(self, message: M) -> Report
where
M: Display + Debug + Send + Sync + 'static,
{
Report::from_adhoc(message)
}
}
pub struct Trait;
pub trait TraitKind: Sized {
#[inline]
fn eyre_kind(&self) -> Trait {
Trait
}
}
impl<E> TraitKind for E where E: Into<Report> {}
impl Trait {
#[cfg_attr(track_caller, track_caller)]
pub fn new<E>(self, error: E) -> Report
where
E: Into<Report>,
{
error.into()
}
}
pub struct Boxed;
pub trait BoxedKind: Sized {
#[inline]
fn eyre_kind(&self) -> Boxed {
Boxed
}
}
impl BoxedKind for Box<dyn StdError + Send + Sync> {}
impl Boxed {
#[cfg_attr(track_caller, track_caller)]
pub fn new(self, error: Box<dyn StdError + Send + Sync>) -> Report {
Report::from_boxed(error)
}
}

1322
third-party/vendor/eyre/src/lib.rs vendored Normal file

File diff suppressed because it is too large Load diff

170
third-party/vendor/eyre/src/macros.rs vendored Normal file
View file

@ -0,0 +1,170 @@
/// Return early with an error.
///
/// This macro is equivalent to `return Err(eyre!(<args>))`.
///
/// # Example
///
/// ```
/// # use eyre::{bail, Result};
/// #
/// # fn has_permission(user: usize, resource: usize) -> bool {
/// # true
/// # }
/// #
/// # fn main() -> Result<()> {
/// # let user = 0;
/// # let resource = 0;
/// #
/// if !has_permission(user, resource) {
/// bail!("permission denied for accessing {}", resource);
/// }
/// # Ok(())
/// # }
/// ```
///
/// ```
/// # use eyre::{bail, Result};
/// # use thiserror::Error;
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// #[derive(Error, Debug)]
/// enum ScienceError {
/// #[error("recursion limit exceeded")]
/// RecursionLimitExceeded,
/// # #[error("...")]
/// # More = (stringify! {
/// ...
/// # }, 1).1,
/// }
///
/// # fn main() -> Result<()> {
/// # let depth = 0;
/// # let err: &'static dyn std::error::Error = &ScienceError::RecursionLimitExceeded;
/// #
/// if depth > MAX_DEPTH {
/// bail!(ScienceError::RecursionLimitExceeded);
/// }
/// # Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! bail {
($msg:literal $(,)?) => {
return $crate::private::Err($crate::eyre!($msg));
};
($err:expr $(,)?) => {
return $crate::private::Err($crate::eyre!($err));
};
($fmt:expr, $($arg:tt)*) => {
return $crate::private::Err($crate::eyre!($fmt, $($arg)*));
};
}
/// Return early with an error if a condition is not satisfied.
///
/// This macro is equivalent to `if !$cond { return Err(eyre!(<other args>)); }`.
///
/// Analogously to `assert!`, `ensure!` takes a condition and exits the function
/// if the condition fails. Unlike `assert!`, `ensure!` returns an `eyre::Result`
/// rather than panicking.
///
/// # Example
///
/// ```
/// # use eyre::{ensure, Result};
/// #
/// # fn main() -> Result<()> {
/// # let user = 0;
/// #
/// ensure!(user == 0, "only user 0 is allowed");
/// # Ok(())
/// # }
/// ```
///
/// ```
/// # use eyre::{ensure, Result};
/// # use thiserror::Error;
/// #
/// # const MAX_DEPTH: usize = 1;
/// #
/// #[derive(Error, Debug)]
/// enum ScienceError {
/// #[error("recursion limit exceeded")]
/// RecursionLimitExceeded,
/// # #[error("...")]
/// # More = (stringify! {
/// ...
/// # }, 1).1,
/// }
///
/// # fn main() -> Result<()> {
/// # let depth = 0;
/// #
/// ensure!(depth <= MAX_DEPTH, ScienceError::RecursionLimitExceeded);
/// # Ok(())
/// # }
/// ```
#[macro_export]
macro_rules! ensure {
($cond:expr $(,)?) => {
if !$cond {
$crate::ensure!($cond, concat!("Condition failed: `", stringify!($cond), "`"))
}
};
($cond:expr, $msg:literal $(,)?) => {
if !$cond {
return $crate::private::Err($crate::eyre!($msg));
}
};
($cond:expr, $err:expr $(,)?) => {
if !$cond {
return $crate::private::Err($crate::eyre!($err));
}
};
($cond:expr, $fmt:expr, $($arg:tt)*) => {
if !$cond {
return $crate::private::Err($crate::eyre!($fmt, $($arg)*));
}
};
}
/// Construct an ad-hoc error from a string.
///
/// This evaluates to a `Report`. 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`.
///
/// # Example
///
/// ```
/// # type V = ();
/// #
/// use eyre::{eyre, Result};
///
/// fn lookup(key: &str) -> Result<V> {
/// if key.len() != 16 {
/// return Err(eyre!("key length must be 16 characters, got {:?}", key));
/// }
///
/// // ...
/// # Ok(())
/// }
/// ```
#[macro_export]
macro_rules! eyre {
($msg:literal $(,)?) => ({
let error = $crate::private::format_err($crate::private::format_args!($msg));
error
});
($err:expr $(,)?) => ({
use $crate::private::kind::*;
let error = match $err {
error => (&error).eyre_kind().new(error),
};
error
});
($fmt:expr, $($arg:tt)*) => {
$crate::private::new_adhoc($crate::private::format!($fmt, $($arg)*))
};
}

15
third-party/vendor/eyre/src/option.rs vendored Normal file
View file

@ -0,0 +1,15 @@
use crate::OptionExt;
use core::fmt::{Debug, Display};
impl<T> OptionExt<T> for Option<T> {
#[track_caller]
fn ok_or_eyre<M>(self, message: M) -> crate::Result<T>
where
M: Debug + Display + Send + Sync + 'static,
{
match self {
Some(ok) => Ok(ok),
None => Err(crate::Report::msg(message)),
}
}
}

149
third-party/vendor/eyre/src/ptr.rs vendored Normal file
View file

@ -0,0 +1,149 @@
use std::{marker::PhantomData, ptr::NonNull};
/// An owned pointer
///
/// **NOTE**: Does not deallocate when dropped
pub(crate) struct OwnedPtr<T: ?Sized> {
ptr: NonNull<T>,
}
impl<T: ?Sized> Copy for OwnedPtr<T> {}
impl<T: ?Sized> Clone for OwnedPtr<T> {
fn clone(&self) -> Self {
*self
}
}
unsafe impl<T> Send for OwnedPtr<T> where T: Send {}
unsafe impl<T> Sync for OwnedPtr<T> where T: Send {}
impl<T> OwnedPtr<T> {
pub(crate) fn new(value: T) -> Self {
Self::from_boxed(Box::new(value))
}
pub(crate) fn from_boxed(boxed: Box<T>) -> Self {
// Safety: `Box::into_raw` is guaranteed to be non-null
Self {
ptr: unsafe { NonNull::new_unchecked(Box::into_raw(boxed)) },
}
}
/// Convert the pointer to another type
pub(crate) fn cast<U>(self) -> OwnedPtr<U> {
OwnedPtr {
ptr: self.ptr.cast(),
}
}
/// Context the pointer into a Box
///
/// # Safety
///
/// Dropping the Box will deallocate a layout of `T` and run the destructor of `T`.
///
/// A cast pointer must therefore be cast back to the original type before calling this method.
pub(crate) unsafe fn into_box(self) -> Box<T> {
unsafe { Box::from_raw(self.ptr.as_ptr()) }
}
pub(crate) const fn as_ref(&self) -> RefPtr<'_, T> {
RefPtr {
ptr: self.ptr,
_marker: PhantomData,
}
}
pub(crate) fn as_mut(&mut self) -> MutPtr<'_, T> {
MutPtr {
ptr: self.ptr,
_marker: PhantomData,
}
}
}
/// Convenience lifetime annotated mutable pointer which facilitates returning an inferred lifetime
/// in a `fn` pointer.
pub(crate) struct RefPtr<'a, T: ?Sized> {
pub(crate) ptr: NonNull<T>,
_marker: PhantomData<&'a T>,
}
/// Safety: RefPtr indicates a shared reference to a value and as such exhibits the same Send +
/// Sync behavior of &'a T
unsafe impl<'a, T: ?Sized> Send for RefPtr<'a, T> where &'a T: Send {}
unsafe impl<'a, T: ?Sized> Sync for RefPtr<'a, T> where &'a T: Sync {}
impl<'a, T: ?Sized> Copy for RefPtr<'a, T> {}
impl<'a, T: ?Sized> Clone for RefPtr<'a, T> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, T: ?Sized> RefPtr<'a, T> {
pub(crate) fn new(ptr: &'a T) -> Self {
Self {
ptr: NonNull::from(ptr),
_marker: PhantomData,
}
}
/// Convert the pointer to another type
pub(crate) fn cast<U>(self) -> RefPtr<'a, U> {
RefPtr {
ptr: self.ptr.cast(),
_marker: PhantomData,
}
}
/// Returns a shared reference to the owned value
///
/// # Safety
///
/// See: [`NonNull::as_ref`]
#[inline]
pub(crate) unsafe fn as_ref(&self) -> &'a T {
unsafe { self.ptr.as_ref() }
}
}
/// Convenience lifetime annotated mutable pointer which facilitates returning an inferred lifetime
/// in a `fn` pointer.
pub(crate) struct MutPtr<'a, T: ?Sized> {
pub(crate) ptr: NonNull<T>,
_marker: PhantomData<&'a mut T>,
}
/// Safety: RefPtr indicates an exclusive reference to a value and as such exhibits the same Send +
/// Sync behavior of &'a mut T
unsafe impl<'a, T: ?Sized> Send for MutPtr<'a, T> where &'a mut T: Send {}
unsafe impl<'a, T: ?Sized> Sync for MutPtr<'a, T> where &'a mut T: Sync {}
impl<'a, T: ?Sized> Copy for MutPtr<'a, T> {}
impl<'a, T: ?Sized> Clone for MutPtr<'a, T> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, T: ?Sized> MutPtr<'a, T> {
/// Convert the pointer to another type
pub(crate) fn cast<U>(self) -> MutPtr<'a, U> {
MutPtr {
ptr: self.ptr.cast(),
_marker: PhantomData,
}
}
/// Returns a mutable reference to the owned value with the lifetime decoupled from self
///
/// # Safety
///
/// See: [`NonNull::as_mut`]
#[inline]
pub(crate) unsafe fn into_mut(mut self) -> &'a mut T {
unsafe { self.ptr.as_mut() }
}
}

93
third-party/vendor/eyre/src/wrapper.rs vendored Normal file
View file

@ -0,0 +1,93 @@
use crate::StdError;
use core::fmt::{self, Debug, Display};
#[repr(transparent)]
pub(crate) struct DisplayError<M>(pub(crate) M);
#[repr(transparent)]
/// Wraps a Debug + Display type as an error.
///
/// Its Debug and Display impls are the same as the wrapped type.
pub(crate) struct MessageError<M>(pub(crate) M);
pub(crate) struct NoneError;
impl<M> Debug for DisplayError<M>
where
M: Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.0, f)
}
}
impl<M> Display for DisplayError<M>
where
M: Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.0, f)
}
}
impl<M> StdError for DisplayError<M> where M: Display + 'static {}
impl<M> Debug for MessageError<M>
where
M: Display + Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.0, f)
}
}
impl<M> Display for MessageError<M>
where
M: Display + Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.0, f)
}
}
impl<M> StdError for MessageError<M> where M: Display + Debug + 'static {}
impl Debug for NoneError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt("Option was None", f)
}
}
impl Display for NoneError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt("Option was None", f)
}
}
impl StdError for NoneError {}
#[repr(transparent)]
pub(crate) struct BoxedError(pub(crate) Box<dyn StdError + Send + Sync>);
impl Debug for BoxedError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Debug::fmt(&self.0, f)
}
}
impl Display for BoxedError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.0, f)
}
}
impl StdError for BoxedError {
#[cfg(backtrace)]
fn backtrace(&self) -> Option<&crate::backtrace::Backtrace> {
self.0.backtrace()
}
fn source(&self) -> Option<&(dyn StdError + 'static)> {
self.0.source()
}
}

View file

@ -0,0 +1,29 @@
#![allow(dead_code)]
use eyre::{bail, set_hook, DefaultHandler, InstallError, Result};
use once_cell::sync::OnceCell;
use std::io;
pub fn bail_literal() -> Result<()> {
bail!("oh no!");
}
pub fn bail_fmt() -> Result<()> {
bail!("{} {}!", "oh", "no");
}
pub fn bail_error() -> Result<()> {
bail!(io::Error::new(io::ErrorKind::Other, "oh no!"));
}
// Tests are multithreaded- use OnceCell to install hook once if auto-install
// feature is disabled.
pub fn maybe_install_handler() -> Result<(), InstallError> {
static INSTALLER: OnceCell<Result<(), InstallError>> = OnceCell::new();
if cfg!(not(feature = "auto-install")) {
*INSTALLER.get_or_init(|| set_hook(Box::new(DefaultHandler::default_with)))
} else {
Ok(())
}
}

View file

@ -0,0 +1,7 @@
#[rustversion::attr(not(nightly), ignore)]
#[cfg_attr(miri, ignore)]
#[test]
fn ui() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/ui/*.rs");
}

View file

@ -0,0 +1,55 @@
use std::error::Error as StdError;
use std::fmt::{self, Display};
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering::SeqCst;
use std::sync::Arc;
#[derive(Debug)]
pub struct Flag {
atomic: Arc<AtomicBool>,
}
impl Flag {
pub fn new() -> Self {
Flag {
atomic: Arc::new(AtomicBool::new(false)),
}
}
pub fn get(&self) -> bool {
self.atomic.load(SeqCst)
}
}
#[derive(Debug)]
pub struct DetectDrop {
has_dropped: Flag,
label: &'static str,
}
impl DetectDrop {
pub fn new(label: &'static str, has_dropped: &Flag) -> Self {
DetectDrop {
label,
has_dropped: Flag {
atomic: Arc::clone(&has_dropped.atomic),
},
}
}
}
impl StdError for DetectDrop {}
impl Display for DetectDrop {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "oh no!")
}
}
impl Drop for DetectDrop {
fn drop(&mut self) {
eprintln!("Dropping {}", self.label);
let already_dropped = self.has_dropped.atomic.swap(true, SeqCst);
assert!(!already_dropped);
}
}

View file

@ -0,0 +1,13 @@
use eyre::Report;
#[test]
fn test_send() {
fn assert_send<T: Send>() {}
assert_send::<Report>();
}
#[test]
fn test_sync() {
fn assert_sync<T: Sync>() {}
assert_sync::<Report>();
}

View file

@ -0,0 +1,66 @@
mod common;
use self::common::maybe_install_handler;
use eyre::{eyre, Report};
use std::error::Error as StdError;
use std::io;
use thiserror::Error;
#[derive(Error, Debug)]
#[error("outer")]
struct MyError {
source: io::Error,
}
#[test]
fn test_boxed_str() {
maybe_install_handler().unwrap();
let error = Box::<dyn StdError + Send + Sync>::from("oh no!");
let error: Report = eyre!(error);
assert_eq!("oh no!", error.to_string());
assert_eq!(
"oh no!",
error
.downcast_ref::<Box<dyn StdError + Send + Sync>>()
.unwrap()
.to_string()
);
}
#[test]
fn test_boxed_thiserror() {
maybe_install_handler().unwrap();
let error = MyError {
source: io::Error::new(io::ErrorKind::Other, "oh no!"),
};
let error: Report = eyre!(error);
assert_eq!("oh no!", error.source().unwrap().to_string());
}
#[test]
fn test_boxed_eyre() {
maybe_install_handler().unwrap();
let error: Report = eyre!("oh no!").wrap_err("it failed");
let error = eyre!(error);
assert_eq!("oh no!", error.source().unwrap().to_string());
}
#[test]
fn test_boxed_sources() {
maybe_install_handler().unwrap();
let error = MyError {
source: io::Error::new(io::ErrorKind::Other, "oh no!"),
};
let error = Box::<dyn StdError + Send + Sync>::from(error);
let error: Report = eyre!(error).wrap_err("it failed");
assert_eq!("it failed", error.to_string());
assert_eq!("outer", error.source().unwrap().to_string());
assert_eq!(
"oh no!",
error.source().unwrap().source().unwrap().to_string()
);
}

View file

@ -0,0 +1,54 @@
mod common;
use self::common::maybe_install_handler;
use eyre::{eyre, Report};
fn error() -> Report {
eyre!({ 0 }).wrap_err(1).wrap_err(2).wrap_err(3)
}
#[test]
fn test_iter() {
maybe_install_handler().unwrap();
let e = error();
let mut chain = e.chain();
assert_eq!("3", chain.next().unwrap().to_string());
assert_eq!("2", chain.next().unwrap().to_string());
assert_eq!("1", chain.next().unwrap().to_string());
assert_eq!("0", chain.next().unwrap().to_string());
assert!(chain.next().is_none());
assert!(chain.next_back().is_none());
}
#[test]
fn test_rev() {
maybe_install_handler().unwrap();
let e = error();
let mut chain = e.chain().rev();
assert_eq!("0", chain.next().unwrap().to_string());
assert_eq!("1", chain.next().unwrap().to_string());
assert_eq!("2", chain.next().unwrap().to_string());
assert_eq!("3", chain.next().unwrap().to_string());
assert!(chain.next().is_none());
assert!(chain.next_back().is_none());
}
#[test]
fn test_len() {
maybe_install_handler().unwrap();
let e = error();
let mut chain = e.chain();
assert_eq!(4, chain.len());
assert_eq!("3", chain.next().unwrap().to_string());
assert_eq!(3, chain.len());
assert_eq!("0", chain.next_back().unwrap().to_string());
assert_eq!(2, chain.len());
assert_eq!("2", chain.next().unwrap().to_string());
assert_eq!(1, chain.len());
assert_eq!("1", chain.next_back().unwrap().to_string());
assert_eq!(0, chain.len());
assert!(chain.next().is_none());
}

View file

@ -0,0 +1,173 @@
mod common;
mod drop;
use crate::common::maybe_install_handler;
use crate::drop::{DetectDrop, Flag};
use eyre::{Report, Result, WrapErr};
use std::fmt::{self, Display};
use thiserror::Error;
// https://github.com/dtolnay/eyre/issues/18
#[test]
fn test_inference() -> Result<()> {
let x = "1";
let y: u32 = x.parse().wrap_err("...")?;
assert_eq!(y, 1);
Ok(())
}
macro_rules! context_type {
($name:ident) => {
#[derive(Debug)]
#[repr(C)]
struct $name {
_drop: DetectDrop,
message: &'static str,
}
impl Display for $name {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(self.message)
}
}
};
}
context_type!(HighLevel);
context_type!(MidLevel);
#[derive(Error, Debug)]
#[error("{message}")]
#[repr(C)]
struct LowLevel {
message: &'static str,
drop: DetectDrop,
}
struct Dropped {
low: Flag,
mid: Flag,
high: Flag,
}
impl Dropped {
fn none(&self) -> bool {
!self.low.get() && !self.mid.get() && !self.high.get()
}
fn all(&self) -> bool {
self.low.get() && self.mid.get() && self.high.get()
}
}
fn make_chain() -> (Report, Dropped) {
let dropped = Dropped {
low: Flag::new(),
mid: Flag::new(),
high: Flag::new(),
};
let low = LowLevel {
message: "no such file or directory",
drop: DetectDrop::new("LowLevel", &dropped.low),
};
// impl Report for Result<T, E>
let mid = Err::<(), LowLevel>(low)
.wrap_err(MidLevel {
message: "failed to load config",
_drop: DetectDrop::new("MidLevel", &dropped.mid),
})
.unwrap_err();
// impl Report for Result<T, Error>
let high = Err::<(), Report>(mid)
.wrap_err(HighLevel {
message: "failed to start server",
_drop: DetectDrop::new("HighLevel", &dropped.high),
})
.unwrap_err();
(high, dropped)
}
#[test]
fn test_downcast_ref() {
maybe_install_handler().unwrap();
let (err, dropped) = make_chain();
assert!(!err.is::<String>());
assert!(err.downcast_ref::<String>().is_none());
assert!(err.is::<HighLevel>());
let high = err.downcast_ref::<HighLevel>().unwrap();
assert_eq!(high.to_string(), "failed to start server");
assert!(err.is::<MidLevel>());
let mid = err.downcast_ref::<MidLevel>().unwrap();
assert_eq!(mid.to_string(), "failed to load config");
assert!(err.is::<LowLevel>());
let low = err.downcast_ref::<LowLevel>().unwrap();
assert_eq!(low.to_string(), "no such file or directory");
assert!(dropped.none());
drop(err);
assert!(dropped.all());
}
#[test]
fn test_downcast_high() {
maybe_install_handler().unwrap();
let (err, dropped) = make_chain();
let err = err.downcast::<HighLevel>().unwrap();
assert!(!dropped.high.get());
assert!(dropped.low.get() && dropped.mid.get());
drop(err);
assert!(dropped.all());
}
#[test]
fn test_downcast_mid() {
maybe_install_handler().unwrap();
let (err, dropped) = make_chain();
let err = err.downcast::<MidLevel>().unwrap();
assert!(!dropped.mid.get());
assert!(dropped.low.get() && dropped.high.get());
drop(err);
assert!(dropped.all());
}
#[test]
fn test_downcast_low() {
maybe_install_handler().unwrap();
let (err, dropped) = make_chain();
let err = err.downcast::<LowLevel>().unwrap();
assert!(!dropped.low.get());
assert!(dropped.mid.get() && dropped.high.get());
drop(err);
assert!(dropped.all());
}
#[test]
fn test_unsuccessful_downcast() {
maybe_install_handler().unwrap();
let (err, dropped) = make_chain();
let err = err.downcast::<String>().unwrap_err();
assert!(dropped.none());
drop(err);
assert!(dropped.all());
}

View file

@ -0,0 +1,13 @@
mod common;
use crate::common::maybe_install_handler;
#[test]
fn test_context() {
use eyre::{eyre, Report};
maybe_install_handler().unwrap();
let error: Report = eyre!("oh no!");
let _ = error.context();
}

View file

@ -0,0 +1,28 @@
mod common;
mod drop;
use self::common::maybe_install_handler;
use self::drop::{DetectDrop, Flag};
use eyre::{Report, Result};
use std::error::Error as StdError;
#[test]
fn test_convert() {
maybe_install_handler().unwrap();
let has_dropped = Flag::new();
let error: Report = Report::new(DetectDrop::new("TestConvert", &has_dropped));
let box_dyn = Box::<dyn StdError + Send + Sync>::from(error);
assert_eq!("oh no!", box_dyn.to_string());
drop(box_dyn);
assert!(has_dropped.get());
}
#[test]
fn test_question_mark() -> Result<(), Box<dyn StdError>> {
fn f() -> Result<()> {
Ok(())
}
f()?;
Ok(())
}

View file

@ -0,0 +1,148 @@
mod common;
mod drop;
use self::common::*;
use self::drop::{DetectDrop, Flag};
use eyre::Report;
use std::error::Error as StdError;
use std::fmt::{self, Display};
use std::io;
#[test]
fn test_downcast() {
maybe_install_handler().unwrap();
#[cfg(not(eyre_no_fmt_arguments_as_str))]
assert_eq!(
"oh no!",
bail_literal().unwrap_err().downcast::<&str>().unwrap(),
);
#[cfg(eyre_no_fmt_arguments_as_str)]
assert_eq!(
"oh no!",
bail_literal().unwrap_err().downcast::<String>().unwrap(),
);
assert_eq!(
"oh no!",
bail_fmt().unwrap_err().downcast::<String>().unwrap(),
);
assert_eq!(
"oh no!",
bail_error()
.unwrap_err()
.downcast::<io::Error>()
.unwrap()
.to_string(),
);
}
#[test]
fn test_downcast_ref() {
maybe_install_handler().unwrap();
#[cfg(not(eyre_no_fmt_arguments_as_str))]
assert_eq!(
"oh no!",
*bail_literal().unwrap_err().downcast_ref::<&str>().unwrap(),
);
#[cfg(eyre_no_fmt_arguments_as_str)]
assert_eq!(
"oh no!",
*bail_literal()
.unwrap_err()
.downcast_ref::<String>()
.unwrap(),
);
assert_eq!(
"oh no!",
bail_fmt().unwrap_err().downcast_ref::<String>().unwrap(),
);
assert_eq!(
"oh no!",
bail_error()
.unwrap_err()
.downcast_ref::<io::Error>()
.unwrap()
.to_string(),
);
}
#[test]
fn test_downcast_mut() {
maybe_install_handler().unwrap();
#[cfg(not(eyre_no_fmt_arguments_as_str))]
assert_eq!(
"oh no!",
*bail_literal().unwrap_err().downcast_mut::<&str>().unwrap(),
);
#[cfg(eyre_no_fmt_arguments_as_str)]
assert_eq!(
"oh no!",
*bail_literal()
.unwrap_err()
.downcast_mut::<String>()
.unwrap(),
);
assert_eq!(
"oh no!",
bail_fmt().unwrap_err().downcast_mut::<String>().unwrap(),
);
assert_eq!(
"oh no!",
bail_error()
.unwrap_err()
.downcast_mut::<io::Error>()
.unwrap()
.to_string(),
);
}
#[test]
fn test_drop() {
maybe_install_handler().unwrap();
let has_dropped = Flag::new();
let error: Report = Report::new(DetectDrop::new("DetectDrop", &has_dropped));
drop(error.downcast::<DetectDrop>().unwrap());
assert!(has_dropped.get());
}
#[test]
fn test_large_alignment() {
maybe_install_handler().unwrap();
#[repr(align(64))]
#[derive(Debug)]
struct LargeAlignedError(&'static str);
impl Display for LargeAlignedError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(self.0)
}
}
impl StdError for LargeAlignedError {}
let error = Report::new(LargeAlignedError("oh no!"));
assert_eq!(
"oh no!",
error.downcast_ref::<LargeAlignedError>().unwrap().0
);
}
#[test]
fn test_unsuccessful_downcast() {
maybe_install_handler().unwrap();
let mut error = bail_error().unwrap_err();
assert!(error.downcast_ref::<&str>().is_none());
assert!(error.downcast_mut::<&str>().is_none());
assert!(error.downcast::<&str>().is_err());
}

View file

@ -0,0 +1,105 @@
mod common;
use self::common::maybe_install_handler;
use eyre::{bail, Result, WrapErr};
use std::io;
fn f() -> Result<()> {
bail!(io::Error::new(io::ErrorKind::PermissionDenied, "oh no!"));
}
fn g() -> Result<()> {
f().wrap_err("f failed")
}
fn h() -> Result<()> {
g().wrap_err("g failed")
}
const EXPECTED_ALTDISPLAY_F: &str = "oh no!";
const EXPECTED_ALTDISPLAY_G: &str = "f failed: oh no!";
const EXPECTED_ALTDISPLAY_H: &str = "g failed: f failed: oh no!";
const EXPECTED_DEBUG_F: &str = "oh no!";
const EXPECTED_DEBUG_G: &str = "\
f failed
Caused by:
oh no!\
";
const EXPECTED_DEBUG_H: &str = "\
g failed
Caused by:
0: f failed
1: oh no!\
";
const EXPECTED_ALTDEBUG_F: &str = "\
Custom {
kind: PermissionDenied,
error: \"oh no!\",
}\
";
const EXPECTED_ALTDEBUG_G: &str = "\
Error {
msg: \"f failed\",
source: Custom {
kind: PermissionDenied,
error: \"oh no!\",
},
}\
";
const EXPECTED_ALTDEBUG_H: &str = "\
Error {
msg: \"g failed\",
source: Error {
msg: \"f failed\",
source: Custom {
kind: PermissionDenied,
error: \"oh no!\",
},
},
}\
";
#[test]
fn test_display() {
maybe_install_handler().unwrap();
assert_eq!("g failed", h().unwrap_err().to_string());
}
#[test]
fn test_altdisplay() {
maybe_install_handler().unwrap();
assert_eq!(EXPECTED_ALTDISPLAY_F, format!("{:#}", f().unwrap_err()));
assert_eq!(EXPECTED_ALTDISPLAY_G, format!("{:#}", g().unwrap_err()));
assert_eq!(EXPECTED_ALTDISPLAY_H, format!("{:#}", h().unwrap_err()));
}
#[test]
#[cfg_attr(any(backtrace, track_caller), ignore)]
fn test_debug() {
maybe_install_handler().unwrap();
assert_eq!(EXPECTED_DEBUG_F, format!("{:?}", f().unwrap_err()));
assert_eq!(EXPECTED_DEBUG_G, format!("{:?}", g().unwrap_err()));
assert_eq!(EXPECTED_DEBUG_H, format!("{:?}", h().unwrap_err()));
}
#[test]
fn test_altdebug() {
maybe_install_handler().unwrap();
assert_eq!(EXPECTED_ALTDEBUG_F, format!("{:#?}", f().unwrap_err()));
assert_eq!(EXPECTED_ALTDEBUG_G, format!("{:#?}", g().unwrap_err()));
assert_eq!(EXPECTED_ALTDEBUG_H, format!("{:#?}", h().unwrap_err()));
}

View file

@ -0,0 +1,183 @@
use std::panic::Location;
use eyre::{OptionExt as _, WrapErr};
struct LocationHandler {
actual: Option<&'static str>,
expected: &'static str,
}
impl LocationHandler {
fn new(expected: &'static str) -> Self {
LocationHandler {
actual: None,
expected,
}
}
}
impl eyre::EyreHandler for LocationHandler {
fn debug(
&self,
_error: &(dyn std::error::Error + 'static),
_f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
// we assume that if the compiler is new enough to support
// `track_caller` that we will always have `actual` be `Some`, so we can
// safely skip the assertion if the location is `None` which should only
// happen in older rust versions.
if let Some(actual) = self.actual {
assert_eq!(self.expected, actual);
}
Ok(())
}
fn track_caller(&mut self, location: &'static Location<'static>) {
dbg!(location);
self.actual = Some(location.file());
}
}
#[test]
fn test_wrap_err() {
let _ = eyre::set_hook(Box::new(|_e| {
let expected_location = file!();
Box::new(LocationHandler::new(expected_location))
}));
let err = read_path("totally_fake_path")
.wrap_err("oopsie")
.unwrap_err();
// should panic if the location isn't in our crate
println!("{:?}", err);
}
#[cfg(not(miri))]
fn read_path(path: &str) -> Result<String, std::io::Error> {
std::fs::read_to_string(path)
}
#[cfg(miri)]
fn read_path(_path: &str) -> Result<String, std::io::Error> {
// Miri doesn't support reading files, so we just return an error
Err(std::io::Error::new(
std::io::ErrorKind::Other,
"Miri doesn't support reading files",
))
}
#[test]
fn test_wrap_err_with() {
let _ = eyre::set_hook(Box::new(|_e| {
let expected_location = file!();
Box::new(LocationHandler::new(expected_location))
}));
let err = read_path("totally_fake_path")
.wrap_err_with(|| "oopsie")
.unwrap_err();
// should panic if the location isn't in our crate
println!("{:?}", err);
}
#[test]
fn test_option_ok_or_eyre() {
let _ = eyre::set_hook(Box::new(|_e| {
let expected_location = file!();
Box::new(LocationHandler::new(expected_location))
}));
let err = None::<()>.ok_or_eyre("oopsie").unwrap_err();
// should panic if the location isn't in our crate
println!("{:?}", err);
}
#[test]
fn test_context() {
let _ = eyre::set_hook(Box::new(|_e| {
let expected_location = file!();
Box::new(LocationHandler::new(expected_location))
}));
let err = read_path("totally_fake_path")
.context("oopsie")
.unwrap_err();
// should panic if the location isn't in our crate
println!("{:?}", err);
}
#[test]
fn test_with_context() {
let _ = eyre::set_hook(Box::new(|_e| {
let expected_location = file!();
Box::new(LocationHandler::new(expected_location))
}));
let err = read_path("totally_fake_path")
.with_context(|| "oopsie")
.unwrap_err();
// should panic if the location isn't in our crate
println!("{:?}", err);
}
#[test]
fn test_option_compat_wrap_err() {
let _ = eyre::set_hook(Box::new(|_e| {
let expected_location = file!();
Box::new(LocationHandler::new(expected_location))
}));
use eyre::ContextCompat;
let err = None::<()>.wrap_err("oopsie").unwrap_err();
// should panic if the location isn't in our crate
println!("{:?}", err);
}
#[test]
fn test_option_compat_wrap_err_with() {
let _ = eyre::set_hook(Box::new(|_e| {
let expected_location = file!();
Box::new(LocationHandler::new(expected_location))
}));
use eyre::ContextCompat;
let err = None::<()>.wrap_err_with(|| "oopsie").unwrap_err();
// should panic if the location isn't in our crate
println!("{:?}", err);
}
#[test]
fn test_option_compat_context() {
let _ = eyre::set_hook(Box::new(|_e| {
let expected_location = file!();
Box::new(LocationHandler::new(expected_location))
}));
use eyre::ContextCompat;
let err = None::<()>.context("oopsie").unwrap_err();
// should panic if the location isn't in our crate
println!("{:?}", err);
}
#[test]
fn test_option_compat_with_context() {
let _ = eyre::set_hook(Box::new(|_e| {
let expected_location = file!();
Box::new(LocationHandler::new(expected_location))
}));
use eyre::ContextCompat;
let err = None::<()>.with_context(|| "oopsie").unwrap_err();
// should panic if the location isn't in our crate
println!("{:?}", err);
}

View file

@ -0,0 +1,102 @@
#![allow(clippy::eq_op)]
mod common;
use self::common::*;
use eyre::{ensure, eyre, Result};
use std::cell::Cell;
use std::future::Future;
use std::pin::Pin;
use std::task::Poll;
#[test]
fn test_messages() {
maybe_install_handler().unwrap();
assert_eq!("oh no!", bail_literal().unwrap_err().to_string());
assert_eq!("oh no!", bail_fmt().unwrap_err().to_string());
assert_eq!("oh no!", bail_error().unwrap_err().to_string());
}
#[test]
fn test_ensure() {
maybe_install_handler().unwrap();
let f = || -> Result<()> {
ensure!(1 + 1 == 2, "This is correct");
Ok(())
};
assert!(f().is_ok());
let v = 1;
let f = || -> Result<()> {
ensure!(v + v == 2, "This is correct, v: {}", v);
Ok(())
};
assert!(f().is_ok());
let f = || -> Result<()> {
ensure!(v + v == 1, "This is not correct, v: {}", v);
Ok(())
};
assert!(f().is_err());
let f = || {
ensure!(v + v == 1);
Ok(())
};
assert_eq!(
f().unwrap_err().to_string(),
"Condition failed: `v + v == 1`",
);
}
#[test]
fn test_temporaries() {
struct Ready<T>(Option<T>);
impl<T> Unpin for Ready<T> {}
impl<T> Future for Ready<T> {
type Output = T;
fn poll(mut self: Pin<&mut Self>, _cx: &mut std::task::Context<'_>) -> Poll<T> {
Poll::Ready(self.0.take().unwrap())
}
}
fn require_send_sync(_: impl Send + Sync) {}
require_send_sync(async {
// If eyre hasn't dropped any temporary format_args it creates by the
// time it's done evaluating, those will stick around until the
// semicolon, which is on the other side of the await point, making the
// enclosing future non-Send.
let _ = Ready(Some(eyre!("..."))).await;
});
fn message(cell: Cell<&str>) -> &str {
cell.get()
}
require_send_sync(async {
let _ = Ready(Some(eyre!(message(Cell::new("..."))))).await;
});
}
#[test]
#[cfg(not(eyre_no_fmt_args_capture))]
fn test_capture_format_args() {
maybe_install_handler().unwrap();
let var = 42;
let err = eyre!("interpolate {var}");
assert_eq!("interpolate 42", err.to_string());
}
#[test]
fn test_brace_escape() {
maybe_install_handler().unwrap();
let err = eyre!("unterminated ${{..}} expression");
assert_eq!("unterminated ${..} expression", err.to_string());
}

View file

@ -0,0 +1,18 @@
#![cfg(not(feature = "auto-install"))]
use eyre::{eyre, set_hook, DefaultHandler, Report};
#[test]
fn test_no_hook_panic() {
let panic_res = std::panic::catch_unwind(|| eyre!("this will never be displayed"));
assert!(panic_res.is_err());
let downcast_res = panic_res.unwrap_err().downcast::<String>();
assert_eq!(
*downcast_res.unwrap(),
"a handler must always be installed if the `auto-install` feature is disabled"
);
assert!(set_hook(Box::new(DefaultHandler::default_with)).is_ok());
let _error: Report = eyre!("this will be displayed if returned");
}

View file

@ -0,0 +1,15 @@
mod common;
use self::common::maybe_install_handler;
use eyre::OptionExt;
#[test]
fn test_option_ok_or_eyre() {
maybe_install_handler().unwrap();
let option: Option<()> = None;
let result = option.ok_or_eyre("static str error");
assert_eq!(result.unwrap_err().to_string(), "static str error");
}

View file

@ -0,0 +1,33 @@
#![cfg(feature = "pyo3")]
use pyo3::prelude::*;
use eyre::{bail, Result, WrapErr};
fn f() -> Result<()> {
use std::io;
bail!(io::Error::new(io::ErrorKind::PermissionDenied, "oh no!"));
}
fn g() -> Result<()> {
f().wrap_err("f failed")
}
fn h() -> Result<()> {
g().wrap_err("g failed")
}
#[test]
fn test_pyo3_exception_contents() {
use pyo3::types::IntoPyDict;
let err = h().unwrap_err();
let expected_contents = format!("{:?}", err);
let pyerr = PyErr::from(err);
Python::with_gil(|py| {
let locals = [("err", pyerr)].into_py_dict(py);
let pyerr = py.run("raise err", None, Some(locals)).unwrap_err();
assert_eq!(pyerr.value(py).to_string(), expected_contents);
})
}

View file

@ -0,0 +1,36 @@
mod common;
mod drop;
use self::common::maybe_install_handler;
use self::drop::{DetectDrop, Flag};
use eyre::Report;
use std::marker::Unpin;
use std::mem;
#[test]
fn test_error_size() {
assert_eq!(mem::size_of::<Report>(), mem::size_of::<usize>());
}
#[test]
fn test_null_pointer_optimization() {
assert_eq!(
mem::size_of::<Result<(), Report>>(),
mem::size_of::<usize>()
);
}
#[test]
fn test_autotraits() {
fn assert<E: Unpin + Send + Sync + 'static>() {}
assert::<Report>();
}
#[test]
fn test_drop() {
maybe_install_handler().unwrap();
let has_dropped = Flag::new();
drop(Report::new(DetectDrop::new("TestDrop", &has_dropped)));
assert!(has_dropped.get());
}

View file

@ -0,0 +1,75 @@
mod common;
use self::common::maybe_install_handler;
use eyre::{eyre, Report};
use std::error::Error as StdError;
use std::fmt::{self, Display};
use std::io;
#[derive(Debug)]
enum TestError {
Io(io::Error),
}
impl Display for TestError {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self {
TestError::Io(e) => Display::fmt(e, formatter),
}
}
}
impl StdError for TestError {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
match self {
TestError::Io(io) => Some(io),
}
}
}
#[test]
fn test_literal_source() {
maybe_install_handler().unwrap();
let error: Report = eyre!("oh no!");
assert!(error.source().is_none());
}
#[test]
fn test_variable_source() {
maybe_install_handler().unwrap();
let msg = "oh no!";
let error = eyre!(msg);
assert!(error.source().is_none());
let msg = msg.to_owned();
let error: Report = eyre!(msg);
assert!(error.source().is_none());
}
#[test]
fn test_fmt_source() {
maybe_install_handler().unwrap();
let error: Report = eyre!("{} {}!", "oh", "no");
assert!(error.source().is_none());
}
#[test]
fn test_io_source() {
maybe_install_handler().unwrap();
let io = io::Error::new(io::ErrorKind::Other, "oh no!");
let error: Report = eyre!(TestError::Io(io));
assert_eq!("oh no!", error.source().unwrap().to_string());
}
#[test]
fn test_eyre_from_eyre() {
maybe_install_handler().unwrap();
let error: Report = eyre!("oh no!").wrap_err("context");
let error = eyre!(error);
assert_eq!("oh no!", error.source().unwrap().to_string());
}

View file

@ -0,0 +1,34 @@
// These tests check our build script against rustversion.
#[rustversion::attr(not(nightly), ignore)]
#[test]
fn nightlytest() {
if !cfg!(nightly) {
panic!("nightly feature isn't set when the toolchain is nightly.");
}
if cfg!(any(beta, stable)) {
panic!("beta, stable, and nightly are mutually exclusive features.")
}
}
#[rustversion::attr(not(beta), ignore)]
#[test]
fn betatest() {
if !cfg!(beta) {
panic!("beta feature is not set when the toolchain is beta.");
}
if cfg!(any(nightly, stable)) {
panic!("beta, stable, and nightly are mutually exclusive features.")
}
}
#[rustversion::attr(not(stable), ignore)]
#[test]
fn stabletest() {
if !cfg!(stable) {
panic!("stable feature is not set when the toolchain is stable.");
}
if cfg!(any(nightly, beta)) {
panic!("beta, stable, and nightly are mutually exclusive features.")
}
}