update cargo modules by cargo vendor

This commit is contained in:
Andrew A. Vasilyev 2023-04-04 16:56:56 +03:00
parent 917c975fa2
commit 897832f835
5907 changed files with 3962490 additions and 1555498 deletions

View File

@ -14,10 +14,6 @@ directory = "vendor"
git = "git://git.proxmox.com/git/proxmox-acme-rs.git"
replace-with = "vendored-sources"
[source."git://git.proxmox.com/git/proxmox-apt.git"]
git = "git://git.proxmox.com/git/proxmox-apt.git"
replace-with = "vendored-sources"
[source."git://git.proxmox.com/git/proxmox-fuse.git"]
git = "git://git.proxmox.com/git/proxmox-fuse.git"
replace-with = "vendored-sources"
@ -60,7 +56,6 @@ proxmox-tfa = { git = "git://git.proxmox.com/git/proxmox.git" }
proxmox-time = { git = "git://git.proxmox.com/git/proxmox.git" }
proxmox-uuid = { git = "git://git.proxmox.com/git/proxmox.git" }
proxmox-apt = { git = "git://git.proxmox.com/git/proxmox-apt.git" }
proxmox-acme-rs = { git = "git://git.proxmox.com/git/proxmox-acme-rs.git" }
proxmox-fuse = { git = "git://git.proxmox.com/git/proxmox-fuse.git" }
proxmox-openid = { git = "git://git.proxmox.com/git/proxmox-openid-rs.git" }

1229
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -82,7 +82,6 @@ proxmox-uuid = "1"
# other proxmox crates
pathpatterns = "0.1.2"
proxmox-acme-rs = "0.4"
proxmox-apt = "0.9.0"
proxmox-openid = "0.9.9"
pxar = "0.10.2"
@ -101,7 +100,6 @@ proxmox-rrd = { path = "proxmox-rrd" }
# regular crates
anyhow = "1.0"
apt-pkg-native = "0.3.2"
base64 = "0.13"
bitflags = "1.2.1"
bytes = "1.0"
@ -154,7 +152,6 @@ zstd = { version = "0.6", features = [ "bindgen" ] }
[dependencies]
anyhow.workspace = true
apt-pkg-native.workspace = true
base64.workspace = true
bitflags.workspace = true
bytes.workspace = true
@ -224,7 +221,6 @@ proxmox-uuid.workspace = true
pathpatterns.workspace = true
proxmox-acme-rs.workspace = true
proxmox-apt.workspace = true
proxmox-openid.workspace = true
pxar.workspace = true

View File

@ -1 +1 @@
{"files":{"CHANGELOG.md":"d4ef249a0a4eff26a34a1f847a3c367dfd9988b4da972ac9c16b1d258b62ad87","Cargo.lock":"290a48d58d1ebfef0f5eaec66191f6c1a41080b89e10e931c6984052008479ab","Cargo.toml":"68243a813e2e6ba40d3e939b9ade5489b3f39a58d7dc391ae447a60591315f4a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"e99d88d232bf57d70f0fb87f6b496d44b6653f99f8a63d250a54c61ea4bcde40","README.md":"76d28502bd2e83f6a9e3576bd45e9a7fe5308448c4b5384b0d249515b5f67a5c","bench.plot.r":"6a5d7a4d36ed6b3d9919be703a479bef47698bf947818b483ff03951df2d4e01","benchmark.sh":"b35f89b1ca2c1dc0476cdd07f0284b72d41920d1c7b6054072f50ffba296d78d","coverage.sh":"4677e81922d08a82e83068a911717a247c66af12e559f37b78b6be3337ac9f07","examples/addr2line.rs":"75ef29e1d07d49d247990ad970892d64f629766bafa36afddff5a88976e58060","rustfmt.toml":"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b","src/function.rs":"395f37cdf03201d416d66bc11abeea627be0abb4585104acd927224a26cb9369","src/lazy.rs":"14ec61761369c21d426673f549c21394221533f444b68cd2a8370952eb19f345","src/lib.rs":"5696c0aee67df576f78935c66bb124f4e5fa19cbc9b25faf8f750e7e8dda113c","tests/correctness.rs":"c9325ffdec577bf5e56f5dd72fdff4927153d0a4c34c0fda5aefaeb44a8d26fd","tests/output_equivalence.rs":"38d7b585b7a2ca43b07eef6b34c11f489d1deae138a010123c33188dfb881c11","tests/parse.rs":"9e421ea9d9348721f6c6533cdba1db5b84287fc685f870c7905dea06b596b4db"},"package":"b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"}
{"files":{"CHANGELOG.md":"59733fc6186af0929ca4b6508e10ea1777f757c333a355d8154498332aee259f","Cargo.lock":"0b30594b7d3f093b44ca9c53366bbcb3f28a97ed24da65e56fe9961e7250c3c2","Cargo.toml":"c68ebf21efe63bb706716dd7b4bb7d33734629f13db36014d6be49fed6c8d731","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"e99d88d232bf57d70f0fb87f6b496d44b6653f99f8a63d250a54c61ea4bcde40","README.md":"76d28502bd2e83f6a9e3576bd45e9a7fe5308448c4b5384b0d249515b5f67a5c","bench.plot.r":"6a5d7a4d36ed6b3d9919be703a479bef47698bf947818b483ff03951df2d4e01","benchmark.sh":"b35f89b1ca2c1dc0476cdd07f0284b72d41920d1c7b6054072f50ffba296d78d","coverage.sh":"4677e81922d08a82e83068a911717a247c66af12e559f37b78b6be3337ac9f07","examples/addr2line.rs":"624548450eda1c8491fe4de60f0a96d20ef9c0d70770de2d76d803850319c876","rustfmt.toml":"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b","src/function.rs":"caa2458f48509a0e0e2c4920719383997e9ccab44efceeabcf3019587f438a57","src/lazy.rs":"21bc1a7d8593c11e93577f1f17163705dbbadf752a007fae4401a4150ec9e473","src/lib.rs":"41d575590b9a683349552d7c4c845ef9a2739e7a4a9e01d53d4e0f4a4947fc45","tests/correctness.rs":"0bd7f9bc9d333cca0649d7bb85e07ebc14855ec2f2b9082f4ec752ccea77e1d6","tests/output_equivalence.rs":"9b637de957f4760ed8bdbfac9e1bacf57f0123c54ed0fbfeb8c2c3b7077f3d81","tests/parse.rs":"f0b2437d0c0b204f6527975b10015a62636a61e5b6e20661824c6ddbdfe3eefe"},"package":"a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"}

View File

@ -1,3 +1,30 @@
## 0.19.0 (2022/11/24)
### Breaking changes
* Updated `gimli` and `object` dependencies.
--------------------------------------------------------------------------------
## 0.18.0 (2022/07/16)
### Breaking changes
* Updated `object` dependency.
### Changed
* Fixed handling of relative path for `DW_AT_comp_dir`.
[#239](https://github.com/gimli-rs/addr2line/pull/239)
* Fixed handling of `DW_FORM_addrx` for DWARF 5 support.
[#243](https://github.com/gimli-rs/addr2line/pull/243)
* Fixed handling of units that are missing range information.
[#249](https://github.com/gimli-rs/addr2line/pull/249)
--------------------------------------------------------------------------------
## 0.17.0 (2021/10/24)
### Breaking changes

180
vendor/addr2line/Cargo.lock generated vendored
View File

@ -4,16 +4,16 @@ version = 3
[[package]]
name = "addr2line"
version = "0.16.0"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd"
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
dependencies = [
"gimli 0.25.0",
"gimli 0.26.2",
]
[[package]]
name = "addr2line"
version = "0.17.0"
version = "0.19.0"
dependencies = [
"backtrace",
"clap",
@ -21,9 +21,9 @@ dependencies = [
"cpp_demangle",
"fallible-iterator",
"findshlibs",
"gimli 0.26.0",
"memmap",
"object",
"gimli 0.27.0",
"memmap2",
"object 0.30.0",
"rustc-demangle",
"rustc-std-workspace-alloc",
"rustc-std-workspace-core",
@ -38,15 +38,6 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "atty"
version = "0.2.14"
@ -60,22 +51,22 @@ dependencies = [
[[package]]
name = "autocfg"
version = "1.0.1"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.62"
version = "0.3.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "091bcdf2da9950f96aa522681ce805e6857f6ca8df73833d35736ab2dc78e152"
checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
dependencies = [
"addr2line 0.16.0",
"addr2line 0.17.0",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"object 0.29.0",
"rustc-demangle",
]
@ -87,9 +78,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.71"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "cfg-if"
@ -99,39 +90,48 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "2.33.3"
version = "3.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
checksum = "ab8b79fe3946ceb4a0b1c080b4018992b8d27e9ff363644c1c9b6387c854614d"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"clap_lex",
"indexmap",
"strsim",
"termcolor",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "clap_lex"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "compiler_builtins"
version = "0.1.51"
version = "0.1.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3587b3669d6f2c1cfd34c475272dabcfef29d52703933f6f72ebb36d6bd81a97"
checksum = "c6e3183e88f659a862835db8f4b67dbeed3d93e44dd4927eef78edb1c149d784"
[[package]]
name = "cpp_demangle"
version = "0.3.3"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea47428dc9d2237f3c6bc134472edfd63ebba0af932e783506dcfd66f10d18a"
checksum = "b446fd40bcc17eddd6a4a78f24315eb90afdb3334999ddfd4909985c47722442"
dependencies = [
"cfg-if",
]
[[package]]
name = "crc32fast"
version = "1.2.1"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
dependencies = [
"cfg-if",
]
@ -144,9 +144,9 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]]
name = "findshlibs"
version = "0.10.1"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d691fdb3f817632d259d09220d4cf0991dbb2c9e59e044a02a59194bf6e14484"
checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64"
dependencies = [
"cc",
"lazy_static",
@ -156,13 +156,11 @@ dependencies = [
[[package]]
name = "flate2"
version = "1.0.22"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f"
checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
dependencies = [
"cfg-if",
"crc32fast",
"libc",
"miniz_oxide",
]
@ -177,15 +175,15 @@ dependencies = [
[[package]]
name = "gimli"
version = "0.25.0"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7"
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
[[package]]
name = "gimli"
version = "0.26.0"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81a03ce013ffccead76c11a15751231f777d9295b845cc1266ed4d34fcbd7977"
checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793"
dependencies = [
"compiler_builtins",
"fallible-iterator",
@ -194,6 +192,12 @@ dependencies = [
"stable_deref_trait",
]
[[package]]
name = "hashbrown"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "607c8a29735385251a339424dd462993c0fed8fa09d378f259377df08c126022"
[[package]]
name = "hermit-abi"
version = "0.1.19"
@ -203,6 +207,16 @@ dependencies = [
"libc",
]
[[package]]
name = "indexmap"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
@ -221,46 +235,59 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.105"
version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
[[package]]
name = "memchr"
version = "2.4.1"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memmap"
version = "0.7.0"
name = "memmap2"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
checksum = "3a79b39c93a7a5a27eeaf9a23b5ff43f1b9e0ad6b1cdd441140ae53c35613fc7"
dependencies = [
"libc",
"winapi 0.3.9",
]
[[package]]
name = "miniz_oxide"
version = "0.4.4"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
dependencies = [
"adler",
"autocfg",
]
[[package]]
name = "object"
version = "0.27.1"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9"
checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
dependencies = [
"memchr",
]
[[package]]
name = "object"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb"
dependencies = [
"flate2",
"memchr",
]
[[package]]
name = "os_str_bytes"
version = "6.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4"
[[package]]
name = "rustc-demangle"
version = "0.1.21"
@ -325,9 +352,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
[[package]]
name = "smallvec"
version = "1.7.0"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
[[package]]
name = "stable_deref_trait"
@ -337,9 +364,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "strsim"
version = "0.8.0"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "term"
@ -352,14 +379,20 @@ dependencies = [
]
[[package]]
name = "textwrap"
version = "0.11.0"
name = "termcolor"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
"unicode-width",
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
[[package]]
name = "time"
version = "0.1.44"
@ -383,12 +416,6 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
@ -423,6 +450,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"

View File

@ -3,38 +3,40 @@
# 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
# to registry (e.g., crates.io) dependencies.
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
# 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]
name = "addr2line"
version = "0.17.0"
exclude = ["/benches/*", "/fixtures/*", ".github"]
version = "0.19.0"
exclude = [
"/benches/*",
"/fixtures/*",
".github",
]
description = "A cross-platform symbolication library written in Rust, using `gimli`"
documentation = "https://docs.rs/addr2line"
readme = "./README.md"
keywords = ["DWARF", "debug", "elf", "symbolicate", "atos"]
keywords = [
"DWARF",
"debug",
"elf",
"symbolicate",
"atos",
]
categories = ["development-tools::debugging"]
license = "Apache-2.0 OR MIT"
repository = "https://github.com/gimli-rs/addr2line"
[profile.bench]
codegen-units = 1
debug = true
split-debuginfo = "packed"
[profile.dev]
split-debuginfo = "packed"
[profile.release]
debug = true
split-debuginfo = "packed"
[profile.test]
split-debuginfo = "packed"
[[example]]
name = "addr2line"
@ -52,6 +54,7 @@ required-features = ["default"]
[[test]]
name = "parse"
required-features = ["std-object"]
[dependencies.alloc]
version = "1.0.0"
optional = true
@ -67,7 +70,8 @@ optional = true
package = "rustc-std-workspace-core"
[dependencies.cpp_demangle]
version = "0.3"
version = "0.4"
features = ["alloc"]
optional = true
default-features = false
@ -77,12 +81,12 @@ optional = true
default-features = false
[dependencies.gimli]
version = "0.26"
version = "0.27.0"
features = ["read"]
default-features = false
[dependencies.object]
version = "0.27.1"
version = "0.30.0"
features = ["read"]
optional = true
default-features = false
@ -95,17 +99,18 @@ optional = true
version = "1"
optional = true
default-features = false
[dev-dependencies.backtrace]
version = "0.3.13"
[dev-dependencies.clap]
version = "2"
version = "3.1.6"
[dev-dependencies.findshlibs]
version = "0.10"
[dev-dependencies.memmap]
version = "0.7"
[dev-dependencies.memmap2]
version = "0.5.5"
[dev-dependencies.rustc-test]
version = "0.3"
@ -114,7 +119,24 @@ version = "0.3"
version = "2"
[features]
default = ["rustc-demangle", "cpp_demangle", "std-object", "fallible-iterator", "smallvec"]
rustc-dep-of-std = ["core", "alloc", "compiler_builtins", "gimli/rustc-dep-of-std"]
default = [
"rustc-demangle",
"cpp_demangle",
"std-object",
"fallible-iterator",
"smallvec",
]
rustc-dep-of-std = [
"core",
"alloc",
"compiler_builtins",
"gimli/rustc-dep-of-std",
]
std = ["gimli/std"]
std-object = ["std", "object", "object/std", "object/compression", "gimli/endian-reader"]
std-object = [
"std",
"object",
"object/std",
"object/compression",
"gimli/endian-reader",
]

View File

@ -2,7 +2,7 @@ extern crate addr2line;
extern crate clap;
extern crate fallible_iterator;
extern crate gimli;
extern crate memmap;
extern crate memmap2;
extern crate object;
extern crate typed_arena;
@ -11,18 +11,18 @@ use std::fs::File;
use std::io::{BufRead, Lines, StdinLock, Write};
use std::path::Path;
use clap::{App, Arg, Values};
use clap::{Arg, Command, Values};
use fallible_iterator::FallibleIterator;
use object::{Object, ObjectSection};
use object::{Object, ObjectSection, SymbolMap, SymbolMapName};
use typed_arena::Arena;
use addr2line::{Context, Location};
fn parse_uint_from_hex_string(string: &str) -> u64 {
fn parse_uint_from_hex_string(string: &str) -> Option<u64> {
if string.len() > 2 && string.starts_with("0x") {
u64::from_str_radix(&string[2..], 16).expect("Failed to parse address")
u64::from_str_radix(&string[2..], 16).ok()
} else {
u64::from_str_radix(string, 16).expect("Failed to parse address")
u64::from_str_radix(string, 16).ok()
}
}
@ -32,9 +32,9 @@ enum Addrs<'a> {
}
impl<'a> Iterator for Addrs<'a> {
type Item = u64;
type Item = Option<u64>;
fn next(&mut self) -> Option<u64> {
fn next(&mut self) -> Option<Option<u64>> {
let text = match *self {
Addrs::Args(ref mut vals) => vals.next().map(Cow::from),
Addrs::Stdin(ref mut lines) => lines.next().map(Result::unwrap).map(Cow::from),
@ -45,15 +45,18 @@ impl<'a> Iterator for Addrs<'a> {
}
}
fn print_loc(loc: &Option<Location>, basenames: bool, llvm: bool) {
if let Some(ref loc) = *loc {
let file = loc.file.as_ref().unwrap();
let path = if basenames {
Path::new(Path::new(file).file_name().unwrap())
fn print_loc(loc: Option<&Location>, basenames: bool, llvm: bool) {
if let Some(ref loc) = loc {
if let Some(ref file) = loc.file.as_ref() {
let path = if basenames {
Path::new(Path::new(file).file_name().unwrap())
} else {
Path::new(file)
};
print!("{}:", path.display());
} else {
Path::new(file)
};
print!("{}:", path.display());
print!("??:");
}
if llvm {
print!("{}:{}", loc.line.unwrap_or(0), loc.column.unwrap_or(0));
} else if let Some(line) = loc.line {
@ -65,15 +68,19 @@ fn print_loc(loc: &Option<Location>, basenames: bool, llvm: bool) {
} else if llvm {
println!("??:0:0");
} else {
println!("??:?");
println!("??:0");
}
}
fn print_function(name: &str, language: Option<gimli::DwLang>, demangle: bool) {
if demangle {
print!("{}", addr2line::demangle_auto(Cow::from(name), language));
fn print_function(name: Option<&str>, language: Option<gimli::DwLang>, demangle: bool) {
if let Some(name) = name {
if demangle {
print!("{}", addr2line::demangle_auto(Cow::from(name), language));
} else {
print!("{}", name);
}
} else {
print!("{}", name);
print!("??");
}
}
@ -94,77 +101,61 @@ fn load_file_section<'input, 'arena, Endian: gimli::Endianity>(
}
}
fn find_name_from_symbols<'a>(
symbols: &'a SymbolMap<SymbolMapName>,
probe: u64,
) -> Option<&'a str> {
symbols.get(probe).map(|x| x.name())
}
fn main() {
let matches = App::new("hardliner")
let matches = Command::new("addr2line")
.version("0.1")
.about("A fast addr2line clone")
.arg(
Arg::with_name("exe")
.short("e")
.about("A fast addr2line Rust port")
.args(&[
Arg::new("exe")
.short('e')
.long("exe")
.value_name("filename")
.help(
"Specify the name of the executable for which addresses should be translated.",
)
.required(true),
)
.arg(
Arg::with_name("sup")
Arg::new("sup")
.long("sup")
.value_name("filename")
.help("Path to supplementary object file."),
)
.arg(
Arg::with_name("functions")
.short("f")
Arg::new("functions")
.short('f')
.long("functions")
.help("Display function names as well as file and line number information."),
)
.arg(
Arg::with_name("pretty")
.short("p")
.long("pretty-print")
.help(
"Make the output more human friendly: each location are printed on \
one line.",
),
)
.arg(Arg::with_name("inlines").short("i").long("inlines").help(
"If the address belongs to a function that was inlined, the source \
information for all enclosing scopes back to the first non-inlined \
function will also be printed.",
))
.arg(
Arg::with_name("addresses")
.short("a")
.long("addresses")
.help(
"Display the address before the function name, file and line \
number information.",
),
)
.arg(
Arg::with_name("basenames")
.short("s")
Arg::new("pretty").short('p').long("pretty-print").help(
"Make the output more human friendly: each location are printed on one line.",
),
Arg::new("inlines").short('i').long("inlines").help(
"If the address belongs to a function that was inlined, the source information for \
all enclosing scopes back to the first non-inlined function will also be printed.",
),
Arg::new("addresses").short('a').long("addresses").help(
"Display the address before the function name, file and line number information.",
),
Arg::new("basenames")
.short('s')
.long("basenames")
.help("Display only the base of each file name."),
)
.arg(Arg::with_name("demangle").short("C").long("demangle").help(
"Demangle function names. \
Specifying a specific demangling style (like GNU addr2line) \
is not supported. (TODO)",
))
.arg(
Arg::with_name("llvm")
Arg::new("demangle").short('C').long("demangle").help(
"Demangle function names. \
Specifying a specific demangling style (like GNU addr2line) is not supported. \
(TODO)"
),
Arg::new("llvm")
.long("llvm")
.help("Display output in the same format as llvm-symbolizer."),
)
.arg(
Arg::with_name("addrs")
Arg::new("addrs")
.takes_value(true)
.multiple(true)
.multiple_occurrences(true)
.help("Addresses to use instead of reading from stdin."),
)
])
.get_matches();
let arena_data = Arena::new();
@ -179,7 +170,7 @@ fn main() {
let path = matches.value_of("exe").unwrap();
let file = File::open(path).unwrap();
let map = unsafe { memmap::Mmap::map(&file).unwrap() };
let map = unsafe { memmap2::Mmap::map(&file).unwrap() };
let object = &object::File::parse(&*map).unwrap();
let endian = if object.is_little_endian() {
@ -195,7 +186,7 @@ fn main() {
let sup_map;
let sup_object = if let Some(sup_path) = matches.value_of("sup") {
let sup_file = File::open(sup_path).unwrap();
sup_map = unsafe { memmap::Mmap::map(&sup_file).unwrap() };
sup_map = unsafe { memmap2::Mmap::map(&sup_file).unwrap() };
Some(object::File::parse(&*sup_map).unwrap())
} else {
None
@ -220,10 +211,11 @@ fn main() {
for probe in addrs {
if print_addrs {
let addr = probe.unwrap_or(0);
if llvm {
print!("0x{:x}", probe);
print!("0x{:x}", addr);
} else {
print!("0x{:016x}", probe);
print!("0x{:016x}", addr);
}
if pretty {
print!(": ");
@ -234,44 +226,46 @@ fn main() {
if do_functions || do_inlines {
let mut printed_anything = false;
let mut frames = ctx.find_frames(probe).unwrap().enumerate();
while let Some((i, frame)) = frames.next().unwrap() {
if pretty && i != 0 {
print!(" (inlined by) ");
}
if do_functions {
if let Some(func) = frame.function {
print_function(&func.raw_name().unwrap(), func.language, demangle);
} else if let Some(name) = symbols.get(probe).map(|x| x.name()) {
print_function(name, None, demangle);
} else {
print!("??");
if let Some(probe) = probe {
let mut frames = ctx.find_frames(probe).unwrap().enumerate();
while let Some((i, frame)) = frames.next().unwrap() {
if pretty && i != 0 {
print!(" (inlined by) ");
}
if pretty {
print!(" at ");
} else {
println!();
if do_functions {
if let Some(func) = frame.function {
print_function(
func.raw_name().ok().as_ref().map(AsRef::as_ref),
func.language,
demangle,
);
} else {
let name = find_name_from_symbols(&symbols, probe);
print_function(name, None, demangle);
}
if pretty {
print!(" at ");
} else {
println!();
}
}
}
print_loc(&frame.location, basenames, llvm);
print_loc(frame.location.as_ref(), basenames, llvm);
printed_anything = true;
printed_anything = true;
if !do_inlines {
break;
if !do_inlines {
break;
}
}
}
if !printed_anything {
if do_functions {
if let Some(name) = symbols.get(probe).map(|x| x.name()) {
print_function(name, None, demangle);
} else {
print!("??");
}
let name = probe.and_then(|probe| find_name_from_symbols(&symbols, probe));
print_function(name, None, demangle);
if pretty {
print!(" at ");
@ -280,15 +274,11 @@ fn main() {
}
}
if llvm {
println!("??:0:0");
} else {
println!("??:?");
}
print_loc(None, basenames, llvm);
}
} else {
let loc = ctx.find_location(probe).unwrap();
print_loc(&loc, basenames, llvm);
let loc = probe.and_then(|probe| ctx.find_location(probe).unwrap());
print_loc(loc.as_ref(), basenames, llvm);
}
if llvm {

View File

@ -68,15 +68,24 @@ impl<R: gimli::Reader> Functions<R> {
match entries.read_attribute(*spec) {
Ok(ref attr) => {
match attr.name() {
gimli::DW_AT_low_pc => {
if let gimli::AttributeValue::Addr(val) = attr.value() {
ranges.low_pc = Some(val);
gimli::DW_AT_low_pc => match attr.value() {
gimli::AttributeValue::Addr(val) => {
ranges.low_pc = Some(val)
}
}
gimli::AttributeValue::DebugAddrIndex(index) => {
ranges.low_pc =
Some(dwarf.sections.address(unit, index)?);
}
_ => {}
},
gimli::DW_AT_high_pc => match attr.value() {
gimli::AttributeValue::Addr(val) => {
ranges.high_pc = Some(val)
}
gimli::AttributeValue::DebugAddrIndex(index) => {
ranges.high_pc =
Some(dwarf.sections.address(unit, index)?);
}
gimli::AttributeValue::Udata(val) => {
ranges.size = Some(val)
}
@ -352,13 +361,18 @@ impl<R: gimli::Reader> InlinedFunction<R> {
for spec in abbrev.attributes() {
match entries.read_attribute(*spec) {
Ok(ref attr) => match attr.name() {
gimli::DW_AT_low_pc => {
if let gimli::AttributeValue::Addr(val) = attr.value() {
ranges.low_pc = Some(val);
gimli::DW_AT_low_pc => match attr.value() {
gimli::AttributeValue::Addr(val) => ranges.low_pc = Some(val),
gimli::AttributeValue::DebugAddrIndex(index) => {
ranges.low_pc = Some(dwarf.sections.address(unit, index)?);
}
}
_ => {}
},
gimli::DW_AT_high_pc => match attr.value() {
gimli::AttributeValue::Addr(val) => ranges.high_pc = Some(val),
gimli::AttributeValue::DebugAddrIndex(index) => {
ranges.high_pc = Some(dwarf.sections.address(unit, index)?);
}
gimli::AttributeValue::Udata(val) => ranges.size = Some(val),
_ => {}
},

View File

@ -11,19 +11,17 @@ impl<T> LazyCell<T> {
}
pub fn borrow_with(&self, closure: impl FnOnce() -> T) -> &T {
unsafe {
// First check if we're already initialized...
let ptr = self.contents.get();
if let Some(val) = &*ptr {
return val;
}
// Note that while we're executing `closure` our `borrow_with` may
// be called recursively. This means we need to check again after
// the closure has executed. For that we use the `get_or_insert`
// method which will only perform mutation if we aren't already
// `Some`.
let val = closure();
(*ptr).get_or_insert(val)
// First check if we're already initialized...
let ptr = self.contents.get();
if let Some(val) = unsafe { &*ptr } {
return val;
}
// Note that while we're executing `closure` our `borrow_with` may
// be called recursively. This means we need to check again after
// the closure has executed. For that we use the `get_or_insert`
// method which will only perform mutation if we aren't already
// `Some`.
let val = closure();
unsafe { (*ptr).get_or_insert(val) }
}
}

View File

@ -181,6 +181,7 @@ impl<R: gimli::Reader> Context<R> {
ranges: gimli::RangeLists::new(debug_ranges, debug_rnglists),
file_type: gimli::DwarfFileType::Main,
sup: None,
abbreviations_cache: gimli::AbbreviationsCache::new(),
})
}
@ -404,6 +405,7 @@ impl<R: gimli::Reader> ResDwarf<R> {
};
let mut lang = None;
let mut have_unit_range = false;
{
let mut entries = dw_unit.entries_raw(None)?;
@ -416,13 +418,18 @@ impl<R: gimli::Reader> ResDwarf<R> {
for spec in abbrev.attributes() {
let attr = entries.read_attribute(*spec)?;
match attr.name() {
gimli::DW_AT_low_pc => {
if let gimli::AttributeValue::Addr(val) = attr.value() {
ranges.low_pc = Some(val);
gimli::DW_AT_low_pc => match attr.value() {
gimli::AttributeValue::Addr(val) => ranges.low_pc = Some(val),
gimli::AttributeValue::DebugAddrIndex(index) => {
ranges.low_pc = Some(sections.address(&dw_unit, index)?);
}
}
_ => {}
},
gimli::DW_AT_high_pc => match attr.value() {
gimli::AttributeValue::Addr(val) => ranges.high_pc = Some(val),
gimli::AttributeValue::DebugAddrIndex(index) => {
ranges.high_pc = Some(sections.address(&dw_unit, index)?);
}
gimli::AttributeValue::Udata(val) => ranges.size = Some(val),
_ => {}
},
@ -472,11 +479,12 @@ impl<R: gimli::Reader> ResDwarf<R> {
unit_id,
max_end: 0,
});
have_unit_range = true;
}
}
}
} else {
ranges.for_each_range(&sections, &dw_unit, |range| {
have_unit_range |= ranges.for_each_range(&sections, &dw_unit, |range| {
unit_ranges.push(UnitRange {
range,
unit_id,
@ -486,11 +494,34 @@ impl<R: gimli::Reader> ResDwarf<R> {
}
}
let lines = LazyCell::new();
if !have_unit_range {
// The unit did not declare any ranges.
// Try to get some ranges from the line program sequences.
if let Some(ref ilnp) = dw_unit.line_program {
if let Ok(lines) = lines
.borrow_with(|| Lines::parse(&dw_unit, ilnp.clone(), &*sections))
.as_ref()
{
for sequence in lines.sequences.iter() {
unit_ranges.push(UnitRange {
range: gimli::Range {
begin: sequence.start,
end: sequence.end,
},
unit_id,
max_end: 0,
})
}
}
}
}
res_units.push(ResUnit {
offset,
dw_unit,
lang,
lines: LazyCell::new(),
lines,
funcs: LazyCell::new(),
});
}
@ -531,6 +562,111 @@ struct Lines {
sequences: Box<[LineSequence]>,
}
impl Lines {
fn parse<R: gimli::Reader>(
dw_unit: &gimli::Unit<R>,
ilnp: gimli::IncompleteLineProgram<R, R::Offset>,
sections: &gimli::Dwarf<R>,
) -> Result<Self, Error> {
let mut sequences = Vec::new();
let mut sequence_rows = Vec::<LineRow>::new();
let mut rows = ilnp.rows();
while let Some((_, row)) = rows.next_row()? {
if row.end_sequence() {
if let Some(start) = sequence_rows.first().map(|x| x.address) {
let end = row.address();
let mut rows = Vec::new();
mem::swap(&mut rows, &mut sequence_rows);
sequences.push(LineSequence {
start,
end,
rows: rows.into_boxed_slice(),
});
}
continue;
}
let address = row.address();
let file_index = row.file_index();
let line = row.line().map(NonZeroU64::get).unwrap_or(0) as u32;
let column = match row.column() {
gimli::ColumnType::LeftEdge => 0,
gimli::ColumnType::Column(x) => x.get() as u32,
};
if let Some(last_row) = sequence_rows.last_mut() {
if last_row.address == address {
last_row.file_index = file_index;
last_row.line = line;
last_row.column = column;
continue;
}
}
sequence_rows.push(LineRow {
address,
file_index,
line,
column,
});
}
sequences.sort_by_key(|x| x.start);
let mut files = Vec::new();
let header = rows.header();
match header.file(0) {
Some(file) => files.push(render_file(dw_unit, file, header, sections)?),
None => files.push(String::from("")), // DWARF version <= 4 may not have 0th index
}
let mut index = 1;
while let Some(file) = header.file(index) {
files.push(render_file(dw_unit, file, header, sections)?);
index += 1;
}
Ok(Self {
files: files.into_boxed_slice(),
sequences: sequences.into_boxed_slice(),
})
}
}
fn render_file<R: gimli::Reader>(
dw_unit: &gimli::Unit<R>,
file: &gimli::FileEntry<R, R::Offset>,
header: &gimli::LineProgramHeader<R, R::Offset>,
sections: &gimli::Dwarf<R>,
) -> Result<String, gimli::Error> {
let mut path = if let Some(ref comp_dir) = dw_unit.comp_dir {
comp_dir.to_string_lossy()?.into_owned()
} else {
String::new()
};
// The directory index 0 is defined to correspond to the compilation unit directory.
if file.directory_index() != 0 {
if let Some(directory) = file.directory(header) {
path_push(
&mut path,
sections
.attr_string(dw_unit, directory)?
.to_string_lossy()?
.as_ref(),
);
}
}
path_push(
&mut path,
sections
.attr_string(dw_unit, file.path_name())?
.to_string_lossy()?
.as_ref(),
);
Ok(path)
}
struct LineSequence {
start: u64,
end: u64,
@ -559,68 +695,7 @@ impl<R: gimli::Reader> ResUnit<R> {
None => return Ok(None),
};
self.lines
.borrow_with(|| {
let mut sequences = Vec::new();
let mut sequence_rows = Vec::<LineRow>::new();
let mut rows = ilnp.clone().rows();
while let Some((_, row)) = rows.next_row()? {
if row.end_sequence() {
if let Some(start) = sequence_rows.first().map(|x| x.address) {
let end = row.address();
let mut rows = Vec::new();
mem::swap(&mut rows, &mut sequence_rows);
sequences.push(LineSequence {
start,
end,
rows: rows.into_boxed_slice(),
});
}
continue;
}
let address = row.address();
let file_index = row.file_index();
let line = row.line().map(NonZeroU64::get).unwrap_or(0) as u32;
let column = match row.column() {
gimli::ColumnType::LeftEdge => 0,
gimli::ColumnType::Column(x) => x.get() as u32,
};
if let Some(last_row) = sequence_rows.last_mut() {
if last_row.address == address {
last_row.file_index = file_index;
last_row.line = line;
last_row.column = column;
continue;
}
}
sequence_rows.push(LineRow {
address,
file_index,
line,
column,
});
}
sequences.sort_by_key(|x| x.start);
let mut files = Vec::new();
let header = ilnp.header();
match header.file(0) {
Some(file) => files.push(self.render_file(file, header, sections)?),
None => files.push(String::from("")), // DWARF version <= 4 may not have 0th index
}
let mut index = 1;
while let Some(file) = header.file(index) {
files.push(self.render_file(file, header, sections)?);
index += 1;
}
Ok(Lines {
files: files.into_boxed_slice(),
sequences: sequences.into_boxed_slice(),
})
})
.borrow_with(|| Lines::parse(&self.dw_unit, ilnp.clone(), sections))
.as_ref()
.map(Some)
.map_err(Error::clone)
@ -688,39 +763,6 @@ impl<R: gimli::Reader> ResUnit<R> {
let location = self.find_location(probe, &dwarf.sections)?;
Ok((function, location))
}
fn render_file(
&self,
file: &gimli::FileEntry<R, R::Offset>,
header: &gimli::LineProgramHeader<R, R::Offset>,
sections: &gimli::Dwarf<R>,
) -> Result<String, gimli::Error> {
let mut path = if let Some(ref comp_dir) = self.dw_unit.comp_dir {
comp_dir.to_string_lossy()?.into_owned()
} else {
String::new()
};
if let Some(directory) = file.directory(header) {
path_push(
&mut path,
sections
.attr_string(&self.dw_unit, directory)?
.to_string_lossy()?
.as_ref(),
);
}
path_push(
&mut path,
sections
.attr_string(&self.dw_unit, file.path_name())?
.to_string_lossy()?
.as_ref(),
);
Ok(path)
}
}
/// Iterator over `Location`s in a range of addresses, returned by `Context::find_location_range`.
@ -928,7 +970,7 @@ fn path_push(path: &mut String, p: &str) {
'/'
};
if !path.ends_with(dir_separator) {
if !path.is_empty() && !path.ends_with(dir_separator) {
path.push(dir_separator);
}
*path += p;

View File

@ -2,7 +2,7 @@ extern crate addr2line;
extern crate fallible_iterator;
extern crate findshlibs;
extern crate gimli;
extern crate memmap;
extern crate memmap2;
extern crate object;
use addr2line::Context;
@ -11,10 +11,10 @@ use findshlibs::{IterationControl, SharedLibrary, TargetSharedLibrary};
use object::Object;
use std::fs::File;
fn find_debuginfo() -> memmap::Mmap {
fn find_debuginfo() -> memmap2::Mmap {
let path = std::env::current_exe().unwrap();
let file = File::open(&path).unwrap();
let map = unsafe { memmap::Mmap::map(&file).unwrap() };
let map = unsafe { memmap2::Mmap::map(&file).unwrap() };
let file = &object::File::parse(&*map).unwrap();
if let Ok(uuid) = file.mach_uuid() {
for candidate in path.parent().unwrap().read_dir().unwrap() {
@ -25,7 +25,7 @@ fn find_debuginfo() -> memmap::Mmap {
for candidate in path.join("Contents/Resources/DWARF").read_dir().unwrap() {
let path = candidate.unwrap().path();
let file = File::open(&path).unwrap();
let map = unsafe { memmap::Mmap::map(&file).unwrap() };
let map = unsafe { memmap2::Mmap::map(&file).unwrap() };
let file = &object::File::parse(&*map).unwrap();
if file.mach_uuid().unwrap() == uuid {
return map;
@ -41,11 +41,12 @@ fn find_debuginfo() -> memmap::Mmap {
fn correctness() {
let map = find_debuginfo();
let file = &object::File::parse(&*map).unwrap();
let module_base = file.relative_address_base();
let ctx = Context::new(file).unwrap();
let mut bias = None;
TargetSharedLibrary::each(|lib| {
bias = Some(lib.virtual_memory_bias().0 as u64);
bias = Some((lib.virtual_memory_bias().0 as u64).wrapping_sub(module_base));
IterationControl::Break
});

View File

@ -11,6 +11,7 @@ use backtrace::Backtrace;
use findshlibs::{IterationControl, SharedLibrary, TargetSharedLibrary};
use test::{ShouldPanic, TestDesc, TestDescAndFn, TestFn, TestName};
#[inline(never)]
fn make_trace() -> Vec<String> {
fn foo() -> Backtrace {
bar()

View File

@ -1,5 +1,5 @@
extern crate addr2line;
extern crate memmap;
extern crate memmap2;
extern crate object;
use std::borrow::Cow;
@ -25,7 +25,7 @@ fn release_fixture_path() -> PathBuf {
fn with_file<F: FnOnce(&object::File)>(target: &path::Path, f: F) {
let file = File::open(target).unwrap();
let map = unsafe { memmap::Mmap::map(&file).unwrap() };
let map = unsafe { memmap2::Mmap::map(&file).unwrap() };
let file = object::File::parse(&*map).unwrap();
f(&file)
}

View File

@ -1 +1 @@
{"files":{"COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"b050d4b44fcbb24a5e032d8e31b6cc85e02acbe8433e60d7accf3c95f8353b02","DESIGN.md":"64ff45ea2a89d4c32b29af91acb7743a861fcac417cb94fde8e6559405d603b2","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"e476891104a2eaea4c5f5f36dc551e8d2a3ed72092a94f3fb189f851fe5db279","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/ahocorasick.rs":"439786043d11756f1ebfaa0d68ff88791519cddc21e441bb181dc94ece6d0ed3","src/automaton.rs":"610b3e2c104c51bf4f51a6d07626c3972e9d1274ca276e987385a231b284cc8b","src/buffer.rs":"dae7ee7c1f846ca9cf115ba4949484000e1837b4fb7311f8d8c9a35011c9c26f","src/byte_frequencies.rs":"2fb85b381c038c1e44ce94294531cdcd339dca48b1e61f41455666e802cbbc9e","src/classes.rs":"99a53a2ed8eea8c13699def90e31dfdff9d0b90572b1db3cb534e3396e7a0ed0","src/dfa.rs":"25e4455b3e179a7e192108d05f3683993456b36e3ebed99f827558c52525b7e6","src/error.rs":"d34c2c9c815df5d9dedc46b4b3ce109cd2cee07825de643f0c574ec960367beb","src/lib.rs":"7a47d4c87f83e0e7ddf0777a71e4858904e73477ce18404cb89e656070e86aef","src/nfa.rs":"2f443951c78196126bfd237ed5770a69077e6190daeecd47131339c25e51a3d0","src/packed/api.rs":"df42e7500c94c9de1ac44145a0dd99ea02047e6bba229da12f2575337beebcf0","src/packed/mod.rs":"d7ee11d487a7f129f16dc8f1473442a7127905933f378504bae83df0f23c5e2a","src/packed/pattern.rs":"3abf3835d4c4f8a43753c52936a894d819f713f233fc046e19de5ef95200dcce","src/packed/rabinkarp.rs":"ad7d4533f96aed336e29c5553657ae57b0d733ace9c707a6cf4d08d8fc6edee5","src/packed/teddy/README.md":"b4b83fb5afafbbea6cb76fe70f49cc8ced888f682d98abe5ea5773e95d9ec2b0","src/packed/teddy/compile.rs":"aad40b3f93d2c388b409b31fb2795d414a365237789d5b1a7510d97ceb8ce260","src/packed/teddy/mod.rs":"83b52bd80272970ad17234d0db293d17c1710ec582302bf516b203c8edec037e","src/packed/teddy/runtime.rs":"836146e90b320b14fa2c65fe4af7915a41f6fb04408aac5fac731c22ff46adae","src/packed/tests.rs":"b8dc4d3281ecd6d0fa2bf7ef16cf292a467dfdce64e470c7921e983bfa60fee2","src/packed/vector.rs":"ab3c0535fca5f09198d58cbfae44c292aeb3ce44bc92bca36d30dc72963639fc","src/prefilter.rs":"82a3eb6d5c0c3f10bc8d5f57d55d6d14cf4cf21c475bb5253e1921084063b8d7","src/state_id.rs":"519ec8c7bf3fa72103d4c561c193759759f535dca924c9853efe630f406d2029","src/tests.rs":"6522ed1b244513c01de5bbcf0fe35571454fdea2c2a9d8dfe13a04bf57b70eca"},"package":"b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"}
{"files":{"COPYING":"01c266bced4a434da0051174d6bee16a4c82cf634e2679b6155d40d75012390f","Cargo.toml":"c9b1b15e299ba4e6ed0d6f25cde30b26b13b6068a7fbd980000c37bca19b0104","DESIGN.md":"64ff45ea2a89d4c32b29af91acb7743a861fcac417cb94fde8e6559405d603b2","LICENSE-MIT":"0f96a83840e146e43c0ec96a22ec1f392e0680e6c1226e6f3ba87e0740af850f","README.md":"5999e5768f5da8ab9b50c016766b5185b4c79936c56bef6d311ddcb0a38c4b94","UNLICENSE":"7e12e5df4bae12cb21581ba157ced20e1986a0508dd10d0e8a4ab9a4cf94e85c","rustfmt.toml":"1ca600239a27401c4a43f363cf3f38183a212affc1f31bff3ae93234bbaec228","src/ahocorasick.rs":"b92c9a65c4ee8029ff5a710aa1514caf838e73072c177dff5375463769f0b1ce","src/automaton.rs":"931af0aad03079bc4f6400d573fce832ce1edeeaf196815a16750d57b54b2183","src/buffer.rs":"dae7ee7c1f846ca9cf115ba4949484000e1837b4fb7311f8d8c9a35011c9c26f","src/byte_frequencies.rs":"2fb85b381c038c1e44ce94294531cdcd339dca48b1e61f41455666e802cbbc9e","src/classes.rs":"99a53a2ed8eea8c13699def90e31dfdff9d0b90572b1db3cb534e3396e7a0ed0","src/dfa.rs":"25e4455b3e179a7e192108d05f3683993456b36e3ebed99f827558c52525b7e6","src/error.rs":"d34c2c9c815df5d9dedc46b4b3ce109cd2cee07825de643f0c574ec960367beb","src/lib.rs":"7a47d4c87f83e0e7ddf0777a71e4858904e73477ce18404cb89e656070e86aef","src/nfa.rs":"3b817b4aa85540e8c0d35aff7ed7cfbab70ec7d2aaa779d63b4f5369bff31ce1","src/packed/api.rs":"df42e7500c94c9de1ac44145a0dd99ea02047e6bba229da12f2575337beebcf0","src/packed/mod.rs":"ad2f8e18996737347a1181a4457387276d139315bcabfc5e34494af0c0319701","src/packed/pattern.rs":"3abf3835d4c4f8a43753c52936a894d819f713f233fc046e19de5ef95200dcce","src/packed/rabinkarp.rs":"ad7d4533f96aed336e29c5553657ae57b0d733ace9c707a6cf4d08d8fc6edee5","src/packed/teddy/README.md":"b4b83fb5afafbbea6cb76fe70f49cc8ced888f682d98abe5ea5773e95d9ec2b0","src/packed/teddy/compile.rs":"aad40b3f93d2c388b409b31fb2795d414a365237789d5b1a7510d97ceb8ce260","src/packed/teddy/mod.rs":"83b52bd80272970ad17234d0db293d17c1710ec582302bf516b203c8edec037e","src/packed/teddy/runtime.rs":"836146e90b320b14fa2c65fe4af7915a41f6fb04408aac5fac731c22ff46adae","src/packed/tests.rs":"b8dc4d3281ecd6d0fa2bf7ef16cf292a467dfdce64e470c7921e983bfa60fee2","src/packed/vector.rs":"ab3c0535fca5f09198d58cbfae44c292aeb3ce44bc92bca36d30dc72963639fc","src/prefilter.rs":"82a3eb6d5c0c3f10bc8d5f57d55d6d14cf4cf21c475bb5253e1921084063b8d7","src/state_id.rs":"519ec8c7bf3fa72103d4c561c193759759f535dca924c9853efe630f406d2029","src/tests.rs":"ee9b85f3c27cb2fba5796e5be8019aafecc13ee9a4f614553f2bc8953f51c6de"},"package":"cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"}

View File

@ -12,14 +12,9 @@
[package]
edition = "2018"
name = "aho-corasick"
version = "0.7.19"
version = "0.7.20"
authors = ["Andrew Gallant <jamslam@gmail.com>"]
exclude = [
"/aho-corasick-debug",
"/ci/*",
"/.travis.yml",
"/appveyor.yml",
]
exclude = ["/aho-corasick-debug"]
autotests = false
description = "Fast multiple substring searching."
homepage = "https://github.com/BurntSushi/aho-corasick"
@ -32,7 +27,7 @@ keywords = [
"multi",
]
categories = ["text-processing"]
license = "Unlicense/MIT"
license = "Unlicense OR MIT"
repository = "https://github.com/BurntSushi/aho-corasick"
[profile.bench]

View File

@ -9,7 +9,7 @@ Features include case insensitive matching, overlapping matches, fast searching
via SIMD and optional full DFA construction and search & replace in streams.
[![Build status](https://github.com/BurntSushi/aho-corasick/workflows/ci/badge.svg)](https://github.com/BurntSushi/aho-corasick/actions)
[![](https://meritbadge.herokuapp.com/aho-corasick)](https://crates.io/crates/aho-corasick)
[![crates.io](https://img.shields.io/crates/v/aho-corasick.svg)](https://crates.io/crates/aho-corasick)
Dual-licensed under MIT or the [UNLICENSE](https://unlicense.org/).

View File

@ -1795,9 +1795,12 @@ impl AhoCorasickBuilder {
/// Enabling this option does not change the search algorithm, but it may
/// increase the size of the automaton.
///
/// **NOTE:** In the future, support for full Unicode case insensitivity
/// may be added, but ASCII case insensitivity is comparatively much
/// simpler to add.
/// **NOTE:** It is unlikely that support for Unicode case folding will
/// be added in the future. The ASCII case works via a simple hack to the
/// underlying automaton, but full Unicode handling requires a fair bit of
/// sophistication. If you do need Unicode handling, you might consider
/// using the [`regex` crate](https://docs.rs/regex) or the lower level
/// [`regex-automata` crate](https://docs.rs/regex-automata).
///
/// # Examples
///

View File

@ -68,11 +68,11 @@ use crate::Match;
///
/// Every automaton has exactly one fail state, one dead state and exactly one
/// start state. Generally, these correspond to the first, second and third
/// states, respectively. The failure state is always treated as a sentinel.
/// That is, no correct Aho-Corasick automaton will ever transition into the
/// fail state. The dead state, however, can be transitioned into, but only
/// when leftmost-first or leftmost-longest match semantics are enabled and
/// only when at least one match has been observed.
/// states, respectively. The dead state is always treated as a sentinel. That
/// is, no correct Aho-Corasick automaton will ever transition into the fail
/// state. The dead state, however, can be transitioned into, but only when
/// leftmost-first or leftmost-longest match semantics are enabled and only
/// when at least one match has been observed.
///
/// Every automaton also has one or more match states, such that
/// `Automaton::is_match_state(id)` returns `true` if and only if `id`
@ -340,7 +340,7 @@ pub trait Automaton {
// dead states are used to stop a search.)
debug_assert!(
last_match.is_some() || self.anchored(),
"failure state should only be seen after match"
"dead state should only be seen after match"
);
return last_match;
}
@ -455,7 +455,7 @@ pub trait Automaton {
// case, dead states are used to stop a search.)
debug_assert!(
last_match.is_some() || self.anchored(),
"failure state should only be seen after match"
"dead state should only be seen after match"
);
return last_match;
}

View File

@ -65,7 +65,7 @@ pub struct NFA<S> {
/// A set of equivalence classes in terms of bytes. We compute this while
/// building the NFA, but don't use it in the NFA's states. Instead, we
/// use this for building the DFA. We store it on the NFA since it's easy
/// to compute while visiting the the patterns.
/// to compute while visiting the patterns.
byte_classes: ByteClasses,
/// A set of states. Each state defines its own transitions, a fail
/// transition and a set of indices corresponding to matches.
@ -313,17 +313,6 @@ impl<S: StateID> State<S> {
!self.matches.is_empty()
}
fn get_longest_match_len(&self) -> Option<usize> {
// Why is this true? Because the first match in any matching state
// will always correspond to the match added to it during trie
// construction (since when we copy matches due to failure transitions,
// we always append them). Therefore, it follows that the first match
// must always be longest since any subsequent match must be from a
// failure transition, and a failure transition by construction points
// to a proper suffix. A proper suffix is, by definition, smaller.
self.matches.get(0).map(|&(_, len)| len)
}
fn next_state(&self, input: u8) -> S {
self.trans.next_state(input)
}
@ -649,11 +638,7 @@ impl<'a, S: StateID> Compiler<'a, S> {
self.add_start_state_loop();
self.add_dead_state_loop();
if !self.builder.anchored {
if self.match_kind().is_leftmost() {
self.fill_failure_transitions_leftmost();
} else {
self.fill_failure_transitions_standard();
}
self.fill_failure_transitions();
}
self.close_start_state_loop();
self.nfa.byte_classes = self.byte_classes.build();
@ -739,7 +724,8 @@ impl<'a, S: StateID> Compiler<'a, S> {
}
/// This routine creates failure transitions according to the standard
/// textbook formulation of the Aho-Corasick algorithm.
/// textbook formulation of the Aho-Corasick algorithm, with a couple small
/// tweaks to support "leftmost" semantics.
///
/// Building failure transitions is the most interesting part of building
/// the Aho-Corasick automaton, because they are what allow searches to
@ -807,11 +793,15 @@ impl<'a, S: StateID> Compiler<'a, S> {
/// 'abcd', 'b', 'bcd' and 'cd':
///
/// ```ignore
/// - a - S1 - b - S2 - c - S3 - d - S4*
/// /
/// S0 - b - S5* - c - S6 - d - S7*
/// \
/// - c - S8 - d - S9*
/// - a - S1 - b - S2* - c - S3 - d - S4*
/// / / /
/// / ------- -------
/// / / /
/// S0 --- b - S5* - c - S6 - d - S7*
/// \ /
/// \ --------
/// \ /
/// - c - S8 - d - S9*
/// ```
///
/// The failure transitions for this trie are defined from S2 to S5,
@ -839,20 +829,50 @@ impl<'a, S: StateID> Compiler<'a, S> {
/// We don't actually use recursion to implement this, but instead, use a
/// breadth first search of the automaton. Our base case is the start
/// state, whose failure transition is just a transition to itself.
fn fill_failure_transitions_standard(&mut self) {
///
/// When building a leftmost automaton, we proceed as above, but only
/// include a subset of failure transitions. Namely, we omit any failure
/// transitions that appear after a match state in the trie. This is
/// because failure transitions always point back to a proper suffix of
/// what has been seen so far. Thus, following a failure transition after
/// a match implies looking for a match that starts after the one that has
/// already been seen, which is of course therefore not the leftmost match.
///
/// N.B. I came up with this algorithm on my own, and after scouring all of
/// the other AC implementations I know of (Perl, Snort, many on GitHub).
/// I couldn't find any that implement leftmost semantics like this.
/// Perl of course needs leftmost-first semantics, but they implement it
/// with a seeming hack at *search* time instead of encoding it into the
/// automaton. There are also a couple Java libraries that support leftmost
/// longest semantics, but they do it by building a queue of matches at
/// search time, which is even worse than what Perl is doing. ---AG
fn fill_failure_transitions(&mut self) {
let kind = self.match_kind();
// Initialize the queue for breadth first search with all transitions
// out of the start state. We handle the start state specially because
// we only want to follow non-self transitions. If we followed self
// transitions, then this would never terminate.
let mut queue = VecDeque::new();
let mut seen = self.queued_set();
for b in AllBytesIter::new() {
let next = self.nfa.start().next_state(b);
if next != self.nfa.start_id {
if !seen.contains(next) {
queue.push_back(next);
seen.insert(next);
}
let mut it = self.nfa.iter_transitions_mut(self.nfa.start_id);
while let Some((_, next)) = it.next() {
// Skip anything we've seen before and any self-transitions on the
// start state.
if next == it.nfa().start_id || seen.contains(next) {
continue;
}
queue.push_back(next);
seen.insert(next);
// Under leftmost semantics, if a state immediately following
// the start state is a match state, then we never want to
// follow its failure transition since the failure transition
// necessarily leads back to the start state, which we never
// want to do for leftmost matching after a match has been
// found.
//
// We apply the same logic to non-start states below as well.
if kind.is_leftmost() && it.nfa().state(next).is_match() {
it.nfa().state_mut(next).fail = dead_id();
}
}
while let Some(id) = queue.pop_front() {
@ -870,6 +890,31 @@ impl<'a, S: StateID> Compiler<'a, S> {
queue.push_back(next);
seen.insert(next);
// As above for start states, under leftmost semantics, once
// we see a match all subsequent states should have no failure
// transitions because failure transitions always imply looking
// for a match that is a suffix of what has been seen so far
// (where "seen so far" corresponds to the string formed by
// following the transitions from the start state to the
// current state). Under leftmost semantics, we specifically do
// not want to allow this to happen because we always want to
// report the match found at the leftmost position.
//
// The difference between leftmost-first and leftmost-longest
// occurs previously while we build the trie. For
// leftmost-first, we simply omit any entries that would
// otherwise require passing through a match state.
//
// Note that for correctness, the failure transition has to be
// set to the dead state for ALL states following a match, not
// just the match state itself. However, by setting the failure
// transition to the dead state on all match states, the dead
// state will automatically propagate to all subsequent states
// via the failure state computation below.
if kind.is_leftmost() && it.nfa().state(next).is_match() {
it.nfa().state_mut(next).fail = dead_id();
continue;
}
let mut fail = it.nfa().state(id).fail;
while it.nfa().state(fail).next_state(b) == fail_id() {
fail = it.nfa().state(fail).fail;
@ -887,217 +932,9 @@ impl<'a, S: StateID> Compiler<'a, S> {
// in addition to its own. For the non-overlapping case, such
// states only report the first match, which is never empty since
// it isn't a start state.
it.nfa().copy_empty_matches(id);
}
}
/// This routine is just like fill_failure_transitions_standard, except
/// it adds failure transitions in a way that preserves leftmost match
/// semantics (for both leftmost-first and leftmost-longest).
///
/// The algorithms are so similar that it would be possible to write it
/// generically. But doing so without overhead would require a bit of
/// ceremony, so we just copy it and add in the extra leftmost logic.
/// Moreover, the standard algorithm above is so simple that it feels like
/// a crime to disturb it.
///
/// In effect, this proceeds just like the standard approach, but we
/// specifically add only a subset of all failure transitions. Namely, we
/// only add failure transitions that either do not occur after a match
/// or failure transitions that do occur after a match but preserve the
/// match. The comments in the implementation below should help.
///
/// N.B. The only differences in the automaton between leftmost-first and
/// leftmost-longest are in trie construction. Otherwise, both have exactly
/// the same set of failure transitions. leftmost-longest adds everything
/// to the trie, where as leftmost-first skips any patterns for which there
/// exists a prefix of it that was added earlier.
///
/// N.B. I came up with this algorithm on my own, and after scouring all of
/// the other AC implementations I know of (Perl, Snort, many on GitHub).
/// I couldn't find any that implement leftmost semantics like this.
/// Perl of course needs leftmost-first semantics, but they implement it
/// with a seeming hack at *search* time instead of encoding it into the
/// automaton. There are also a couple Java libraries that support leftmost
/// longest semantics, but they do it by building a queue of matches at
/// search time, which is even worse than what Perl is doing. ---AG
fn fill_failure_transitions_leftmost(&mut self) {
/// Represents an item in our queue of states to process.
///
/// Fundamentally, this queue serves the same purpose as the queue
/// for filling failure transitions using the standard formulation.
/// In the leftmost case, though, we need to track a bit more
/// information. See comments below.
#[derive(Clone, Copy, Debug)]
struct QueuedState<S> {
/// The id of the state to visit.
id: S,
/// The depth at which the first match was observed in the path
/// to this state. Note that this corresponds to the depth at
/// which the beginning of the match was detected. If no match
/// has been seen, then this is None.
match_at_depth: Option<usize>,
}
impl<S: StateID> QueuedState<S> {
/// Create a queued state corresponding to the given NFA's start
/// state.
fn start(nfa: &NFA<S>) -> QueuedState<S> {
let match_at_depth =
if nfa.start().is_match() { Some(0) } else { None };
QueuedState { id: nfa.start_id, match_at_depth }
if !kind.is_leftmost() {
it.nfa().copy_empty_matches(id);
}
/// Return the next state to queue up. The given id must be a state
/// corresponding to a single transition from this queued state.
fn next_queued_state(
&self,
nfa: &NFA<S>,
id: S,
) -> QueuedState<S> {
let match_at_depth = self.next_match_at_depth(nfa, id);
QueuedState { id, match_at_depth }
}
/// Return the earliest depth at which a match has occurred for
/// the given state. The given state must correspond to a single
/// transition from this queued state.
fn next_match_at_depth(
&self,
nfa: &NFA<S>,
next: S,
) -> Option<usize> {
// This is a little tricky. If the previous state has already
// seen a match or if `next` isn't a match state, then nothing
// needs to change since a later state cannot find an earlier
// match.
match self.match_at_depth {
Some(x) => return Some(x),
None if nfa.state(next).is_match() => {}
None => return None,
}
let depth = nfa.state(next).depth
- nfa.state(next).get_longest_match_len().unwrap()
+ 1;
Some(depth)
}
}
// Initialize the queue for breadth first search with all transitions
// out of the start state. We handle the start state specially because
// we only want to follow non-self transitions. If we followed self
// transitions, then this would never terminate.
let mut queue: VecDeque<QueuedState<S>> = VecDeque::new();
let mut seen = self.queued_set();
let start = QueuedState::start(&self.nfa);
for b in AllBytesIter::new() {
let next_id = self.nfa.start().next_state(b);
if next_id != start.id {
let next = start.next_queued_state(&self.nfa, next_id);
if !seen.contains(next.id) {
queue.push_back(next);
seen.insert(next.id);
}
// If a state immediately following the start state is a match
// state, then we never want to follow its failure transition
// since the failure transition necessarily leads back to the
// start state, which we never want to do for leftmost matching
// after a match has been found.
//
// N.B. This is a special case of the more general handling
// found below.
if self.nfa.state(next_id).is_match() {
self.nfa.state_mut(next_id).fail = dead_id();
}
}
}
while let Some(item) = queue.pop_front() {
let mut any_trans = false;
let mut it = self.nfa.iter_transitions_mut(item.id);
while let Some((b, next_id)) = it.next() {
any_trans = true;
// Queue up the next state.
let next = item.next_queued_state(it.nfa(), next_id);
if seen.contains(next.id) {
// The only way to visit a duplicate state in a transition
// list is when ASCII case insensitivity is enabled. In
// this case, we want to skip it since it's redundant work.
// But it would also end up duplicating matches, which
// results in reporting duplicate matches in some cases.
// See the 'acasei010' regression test.
continue;
}
queue.push_back(next);
seen.insert(next.id);
// Find the failure state for next. Same as standard.
let mut fail = it.nfa().state(item.id).fail;
while it.nfa().state(fail).next_state(b) == fail_id() {
fail = it.nfa().state(fail).fail;
}
fail = it.nfa().state(fail).next_state(b);
// This is the key difference from the standard formulation.
// Namely, if we've seen a match, then we only want a failure
// transition if the failure transition preserves the match
// we've seen. In general, this is not true of all failure
// transitions since they can point back to any suffix of what
// we've seen so far. Instead, we only want to point back to
// suffixes that contain any match we've seen.
//
// We achieve this by comparing the depth of the failure
// transition with the number of states between this state
// and the beginning of the earliest match detected. If the
// depth of the failure state is smaller than this difference,
// then it cannot contain the match. If it's bigger or equal
// to the difference, then it necessarily includes the match
// we've seen since all failure transitions correspond to a
// suffix.
//
// If we've determined that we don't want the failure
// transition, then we set this state's failure transition to
// the dead state. In other words, when a search hits this
// state, it will not continue and correctly stop. (N.B. A
// dead state is different than a fail state. A dead state
// MUST be preceded by a match and acts as a sentinel to search
// routines to terminate.)
//
// Understanding this is tricky, and it took me several days
// to think through this and get it right. If you want to grok
// it, then I'd recommend: 1) switch the implementation to
// always use the standard algorithm for filling in failure
// transitions, 2) run the test suite and 3) examine the test
// failures. Write out the automatons for them and try to work
// backwards by figuring out which failure transitions should
// be removed. You should arrive at the same rule used below.
if let Some(match_depth) = next.match_at_depth {
let fail_depth = it.nfa().state(fail).depth;
let next_depth = it.nfa().state(next.id).depth;
if next_depth - match_depth + 1 > fail_depth {
it.nfa().state_mut(next.id).fail = dead_id();
continue;
}
assert_ne!(
start.id,
it.nfa().state(next.id).fail,
"states that are match states or follow match \
states should never have a failure transition \
back to the start state in leftmost searching",
);
}
it.nfa().state_mut(next.id).fail = fail;
it.nfa().copy_matches(fail, next.id);
}
// If there are no transitions for this state and if it's a match
// state, then we must set its failure transition to the dead
// state since we never want it to restart the search.
if !any_trans && it.nfa().state(item.id).is_match() {
it.nfa().state_mut(item.id).fail = dead_id();
}
// We don't need to copy empty matches from the start state here
// because that's only necessary for overlapping matches and
// leftmost match kinds don't support overlapping matches.
}
}
@ -1176,7 +1013,7 @@ impl<'a, S: StateID> Compiler<'a, S> {
fn calculate_size(&mut self) {
let mut size = 0;
for state in &self.nfa.states {
size += state.heap_bytes();
size += size_of::<State<S>>() + state.heap_bytes();
}
self.nfa.heap_bytes = size;
}

View File

@ -4,7 +4,7 @@ number of patterns.
This sub-module provides vectorized routines for quickly finding matches of a
small number of patterns. In general, users of this crate shouldn't need to
interface with this module directory, as the primary
interface with this module directly, as the primary
[`AhoCorasick`](../struct.AhoCorasick.html)
searcher will use these routines automatically as a prefilter when applicable.
However, in some cases, callers may want to bypass the Aho-Corasick machinery

View File

@ -337,6 +337,7 @@ const LEFTMOST_FIRST: &'static [SearchTest] = &[
&[(0, 0, 1), (2, 7, 9),]
),
t!(leftfirst330, &["a", "abab"], "abab", &[(0, 0, 1), (0, 2, 3)]),
t!(leftfirst400, &["amwix", "samwise", "sam"], "Zsamwix", &[(2, 1, 4)]),
];
/// Like LEFTMOST_FIRST, but for anchored searches.
@ -360,6 +361,7 @@ const ANCHORED_LEFTMOST_FIRST: &'static [SearchTest] = &[
&[(0, 0, 1)]
),
t!(aleftfirst330, &["a", "abab"], "abab", &[(0, 0, 1)]),
t!(aleftfirst400, &["wise", "samwise", "sam"], "samwix", &[(2, 0, 3)]),
];
/// Tests for non-overlapping leftmost-longest match semantics. These tests

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"5779c6bea2555cdabd4560de187ac5e3c88ff2df8172077397643edc51c6fcc3","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"4bd4d352368ac0f5447031d82454490f6ac0c80d2fa4cb64ba0c23c614670d49","build.rs":"88bf7100143c79c0af683da7f28deaac031c9b9b213a6426560dc089b0ba45aa","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/backtrace.rs":"5b4103a7d24d6f438a64b8cc0fafe28d55fc0ca090368174ce44d64e3940badd","src/chain.rs":"6edefc5f3c7d69683095862e54e3bb56faba5b3387bf2eeaed429da090007a0a","src/context.rs":"0bb1566aae147d393796dd6ede6ba329916e0a373b7cbc38335c3eeeb3d48b57","src/ensure.rs":"498bc9c7fb8b93168ed12f532cb97df6ccdda9ce25371586d7f5b1b1c98a14bf","src/error.rs":"e45d4dcfe64b1823b42fbf9bb260e6437987e8c2d51f92434db9d808b36e700a","src/fmt.rs":"c2d4aad6ce20625a70a7c091e3087b6a2c19a4a87c7a12edb4c98978307245ea","src/kind.rs":"332854c5eb07d44447c356a2e7dc585634b0da1ffbbfa81269c369deaefbc247","src/lib.rs":"82011e86fb9b41fe10ab2fde2b797b4858e697e7ead3a5f0d30b018357f1721d","src/macros.rs":"dd35f2ec2a0a25e4504fb04bcd42f6d0963bc0035aaaefc412f5ee1d78945fe1","src/ptr.rs":"f4e28bc9feba1e84160ca9d185008a51b5d72e168e6546f3e942f4258c361e19","src/wrapper.rs":"ff3ad72065a30cc32e9acb0614a30703c49c57b941a335c348b6439af684316b","tests/common/mod.rs":"f9088c2d7afafa64ff730b629272045b776bfafc2f5957508242da630635f2e1","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/drop/mod.rs":"08c3e553c1cc0d2dbd936fc45f4b5b1105057186affd6865e8d261e05f0f0646","tests/test_autotrait.rs":"981e792db353be2f14c7a1cabe43b5f1329c168cb7679077cc2be786a0920d48","tests/test_backtrace.rs":"0e50edbb33b6bd07ba89ff3db72fb7c688ba2a4371fccdbbb20309ab02948b6a","tests/test_boxed.rs":"6b26db0e2eb72afe9af7352ea820837aab90f8d486294616dd5dc34c1b94038c","tests/test_chain.rs":"d5e90e3eba58abc60d241d3aade39e0b8d4006d9a14f3cf015d3d925160b5812","tests/test_context.rs":"8409c53b328562c11e822bd6c3cd17e0d4d50b9bbb8fc3617333fd77303a6a33","tests/test_convert.rs":"7e7a8b4772a427a911014ac4d1083f9519000e786177f898808980dd9bdfde61","tests/test_downcast.rs":"797e69a72d125758c4c4897e5dc776d549d52cc9a6a633e0a33193f588a62b88","tests/test_ensure.rs":"c8137a9565685aedf02b365008b27c707f4c3d81cd2b986b3b7105b426c723b1","tests/test_ffi.rs":"d0cb4c1d6d9154090982dee72ae3ebe05a5981f976058c3250f1c9da5a45edef","tests/test_fmt.rs":"17572596f257aac9aa2ec4620e292ca6a954128b94772bb948399fab53832e70","tests/test_macros.rs":"11f05010bc9b16319884c1286444100e30cddc2ecd1ffe5e0fd3fee5ffb32683","tests/test_repr.rs":"dbb9b04ddbe1ab31eb5331ea69f05bb3a147299da2275a3d4dcc92947b5591b9","tests/test_source.rs":"b80723cf635a4f8c4df21891b34bfab9ed2b2aa407e7a2f826d24e334cd5f88e","tests/ui/chained-comparison.rs":"6504b03d95b5acc232a7f4defc9f343b2be6733bf475fa0992e8e6545b912bd4","tests/ui/chained-comparison.stderr":"7f1d0a8c251b0ede2d30b3087ec157fc660945c97a642c4a5acf5a14ec58de34","tests/ui/empty-ensure.rs":"ab5bf37c846a0d689f26ce9257a27228411ed64154f9c950f1602d88a355d94b","tests/ui/empty-ensure.stderr":"345102cbef47310f2f4066a669199873a627ca4f1fcb885505c6e17d1fc95e88","tests/ui/must-use.rs":"fb59860b43f673bf4a430a6036ba463e95028844d8dd4243cfe5ebc7f2be582f","tests/ui/must-use.stderr":"c2848c5f254b4c061eea6714d9baf709924aba06619eaf2a8b3aee1266b75f9e","tests/ui/no-impl.rs":"fab6cbf2f6ea510b86f567dfb3b7c31250a9fd71ae5d110dbb9188be569ec593","tests/ui/no-impl.stderr":"9d36a96220f0b5a81db027bcba411a61a72cc2e370c38058ab556442e8bb8a8b","tests/ui/temporary-value.rs":"4dcc96271b2403e6372cf4cfc813445e5ce4365fc6e156b6bc38274098499a70","tests/ui/temporary-value.stderr":"64e448b6759cf51d41b1360307a638452bbe53ffa706f93e4a503b712d7b89a8","tests/ui/wrong-interpolation.rs":"9c44d4674c2dccd27b9dedd03341346ec02d993b41793ee89b5755202e7e367e","tests/ui/wrong-interpolation.stderr":"301e60e2eb9401782c7dc0b3580613a4cb2aafd4cc8065734a630a62e1161aa5"},"package":"98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602"}
{"files":{"Cargo.toml":"dab2cfb5a74702e3e10287a09abd9324d515258b3082a7afdda55b72c42f8b16","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"62fc2a591c37e781f76fe4d89bcd964eca4fbde246bc43cd4e2fe9db2d30ee70","build.rs":"88bf7100143c79c0af683da7f28deaac031c9b9b213a6426560dc089b0ba45aa","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/backtrace.rs":"5b4103a7d24d6f438a64b8cc0fafe28d55fc0ca090368174ce44d64e3940badd","src/chain.rs":"6edefc5f3c7d69683095862e54e3bb56faba5b3387bf2eeaed429da090007a0a","src/context.rs":"e129c580b5c2f3017dd977e4122a93f9fbc04b451e930d68f390f51e6be3bdcb","src/ensure.rs":"d4c2588608e529275bfee1c1afc8860d7def868ab01e95a692a995ee06b2936e","src/error.rs":"e45d4dcfe64b1823b42fbf9bb260e6437987e8c2d51f92434db9d808b36e700a","src/fmt.rs":"c2d4aad6ce20625a70a7c091e3087b6a2c19a4a87c7a12edb4c98978307245ea","src/kind.rs":"332854c5eb07d44447c356a2e7dc585634b0da1ffbbfa81269c369deaefbc247","src/lib.rs":"2a963842f4df70e23e1726d37e5a113ab90dd947a9afa09e6d017f254e2da9ae","src/macros.rs":"dd35f2ec2a0a25e4504fb04bcd42f6d0963bc0035aaaefc412f5ee1d78945fe1","src/ptr.rs":"f4e28bc9feba1e84160ca9d185008a51b5d72e168e6546f3e942f4258c361e19","src/wrapper.rs":"ff3ad72065a30cc32e9acb0614a30703c49c57b941a335c348b6439af684316b","tests/common/mod.rs":"f9088c2d7afafa64ff730b629272045b776bfafc2f5957508242da630635f2e1","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/drop/mod.rs":"08c3e553c1cc0d2dbd936fc45f4b5b1105057186affd6865e8d261e05f0f0646","tests/test_autotrait.rs":"ecccf9202a33611f64b76598806aa82abec2560ae058e32f63fb2fb3ef225be9","tests/test_backtrace.rs":"ed144f90bf62cc441de067f6cee09ece94bca9da8f9b492d11d3dc652ba83e26","tests/test_boxed.rs":"6b26db0e2eb72afe9af7352ea820837aab90f8d486294616dd5dc34c1b94038c","tests/test_chain.rs":"3a8a8d7569913bd98c0e27c69d0bda35101e7fde7c056ed57cdd8ed018e4cbcb","tests/test_context.rs":"8409c53b328562c11e822bd6c3cd17e0d4d50b9bbb8fc3617333fd77303a6a33","tests/test_convert.rs":"7e7a8b4772a427a911014ac4d1083f9519000e786177f898808980dd9bdfde61","tests/test_downcast.rs":"797e69a72d125758c4c4897e5dc776d549d52cc9a6a633e0a33193f588a62b88","tests/test_ensure.rs":"3224fe4d9917944292e2458959feead9f80fa45ea1c80fae54b37951d631723a","tests/test_ffi.rs":"d0cb4c1d6d9154090982dee72ae3ebe05a5981f976058c3250f1c9da5a45edef","tests/test_fmt.rs":"17572596f257aac9aa2ec4620e292ca6a954128b94772bb948399fab53832e70","tests/test_macros.rs":"11f05010bc9b16319884c1286444100e30cddc2ecd1ffe5e0fd3fee5ffb32683","tests/test_repr.rs":"b3fa96b52a98b2111e845b59974910acb107a6526514c80fc5d9db7eed402682","tests/test_source.rs":"b80723cf635a4f8c4df21891b34bfab9ed2b2aa407e7a2f826d24e334cd5f88e","tests/ui/chained-comparison.rs":"6504b03d95b5acc232a7f4defc9f343b2be6733bf475fa0992e8e6545b912bd4","tests/ui/chained-comparison.stderr":"7f1d0a8c251b0ede2d30b3087ec157fc660945c97a642c4a5acf5a14ec58de34","tests/ui/empty-ensure.rs":"ab5bf37c846a0d689f26ce9257a27228411ed64154f9c950f1602d88a355d94b","tests/ui/empty-ensure.stderr":"315782f5f4246290fe190e3767b22c3dcaffaabc19c5ace0373537d53e765278","tests/ui/must-use.rs":"fb59860b43f673bf4a430a6036ba463e95028844d8dd4243cfe5ebc7f2be582f","tests/ui/must-use.stderr":"c2848c5f254b4c061eea6714d9baf709924aba06619eaf2a8b3aee1266b75f9e","tests/ui/no-impl.rs":"fab6cbf2f6ea510b86f567dfb3b7c31250a9fd71ae5d110dbb9188be569ec593","tests/ui/no-impl.stderr":"04415aeaa14995f47f06f35fb1f6971d332d2110aabca920c30ab0803d6a0a5e","tests/ui/temporary-value.rs":"4dcc96271b2403e6372cf4cfc813445e5ce4365fc6e156b6bc38274098499a70","tests/ui/temporary-value.stderr":"171f6c1c962503855480696e5d39e68946ec2a027b61a6f36ca1ad1b40265c5d","tests/ui/wrong-interpolation.rs":"9c44d4674c2dccd27b9dedd03341346ec02d993b41793ee89b5755202e7e367e","tests/ui/wrong-interpolation.stderr":"301e60e2eb9401782c7dc0b3580613a4cb2aafd4cc8065734a630a62e1161aa5"},"package":"7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"}

View File

@ -11,9 +11,9 @@
[package]
edition = "2018"
rust-version = "1.38"
rust-version = "1.39"
name = "anyhow"
version = "1.0.65"
version = "1.0.70"
authors = ["David Tolnay <dtolnay@gmail.com>"]
description = "Flexible concrete Error type built on std::error::Error"
documentation = "https://docs.rs/anyhow"
@ -30,11 +30,14 @@ license = "MIT OR Apache-2.0"
repository = "https://github.com/dtolnay/anyhow"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
rustdoc-args = [
"--cfg",
"doc_cfg",
]
targets = ["x86_64-unknown-linux-gnu"]
[lib]
doc-scrape-examples = false
[dependencies.backtrace]
version = "0.3.51"
@ -48,14 +51,14 @@ default-features = false
version = "1.0.6"
[dev-dependencies.syn]
version = "1.0"
version = "2.0"
features = ["full"]
[dev-dependencies.thiserror]
version = "1.0"
[dev-dependencies.trybuild]
version = "1.0.49"
version = "1.0.66"
features = ["diff"]
[features]

View File

@ -174,28 +174,3 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
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.

View File

@ -4,7 +4,7 @@ Anyhow&ensp;¯\\\_(°ペ)\_/¯
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/anyhow-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/anyhow)
[<img alt="crates.io" src="https://img.shields.io/crates/v/anyhow.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/anyhow)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-anyhow-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/anyhow)
[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/anyhow/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/anyhow/actions?query=branch%3Amaster)
[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/anyhow/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/anyhow/actions?query=branch%3Amaster)
This library provides [`anyhow::Error`][Error], a trait object based error type
for easy idiomatic error handling in Rust applications.
@ -16,7 +16,7 @@ for easy idiomatic error handling in Rust applications.
anyhow = "1.0"
```
*Compiler support: requires rustc 1.38+*
*Compiler support: requires rustc 1.39+*
<br>

View File

@ -4,7 +4,7 @@ use core::convert::Infallible;
use core::fmt::{self, Debug, Display, Write};
#[cfg(backtrace)]
use std::any::Demand;
use std::any::{Demand, Provider};
mod ext {
use super::*;
@ -47,7 +47,12 @@ where
where
C: Display + Send + Sync + 'static,
{
self.map_err(|error| error.ext_context(context))
// Not using map_err to save 2 useless frames off the captured backtrace
// in ext_context.
match self {
Ok(ok) => Ok(ok),
Err(error) => Err(error.ext_context(context)),
}
}
fn with_context<C, F>(self, context: F) -> Result<T, Error>
@ -55,7 +60,10 @@ where
C: Display + Send + Sync + 'static,
F: FnOnce() -> C,
{
self.map_err(|error| error.ext_context(context()))
match self {
Ok(ok) => Ok(ok),
Err(error) => Err(error.ext_context(context())),
}
}
}
@ -84,7 +92,12 @@ impl<T> Context<T, Infallible> for Option<T> {
where
C: Display + Send + Sync + 'static,
{
self.ok_or_else(|| Error::from_display(context, backtrace!()))
// Not using ok_or_else to save 2 useless frames off the captured
// backtrace.
match self {
Some(ok) => Ok(ok),
None => Err(Error::from_display(context, backtrace!())),
}
}
fn with_context<C, F>(self, context: F) -> Result<T, Error>
@ -92,7 +105,10 @@ impl<T> Context<T, Infallible> for Option<T> {
C: Display + Send + Sync + 'static,
F: FnOnce() -> C,
{
self.ok_or_else(|| Error::from_display(context(), backtrace!()))
match self {
Some(ok) => Ok(ok),
None => Err(Error::from_display(context(), backtrace!())),
}
}
}
@ -129,7 +145,7 @@ where
#[cfg(backtrace)]
fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
self.error.provide(demand);
StdError::provide(&self.error, demand);
}
}
@ -143,8 +159,7 @@ where
#[cfg(backtrace)]
fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
demand.provide_ref(self.error.backtrace());
self.error.provide(demand);
Provider::provide(&self.error, demand);
}
}

View File

@ -231,6 +231,11 @@ macro_rules! __parse_ensure {
$crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $unsafe $block) $($parse)*} ($($rest)*) $($rest)*)
};
(0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} ($const:tt $block:tt $($dup:tt)*) const {$($body:tt)*} $($rest:tt)*) => {
// TODO: this is mostly useless due to https://github.com/rust-lang/rust/issues/86730
$crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $const $block) $($parse)*} ($($rest)*) $($rest)*)
};
(0 $stack:tt $bail:tt (~$($fuel:tt)*) {($($buf:tt)*) $($parse:tt)*} $dup:tt $lit:literal $($rest:tt)*) => {
$crate::__parse_ensure!(atom $stack $bail ($($fuel)*) {($($buf)* $lit) $($parse)*} ($($rest)*) $($rest)*)
};

View File

@ -210,7 +210,7 @@
//! will require an explicit `.map_err(Error::msg)` when working with a
//! non-Anyhow error type inside a function that returns Anyhow's error type.
#![doc(html_root_url = "https://docs.rs/anyhow/1.0.65")]
#![doc(html_root_url = "https://docs.rs/anyhow/1.0.70")]
#![cfg_attr(backtrace, feature(error_generic_member_access, provide_any))]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![cfg_attr(not(feature = "std"), no_std)]
@ -219,6 +219,8 @@
clippy::doc_markdown,
clippy::enum_glob_use,
clippy::explicit_auto_deref,
clippy::extra_unused_type_parameters,
clippy::let_underscore_untyped,
clippy::missing_errors_doc,
clippy::missing_panics_doc,
clippy::module_name_repetitions,
@ -367,7 +369,7 @@ pub use anyhow as format_err;
/// # Ok(())
/// }
/// ```
#[repr(transparent)]
#[cfg_attr(not(doc), repr(transparent))]
pub struct Error {
inner: Own<ErrorImpl>,
}

View File

@ -1,3 +1,5 @@
#![allow(clippy::extra_unused_type_parameters)]
use anyhow::Error;
#[test]

View File

@ -1,3 +1,5 @@
#![allow(clippy::let_underscore_untyped)]
#[rustversion::not(nightly)]
#[ignore]
#[test]

View File

@ -56,6 +56,7 @@ fn test_default() {
}
#[test]
#[allow(clippy::redundant_clone)]
fn test_clone() {
let e = error();
let mut chain = e.chain().clone();

View File

@ -1,10 +1,12 @@
#![allow(
clippy::bool_to_int_with_if,
clippy::diverging_sub_expression,
clippy::extra_unused_type_parameters,
clippy::if_same_then_else,
clippy::ifs_same_cond,
clippy::items_after_statements,
clippy::let_and_return,
clippy::let_underscore_drop,
clippy::let_underscore_untyped,
clippy::match_bool,
clippy::never_loop,
clippy::overly_complex_bool_expr,
@ -17,10 +19,12 @@
irrefutable_let_patterns
)]
use self::Enum::Generic;
use anyhow::{anyhow, ensure, Chain, Error, Result};
use std::fmt::Debug;
use std::fmt::{self, Debug};
use std::iter;
use std::marker::{PhantomData, PhantomData as P};
use std::mem;
use std::ops::Add;
use std::ptr;
@ -43,6 +47,24 @@ trait Trait: Sized {
impl<T> Trait for T {}
enum Enum<T: ?Sized> {
#[allow(dead_code)]
Thing(PhantomData<T>),
Generic,
}
impl<T: ?Sized> PartialEq for Enum<T> {
fn eq(&self, rhs: &Self) -> bool {
mem::discriminant(self) == mem::discriminant(rhs)
}
}
impl<T: ?Sized> Debug for Enum<T> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("Generic")
}
}
#[track_caller]
fn assert_err<T: Debug>(result: impl FnOnce() -> Result<T>, expected: &'static str) {
let actual = result().unwrap_err().to_string();
@ -355,27 +377,27 @@ fn test_path() {
let test = || Ok(ensure!(E::U::<u8,>>E::U));
assert_err(test, "Condition failed: `E::U::<u8> > E::U` (U vs U)");
let test = || Ok(ensure!(PhantomData::<dyn Debug + Sync> != PhantomData));
let test = || Ok(ensure!(Generic::<dyn Debug + Sync> != Generic));
assert_err(
test,
"Condition failed: `PhantomData::<dyn Debug + Sync> != PhantomData` (PhantomData vs PhantomData)",
"Condition failed: `Generic::<dyn Debug + Sync> != Generic` (Generic vs Generic)",
);
let test = || Ok(ensure!(PhantomData::<dyn Fn() + Sync> != PhantomData));
let test = || Ok(ensure!(Generic::<dyn Fn() + Sync> != Generic));
assert_err(
test,
"Condition failed: `PhantomData::<dyn Fn() + Sync> != PhantomData` (PhantomData vs PhantomData)",
"Condition failed: `Generic::<dyn Fn() + Sync> != Generic` (Generic vs Generic)",
);
#[rustfmt::skip]
let test = || {
Ok(ensure!(
PhantomData::<dyn Fn::() + ::std::marker::Sync> != PhantomData
Generic::<dyn Fn::() + ::std::marker::Sync> != Generic
))
};
assert_err(
test,
"Condition failed: `PhantomData::<dyn Fn() + ::std::marker::Sync> != PhantomData` (PhantomData vs PhantomData)",
"Condition failed: `Generic::<dyn Fn() + ::std::marker::Sync> != Generic` (Generic vs Generic)",
);
}
@ -408,7 +430,7 @@ fn test_trailer() {
let test = || Ok(ensure!(PhantomData::<u8> {} != PhantomData));
assert_err(
test,
"Condition failed: `PhantomData::<u8> {} != PhantomData` (PhantomData vs PhantomData)",
"Condition failed: `PhantomData::<u8> {} != PhantomData` (PhantomData<u8> vs PhantomData<u8>)",
);
let result = Ok::<_, Error>(1);
@ -596,7 +618,7 @@ fn test_as() {
};
assert_err(
test,
"Condition failed: `PhantomData as PhantomData<<i32 as ToOwned>::Owned> != PhantomData` (PhantomData vs PhantomData)",
"Condition failed: `PhantomData as PhantomData<<i32 as ToOwned>::Owned> != PhantomData` (PhantomData<i32> vs PhantomData<i32>)",
);
macro_rules! int {

View File

@ -1,3 +1,5 @@
#![allow(clippy::extra_unused_type_parameters)]
mod drop;
use self::drop::{DetectDrop, Flag};

View File

@ -4,4 +4,9 @@ error: unexpected end of macro invocation
4 | ensure!();
| ^^^^^^^^^ missing tokens in macro arguments
|
note: while trying to match meta-variable `$cond:expr`
--> src/ensure.rs
|
| ($cond:expr $(,)?) => {
| ^^^^^^^^^^
= note: this error originates in the macro `$crate::__parse_ensure` which comes from the expansion of the macro `ensure` (in Nightly builds, run with -Z macro-backtrace for more info)

View File

@ -1,31 +1,31 @@
error[E0599]: the method `anyhow_kind` exists for reference `&Error`, but its trait bounds were not satisfied
--> tests/ui/no-impl.rs:7:13
|
4 | struct Error;
| ------------
| |
| doesn't satisfy `Error: Into<anyhow::Error>`
| doesn't satisfy `Error: anyhow::kind::TraitKind`
| doesn't satisfy `Error: std::fmt::Display`
--> tests/ui/no-impl.rs:7:13
|
4 | struct Error;
| ------------
| |
| doesn't satisfy `Error: Into<anyhow::Error>`
| doesn't satisfy `Error: anyhow::kind::TraitKind`
| doesn't satisfy `Error: std::fmt::Display`
...
7 | let _ = anyhow!(Error);
| ^^^^^^^^^^^^^^ method cannot be called on `&Error` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`Error: Into<anyhow::Error>`
which is required by `Error: anyhow::kind::TraitKind`
`Error: std::fmt::Display`
which is required by `&Error: anyhow::kind::AdhocKind`
`&Error: Into<anyhow::Error>`
which is required by `&Error: anyhow::kind::TraitKind`
note: the following traits must be implemented
--> $RUST/core/src/fmt/mod.rs
|
| pub trait Display {
| ^^^^^^^^^^^^^^^^^
|
::: $RUST/core/src/convert/mod.rs
|
| pub trait Into<T>: Sized {
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `anyhow` (in Nightly builds, run with -Z macro-backtrace for more info)
7 | let _ = anyhow!(Error);
| ^^^^^^^^^^^^^^ method cannot be called on `&Error` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`Error: Into<anyhow::Error>`
which is required by `Error: anyhow::kind::TraitKind`
`Error: std::fmt::Display`
which is required by `&Error: anyhow::kind::AdhocKind`
`&Error: Into<anyhow::Error>`
which is required by `&Error: anyhow::kind::TraitKind`
note: the traits `Into` and `std::fmt::Display` must be implemented
--> $RUST/core/src/fmt/mod.rs
|
| pub trait Display {
| ^^^^^^^^^^^^^^^^^
|
::: $RUST/core/src/convert/mod.rs
|
| pub trait Into<T>: Sized {
| ^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `anyhow` (in Nightly builds, run with -Z macro-backtrace for more info)

View File

@ -4,6 +4,6 @@ error[E0716]: temporary value dropped while borrowed
4 | let _ = anyhow!(&String::new());
| ---------^^^^^^^^^^^^^-
| | |
| | creates a temporary which is freed while still in use
| | creates a temporary value which is freed while still in use
| temporary value is freed at the end of this statement
| argument requires that borrow lasts for `'static`

View File

@ -0,0 +1 @@
{"files":{"Cargo.toml":"d002beb585149d124307b03b7a70ae3e85efe24d2cafdcdef50f80a9b76b54ec","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"5b94948e52c1410eae55fb8e4084e8837d0f8eb0c000698dc13fac591c70dc1b","build.rs":"626c9fc3a055a6b64b6cf85f5aad1b22c9f6a49f9ff163316fa8dac3b34aef75","src/args.rs":"6eed5497db91752b3aae597943c39e769f60406b37055304e69e4699f1f87b15","src/bound.rs":"ea6a8d0c1a33521163e5546463f68f6dbda0d35a59e75597be6bf04e0b7b23ad","src/expand.rs":"989f2447e69c8274ab666b27c3294c258d248d6b979daae16e3c4735d67a2876","src/lib.rs":"41127e36310d2fa515c48c8e591816bcc6d4b118ac3fdaee288d1d4ccd6dffed","src/lifetime.rs":"e5ccfba2fa7ecb226cba247286c661f20a84e9a0ad2d789bdfee166cd5250160","src/parse.rs":"cd9032fe2c6dcf41050b3a59b9fb98eb9700a29bbe2fa011ee2854014c1666b7","src/receiver.rs":"57ce64e282ba537da5e8d14c1fd49574f20255379bf001905809ace6013c4c3e","src/verbatim.rs":"45d0b691fab21f20d3414733f00d82845442d23b6f2547f8d6880a709d0d3b2a","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/executor/mod.rs":"3cf48614288715f625514a73ae642f649c2635a402a3ad90278bbee116a7234c","tests/test.rs":"71751eaa9e549e5fd2c96888bf1d195922492cccb6c6b1dfd13a29aa5e4533c2","tests/ui/arg-implementation-detail.rs":"7199aba887dd0a8a14c86ec16542a73a70244930f8202940f43e40a62f72d200","tests/ui/arg-implementation-detail.stderr":"c3ff1a2a9a9ca4368cb8719e2a035a6d2d45b367212bec2b1fe2712fcfbbbe5d","tests/ui/bare-trait-object.rs":"4546e8bd6682de11920fa4c768295fed61954484ef0550dfadbc5677b77f29a5","tests/ui/bare-trait-object.stderr":"bbdad7cb35b3a92026b85941532964410ae837ea75ea0db0d2ba56a809f20fe9","tests/ui/consider-restricting.rs":"bff794222d9324241155568d541e7beac0238b66ce14039b242d4392f4e531b6","tests/ui/consider-restricting.stderr":"e9b6bb14ab40b55cadae9d5824b9ed09a5dd9375c8443855798e4dd82ab985b6","tests/ui/delimiter-span.rs":"f4fd804223ce3be0d4eecdfd222afdd835c5393e2473ff4932116163943c0bc9","tests/ui/delimiter-span.stderr":"7b5bbe4be3be533d31d1302649b317465bc28cc7f042b98ec78e8b9a82828155","tests/ui/lifetime-defined-here.rs":"3139a3d92cf787c43afd93da2d967ee80d114ee3a0b9c924da9601b5c6614ef5","tests/ui/lifetime-defined-here.stderr":"0d4236821e0f43e5ae38a99319a64020576e78a49a71d8c94eb8a486d384308c","tests/ui/lifetime-span.rs":"bbcaa92c2bc08e18cf0c7e9ca1f0bd8080772ebde8b067d819eb2fd662e47b3b","tests/ui/lifetime-span.stderr":"db67c5078ab66725227b8f4c612ff97b39cb45d5d6b7a4191766a34a6c711547","tests/ui/missing-async-in-impl.rs":"5a5538d08d11c145211a92af0d8973eee8b21f33b90adda85430805bd3dbbc83","tests/ui/missing-async-in-impl.stderr":"2916bc8a51e25f4dd18eaf433b916d533943eac2c1afbee64e9a89e7b928040d","tests/ui/missing-async-in-trait.rs":"dc67241593f270233ba885df92e59164126416e68d49d8d62edc251666b5db6e","tests/ui/missing-async-in-trait.stderr":"67e66e7b19358830deff3ba01f5d701a9ae05c4e6fa9c081c49c1c75efbb7ade","tests/ui/missing-body.rs":"d06c0da8c6044e7c790b924136f167e2edc0d0d3fa01f23521f3f08ca605929b","tests/ui/missing-body.stderr":"e5ee994398bf8294324d61df02467a4229f68f4113bf5acc004851c03d66ec6a","tests/ui/must-use.rs":"75090c7df984df0996464337f60371d198bd0caf3f9f44b10d1e131f15fd4fca","tests/ui/must-use.stderr":"e9989ec6ae4e87f117cd9ffd73e774b5477eb28c9df5b508dbd3654b783e5bf4","tests/ui/self-span.rs":"67ddde05907d7014bfb3f2c63d427b1d72d6c4369a9108a4335dac6bee5832b2","tests/ui/self-span.stderr":"016ef4f29156250f073f4f6cd3096d2889325709bd693938e0d368077b752551","tests/ui/send-not-implemented.rs":"affbbe8bc9c3501d3db3a024e06daa9d076f1d142dba290c7aa1ea119daebd19","tests/ui/send-not-implemented.stderr":"7a652da919da2dd8cd089c331b8cd242951f383153eef036a1fa5086aaed421a","tests/ui/unreachable.rs":"be0aa7cc129fe42a1fbd85e36b3f08c6a2bd16c90ed2e33fc4c50e40ce085bcd","tests/ui/unreachable.stderr":"73beb71cb74076f2cb45485271de31658cf59f4143e62daa34b9f2a8980ddfcd","tests/ui/unsupported-self.rs":"f7855bc39dab1fd2f533fb2e873a27c3757dcb9fb57001e4b19f58d3dda36d01","tests/ui/unsupported-self.stderr":"64fc5d45cb51330f0a1e85e69a28b69ddda12a109aa6a8ba3eaee1ac58d93b5f"},"package":"b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"}

62
vendor/async-trait/Cargo.toml vendored Normal file
View File

@ -0,0 +1,62 @@
# 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.56"
name = "async-trait"
version = "0.1.68"
authors = ["David Tolnay <dtolnay@gmail.com>"]
description = "Type erasure for async trait methods"
documentation = "https://docs.rs/async-trait"
readme = "README.md"
keywords = ["async"]
categories = [
"asynchronous",
"no-std",
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/dtolnay/async-trait"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[lib]
proc-macro = true
[dependencies.proc-macro2]
version = "1.0"
[dependencies.quote]
version = "1.0"
[dependencies.syn]
version = "2.0.9"
features = [
"full",
"visit-mut",
]
[dev-dependencies.futures]
version = "0.3"
[dev-dependencies.rustversion]
version = "1.0"
[dev-dependencies.tracing]
version = "0.1.14"
[dev-dependencies.tracing-attributes]
version = "0.1.14"
[dev-dependencies.trybuild]
version = "1.0.49"
features = ["diff"]

176
vendor/async-trait/LICENSE-APACHE vendored Normal file
View File

@ -0,0 +1,176 @@
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

23
vendor/async-trait/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.

262
vendor/async-trait/README.md vendored Normal file
View File

@ -0,0 +1,262 @@
Async trait methods
===================
[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/async--trait-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/async-trait)
[<img alt="crates.io" src="https://img.shields.io/crates/v/async-trait.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/async-trait)
[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-async--trait-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="20">](https://docs.rs/async-trait)
[<img alt="build status" src="https://img.shields.io/github/actions/workflow/status/dtolnay/async-trait/ci.yml?branch=master&style=for-the-badge" height="20">](https://github.com/dtolnay/async-trait/actions?query=branch%3Amaster)
The initial round of stabilizations for the async/await language feature in Rust
1.39 did not include support for async fn in traits. Trying to include an async
fn in a trait produces the following error:
```rust
trait MyTrait {
async fn f() {}
}
```
```console
error[E0706]: trait fns cannot be declared `async`
--> src/main.rs:4:5
|
4 | async fn f() {}
| ^^^^^^^^^^^^^^^
```
This crate provides an attribute macro to make async fn in traits work.
Please refer to [*why async fn in traits are hard*][hard] for a deeper analysis
of how this implementation differs from what the compiler and language hope to
deliver in the future.
[hard]: https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/
<br>
## Example
This example implements the core of a highly effective advertising platform
using async fn in a trait.
The only thing to notice here is that we write an `#[async_trait]` macro on top
of traits and trait impls that contain async fn, and then they work.
```rust
use async_trait::async_trait;
#[async_trait]
trait Advertisement {
async fn run(&self);
}
struct Modal;
#[async_trait]
impl Advertisement for Modal {
async fn run(&self) {
self.render_fullscreen().await;
for _ in 0..4u16 {
remind_user_to_join_mailing_list().await;
}
self.hide_for_now().await;
}
}
struct AutoplayingVideo {
media_url: String,
}
#[async_trait]
impl Advertisement for AutoplayingVideo {
async fn run(&self) {
let stream = connect(&self.media_url).await;
stream.play().await;
// Video probably persuaded user to join our mailing list!
Modal.run().await;
}
}
```
<br>
## Supported features
It is the intention that all features of Rust traits should work nicely with
\#\[async_trait\], but the edge cases are numerous. *Please file an issue if you
see unexpected borrow checker errors, type errors, or warnings.* There is no use
of `unsafe` in the expanded code, so rest assured that if your code compiles it
can't be that badly broken.
- &#128077;&ensp;Self by value, by reference, by mut reference, or no self;
- &#128077;&ensp;Any number of arguments, any return value;
- &#128077;&ensp;Generic type parameters and lifetime parameters;
- &#128077;&ensp;Associated types;
- &#128077;&ensp;Having async and non-async functions in the same trait;
- &#128077;&ensp;Default implementations provided by the trait;
- &#128077;&ensp;Elided lifetimes;
- &#128077;&ensp;Dyn-capable traits.
<br>
## Explanation
Async fns get transformed into methods that return `Pin<Box<dyn Future + Send +
'async_trait>>` and delegate to a private async freestanding function.
For example the `impl Advertisement for AutoplayingVideo` above would be
expanded as:
```rust
impl Advertisement for AutoplayingVideo {
fn run<'async_trait>(
&'async_trait self,
) -> Pin<Box<dyn std::future::Future<Output = ()> + Send + 'async_trait>>
where
Self: Sync + 'async_trait,
{
async fn run(_self: &AutoplayingVideo) {
/* the original method body */
}
Box::pin(run(self))
}
}
```
<br>
## Non-threadsafe futures
Not all async traits need futures that are `dyn Future + Send`. To avoid having
Send and Sync bounds placed on the async trait methods, invoke the async trait
macro as `#[async_trait(?Send)]` on both the trait and the impl blocks.
<br>
## Elided lifetimes
Be aware that async fn syntax does not allow lifetime elision outside of `&` and
`&mut` references. (This is true even when not using #\[async_trait\].)
Lifetimes must be named or marked by the placeholder `'_`.
Fortunately the compiler is able to diagnose missing lifetimes with a good error
message.
```rust
type Elided<'a> = &'a usize;
#[async_trait]
trait Test {
async fn test(not_okay: Elided, okay: &usize) {}
}
```
```console
error[E0726]: implicit elided lifetime not allowed here
--> src/main.rs:9:29
|
9 | async fn test(not_okay: Elided, okay: &usize) {}
| ^^^^^^- help: indicate the anonymous lifetime: `<'_>`
```
The fix is to name the lifetime or use `'_`.
```rust
#[async_trait]
trait Test {
// either
async fn test<'e>(elided: Elided<'e>) {}
// or
async fn test(elided: Elided<'_>) {}
}
```
<br>
## Dyn traits
Traits with async methods can be used as trait objects as long as they meet the
usual requirements for dyn -- no methods with type parameters, no self by value,
no associated types, etc.
```rust
#[async_trait]
pub trait ObjectSafe {
async fn f(&self);
async fn g(&mut self);
}
impl ObjectSafe for MyType {...}
let value: MyType = ...;
let object = &value as &dyn ObjectSafe; // make trait object
```
The one wrinkle is in traits that provide default implementations of async
methods. In order for the default implementation to produce a future that is
Send, the async\_trait macro must emit a bound of `Self: Sync` on trait methods
that take `&self` and a bound `Self: Send` on trait methods that take `&mut
self`. An example of the former is visible in the expanded code in the
explanation section above.
If you make a trait with async methods that have default implementations,
everything will work except that the trait cannot be used as a trait object.
Creating a value of type `&dyn Trait` will produce an error that looks like
this:
```console
error: the trait `Test` cannot be made into an object
--> src/main.rs:8:5
|
8 | async fn cannot_dyn(&self) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
For traits that need to be object safe and need to have default implementations
for some async methods, there are two resolutions. Either you can add Send
and/or Sync as supertraits (Send if there are `&mut self` methods with default
implementations, Sync if there are `&self` methods with default implementations)
to constrain all implementors of the trait such that the default implementations
are applicable to them:
```rust
#[async_trait]
pub trait ObjectSafe: Sync { // added supertrait
async fn can_dyn(&self) {}
}
let object = &value as &dyn ObjectSafe;
```
or you can strike the problematic methods from your trait object by bounding
them with `Self: Sized`:
```rust
#[async_trait]
pub trait ObjectSafe {
async fn cannot_dyn(&self) where Self: Sized {}
// presumably other methods
}
let object = &value as &dyn ObjectSafe;
```
<br>
#### 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>

31
vendor/async-trait/build.rs vendored Normal file
View File

@ -0,0 +1,31 @@
use std::env;
use std::process::Command;
use std::str;
fn main() {
println!("cargo:rerun-if-changed=build.rs");
let compiler = match rustc_minor_version() {
Some(compiler) => compiler,
None => return,
};
if compiler < 45 {
println!("cargo:rustc-cfg=no_span_mixed_site");
}
if compiler < 47 {
println!("cargo:rustc-cfg=self_span_hack");
}
}
fn rustc_minor_version() -> Option<u32> {
let rustc = env::var_os("RUSTC")?;
let output = Command::new(rustc).arg("--version").output().ok()?;
let version = str::from_utf8(&output.stdout).ok()?;
let mut pieces = version.split('.');
if pieces.next() != Some("rustc 1") {
return None;
}
pieces.next()?.parse().ok()
}

36
vendor/async-trait/src/args.rs vendored Normal file
View File

@ -0,0 +1,36 @@
use proc_macro2::Span;
use syn::parse::{Error, Parse, ParseStream, Result};
use syn::Token;
#[derive(Copy, Clone)]
pub struct Args {
pub local: bool,
}
mod kw {
syn::custom_keyword!(Send);
}
impl Parse for Args {
fn parse(input: ParseStream) -> Result<Self> {
match try_parse(input) {
Ok(args) if input.is_empty() => Ok(args),
_ => Err(error()),
}
}
}
fn try_parse(input: ParseStream) -> Result<Args> {
if input.peek(Token![?]) {
input.parse::<Token![?]>()?;
input.parse::<kw::Send>()?;
Ok(Args { local: true })
} else {
Ok(Args { local: false })
}
}
fn error() -> Error {
let msg = "expected #[async_trait] or #[async_trait(?Send)]";
Error::new(Span::call_site(), msg)
}

48
vendor/async-trait/src/bound.rs vendored Normal file
View File

@ -0,0 +1,48 @@
use proc_macro2::{Ident, Span, TokenStream};
use quote::quote_spanned;
use syn::punctuated::Punctuated;
use syn::{Token, TypeParamBound};
pub type Supertraits = Punctuated<TypeParamBound, Token![+]>;
pub enum InferredBound {
Send,
Sync,
}
pub fn has_bound(supertraits: &Supertraits, bound: &InferredBound) -> bool {
for supertrait in supertraits {
if let TypeParamBound::Trait(supertrait) = supertrait {
if supertrait.path.is_ident(bound)
|| supertrait.path.segments.len() == 3
&& (supertrait.path.segments[0].ident == "std"
|| supertrait.path.segments[0].ident == "core")
&& supertrait.path.segments[1].ident == "marker"
&& supertrait.path.segments[2].ident == *bound
{
return true;
}
}
}
false
}
impl InferredBound {
fn as_str(&self) -> &str {
match self {
InferredBound::Send => "Send",
InferredBound::Sync => "Sync",
}
}
pub fn spanned_path(&self, span: Span) -> TokenStream {
let ident = Ident::new(self.as_str(), span);
quote_spanned!(span=> ::core::marker::#ident)
}
}
impl PartialEq<InferredBound> for Ident {
fn eq(&self, bound: &InferredBound) -> bool {
self == bound.as_str()
}
}

483
vendor/async-trait/src/expand.rs vendored Normal file
View File

@ -0,0 +1,483 @@
use crate::bound::{has_bound, InferredBound, Supertraits};
use crate::lifetime::{AddLifetimeToImplTrait, CollectLifetimes};
use crate::parse::Item;
use crate::receiver::{has_self_in_block, has_self_in_sig, mut_pat, ReplaceSelf};
use crate::verbatim::VerbatimFn;
use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote, quote_spanned, ToTokens};
use std::collections::BTreeSet as Set;
use std::mem;
use syn::punctuated::Punctuated;
use syn::visit_mut::{self, VisitMut};
use syn::{
parse_quote, parse_quote_spanned, Attribute, Block, FnArg, GenericArgument, GenericParam,
Generics, Ident, ImplItem, Lifetime, LifetimeParam, Pat, PatIdent, PathArguments, Receiver,
ReturnType, Signature, Token, TraitItem, Type, TypePath, WhereClause,
};
impl ToTokens for Item {
fn to_tokens(&self, tokens: &mut TokenStream) {
match self {
Item::Trait(item) => item.to_tokens(tokens),
Item::Impl(item) => item.to_tokens(tokens),
}
}
}
#[derive(Clone, Copy)]
enum Context<'a> {
Trait {
generics: &'a Generics,
supertraits: &'a Supertraits,
},
Impl {
impl_generics: &'a Generics,
associated_type_impl_traits: &'a Set<Ident>,
},
}
impl Context<'_> {
fn lifetimes<'a>(&'a self, used: &'a [Lifetime]) -> impl Iterator<Item = &'a LifetimeParam> {
let generics = match self {
Context::Trait { generics, .. } => generics,
Context::Impl { impl_generics, .. } => impl_generics,
};
generics.params.iter().filter_map(move |param| {
if let GenericParam::Lifetime(param) = param {
if used.contains(&param.lifetime) {
return Some(param);
}
}
None
})
}
}
pub fn expand(input: &mut Item, is_local: bool) {
match input {
Item::Trait(input) => {
let context = Context::Trait {
generics: &input.generics,
supertraits: &input.supertraits,
};
for inner in &mut input.items {
if let TraitItem::Fn(method) = inner {
let sig = &mut method.sig;
if sig.asyncness.is_some() {
let block = &mut method.default;
let mut has_self = has_self_in_sig(sig);
method.attrs.push(parse_quote!(#[must_use]));
if let Some(block) = block {
has_self |= has_self_in_block(block);
transform_block(context, sig, block);
method.attrs.push(lint_suppress_with_body());
} else {
method.attrs.push(lint_suppress_without_body());
}
let has_default = method.default.is_some();
transform_sig(context, sig, has_self, has_default, is_local);
}
}
}
}
Item::Impl(input) => {
let mut associated_type_impl_traits = Set::new();
for inner in &input.items {
if let ImplItem::Type(assoc) = inner {
if let Type::ImplTrait(_) = assoc.ty {
associated_type_impl_traits.insert(assoc.ident.clone());
}
}
}
let context = Context::Impl {
impl_generics: &input.generics,
associated_type_impl_traits: &associated_type_impl_traits,
};
for inner in &mut input.items {
match inner {
ImplItem::Fn(method) if method.sig.asyncness.is_some() => {
let sig = &mut method.sig;
let block = &mut method.block;
let has_self = has_self_in_sig(sig) || has_self_in_block(block);
transform_block(context, sig, block);
transform_sig(context, sig, has_self, false, is_local);
method.attrs.push(lint_suppress_with_body());
}
ImplItem::Verbatim(tokens) => {
let mut method = match syn::parse2::<VerbatimFn>(tokens.clone()) {
Ok(method) if method.sig.asyncness.is_some() => method,
_ => continue,
};
let sig = &mut method.sig;
let has_self = has_self_in_sig(sig);
transform_sig(context, sig, has_self, false, is_local);
method.attrs.push(lint_suppress_with_body());
*tokens = quote!(#method);
}
_ => {}
}
}
}
}
}
fn lint_suppress_with_body() -> Attribute {
parse_quote! {
#[allow(
clippy::async_yields_async,
clippy::let_unit_value,
clippy::no_effect_underscore_binding,
clippy::shadow_same,
clippy::type_complexity,
clippy::type_repetition_in_bounds,
clippy::used_underscore_binding
)]
}
}
fn lint_suppress_without_body() -> Attribute {
parse_quote! {
#[allow(
clippy::type_complexity,
clippy::type_repetition_in_bounds
)]
}
}
// Input:
// async fn f<T>(&self, x: &T) -> Ret;
//
// Output:
// fn f<'life0, 'life1, 'async_trait, T>(
// &'life0 self,
// x: &'life1 T,
// ) -> Pin<Box<dyn Future<Output = Ret> + Send + 'async_trait>>
// where
// 'life0: 'async_trait,
// 'life1: 'async_trait,
// T: 'async_trait,
// Self: Sync + 'async_trait;
fn transform_sig(
context: Context,
sig: &mut Signature,
has_self: bool,
has_default: bool,
is_local: bool,
) {
let default_span = sig.asyncness.take().unwrap().span;
sig.fn_token.span = default_span;
let (ret_arrow, ret) = match &sig.output {
ReturnType::Default => (Token![->](default_span), quote_spanned!(default_span=> ())),
ReturnType::Type(arrow, ret) => (*arrow, quote!(#ret)),
};
let mut lifetimes = CollectLifetimes::new();
for arg in sig.inputs.iter_mut() {
match arg {
FnArg::Receiver(arg) => lifetimes.visit_receiver_mut(arg),
FnArg::Typed(arg) => lifetimes.visit_type_mut(&mut arg.ty),
}
}
for param in &mut sig.generics.params {
match param {
GenericParam::Type(param) => {
let param_name = &param.ident;
let span = match param.colon_token.take() {
Some(colon_token) => colon_token.span,
None => param_name.span(),
};
let bounds = mem::replace(&mut param.bounds, Punctuated::new());
where_clause_or_default(&mut sig.generics.where_clause)
.predicates
.push(parse_quote_spanned!(span=> #param_name: 'async_trait + #bounds));
}
GenericParam::Lifetime(param) => {
let param_name = &param.lifetime;
let span = match param.colon_token.take() {
Some(colon_token) => colon_token.span,
None => param_name.span(),
};
let bounds = mem::replace(&mut param.bounds, Punctuated::new());
where_clause_or_default(&mut sig.generics.where_clause)
.predicates
.push(parse_quote_spanned!(span=> #param: 'async_trait + #bounds));
}
GenericParam::Const(_) => {}
}
}
for param in context.lifetimes(&lifetimes.explicit) {
let param = &param.lifetime;
let span = param.span();
where_clause_or_default(&mut sig.generics.where_clause)
.predicates
.push(parse_quote_spanned!(span=> #param: 'async_trait));
}
if sig.generics.lt_token.is_none() {
sig.generics.lt_token = Some(Token![<](sig.ident.span()));
}
if sig.generics.gt_token.is_none() {
sig.generics.gt_token = Some(Token![>](sig.paren_token.span.join()));
}
for elided in lifetimes.elided {
sig.generics.params.push(parse_quote!(#elided));
where_clause_or_default(&mut sig.generics.where_clause)
.predicates
.push(parse_quote_spanned!(elided.span()=> #elided: 'async_trait));
}
sig.generics
.params
.push(parse_quote_spanned!(default_span=> 'async_trait));
if has_self {
let bounds: &[InferredBound] = if let Some(receiver) = sig.receiver() {
match receiver.ty.as_ref() {
// self: &Self
Type::Reference(ty) if ty.mutability.is_none() => &[InferredBound::Sync],
// self: Arc<Self>
Type::Path(ty)
if {
let segment = ty.path.segments.last().unwrap();
segment.ident == "Arc"
&& match &segment.arguments {
PathArguments::AngleBracketed(arguments) => {
arguments.args.len() == 1
&& match &arguments.args[0] {
GenericArgument::Type(Type::Path(arg)) => {
arg.path.is_ident("Self")
}
_ => false,
}
}
_ => false,
}
} =>
{
&[InferredBound::Sync, InferredBound::Send]
}
_ => &[InferredBound::Send],
}
} else {
&[InferredBound::Send]
};
let bounds = bounds.iter().filter_map(|bound| {
let assume_bound = match context {
Context::Trait { supertraits, .. } => !has_default || has_bound(supertraits, bound),
Context::Impl { .. } => true,
};
if assume_bound || is_local {
None
} else {
Some(bound.spanned_path(default_span))
}
});
where_clause_or_default(&mut sig.generics.where_clause)
.predicates
.push(parse_quote_spanned! {default_span=>
Self: #(#bounds +)* 'async_trait
});
}
for (i, arg) in sig.inputs.iter_mut().enumerate() {
match arg {
FnArg::Receiver(receiver) => {
if receiver.reference.is_none() {
receiver.mutability = None;
}
}
FnArg::Typed(arg) => {
if match *arg.ty {
Type::Reference(_) => false,
_ => true,
} {
if let Pat::Ident(pat) = &mut *arg.pat {
pat.by_ref = None;
pat.mutability = None;
} else {
let positional = positional_arg(i, &arg.pat);
let m = mut_pat(&mut arg.pat);
arg.pat = parse_quote!(#m #positional);
}
}
AddLifetimeToImplTrait.visit_type_mut(&mut arg.ty);
}
}
}
let bounds = if is_local {
quote_spanned!(default_span=> 'async_trait)
} else {
quote_spanned!(default_span=> ::core::marker::Send + 'async_trait)
};
sig.output = parse_quote_spanned! {default_span=>
#ret_arrow ::core::pin::Pin<Box<
dyn ::core::future::Future<Output = #ret> + #bounds
>>
};
}
// Input:
// async fn f<T>(&self, x: &T, (a, b): (A, B)) -> Ret {
// self + x + a + b
// }
//
// Output:
// Box::pin(async move {
// let ___ret: Ret = {
// let __self = self;
// let x = x;
// let (a, b) = __arg1;
//
// __self + x + a + b
// };
//
// ___ret
// })
fn transform_block(context: Context, sig: &mut Signature, block: &mut Block) {
let mut self_span = None;
let decls = sig
.inputs
.iter()
.enumerate()
.map(|(i, arg)| match arg {
FnArg::Receiver(Receiver {
self_token,
mutability,
..
}) => {
let ident = Ident::new("__self", self_token.span);
self_span = Some(self_token.span);
quote!(let #mutability #ident = #self_token;)
}
FnArg::Typed(arg) => {
// If there is a #[cfg(...)] attribute that selectively enables
// the parameter, forward it to the variable.
//
// This is currently not applied to the `self` parameter.
let attrs = arg.attrs.iter().filter(|attr| attr.path().is_ident("cfg"));
if let Type::Reference(_) = *arg.ty {
quote!()
} else if let Pat::Ident(PatIdent {
ident, mutability, ..
}) = &*arg.pat
{
quote! {
#(#attrs)*
let #mutability #ident = #ident;
}
} else {
let pat = &arg.pat;
let ident = positional_arg(i, pat);
if let Pat::Wild(_) = **pat {
quote! {
#(#attrs)*
let #ident = #ident;
}
} else {
quote! {
#(#attrs)*
let #pat = {
let #ident = #ident;
#ident
};
}
}
}
}
})
.collect::<Vec<_>>();
if let Some(span) = self_span {
let mut replace_self = ReplaceSelf(span);
replace_self.visit_block_mut(block);
}
let stmts = &block.stmts;
let let_ret = match &mut sig.output {
ReturnType::Default => quote_spanned! {block.brace_token.span=>
#(#decls)*
let _: () = { #(#stmts)* };
},
ReturnType::Type(_, ret) => {
if contains_associated_type_impl_trait(context, ret) {
if decls.is_empty() {
quote!(#(#stmts)*)
} else {
quote!(#(#decls)* { #(#stmts)* })
}
} else {
quote_spanned! {block.brace_token.span=>
if let ::core::option::Option::Some(__ret) = ::core::option::Option::None::<#ret> {
return __ret;
}
#(#decls)*
let __ret: #ret = { #(#stmts)* };
#[allow(unreachable_code)]
__ret
}
}
}
};
let box_pin = quote_spanned!(block.brace_token.span=>
Box::pin(async move { #let_ret })
);
block.stmts = parse_quote!(#box_pin);
}
fn positional_arg(i: usize, pat: &Pat) -> Ident {
let span: Span = syn::spanned::Spanned::span(pat);
#[cfg(not(no_span_mixed_site))]
let span = span.resolved_at(Span::mixed_site());
format_ident!("__arg{}", i, span = span)
}
fn contains_associated_type_impl_trait(context: Context, ret: &mut Type) -> bool {
struct AssociatedTypeImplTraits<'a> {
set: &'a Set<Ident>,
contains: bool,
}
impl<'a> VisitMut for AssociatedTypeImplTraits<'a> {
fn visit_type_path_mut(&mut self, ty: &mut TypePath) {
if ty.qself.is_none()
&& ty.path.segments.len() == 2
&& ty.path.segments[0].ident == "Self"
&& self.set.contains(&ty.path.segments[1].ident)
{
self.contains = true;
}
visit_mut::visit_type_path_mut(self, ty);
}
}
match context {
Context::Trait { .. } => false,
Context::Impl {
associated_type_impl_traits,
..
} => {
let mut visit = AssociatedTypeImplTraits {
set: associated_type_impl_traits,
contains: false,
};
visit.visit_type_mut(ret);
visit.contains
}
}
}
fn where_clause_or_default(clause: &mut Option<WhereClause>) -> &mut WhereClause {
clause.get_or_insert_with(|| WhereClause {
where_token: Default::default(),
predicates: Punctuated::new(),
})
}

343
vendor/async-trait/src/lib.rs vendored Normal file
View File

@ -0,0 +1,343 @@
//! [![github]](https://github.com/dtolnay/async-trait)&ensp;[![crates-io]](https://crates.io/crates/async-trait)&ensp;[![docs-rs]](https://docs.rs/async-trait)
//!
//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
//!
//! <br>
//!
//! <h5>Type erasure for async trait methods</h5>
//!
//! The initial round of stabilizations for the async/await language feature in
//! Rust 1.39 did not include support for async fn in traits. Trying to include
//! an async fn in a trait produces the following error:
//!
//! ```compile_fail
//! trait MyTrait {
//! async fn f() {}
//! }
//! ```
//!
//! ```text
//! error[E0706]: trait fns cannot be declared `async`
//! --> src/main.rs:4:5
//! |
//! 4 | async fn f() {}
//! | ^^^^^^^^^^^^^^^
//! ```
//!
//! This crate provides an attribute macro to make async fn in traits work.
//!
//! Please refer to [*why async fn in traits are hard*][hard] for a deeper
//! analysis of how this implementation differs from what the compiler and
//! language hope to deliver in the future.
//!
//! [hard]: https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/
//!
//! <br>
//!
//! # Example
//!
//! This example implements the core of a highly effective advertising platform
//! using async fn in a trait.
//!
//! The only thing to notice here is that we write an `#[async_trait]` macro on
//! top of traits and trait impls that contain async fn, and then they work.
//!
//! ```
//! use async_trait::async_trait;
//!
//! #[async_trait]
//! trait Advertisement {
//! async fn run(&self);
//! }
//!
//! struct Modal;
//!
//! #[async_trait]
//! impl Advertisement for Modal {
//! async fn run(&self) {
//! self.render_fullscreen().await;
//! for _ in 0..4u16 {
//! remind_user_to_join_mailing_list().await;
//! }
//! self.hide_for_now().await;
//! }
//! }
//!
//! struct AutoplayingVideo {
//! media_url: String,
//! }
//!
//! #[async_trait]
//! impl Advertisement for AutoplayingVideo {
//! async fn run(&self) {
//! let stream = connect(&self.media_url).await;
//! stream.play().await;
//!
//! // Video probably persuaded user to join our mailing list!
//! Modal.run().await;
//! }
//! }
//! #
//! # impl Modal {
//! # async fn render_fullscreen(&self) {}
//! # async fn hide_for_now(&self) {}
//! # }
//! #
//! # async fn remind_user_to_join_mailing_list() {}
//! #
//! # struct Stream;
//! # async fn connect(_media_url: &str) -> Stream { Stream }
//! # impl Stream {
//! # async fn play(&self) {}
//! # }
//! ```
//!
//! <br><br>
//!
//! # Supported features
//!
//! It is the intention that all features of Rust traits should work nicely with
//! #\[async_trait\], but the edge cases are numerous. Please file an issue if
//! you see unexpected borrow checker errors, type errors, or warnings. There is
//! no use of `unsafe` in the expanded code, so rest assured that if your code
//! compiles it can't be that badly broken.
//!
//! > &#9745;&emsp;Self by value, by reference, by mut reference, or no self;<br>
//! > &#9745;&emsp;Any number of arguments, any return value;<br>
//! > &#9745;&emsp;Generic type parameters and lifetime parameters;<br>
//! > &#9745;&emsp;Associated types;<br>
//! > &#9745;&emsp;Having async and non-async functions in the same trait;<br>
//! > &#9745;&emsp;Default implementations provided by the trait;<br>
//! > &#9745;&emsp;Elided lifetimes;<br>
//! > &#9745;&emsp;Dyn-capable traits.<br>
//!
//! <br>
//!
//! # Explanation
//!
//! Async fns get transformed into methods that return `Pin<Box<dyn Future +
//! Send + 'async>>` and delegate to a private async freestanding function.
//!
//! For example the `impl Advertisement for AutoplayingVideo` above would be
//! expanded as:
//!
//! ```
//! # const IGNORE: &str = stringify! {
//! impl Advertisement for AutoplayingVideo {
//! fn run<'async>(
//! &'async self,
//! ) -> Pin<Box<dyn core::future::Future<Output = ()> + Send + 'async>>
//! where
//! Self: Sync + 'async,
//! {
//! async fn run(_self: &AutoplayingVideo) {
//! /* the original method body */
//! }
//!
//! Box::pin(run(self))
//! }
//! }
//! # };
//! ```
//!
//! <br><br>
//!
//! # Non-threadsafe futures
//!
//! Not all async traits need futures that are `dyn Future + Send`. To avoid
//! having Send and Sync bounds placed on the async trait methods, invoke the
//! async trait macro as `#[async_trait(?Send)]` on both the trait and the impl
//! blocks.
//!
//! <br>
//!
//! # Elided lifetimes
//!
//! Be aware that async fn syntax does not allow lifetime elision outside of `&`
//! and `&mut` references. (This is true even when not using #\[async_trait\].)
//! Lifetimes must be named or marked by the placeholder `'_`.
//!
//! Fortunately the compiler is able to diagnose missing lifetimes with a good
//! error message.
//!
//! ```compile_fail
//! # use async_trait::async_trait;
//! #
//! type Elided<'a> = &'a usize;
//!
//! #[async_trait]
//! trait Test {
//! async fn test(not_okay: Elided, okay: &usize) {}
//! }
//! ```
//!
//! ```text
//! error[E0726]: implicit elided lifetime not allowed here
//! --> src/main.rs:9:29
//! |
//! 9 | async fn test(not_okay: Elided, okay: &usize) {}
//! | ^^^^^^- help: indicate the anonymous lifetime: `<'_>`
//! ```
//!
//! The fix is to name the lifetime or use `'_`.
//!
//! ```
//! # use async_trait::async_trait;
//! #
//! # type Elided<'a> = &'a usize;
//! #
//! #[async_trait]
//! trait Test {
//! // either
//! async fn test<'e>(elided: Elided<'e>) {}
//! # }
//! # #[async_trait]
//! # trait Test2 {
//! // or
//! async fn test(elided: Elided<'_>) {}
//! }
//! ```
//!
//! <br><br>
//!
//! # Dyn traits
//!
//! Traits with async methods can be used as trait objects as long as they meet
//! the usual requirements for dyn -- no methods with type parameters, no self
//! by value, no associated types, etc.
//!
//! ```
//! # use async_trait::async_trait;
//! #
//! #[async_trait]
//! pub trait ObjectSafe {
//! async fn f(&self);
//! async fn g(&mut self);
//! }
//!
//! # const IGNORE: &str = stringify! {
//! impl ObjectSafe for MyType {...}
//!
//! let value: MyType = ...;
//! # };
//! #
//! # struct MyType;
//! #
//! # #[async_trait]
//! # impl ObjectSafe for MyType {
//! # async fn f(&self) {}
//! # async fn g(&mut self) {}
//! # }
//! #
//! # let value: MyType = MyType;
//! let object = &value as &dyn ObjectSafe; // make trait object
//! ```
//!
//! The one wrinkle is in traits that provide default implementations of async
//! methods. In order for the default implementation to produce a future that is
//! Send, the async_trait macro must emit a bound of `Self: Sync` on trait
//! methods that take `&self` and a bound `Self: Send` on trait methods that
//! take `&mut self`. An example of the former is visible in the expanded code
//! in the explanation section above.
//!
//! If you make a trait with async methods that have default implementations,
//! everything will work except that the trait cannot be used as a trait object.
//! Creating a value of type `&dyn Trait` will produce an error that looks like
//! this:
//!
//! ```text
//! error: the trait `Test` cannot be made into an object
//! --> src/main.rs:8:5
//! |
//! 8 | async fn cannot_dyn(&self) {}
//! | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//! ```
//!
//! For traits that need to be object safe and need to have default
//! implementations for some async methods, there are two resolutions. Either
//! you can add Send and/or Sync as supertraits (Send if there are `&mut self`
//! methods with default implementations, Sync if there are `&self` methods with
//! default implementations) to constrain all implementors of the trait such that
//! the default implementations are applicable to them:
//!
//! ```
//! # use async_trait::async_trait;
//! #
//! #[async_trait]
//! pub trait ObjectSafe: Sync { // added supertrait
//! async fn can_dyn(&self) {}
//! }
//! #
//! # struct MyType;
//! #
//! # #[async_trait]
//! # impl ObjectSafe for MyType {}
//! #
//! # let value = MyType;
//!
//! let object = &value as &dyn ObjectSafe;
//! ```
//!
//! or you can strike the problematic methods from your trait object by
//! bounding them with `Self: Sized`:
//!
//! ```
//! # use async_trait::async_trait;
//! #
//! #[async_trait]
//! pub trait ObjectSafe {
//! async fn cannot_dyn(&self) where Self: Sized {}
//!
//! // presumably other methods
//! }
//! #
//! # struct MyType;
//! #
//! # #[async_trait]
//! # impl ObjectSafe for MyType {}
//! #
//! # let value = MyType;
//!
//! let object = &value as &dyn ObjectSafe;
//! ```
#![doc(html_root_url = "https://docs.rs/async-trait/0.1.68")]
#![allow(
clippy::default_trait_access,
clippy::doc_markdown,
clippy::explicit_auto_deref,
clippy::if_not_else,
clippy::items_after_statements,
clippy::match_like_matches_macro,
clippy::module_name_repetitions,
clippy::shadow_unrelated,
clippy::similar_names,
clippy::too_many_lines
)]
extern crate proc_macro;
mod args;
mod bound;
mod expand;
mod lifetime;
mod parse;
mod receiver;
mod verbatim;
use crate::args::Args;
use crate::expand::expand;
use crate::parse::Item;
use proc_macro::TokenStream;
use quote::quote;
use syn::parse_macro_input;
#[proc_macro_attribute]
pub fn async_trait(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as Args);
let mut item = parse_macro_input!(input as Item);
expand(&mut item, args.local);
TokenStream::from(quote!(#item))
}

112
vendor/async-trait/src/lifetime.rs vendored Normal file
View File

@ -0,0 +1,112 @@
use proc_macro2::{Span, TokenStream};
use std::mem;
use syn::visit_mut::{self, VisitMut};
use syn::{
parse_quote_spanned, token, Expr, GenericArgument, Lifetime, Receiver, ReturnType, Token, Type,
TypeBareFn, TypeImplTrait, TypeParen, TypePtr, TypeReference,
};
pub struct CollectLifetimes {
pub elided: Vec<Lifetime>,
pub explicit: Vec<Lifetime>,
}
impl CollectLifetimes {
pub fn new() -> Self {
CollectLifetimes {
elided: Vec::new(),
explicit: Vec::new(),
}
}
fn visit_opt_lifetime(&mut self, reference: Token![&], lifetime: &mut Option<Lifetime>) {
match lifetime {
None => *lifetime = Some(self.next_lifetime(reference.span)),
Some(lifetime) => self.visit_lifetime(lifetime),
}
}
fn visit_lifetime(&mut self, lifetime: &mut Lifetime) {
if lifetime.ident == "_" {
*lifetime = self.next_lifetime(lifetime.span());
} else {
self.explicit.push(lifetime.clone());
}
}
fn next_lifetime(&mut self, span: Span) -> Lifetime {
let name = format!("'life{}", self.elided.len());
let life = Lifetime::new(&name, span);
self.elided.push(life.clone());
life
}
}
impl VisitMut for CollectLifetimes {
fn visit_receiver_mut(&mut self, arg: &mut Receiver) {
if let Some((reference, lifetime)) = &mut arg.reference {
self.visit_opt_lifetime(*reference, lifetime);
} else {
visit_mut::visit_type_mut(self, &mut arg.ty);
}
}
fn visit_type_reference_mut(&mut self, ty: &mut TypeReference) {
self.visit_opt_lifetime(ty.and_token, &mut ty.lifetime);
visit_mut::visit_type_reference_mut(self, ty);
}
fn visit_generic_argument_mut(&mut self, gen: &mut GenericArgument) {
if let GenericArgument::Lifetime(lifetime) = gen {
self.visit_lifetime(lifetime);
}
visit_mut::visit_generic_argument_mut(self, gen);
}
}
pub struct AddLifetimeToImplTrait;
impl VisitMut for AddLifetimeToImplTrait {
fn visit_type_impl_trait_mut(&mut self, ty: &mut TypeImplTrait) {
let span = ty.impl_token.span;
let lifetime = parse_quote_spanned!(span=> 'async_trait);
ty.bounds.insert(0, lifetime);
if let Some(punct) = ty.bounds.pairs_mut().next().unwrap().punct_mut() {
punct.span = span;
}
visit_mut::visit_type_impl_trait_mut(self, ty);
}
fn visit_type_reference_mut(&mut self, ty: &mut TypeReference) {
parenthesize_impl_trait(&mut ty.elem, ty.and_token.span);
visit_mut::visit_type_reference_mut(self, ty);
}
fn visit_type_ptr_mut(&mut self, ty: &mut TypePtr) {
parenthesize_impl_trait(&mut ty.elem, ty.star_token.span);
visit_mut::visit_type_ptr_mut(self, ty);
}
fn visit_type_bare_fn_mut(&mut self, ty: &mut TypeBareFn) {
if let ReturnType::Type(arrow, return_type) = &mut ty.output {
parenthesize_impl_trait(return_type, arrow.spans[0]);
}
visit_mut::visit_type_bare_fn_mut(self, ty);
}
fn visit_expr_mut(&mut self, _e: &mut Expr) {
// Do not recurse into impl Traits inside of an array length expression.
//
// fn outer(arg: [u8; { fn inner(_: impl Trait) {}; 0 }]);
}
}
fn parenthesize_impl_trait(elem: &mut Type, paren_span: Span) {
if let Type::ImplTrait(_) = *elem {
let placeholder = Type::Verbatim(TokenStream::new());
*elem = Type::Paren(TypeParen {
paren_token: token::Paren(paren_span),
elem: Box::new(mem::replace(elem, placeholder)),
});
}
}

34
vendor/async-trait/src/parse.rs vendored Normal file
View File

@ -0,0 +1,34 @@
use proc_macro2::Span;
use syn::parse::{Error, Parse, ParseStream, Result};
use syn::{Attribute, ItemImpl, ItemTrait, Token};
pub enum Item {
Trait(ItemTrait),
Impl(ItemImpl),
}
impl Parse for Item {
fn parse(input: ParseStream) -> Result<Self> {
let attrs = input.call(Attribute::parse_outer)?;
let mut lookahead = input.lookahead1();
if lookahead.peek(Token![unsafe]) {
let ahead = input.fork();
ahead.parse::<Token![unsafe]>()?;
lookahead = ahead.lookahead1();
}
if lookahead.peek(Token![pub]) || lookahead.peek(Token![trait]) {
let mut item: ItemTrait = input.parse()?;
item.attrs = attrs;
Ok(Item::Trait(item))
} else if lookahead.peek(Token![impl]) {
let mut item: ItemImpl = input.parse()?;
if item.trait_.is_none() {
return Err(Error::new(Span::call_site(), "expected a trait impl"));
}
item.attrs = attrs;
Ok(Item::Impl(item))
} else {
Err(lookahead.error())
}
}
}

173
vendor/async-trait/src/receiver.rs vendored Normal file
View File

@ -0,0 +1,173 @@
use proc_macro2::{Group, Span, TokenStream, TokenTree};
use std::iter::FromIterator;
use syn::visit_mut::{self, VisitMut};
use syn::{
Block, ExprPath, Ident, Item, Macro, Pat, PatIdent, Path, Receiver, Signature, Token, TypePath,
};
pub fn has_self_in_sig(sig: &mut Signature) -> bool {
let mut visitor = HasSelf(false);
visitor.visit_signature_mut(sig);
visitor.0
}
pub fn has_self_in_block(block: &mut Block) -> bool {
let mut visitor = HasSelf(false);
visitor.visit_block_mut(block);
visitor.0
}
fn has_self_in_token_stream(tokens: TokenStream) -> bool {
tokens.into_iter().any(|tt| match tt {
TokenTree::Ident(ident) => ident == "Self",
TokenTree::Group(group) => has_self_in_token_stream(group.stream()),
_ => false,
})
}
pub fn mut_pat(pat: &mut Pat) -> Option<Token![mut]> {
let mut visitor = HasMutPat(None);
visitor.visit_pat_mut(pat);
visitor.0
}
fn contains_fn(tokens: TokenStream) -> bool {
tokens.into_iter().any(|tt| match tt {
TokenTree::Ident(ident) => ident == "fn",
TokenTree::Group(group) => contains_fn(group.stream()),
_ => false,
})
}
struct HasMutPat(Option<Token![mut]>);
impl VisitMut for HasMutPat {
fn visit_pat_ident_mut(&mut self, i: &mut PatIdent) {
if let Some(m) = i.mutability {
self.0 = Some(m);
} else {
visit_mut::visit_pat_ident_mut(self, i);
}
}
}
struct HasSelf(bool);
impl VisitMut for HasSelf {
fn visit_expr_path_mut(&mut self, expr: &mut ExprPath) {
self.0 |= expr.path.segments[0].ident == "Self";
visit_mut::visit_expr_path_mut(self, expr);
}
fn visit_type_path_mut(&mut self, ty: &mut TypePath) {
self.0 |= ty.path.segments[0].ident == "Self";
visit_mut::visit_type_path_mut(self, ty);
}
fn visit_receiver_mut(&mut self, _arg: &mut Receiver) {
self.0 = true;
}
fn visit_item_mut(&mut self, _: &mut Item) {
// Do not recurse into nested items.
}
fn visit_macro_mut(&mut self, mac: &mut Macro) {
if !contains_fn(mac.tokens.clone()) {
self.0 |= has_self_in_token_stream(mac.tokens.clone());
}
}
}
pub struct ReplaceSelf(pub Span);
impl ReplaceSelf {
#[cfg_attr(not(self_span_hack), allow(clippy::unused_self))]
fn prepend_underscore_to_self(&self, ident: &mut Ident) -> bool {
let modified = ident == "self";
if modified {
*ident = Ident::new("__self", ident.span());
#[cfg(self_span_hack)]
ident.set_span(self.0);
}
modified
}
fn visit_token_stream(&mut self, tokens: &mut TokenStream) -> bool {
let mut out = Vec::new();
let mut modified = false;
visit_token_stream_impl(self, tokens.clone(), &mut modified, &mut out);
if modified {
*tokens = TokenStream::from_iter(out);
}
return modified;
fn visit_token_stream_impl(
visitor: &mut ReplaceSelf,
tokens: TokenStream,
modified: &mut bool,
out: &mut Vec<TokenTree>,
) {
for tt in tokens {
match tt {
TokenTree::Ident(mut ident) => {
*modified |= visitor.prepend_underscore_to_self(&mut ident);
out.push(TokenTree::Ident(ident));
}
TokenTree::Group(group) => {
let mut content = group.stream();
*modified |= visitor.visit_token_stream(&mut content);
let mut new = Group::new(group.delimiter(), content);
new.set_span(group.span());
out.push(TokenTree::Group(new));
}
other => out.push(other),
}
}
}
}
}
impl VisitMut for ReplaceSelf {
fn visit_ident_mut(&mut self, i: &mut Ident) {
self.prepend_underscore_to_self(i);
}
fn visit_path_mut(&mut self, p: &mut Path) {
if p.segments.len() == 1 {
// Replace `self`, but not `self::function`.
self.visit_ident_mut(&mut p.segments[0].ident);
}
for segment in &mut p.segments {
self.visit_path_arguments_mut(&mut segment.arguments);
}
}
fn visit_item_mut(&mut self, i: &mut Item) {
// Visit `macro_rules!` because locally defined macros can refer to
// `self`.
//
// Visit `futures::select` and similar select macros, which commonly
// appear syntactically like an item despite expanding to an expression.
//
// Otherwise, do not recurse into nested items.
if let Item::Macro(i) = i {
if i.mac.path.is_ident("macro_rules")
|| i.mac.path.segments.last().unwrap().ident == "select"
{
self.visit_macro_mut(&mut i.mac);
}
}
}
fn visit_macro_mut(&mut self, mac: &mut Macro) {
// We can't tell in general whether `self` inside a macro invocation
// refers to the self in the argument list or a different self
// introduced within the macro. Heuristic: if the macro input contains
// `fn`, then `self` is more likely to refer to something other than the
// outer function's self argument.
if !contains_fn(mac.tokens.clone()) {
self.visit_token_stream(&mut mac.tokens);
}
}
}

34
vendor/async-trait/src/verbatim.rs vendored Normal file
View File

@ -0,0 +1,34 @@
use proc_macro2::TokenStream;
use quote::{ToTokens, TokenStreamExt};
use syn::parse::{Parse, ParseStream, Result};
use syn::{Attribute, Signature, Token, Visibility};
pub struct VerbatimFn {
pub attrs: Vec<Attribute>,
pub vis: Visibility,
pub defaultness: Option<Token![default]>,
pub sig: Signature,
pub semi_token: Token![;],
}
impl Parse for VerbatimFn {
fn parse(input: ParseStream) -> Result<Self> {
Ok(VerbatimFn {
attrs: input.call(Attribute::parse_outer)?,
vis: input.parse()?,
defaultness: input.parse()?,
sig: input.parse()?,
semi_token: input.parse()?,
})
}
}
impl ToTokens for VerbatimFn {
fn to_tokens(&self, tokens: &mut TokenStream) {
tokens.append_all(&self.attrs);
self.vis.to_tokens(tokens);
self.defaultness.to_tokens(tokens);
self.sig.to_tokens(tokens);
self.semi_token.to_tokens(tokens);
}
}

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,36 @@
use std::future::Future;
use std::pin::Pin;
use std::ptr;
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
// Executor for a future that resolves immediately (test only).
#[allow(clippy::missing_panics_doc)]
pub fn block_on_simple<F: Future>(mut fut: F) -> F::Output {
unsafe fn clone(_null: *const ()) -> RawWaker {
unimplemented!()
}
unsafe fn wake(_null: *const ()) {
unimplemented!()
}
unsafe fn wake_by_ref(_null: *const ()) {
unimplemented!()
}
unsafe fn drop(_null: *const ()) {}
let data = ptr::null();
let vtable = &RawWakerVTable::new(clone, wake, wake_by_ref, drop);
let raw_waker = RawWaker::new(data, vtable);
let waker = unsafe { Waker::from_raw(raw_waker) };
let mut cx = Context::from_waker(&waker);
// fut does not move until it gets dropped.
let fut = unsafe { Pin::new_unchecked(&mut fut) };
match fut.poll(&mut cx) {
Poll::Ready(output) => output,
Poll::Pending => panic!("future did not resolve immediately"),
}
}

1605
vendor/async-trait/tests/test.rs vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
use async_trait::async_trait;
pub struct Struct;
#[async_trait]
pub trait Trait {
async fn f((_a, _b): (Struct, Struct)) {
// Expands to something like:
//
// fn f(__arg0: (Struct, Struct)) -> … {
// Box::pin(async move {
// let (_a, _b) = __arg0;
// …
// })
// }
//
// but user's code must not be allowed to name that temporary argument:
let _ = __arg0;
}
}
fn main() {}

View File

@ -0,0 +1,5 @@
error[E0425]: cannot find value `__arg0` in this scope
--> tests/ui/arg-implementation-detail.rs:18:17
|
18 | let _ = __arg0;
| ^^^^^^ not found in this scope

View File

@ -0,0 +1,15 @@
#![deny(bare_trait_objects)]
use async_trait::async_trait;
#[async_trait]
trait Trait {
async fn f(&self);
}
#[async_trait]
impl Trait for Send + Sync {
async fn f(&self) {}
}
fn main() {}

View File

@ -0,0 +1,21 @@
error: trait objects without an explicit `dyn` are deprecated
--> tests/ui/bare-trait-object.rs:11:16
|
11 | impl Trait for Send + Sync {
| ^^^^^^^^^^^
|
= warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
note: the lint level is defined here
--> tests/ui/bare-trait-object.rs:1:9
|
1 | #![deny(bare_trait_objects)]
| ^^^^^^^^^^^^^^^^^^
help: use `dyn`
|
11 | impl Trait for dyn Send + Sync {
| +++
help: alternatively use a blanket implementation to implement `Trait` for all types that also implement `Send + Sync`
|
11 | impl<T: Send + Sync> Trait for T {
| ++++++++++++++++ ~

View File

@ -0,0 +1,26 @@
// https://github.com/rust-lang/rust/issues/93828
use async_trait::async_trait;
pub trait IntoUrl {}
#[async_trait]
pub trait ClientExt {
async fn publish<T: IntoUrl>(&self, url: T);
}
struct Client;
#[async_trait]
impl ClientExt for Client {
async fn publish<T: IntoUrl>(&self, url: T) {}
}
struct Client2;
#[async_trait]
impl ClientExt for Client2 {
async fn publish<T>(&self, url: T) {}
}
fn main() {}

View File

@ -0,0 +1,33 @@
error: future cannot be sent between threads safely
--> tests/ui/consider-restricting.rs:16:49
|
16 | async fn publish<T: IntoUrl>(&self, url: T) {}
| ^^ future created by async block is not `Send`
|
note: captured value is not `Send`
--> tests/ui/consider-restricting.rs:16:41
|
16 | async fn publish<T: IntoUrl>(&self, url: T) {}
| ^^^ has type `T` which is not `Send`
= note: required for the cast from `[async block@$DIR/tests/ui/consider-restricting.rs:16:49: 16:51]` to the object type `dyn Future<Output = ()> + Send`
help: consider further restricting this bound
|
16 | async fn publish<T: IntoUrl + std::marker::Send>(&self, url: T) {}
| +++++++++++++++++++
error: future cannot be sent between threads safely
--> tests/ui/consider-restricting.rs:23:40
|
23 | async fn publish<T>(&self, url: T) {}
| ^^ future created by async block is not `Send`
|
note: captured value is not `Send`
--> tests/ui/consider-restricting.rs:23:32
|
23 | async fn publish<T>(&self, url: T) {}
| ^^^ has type `T` which is not `Send`
= note: required for the cast from `[async block@$DIR/tests/ui/consider-restricting.rs:23:40: 23:42]` to the object type `dyn Future<Output = ()> + Send`
help: consider further restricting this bound
|
23 | async fn publish<T + std::marker::Send>(&self, url: T) {}
| +++++++++++++++++++

View File

@ -0,0 +1,24 @@
#![allow(unused_macro_rules)]
use async_trait::async_trait;
macro_rules! picky {
($(t:tt)*) => {};
}
#[async_trait]
trait Trait {
async fn method();
}
struct Struct;
#[async_trait]
impl Trait for Struct {
async fn method() {
picky!({ 123, self });
picky!({ 123 });
}
}
fn main() {}

View File

@ -0,0 +1,21 @@
error: no rules expected the token `{`
--> tests/ui/delimiter-span.rs:19:16
|
5 | macro_rules! picky {
| ------------------ when calling this macro
...
19 | picky!({ 123, self });
| ^ no rules expected this token in macro call
|
= note: while trying to match sequence start
error: no rules expected the token `{`
--> tests/ui/delimiter-span.rs:20:16
|
5 | macro_rules! picky {
| ------------------ when calling this macro
...
20 | picky!({ 123 });
| ^ no rules expected this token in macro call
|
= note: while trying to match sequence start

View File

@ -0,0 +1,23 @@
use async_trait::async_trait;
#[async_trait]
trait Foo {
async fn bar(&self, x: &str, y: &'_ str) -> &'static str;
}
struct S(String);
#[async_trait]
impl Foo for S {
async fn bar(&self, x: &str, y: &'_ str) -> &'static str {
if false {
&self.0
} else if false {
x
} else {
y
}
}
}
fn main() {}

View File

@ -0,0 +1,29 @@
error: lifetime may not live long enough
--> tests/ui/lifetime-defined-here.rs:12:49
|
12 | async fn bar(&self, x: &str, y: &'_ str) -> &'static str {
| - ^^^^^^^^^^^^ type annotation requires that `'life0` must outlive `'static`
| |
| lifetime `'life0` defined here
error: lifetime may not live long enough
--> tests/ui/lifetime-defined-here.rs:12:49
|
12 | async fn bar(&self, x: &str, y: &'_ str) -> &'static str {
| - ^^^^^^^^^^^^ type annotation requires that `'life1` must outlive `'static`
| |
| lifetime `'life1` defined here
error: lifetime may not live long enough
--> tests/ui/lifetime-defined-here.rs:12:49
|
12 | async fn bar(&self, x: &str, y: &'_ str) -> &'static str {
| -- ^^^^^^^^^^^^ type annotation requires that `'life2` must outlive `'static`
| |
| lifetime `'life2` defined here
help: the following changes may resolve your lifetime errors
|
= help: replace `'life0` with `'static`
= help: replace `'life1` with `'static`
= help: replace `'life2` with `'static`

View File

@ -0,0 +1,36 @@
use async_trait::async_trait;
struct A;
struct B;
#[async_trait]
pub trait Trait<'r> {
async fn method(&'r self);
}
#[async_trait]
impl Trait for A {
async fn method(&self) {}
}
#[async_trait]
impl<'r> Trait<'r> for B {
async fn method(&self) {}
}
#[async_trait]
pub trait Trait2 {
async fn method<'r>(&'r self);
}
#[async_trait]
impl Trait2 for A {
async fn method(&self) {}
}
#[async_trait]
impl<'r> Trait2<'r> for B {
async fn method(&'r self) {}
}
fn main() {}

View File

@ -0,0 +1,24 @@
error[E0726]: implicit elided lifetime not allowed here
--> tests/ui/lifetime-span.rs:12:6
|
12 | impl Trait for A {
| ^^^^^ expected lifetime parameter
|
help: indicate the anonymous lifetime
|
12 | impl Trait<'_> for A {
| ++++
error[E0107]: trait takes 0 lifetime arguments but 1 lifetime argument was supplied
--> tests/ui/lifetime-span.rs:32:10
|
32 | impl<'r> Trait2<'r> for B {
| ^^^^^^---- help: remove these generics
| |
| expected 0 lifetime arguments
|
note: trait defined here, with 0 lifetime parameters
--> tests/ui/lifetime-span.rs:22:11
|
22 | pub trait Trait2 {
| ^^^^^^

View File

@ -0,0 +1,15 @@
use async_trait::async_trait;
#[async_trait]
pub trait Trait {
async fn method();
}
pub struct Struct;
#[async_trait]
impl Trait for Struct {
fn method() {}
}
fn main() {}

View File

@ -0,0 +1,8 @@
error[E0195]: lifetime parameters or bounds on method `method` do not match the trait declaration
--> tests/ui/missing-async-in-impl.rs:12:14
|
5 | async fn method();
| -------- lifetimes in impl do not match this method in trait
...
12 | fn method() {}
| ^ lifetimes do not match method in trait

View File

@ -0,0 +1,15 @@
use async_trait::async_trait;
#[async_trait]
pub trait Trait {
fn method();
}
pub struct Struct;
#[async_trait]
impl Trait for Struct {
async fn method() {}
}
fn main() {}

View File

@ -0,0 +1,8 @@
error[E0195]: lifetime parameters or bounds on method `method` do not match the trait declaration
--> tests/ui/missing-async-in-trait.rs:12:14
|
5 | fn method();
| - lifetimes in impl do not match this method in trait
...
12 | async fn method() {}
| ^^^^^^^^ lifetimes do not match method in trait

View File

@ -0,0 +1,15 @@
use async_trait::async_trait;
#[async_trait]
trait Trait {
async fn f(&self);
}
struct Thing;
#[async_trait]
impl Trait for Thing {
async fn f(&self);
}
fn main() {}

View File

@ -0,0 +1,7 @@
error: associated function in `impl` without body
--> tests/ui/missing-body.rs:12:5
|
12 | async fn f(&self);
| ^^^^^^^^^^^^^^^^^-
| |
| help: provide a definition for the function: `{ <body> }`

21
vendor/async-trait/tests/ui/must-use.rs vendored Normal file
View File

@ -0,0 +1,21 @@
#![deny(unused_must_use)]
use async_trait::async_trait;
#[async_trait]
trait Interface {
async fn f(&self);
}
struct Thing;
#[async_trait]
impl Interface for Thing {
async fn f(&self) {}
}
pub async fn f() {
Thing.f();
}
fn main() {}

View File

@ -0,0 +1,15 @@
error: unused return value of `Interface::f` that must be used
--> tests/ui/must-use.rs:18:5
|
18 | Thing.f();
| ^^^^^^^^^
|
note: the lint level is defined here
--> tests/ui/must-use.rs:1:9
|
1 | #![deny(unused_must_use)]
| ^^^^^^^^^^^^^^^
help: use `let _ = ...` to ignore the resulting value
|
18 | let _ = Thing.f();
| +++++++

View File

@ -0,0 +1,30 @@
use async_trait::async_trait;
pub struct S {}
pub enum E {
V {},
}
#[async_trait]
pub trait Trait {
async fn method(self);
}
#[async_trait]
impl Trait for S {
async fn method(self) {
let _: () = self;
let _: Self = Self;
}
}
#[async_trait]
impl Trait for E {
async fn method(self) {
let _: () = self;
let _: Self = Self::V;
}
}
fn main() {}

View File

@ -0,0 +1,27 @@
error[E0308]: mismatched types
--> tests/ui/self-span.rs:17:21
|
17 | let _: () = self;
| -- ^^^^ expected `()`, found `S`
| |
| expected due to this
error: the `Self` constructor can only be used with tuple or unit structs
--> tests/ui/self-span.rs:18:23
|
18 | let _: Self = Self;
| ^^^^ help: use curly brackets: `Self { /* fields */ }`
error[E0308]: mismatched types
--> tests/ui/self-span.rs:25:21
|
25 | let _: () = self;
| -- ^^^^ expected `()`, found `E`
| |
| expected due to this
error[E0533]: expected value, found struct variant `Self::V`
--> tests/ui/self-span.rs:26:23
|
26 | let _: Self = Self::V;
| ^^^^^^^ not a value

View File

@ -0,0 +1,22 @@
use async_trait::async_trait;
use std::sync::Mutex;
async fn f() {}
#[async_trait]
trait Test {
async fn test(&self) {
let mutex = Mutex::new(());
let _guard = mutex.lock().unwrap();
f().await;
}
async fn test_ret(&self) -> bool {
let mutex = Mutex::new(());
let _guard = mutex.lock().unwrap();
f().await;
true
}
}
fn main() {}

View File

@ -0,0 +1,47 @@
error: future cannot be sent between threads safely
--> tests/ui/send-not-implemented.rs:8:26
|
8 | async fn test(&self) {
| __________________________^
9 | | let mutex = Mutex::new(());
10 | | let _guard = mutex.lock().unwrap();
11 | | f().await;
12 | | }
| |_____^ future created by async block is not `Send`
|
= help: within `[async block@$DIR/tests/ui/send-not-implemented.rs:8:26: 12:6]`, the trait `Send` is not implemented for `MutexGuard<'_, ()>`
note: future is not `Send` as this value is used across an await
--> tests/ui/send-not-implemented.rs:11:12
|
10 | let _guard = mutex.lock().unwrap();
| ------ has type `MutexGuard<'_, ()>` which is not `Send`
11 | f().await;
| ^^^^^^ await occurs here, with `_guard` maybe used later
12 | }
| - `_guard` is later dropped here
= note: required for the cast from `[async block@$DIR/tests/ui/send-not-implemented.rs:8:26: 12:6]` to the object type `dyn Future<Output = ()> + Send`
error: future cannot be sent between threads safely
--> tests/ui/send-not-implemented.rs:14:38
|
14 | async fn test_ret(&self) -> bool {
| ______________________________________^
15 | | let mutex = Mutex::new(());
16 | | let _guard = mutex.lock().unwrap();
17 | | f().await;
18 | | true
19 | | }
| |_____^ future created by async block is not `Send`
|
= help: within `[async block@$DIR/tests/ui/send-not-implemented.rs:14:38: 19:6]`, the trait `Send` is not implemented for `MutexGuard<'_, ()>`
note: future is not `Send` as this value is used across an await
--> tests/ui/send-not-implemented.rs:17:12
|
16 | let _guard = mutex.lock().unwrap();
| ------ has type `MutexGuard<'_, ()>` which is not `Send`
17 | f().await;
| ^^^^^^ await occurs here, with `_guard` maybe used later
18 | true
19 | }
| - `_guard` is later dropped here
= note: required for the cast from `[async block@$DIR/tests/ui/send-not-implemented.rs:14:38: 19:6]` to the object type `dyn Future<Output = bool> + Send`

View File

@ -0,0 +1,20 @@
#![deny(warnings)]
use async_trait::async_trait;
#[async_trait]
pub trait Trait {
async fn f() {
unimplemented!()
}
}
#[async_trait]
pub trait TraitFoo {
async fn f() {
let _y = unimplemented!();
let _z = _y;
}
}
fn main() {}

View File

@ -0,0 +1,14 @@
error: unreachable statement
--> tests/ui/unreachable.rs:16:9
|
15 | let _y = unimplemented!();
| ---------------- any code following this expression is unreachable
16 | let _z = _y;
| ^^^^^^^^^^^^ unreachable statement
|
note: the lint level is defined here
--> tests/ui/unreachable.rs:1:9
|
1 | #![deny(warnings)]
| ^^^^^^^^
= note: `#[deny(unreachable_code)]` implied by `#[deny(warnings)]`

View File

@ -0,0 +1,15 @@
use async_trait::async_trait;
#[async_trait]
pub trait Trait {
async fn method();
}
#[async_trait]
impl Trait for &'static str {
async fn method() {
let _ = Self;
}
}
fn main() {}

View File

@ -0,0 +1,5 @@
error: the `Self` constructor can only be used with tuple or unit structs
--> tests/ui/unsupported-self.rs:11:17
|
11 | let _ = Self;
| ^^^^

File diff suppressed because one or more lines are too long

58
vendor/backtrace/Cargo.lock generated vendored
View File

@ -4,9 +4,9 @@ version = 3
[[package]]
name = "addr2line"
version = "0.17.0"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
dependencies = [
"gimli",
]
@ -19,7 +19,7 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "backtrace"
version = "0.3.66"
version = "0.3.67"
dependencies = [
"addr2line",
"cc",
@ -37,9 +37,9 @@ dependencies = [
[[package]]
name = "cc"
version = "1.0.73"
version = "1.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
[[package]]
name = "cfg-if"
@ -49,30 +49,30 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cpp_demangle"
version = "0.3.5"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f"
checksum = "b446fd40bcc17eddd6a4a78f24315eb90afdb3334999ddfd4909985c47722442"
dependencies = [
"cfg-if",
]
[[package]]
name = "gimli"
version = "0.26.1"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793"
[[package]]
name = "libc"
version = "0.2.126"
version = "0.2.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
[[package]]
name = "libloading"
version = "0.7.3"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
dependencies = [
"cfg-if",
"winapi",
@ -86,36 +86,36 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "miniz_oxide"
version = "0.5.3"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
dependencies = [
"adler",
]
[[package]]
name = "object"
version = "0.29.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb"
dependencies = [
"memchr",
]
[[package]]
name = "proc-macro2"
version = "1.0.40"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.20"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
@ -134,18 +134,18 @@ checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
[[package]]
name = "serde"
version = "1.0.138"
version = "1.0.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1578c6245786b9d168c5447eeacfb96856573ca56c9d68fdcf394be134882a47"
checksum = "e326c9ec8042f1b5da33252c8a37e9ffbd2c9bef0155215b6e6c80c790e05f91"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.138"
version = "1.0.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "023e9b1467aef8a10fb88f25611870ada9800ef7e22afce356bb0d2387b6f27c"
checksum = "42a3df25b0713732468deadad63ab9da1f1fd75a48a15024b50363f128db627e"
dependencies = [
"proc-macro2",
"quote",
@ -154,9 +154,9 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.98"
version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
dependencies = [
"proc-macro2",
"quote",
@ -165,9 +165,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.1"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
[[package]]
name = "winapi"

View File

@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "backtrace"
version = "0.3.66"
version = "0.3.67"
authors = ["The Rust Project Developers"]
build = "build.rs"
autoexamples = true
@ -23,7 +23,7 @@ A library to acquire a stack trace (backtrace) at runtime in a Rust program.
homepage = "https://github.com/rust-lang/backtrace-rs"
documentation = "https://docs.rs/backtrace"
readme = "README.md"
license = "MIT/Apache-2.0"
license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-lang/backtrace-rs"
[[example]]
@ -57,15 +57,21 @@ name = "concurrent-panics"
harness = false
required-features = ["std"]
[[test]]
name = "current-exe-mismatch"
harness = false
required-features = ["std"]
[dependencies.addr2line]
version = "0.17.0"
version = "0.19.0"
default-features = false
[dependencies.cfg-if]
version = "1.0"
[dependencies.cpp_demangle]
version = "0.3.0"
version = "0.4.0"
features = ["alloc"]
optional = true
default-features = false
@ -74,11 +80,11 @@ version = "0.2.94"
default-features = false
[dependencies.miniz_oxide]
version = "0.5.0"
version = "0.6.0"
default-features = false
[dependencies.object]
version = "0.29.0"
version = "0.30.0"
features = [
"read_core",
"elf",

View File

@ -91,7 +91,7 @@ pub fn resolve_addr(ptr: *mut c_void) -> Frame {
}
}
pub unsafe fn trace_unsynchronized<F: FnMut(&super::Frame) -> bool>(mut cb: F) {
unsafe fn trace_unsynchronized<F: FnMut(&super::Frame) -> bool>(mut cb: F) {
let len = miri_backtrace_size(0);
let mut frames = Vec::with_capacity(len);
@ -102,6 +102,8 @@ pub unsafe fn trace_unsynchronized<F: FnMut(&super::Frame) -> bool>(mut cb: F) {
for ptr in frames.iter() {
let frame = resolve_addr(*ptr as *mut c_void);
cb(&super::Frame { inner: frame });
if !cb(&super::Frame { inner: frame }) {
return;
}
}
}

View File

@ -135,7 +135,7 @@ impl BacktraceFrameFmt<'_, '_, '_> {
symbol.name(),
// TODO: this isn't great that we don't end up printing anything
// with non-utf8 filenames. Thankfully almost everything is utf8 so
// this shouldn't be too too bad.
// this shouldn't be too bad.
symbol
.filename()
.and_then(|p| Some(BytesOrWideString::Bytes(p.to_str()?.as_bytes()))),

View File

@ -184,6 +184,8 @@ cfg_if::cfg_if! {
))] {
mod libs_dl_iterate_phdr;
use libs_dl_iterate_phdr::native_libraries;
#[path = "gimli/parse_running_mmaps_unix.rs"]
mod parse_running_mmaps;
} else if #[cfg(target_env = "libnx")] {
mod libs_libnx;
use libs_libnx::native_libraries;

View File

@ -17,6 +17,20 @@ pub(super) fn native_libraries() -> Vec<Library> {
return ret;
}
fn infer_current_exe(base_addr: usize) -> OsString {
if let Ok(entries) = super::parse_running_mmaps::parse_maps() {
let opt_path = entries
.iter()
.find(|e| e.ip_matches(base_addr) && e.pathname().len() > 0)
.map(|e| e.pathname())
.cloned();
if let Some(path) = opt_path {
return path;
}
}
env::current_exe().map(|e| e.into()).unwrap_or_default()
}
// `info` should be a valid pointers.
// `vec` should be a valid pointer to a `std::Vec`.
unsafe extern "C" fn callback(
@ -28,8 +42,12 @@ unsafe extern "C" fn callback(
let libs = &mut *(vec as *mut Vec<Library>);
let is_main_prog = info.dlpi_name.is_null() || *info.dlpi_name == 0;
let name = if is_main_prog {
// The man page for dl_iterate_phdr says that the first object visited by
// callback is the main program; so the first time we encounter a
// nameless entry, we can assume its the main program and try to infer its path.
// After that, we cannot continue that assumption, and we use an empty string.
if libs.is_empty() {
env::current_exe().map(|e| e.into()).unwrap_or_default()
infer_current_exe(info.dlpi_addr as usize)
} else {
OsString::new()
}

View File

@ -113,8 +113,8 @@ fn native_library(i: u32) -> Option<Library> {
// file offset 0 with a nonzero size. For whatever reason when this
// is present it appears to mean that the symbol table is relative
// to just the vmaddr slide for the library. If it's *not* present
// then the symbol table is relative to the the vmaddr slide plus
// the segment's stated address.
// then the symbol table is relative to the vmaddr slide plus the
// segment's stated address.
//
// To handle this situation if we *don't* find a text section at
// file offset zero then we increase the bias by the first text

View File

@ -13,8 +13,8 @@ type MachSection = <Mach as MachHeader>::Section;
type MachNlist = <Mach as MachHeader>::Nlist;
impl Mapping {
// The loading path for OSX is is so different we just have a completely
// different implementation of the function here. On OSX we need to go
// The loading path for macOS is so different we just have a completely
// different implementation of the function here. On macOS we need to go
// probing the filesystem for a bunch of files.
pub fn new(path: &Path) -> Option<Mapping> {
// First up we need to load the unique UUID which is stored in the macho

View File

@ -0,0 +1,242 @@
// Note: This file is only currently used on targets that call out to the code
// in `mod libs_dl_iterate_phdr` (e.g. linux, freebsd, ...); it may be more
// general purpose, but it hasn't been tested elsewhere.
use super::mystd::fs::File;
use super::mystd::io::Read;
use super::mystd::str::FromStr;
use super::{OsString, String, Vec};
#[derive(PartialEq, Eq, Debug)]
pub(super) struct MapsEntry {
/// start (inclusive) and limit (exclusive) of address range.
address: (usize, usize),
/// The perms field are the permissions for the entry
///
/// r = read
/// w = write
/// x = execute
/// s = shared
/// p = private (copy on write)
perms: [char; 4],
/// Offset into the file (or "whatever").
offset: usize,
/// device (major, minor)
dev: (usize, usize),
/// inode on the device. 0 indicates that no inode is associated with the memory region (e.g. uninitalized data aka BSS).
inode: usize,
/// Usually the file backing the mapping.
///
/// Note: The man page for proc includes a note about "coordination" by
/// using readelf to see the Offset field in ELF program headers. pnkfelix
/// is not yet sure if that is intended to be a comment on pathname, or what
/// form/purpose such coordination is meant to have.
///
/// There are also some pseudo-paths:
/// "[stack]": The initial process's (aka main thread's) stack.
/// "[stack:<tid>]": a specific thread's stack. (This was only present for a limited range of Linux verisons; it was determined to be too expensive to provide.)
/// "[vdso]": Virtual dynamically linked shared object
/// "[heap]": The process's heap
///
/// The pathname can be blank, which means it is an anonymous mapping
/// obtained via mmap.
///
/// Newlines in pathname are replaced with an octal escape sequence.
///
/// The pathname may have "(deleted)" appended onto it if the file-backed
/// path has been deleted.
///
/// Note that modifications like the latter two indicated above imply that
/// in general the pathname may be ambiguous. (I.e. you cannot tell if the
/// denoted filename actually ended with the text "(deleted)", or if that
/// was added by the maps rendering.
pathname: OsString,
}
pub(super) fn parse_maps() -> Result<Vec<MapsEntry>, &'static str> {
let mut v = Vec::new();
let mut proc_self_maps =
File::open("/proc/self/maps").map_err(|_| "Couldn't open /proc/self/maps")?;
let mut buf = String::new();
let _bytes_read = proc_self_maps
.read_to_string(&mut buf)
.map_err(|_| "Couldn't read /proc/self/maps")?;
for line in buf.lines() {
v.push(line.parse()?);
}
Ok(v)
}
impl MapsEntry {
pub(super) fn pathname(&self) -> &OsString {
&self.pathname
}
pub(super) fn ip_matches(&self, ip: usize) -> bool {
self.address.0 <= ip && ip < self.address.1
}
}
impl FromStr for MapsEntry {
type Err = &'static str;
// Format: address perms offset dev inode pathname
// e.g.: "ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]"
// e.g.: "7f5985f46000-7f5985f48000 rw-p 00039000 103:06 76021795 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2"
// e.g.: "35b1a21000-35b1a22000 rw-p 00000000 00:00 0"
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut parts = s
.split(' ') // space-separated fields
.filter(|s| s.len() > 0); // multiple spaces implies empty strings that need to be skipped.
let range_str = parts.next().ok_or("Couldn't find address")?;
let perms_str = parts.next().ok_or("Couldn't find permissions")?;
let offset_str = parts.next().ok_or("Couldn't find offset")?;
let dev_str = parts.next().ok_or("Couldn't find dev")?;
let inode_str = parts.next().ok_or("Couldn't find inode")?;
let pathname_str = parts.next().unwrap_or(""); // pathname may be omitted.
let hex = |s| usize::from_str_radix(s, 16).map_err(|_| "Couldn't parse hex number");
let address = {
// This could use `range_str.split_once('-')` once the MSRV passes 1.52.
if let Some(idx) = range_str.find('-') {
let (start, rest) = range_str.split_at(idx);
let (_div, limit) = rest.split_at(1);
(hex(start)?, hex(limit)?)
} else {
return Err("Couldn't parse address range");
}
};
let perms: [char; 4] = {
let mut chars = perms_str.chars();
let mut c = || chars.next().ok_or("insufficient perms");
let perms = [c()?, c()?, c()?, c()?];
if chars.next().is_some() {
return Err("too many perms");
}
perms
};
let offset = hex(offset_str)?;
let dev = {
// This could use `dev_str.split_once(':')` once the MSRV passes 1.52.
if let Some(idx) = dev_str.find(':') {
let (major, rest) = dev_str.split_at(idx);
let (_div, minor) = rest.split_at(1);
(hex(major)?, hex(minor)?)
} else {
return Err("Couldn't parse dev")?;
}
};
let inode = hex(inode_str)?;
let pathname = pathname_str.into();
Ok(MapsEntry {
address,
perms,
offset,
dev,
inode,
pathname,
})
}
}
// Make sure we can parse 64-bit sample output if we're on a 64-bit target.
#[cfg(target_pointer_width = "64")]
#[test]
fn check_maps_entry_parsing_64bit() {
assert_eq!(
"ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 \
[vsyscall]"
.parse::<MapsEntry>()
.unwrap(),
MapsEntry {
address: (0xffffffffff600000, 0xffffffffff601000),
perms: ['-', '-', 'x', 'p'],
offset: 0x00000000,
dev: (0x00, 0x00),
inode: 0x0,
pathname: "[vsyscall]".into(),
}
);
assert_eq!(
"7f5985f46000-7f5985f48000 rw-p 00039000 103:06 76021795 \
/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2"
.parse::<MapsEntry>()
.unwrap(),
MapsEntry {
address: (0x7f5985f46000, 0x7f5985f48000),
perms: ['r', 'w', '-', 'p'],
offset: 0x00039000,
dev: (0x103, 0x06),
inode: 0x76021795,
pathname: "/usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2".into(),
}
);
assert_eq!(
"35b1a21000-35b1a22000 rw-p 00000000 00:00 0"
.parse::<MapsEntry>()
.unwrap(),
MapsEntry {
address: (0x35b1a21000, 0x35b1a22000),
perms: ['r', 'w', '-', 'p'],
offset: 0x00000000,
dev: (0x00, 0x00),
inode: 0x0,
pathname: Default::default(),
}
);
}
// (This output was taken from a 32-bit machine, but will work on any target)
#[test]
fn check_maps_entry_parsing_32bit() {
/* Example snippet of output:
08056000-08077000 rw-p 00000000 00:00 0 [heap]
b7c79000-b7e02000 r--p 00000000 08:01 60662705 /usr/lib/locale/locale-archive
b7e02000-b7e03000 rw-p 00000000 00:00 0
*/
assert_eq!(
"08056000-08077000 rw-p 00000000 00:00 0 \
[heap]"
.parse::<MapsEntry>()
.unwrap(),
MapsEntry {
address: (0x08056000, 0x08077000),
perms: ['r', 'w', '-', 'p'],
offset: 0x00000000,
dev: (0x00, 0x00),
inode: 0x0,
pathname: "[heap]".into(),
}
);
assert_eq!(
"b7c79000-b7e02000 r--p 00000000 08:01 60662705 \
/usr/lib/locale/locale-archive"
.parse::<MapsEntry>()
.unwrap(),
MapsEntry {
address: (0xb7c79000, 0xb7e02000),
perms: ['r', '-', '-', 'p'],
offset: 0x00000000,
dev: (0x08, 0x01),
inode: 0x60662705,
pathname: "/usr/lib/locale/locale-archive".into(),
}
);
assert_eq!(
"b7e02000-b7e03000 rw-p 00000000 00:00 0"
.parse::<MapsEntry>()
.unwrap(),
MapsEntry {
address: (0xb7e02000, 0xb7e03000),
perms: ['r', 'w', '-', 'p'],
offset: 0x00000000,
dev: (0x00, 0x00),
inode: 0x0,
pathname: Default::default(),
}
);
}

View File

@ -162,8 +162,8 @@ macro_rules! ffi {
ffi!($($rest)*);
);
(extern "system" { $(pub fn $name:ident($($args:tt)*) -> $ret:ty;)* } $($rest:tt)*) => (
extern "system" {
($(#[$meta:meta])* extern "system" { $(pub fn $name:ident($($args:tt)*) -> $ret:ty;)* } $($rest:tt)*) => (
$(#[$meta])* extern "system" {
$(pub fn $name($($args)*) -> $ret;)*
}
@ -371,6 +371,7 @@ ffi! {
pub type LPCVOID = *const c_void;
pub type LPMODULEENTRY32W = *mut MODULEENTRY32W;
#[link(name = "kernel32")]
extern "system" {
pub fn GetCurrentProcess() -> HANDLE;
pub fn GetCurrentThread() -> HANDLE;
@ -438,6 +439,7 @@ ffi! {
#[cfg(target_pointer_width = "64")]
ffi! {
#[link(name = "kernel32")]
extern "system" {
pub fn RtlLookupFunctionEntry(
ControlPc: DWORD64,

14
vendor/backtrace/tests/common/mod.rs vendored Normal file
View File

@ -0,0 +1,14 @@
/// Some tests only make sense in contexts where they can re-exec the test
/// itself. Not all contexts support this, so you can call this method to find
/// out which case you are in.
pub fn cannot_reexec_the_test() -> bool {
// These run in docker containers on CI where they can't re-exec the test,
// so just skip these for CI. No other reason this can't run on those
// platforms though.
// Miri does not have support for re-execing a file
cfg!(unix)
&& (cfg!(target_arch = "arm")
|| cfg!(target_arch = "aarch64")
|| cfg!(target_arch = "s390x"))
|| cfg!(miri)
}

View File

@ -9,17 +9,11 @@ const PANICS: usize = 100;
const THREADS: usize = 8;
const VAR: &str = "__THE_TEST_YOU_ARE_LUKE";
mod common;
fn main() {
// These run in docker containers on CI where they can't re-exec the test,
// so just skip these for CI. No other reason this can't run on those
// platforms though.
// Miri does not have support for re-execing a file
if cfg!(unix)
&& (cfg!(target_arch = "arm")
|| cfg!(target_arch = "aarch64")
|| cfg!(target_arch = "s390x"))
|| cfg!(miri)
{
// If we cannot re-exec this test, there's no point in trying to do it.
if common::cannot_reexec_the_test() {
println!("test result: ok");
return;
}

View File

@ -0,0 +1,137 @@
// rust-lang/rust#101913: when you run your program explicitly via `ld.so`,
// `std::env::current_exe` will return the path of *that* program, and not
// the Rust program itself.
use std::io::{BufRead, BufReader};
use std::path::{Path, PathBuf};
use std::process::Command;
mod common;
fn main() {
if std::env::var(VAR).is_err() {
// the parent waits for the child; then we then handle either printing
// "test result: ok", "test result: ignored", or panicking.
match parent() {
Ok(()) => {
println!("test result: ok");
}
Err(EarlyExit::IgnoreTest(_)) => {
println!("test result: ignored");
}
Err(EarlyExit::IoError(e)) => {
println!("{} parent encoutered IoError: {:?}", file!(), e);
panic!();
}
}
} else {
// println!("{} running child", file!());
child().unwrap();
}
}
const VAR: &str = "__THE_TEST_YOU_ARE_LUKE";
#[derive(Debug)]
enum EarlyExit {
IgnoreTest(String),
IoError(std::io::Error),
}
impl From<std::io::Error> for EarlyExit {
fn from(e: std::io::Error) -> Self {
EarlyExit::IoError(e)
}
}
fn parent() -> Result<(), EarlyExit> {
// If we cannot re-exec this test, there's no point in trying to do it.
if common::cannot_reexec_the_test() {
return Err(EarlyExit::IgnoreTest("(cannot reexec)".into()));
}
let me = std::env::current_exe().unwrap();
let ld_so = find_interpreter(&me)?;
// use interp to invoke current exe, yielding child test.
//
// (if you're curious what you might compare this against, you can try
// swapping in the below definition for `result`, which is the easy case of
// not using the ld.so interpreter directly that Rust handled fine even
// prior to resolution of rust-lang/rust#101913.)
//
// let result = Command::new(me).env(VAR, "1").output()?;
let result = Command::new(ld_so).env(VAR, "1").arg(&me).output().unwrap();
if result.status.success() {
return Ok(());
}
println!("stdout:\n{}", String::from_utf8_lossy(&result.stdout));
println!("stderr:\n{}", String::from_utf8_lossy(&result.stderr));
println!("code: {}", result.status);
panic!();
}
fn child() -> Result<(), EarlyExit> {
let bt = backtrace::Backtrace::new();
println!("{:?}", bt);
let mut found_my_name = false;
let my_filename = file!();
'frames: for frame in bt.frames() {
let symbols = frame.symbols();
if symbols.is_empty() {
continue;
}
for sym in symbols {
if let Some(filename) = sym.filename() {
if filename.ends_with(my_filename) {
// huzzah!
found_my_name = true;
break 'frames;
}
}
}
}
assert!(found_my_name);
Ok(())
}
// we use the `readelf` command to extract the path to the interpreter requested
// by our binary.
//
// if we cannot `readelf` for some reason, or if we fail to parse its output,
// then we will just give up on this test (and not treat it as a test failure).
fn find_interpreter(me: &Path) -> Result<PathBuf, EarlyExit> {
let result = Command::new("readelf")
.arg("-l")
.arg(me)
.output()
.map_err(|_err| EarlyExit::IgnoreTest("readelf invocation failed".into()))?;
if result.status.success() {
let r = BufReader::new(&result.stdout[..]);
for line in r.lines() {
let line = line?;
let line = line.trim();
let prefix = "[Requesting program interpreter: ";
// This could use `line.split_once` and `suffix.rsplit_once` once the MSRV passes 1.52
if let Some(idx) = line.find(prefix) {
let (_, suffix) = line.split_at(idx + prefix.len());
if let Some(idx) = suffix.rfind("]") {
let (found_path, _ignore_remainder) = suffix.split_at(idx);
return Ok(found_path.into());
}
}
}
Err(EarlyExit::IgnoreTest(
"could not find interpreter from readelf output".into(),
))
} else {
Err(EarlyExit::IgnoreTest("readelf returned non-success".into()))
}
}

View File

@ -4,7 +4,7 @@ use backtrace::Backtrace;
// function for frames which reports the starting address of a symbol. As a
// result it's only enabled on a few platforms.
const ENABLED: bool = cfg!(all(
// Windows hasn't really been tested, and OSX doesn't support actually
// Windows hasn't really been tested, and macOS doesn't support actually
// finding an enclosing frame, so disable this
target_os = "linux",
// On ARM finding the enclosing function is simply returning the ip itself.

View File

@ -1 +1 @@
{"files":{"Cargo.lock":"ba3f757ac955932ea298d293ce44dfb25e064ffac93e429c13bd684a686d2ec1","Cargo.toml":"3402755896ee085ef905b9ff4d2ed25040e4fd53e254353f1bb044252404072b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0dd882e53de11566d50f8e8e2d5a651bcf3fabee4987d70f306233cf39094ba7","README.md":"2810098d290f3df719e6f41ffca38bb954d0fe62d4e56905a9a2436c4784bebf","RELEASE-NOTES.md":"5aaccee22ad349c72531bdd6c68b233bccc8c1eb23dce2cf5e05ae4498a15a1a","benches/benchmarks.rs":"bc1f603c5aa87627a93eee71eaed64fbd767d013051bac00ea265c16fecb30b9","examples/base64.rs":"f397b8726df41fce0793a8c6ebe95d4651aa37ed746da305032f1e99d9c37235","examples/make_tables.rs":"392f51b3edb1b5a2c62b823337c7785a6b8535f39f09283b1913a5c68fb186bf","icon_CLion.svg":"cffa044ba75cb998ee3306991dc4a3755ec2f39ab95ddd4b74bc21988389020f","src/chunked_encoder.rs":"fba5ea5f1204b9bf11291ec3483bcb23d330101eb2f6635e33cd63e4de13b653","src/decode.rs":"fa18535da4c549bdb29e4c4f074387645467384f88a1ecdb72c31828bd930ee3","src/display.rs":"55f9cd05ba037b77689e2558fa174055fad5273959d1edce3a2289f94244fd5d","src/encode.rs":"8a0a6b71581b4c52c2844111a3611cf73522533452a27f5ef8d09eaa73594e2e","src/lib.rs":"c7b904fac8706bc4758c2763e7a43dc1edd99ed5641ac2355957f6aeff91eece","src/read/decoder.rs":"9a7b65e165f7aed6b007bf7436ac9ba9b03d3b03e9d5a1e16691874e21509ced","src/read/decoder_tests.rs":"aacb7624c33ed6b90e068ff9af6095c839b4088060b4c406c08dce25ce837f6d","src/read/mod.rs":"e0b714eda02d16b1ffa6f78fd09b2f963e01c881b1f7c17b39db4e904be5e746","src/tables.rs":"73ce100fd3f4917ec1e8d9277ff0b956cc2636b33145f101a7cf1a5a8b7bacc1","src/tests.rs":"202ddced9cf52205182c6202e583c4c4f929b9d225fd9d1ebdbfd389cb2df0ba","src/write/encoder.rs":"afabacf7fa54f2ec9b1fe4987de818d368d7470ade0396649743a11c81dba28e","src/write/encoder_string_writer.rs":"3f9109585babe048230659f64973cb1633bbb2ed9de255177336260226127b81","src/write/encoder_tests.rs":"381d7c2871407157c36e909c928307ac0389b3d4504fb80607134e94ac59e68f","src/write/mod.rs":"1503b9457e4f5d2895b24136c3af893f0b7ce18dfe4de1096fc5d17f8d78e99b","tests/decode.rs":"da2cbd49b84e0d8b1d8a52136ba3d97cfb248920a45f9955db1e5bc5367218ce","tests/encode.rs":"5efb6904c36c6f899a05078e5c9be756fc58af1ee9940edfa8dea1ee53675364","tests/helpers.rs":"a76015e4a4e8f98213bdbaa592cd9574ccdc95a28e1b1f835a2753e09fa6037f","tests/tests.rs":"05753e5f1d4a6c75015a5342f9b5dc3073c00bdfe0a829a962f8723321c75549"},"package":"904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"}
{"files":{"Cargo.lock":"0ed67b0f1f68ba5e19475d679df711f1f2c421768462b58e327b5b3ae9111825","Cargo.toml":"ac3f54d7667cfc0baac784fcc6f0a6cc0da9b496af69917fe7abb95f7e3b4a36","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0dd882e53de11566d50f8e8e2d5a651bcf3fabee4987d70f306233cf39094ba7","README.md":"2810098d290f3df719e6f41ffca38bb954d0fe62d4e56905a9a2436c4784bebf","RELEASE-NOTES.md":"ef116f3596474c9920957f65e346d7d1954f194aa3458eac5b626781116c500b","benches/benchmarks.rs":"bc1f603c5aa87627a93eee71eaed64fbd767d013051bac00ea265c16fecb30b9","examples/base64.rs":"f397b8726df41fce0793a8c6ebe95d4651aa37ed746da305032f1e99d9c37235","examples/make_tables.rs":"392f51b3edb1b5a2c62b823337c7785a6b8535f39f09283b1913a5c68fb186bf","icon_CLion.svg":"cffa044ba75cb998ee3306991dc4a3755ec2f39ab95ddd4b74bc21988389020f","src/chunked_encoder.rs":"fba5ea5f1204b9bf11291ec3483bcb23d330101eb2f6635e33cd63e4de13b653","src/decode.rs":"ba67f53612c494281e2e4aae4350165d54ee827ea7e1170b8e02e2db81b55c6e","src/display.rs":"55f9cd05ba037b77689e2558fa174055fad5273959d1edce3a2289f94244fd5d","src/encode.rs":"8a0a6b71581b4c52c2844111a3611cf73522533452a27f5ef8d09eaa73594e2e","src/lib.rs":"c7b904fac8706bc4758c2763e7a43dc1edd99ed5641ac2355957f6aeff91eece","src/read/decoder.rs":"9a7b65e165f7aed6b007bf7436ac9ba9b03d3b03e9d5a1e16691874e21509ced","src/read/decoder_tests.rs":"aacb7624c33ed6b90e068ff9af6095c839b4088060b4c406c08dce25ce837f6d","src/read/mod.rs":"e0b714eda02d16b1ffa6f78fd09b2f963e01c881b1f7c17b39db4e904be5e746","src/tables.rs":"73ce100fd3f4917ec1e8d9277ff0b956cc2636b33145f101a7cf1a5a8b7bacc1","src/tests.rs":"202ddced9cf52205182c6202e583c4c4f929b9d225fd9d1ebdbfd389cb2df0ba","src/write/encoder.rs":"573f058a66f0a6af4215f5ae75a3e96b07a5e345975693abe30bd1e8ce2d235c","src/write/encoder_string_writer.rs":"3f9109585babe048230659f64973cb1633bbb2ed9de255177336260226127b81","src/write/encoder_tests.rs":"381d7c2871407157c36e909c928307ac0389b3d4504fb80607134e94ac59e68f","src/write/mod.rs":"1503b9457e4f5d2895b24136c3af893f0b7ce18dfe4de1096fc5d17f8d78e99b","tests/decode.rs":"da2cbd49b84e0d8b1d8a52136ba3d97cfb248920a45f9955db1e5bc5367218ce","tests/encode.rs":"5efb6904c36c6f899a05078e5c9be756fc58af1ee9940edfa8dea1ee53675364","tests/helpers.rs":"a76015e4a4e8f98213bdbaa592cd9574ccdc95a28e1b1f835a2753e09fa6037f","tests/tests.rs":"05753e5f1d4a6c75015a5342f9b5dc3073c00bdfe0a829a962f8723321c75549"},"package":"9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"}

698
vendor/base64/Cargo.lock generated vendored

File diff suppressed because it is too large Load Diff

View File

@ -3,31 +3,41 @@
# 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
# to registry (e.g., crates.io) dependencies.
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
# 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"
name = "base64"
version = "0.13.0"
authors = ["Alice Maz <alice@alicemaz.com>", "Marshall Pierce <marshall@mpierce.org>"]
version = "0.13.1"
authors = [
"Alice Maz <alice@alicemaz.com>",
"Marshall Pierce <marshall@mpierce.org>",
]
description = "encodes and decodes base64 as bytes or utf8"
documentation = "https://docs.rs/base64"
readme = "README.md"
keywords = ["base64", "utf8", "encode", "decode", "no_std"]
keywords = [
"base64",
"utf8",
"encode",
"decode",
"no_std",
]
categories = ["encoding"]
license = "MIT/Apache-2.0"
repository = "https://github.com/marshallpierce/rust-base64"
[profile.bench]
debug = true
[[bench]]
name = "benchmarks"
harness = false
[dev-dependencies.criterion]
version = "=0.3.2"

Some files were not shown because too many files have changed in this diff Show More