diff --git a/.editorconfig b/.editorconfig index 03aab32bfc6e..d065fa46469f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -20,3 +20,6 @@ trim_trailing_whitespace = false [*.yml] indent_size = 2 + +[Makefile] +indent_style = tab diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 353bfcb6ac1a..4c445f635d7d 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -12,3 +12,5 @@ a06baa56b95674fc626b3c3fd680d6a65357fe60 c34fbfaad38cf5829ef5cfe780dc9d58480adeaa # move tests cf2dff2b1e3fa55fa5415d524200070d0d7aacfe +# Run rustfmt on bootstrap +b39a1d6f1a30ba29f25d7141038b9a5bf0126e36 diff --git a/.github/ISSUE_TEMPLATE/library_tracking_issue.md b/.github/ISSUE_TEMPLATE/library_tracking_issue.md index 91c06402ca10..934312662beb 100644 --- a/.github/ISSUE_TEMPLATE/library_tracking_issue.md +++ b/.github/ISSUE_TEMPLATE/library_tracking_issue.md @@ -12,7 +12,7 @@ Tracking issues are for tracking a feature from implementation to stabilization. Make sure to include the relevant RFC for the feature if it has one. If the new feature is small, it may be fine to skip the RFC process. In that -case, you can use use `issue = "none"` in your initial implementation PR. The +case, you can use `issue = "none"` in your initial implementation PR. The reviewer will ask you to open a tracking issue if they agree your feature can be added without an RFC. --> @@ -65,7 +65,7 @@ the rfcbot will ask all the team members to verify they agree with stabilization. Once enough members agree and there are no concerns, the final comment period begins: this issue will be marked as such and will be listed in the next This Week in Rust newsletter. If no blocking concerns are raised in -that period of 10 days, a stabilzation PR can be opened by anyone. +that period of 10 days, a stabilization PR can be opened by anyone. --> ### Unresolved Questions diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a917d9a7d55d..32c18cab0990 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -181,70 +181,70 @@ jobs: - ARM64 - linux - name: arm-android - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: armhf-gnu - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-aarch64-linux - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-android - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-arm-linux os: ubuntu-20.04-16core-64gb env: {} - name: dist-armhf-linux - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-armv7-linux - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-i586-gnu-i586-i686-musl - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-i686-linux - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-mips-linux - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-mips64-linux - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-mips64el-linux - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-mipsel-linux - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-powerpc-linux - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-powerpc64-linux - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-powerpc64le-linux - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-riscv64-linux - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-s390x-linux - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-various-1 - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-various-2 - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-x86_64-freebsd - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-x86_64-illumos - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-x86_64-linux os: ubuntu-20.04-16core-64gb @@ -254,10 +254,10 @@ jobs: IMAGE: dist-x86_64-linux os: ubuntu-20.04-16core-64gb - name: dist-x86_64-musl - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: dist-x86_64-netbsd - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: i686-gnu os: ubuntu-20.04-16core-64gb @@ -266,51 +266,55 @@ jobs: os: ubuntu-20.04-16core-64gb env: {} - name: mingw-check - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: test-various - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: wasm32 - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: x86_64-gnu - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: x86_64-gnu-stable env: IMAGE: x86_64-gnu RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable CI_ONLY_WHEN_CHANNEL: nightly - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb - name: x86_64-gnu-aux - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: x86_64-gnu-debug - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: x86_64-gnu-distcheck - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} + - name: x86_64-gnu-llvm-16 + env: + RUST_BACKTRACE: 1 + os: ubuntu-20.04-8core-32gb - name: x86_64-gnu-llvm-15 env: RUST_BACKTRACE: 1 - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb - name: x86_64-gnu-llvm-14 env: RUST_BACKTRACE: 1 - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb - name: x86_64-gnu-llvm-14-stage1 env: RUST_BACKTRACE: 1 - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb - name: x86_64-gnu-nopt - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb env: {} - name: x86_64-gnu-tools env: DEPLOY_TOOLSTATES_JSON: toolstates-linux.json - os: ubuntu-20.04-16core-64gb + os: ubuntu-20.04-8core-32gb - name: dist-x86_64-apple env: SCRIPT: "./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin" @@ -322,7 +326,7 @@ jobs: NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 - os: macos-12-xl + os: macos-latest - name: dist-apple-various env: SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim" @@ -333,7 +337,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-12-xl + os: macos-latest - name: dist-x86_64-apple-alt env: SCRIPT: "./x.py dist bootstrap --include-default-paths" @@ -344,7 +348,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-12-xl + os: macos-latest - name: x86_64-apple-1 env: SCRIPT: "./x.py --stage 2 test --exclude tests/ui --exclude tests/rustdoc --exclude tests/run-make-fulldeps" @@ -355,7 +359,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-12-xl + os: macos-latest - name: x86_64-apple-2 env: SCRIPT: "./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps" @@ -366,7 +370,7 @@ jobs: NO_LLVM_ASSERTIONS: 1 NO_DEBUG_ASSERTIONS: 1 NO_OVERFLOW_CHECKS: 1 - os: macos-12-xl + os: macos-latest - name: dist-aarch64-apple env: SCRIPT: "./x.py dist bootstrap --include-default-paths --stage 2" @@ -381,7 +385,7 @@ jobs: NO_OVERFLOW_CHECKS: 1 DIST_REQUIRE_ALL_TOOLS: 1 JEMALLOC_SYS_WITH_LG_PAGE: 14 - os: macos-12-xl + os: macos-latest - name: x86_64-msvc-1 env: RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler" diff --git a/Cargo.lock b/Cargo.lock index 3f617af19b39..f99957ae9ce7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,12 +4,12 @@ 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 = [ "compiler_builtins", - "gimli", + "gimli 0.27.2", "rustc-std-workspace-alloc", "rustc-std-workspace-core", ] @@ -42,7 +42,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107" dependencies = [ "cfg-if", - "getrandom", "once_cell", "version_check", ] @@ -79,6 +78,15 @@ dependencies = [ "url", ] +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "annotate-snippets" version = "0.9.1" @@ -108,7 +116,7 @@ dependencies = [ "anstyle-parse", "anstyle-wincon", "concolor-override", - "concolor-query 0.3.3", + "concolor-query", "is-terminal", "utf8parse", ] @@ -150,27 +158,15 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0639441fd17a3197d1cbca8dc8768cc172a63b64b4bb6c372e8f41ed0acc9bb" dependencies = [ - "object 0.30.1", + "object", ] -[[package]] -name = "arc-swap" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" - [[package]] name = "array_tool" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271" -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "arrayvec" version = "0.7.0" @@ -228,37 +224,19 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" dependencies = [ "addr2line", "cc", "cfg-if", "libc", "miniz_oxide", - "object 0.29.0", + "object", "rustc-demangle", ] -[[package]] -name = "base16ct" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" - -[[package]] -name = "base64" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" - -[[package]] -name = "base64ct" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" - [[package]] name = "basic-toml" version = "0.1.2" @@ -274,15 +252,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitmaps" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" -dependencies = [ - "typenum", -] - [[package]] name = "block-buffer" version = "0.10.2" @@ -315,15 +284,6 @@ dependencies = [ "serde", ] -[[package]] -name = "btoi" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd6407f73a9b8b6162d8a2ef999fe6afd7cc15902ebf42c5cd296addf17e0ad" -dependencies = [ - "num-traits", -] - [[package]] name = "build-manifest" version = "0.1.0" @@ -336,7 +296,7 @@ dependencies = [ "serde_json", "sha2", "tar", - "toml 0.5.7", + "toml", ] [[package]] @@ -352,14 +312,14 @@ dependencies = [ "indexmap", "serde", "serde_json", - "toml 0.5.7", + "toml", ] [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" [[package]] name = "bytecount" @@ -376,12 +336,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" -[[package]] -name = "bytesize" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da" - [[package]] name = "camino" version = "1.0.9" @@ -391,108 +345,6 @@ dependencies = [ "serde", ] -[[package]] -name = "cargo" -version = "0.71.0" -dependencies = [ - "anyhow", - "base64", - "bytesize", - "cargo-platform 0.1.2", - "cargo-test-macro", - "cargo-test-support", - "cargo-util", - "clap 4.2.1", - "crates-io", - "curl", - "curl-sys", - "env_logger 0.10.0", - "filetime", - "flate2", - "fwdansi", - "git2", - "git2-curl", - "gix", - "gix-features", - "glob", - "hex", - "hmac", - "home", - "http-auth", - "humantime 2.0.1", - "ignore", - "im-rc", - "indexmap", - "is-terminal", - "itertools", - "jobserver", - "lazy_static", - "lazycell", - "libc", - "libgit2-sys", - "log", - "memchr", - "opener", - "openssl", - "os_info", - "pasetors", - "pathdiff", - "pretty_env_logger", - "rand", - "rustc-workspace-hack", - "rustfix", - "same-file", - "semver", - "serde", - "serde-value", - "serde_ignored", - "serde_json", - "sha1", - "shell-escape", - "snapbox", - "strip-ansi-escapes", - "tar", - "tempfile", - "termcolor", - "time 0.3.17", - "toml 0.7.2", - "toml_edit", - "unicode-width", - "unicode-xid", - "url", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "cargo-credential" -version = "0.2.0" - -[[package]] -name = "cargo-credential-1password" -version = "0.2.0" -dependencies = [ - "cargo-credential", - "serde", - "serde_json", -] - -[[package]] -name = "cargo-credential-macos-keychain" -version = "0.2.0" -dependencies = [ - "cargo-credential", - "security-framework", -] - -[[package]] -name = "cargo-credential-wincred" -version = "0.2.0" -dependencies = [ - "cargo-credential", - "windows-sys 0.45.0", -] - [[package]] name = "cargo-miri" version = "0.1.0" @@ -507,13 +359,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "cargo-platform" -version = "0.1.2" -dependencies = [ - "serde", -] - [[package]] name = "cargo-platform" version = "0.1.2" @@ -523,56 +368,6 @@ dependencies = [ "serde", ] -[[package]] -name = "cargo-test-macro" -version = "0.1.0" - -[[package]] -name = "cargo-test-support" -version = "0.1.0" -dependencies = [ - "anyhow", - "cargo-test-macro", - "cargo-util", - "crates-io", - "filetime", - "flate2", - "git2", - "glob", - "itertools", - "lazy_static", - "pasetors", - "serde", - "serde_json", - "snapbox", - "tar", - "termcolor", - "time 0.3.17", - "toml 0.7.2", - "url", - "windows-sys 0.45.0", -] - -[[package]] -name = "cargo-util" -version = "0.2.4" -dependencies = [ - "anyhow", - "core-foundation", - "filetime", - "hex", - "jobserver", - "libc", - "log", - "miow 0.5.0", - "same-file", - "sha2", - "shell-escape", - "tempfile", - "walkdir", - "windows-sys 0.45.0", -] - [[package]] name = "cargo_metadata" version = "0.14.0" @@ -580,7 +375,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c297bd3135f558552f99a0daa180876984ea2c4ffa7470314540dff8c654109a" dependencies = [ "camino", - "cargo-platform 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo-platform", "semver", "serde", "serde_json", @@ -593,7 +388,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08a1ec454bc3eead8719cb56e15dbbfecdbc14e4b3a3ae4936cc6e31f5fc0d07" dependencies = [ "camino", - "cargo-platform 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo-platform", "semver", "serde", "serde_json", @@ -609,9 +404,6 @@ name = "cc" version = "1.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" -dependencies = [ - "jobserver", -] [[package]] name = "cfg-if" @@ -679,15 +471,14 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" dependencies = [ - "libc", + "iana-time-zone", "num-integer", "num-traits", "serde", - "time 0.1.43", "winapi", ] @@ -802,14 +593,13 @@ dependencies = [ "rustc-semver", "rustc-workspace-hack", "rustc_tools_util", - "semver", "serde", - "syn 1.0.102", + "syn 2.0.8", "tempfile", "termize", "tester", "tokio", - "toml 0.5.7", + "toml", "walkdir", ] @@ -830,7 +620,7 @@ dependencies = [ name = "clippy_lints" version = "0.1.70" dependencies = [ - "arrayvec 0.7.0", + "arrayvec", "cargo_metadata 0.15.3", "clippy_utils", "declare_clippy_lint", @@ -844,7 +634,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "toml 0.5.7", + "toml", "unicode-normalization", "unicode-script", "url", @@ -854,17 +644,21 @@ dependencies = [ name = "clippy_utils" version = "0.1.70" dependencies = [ - "arrayvec 0.7.0", + "arrayvec", "if_chain", "itertools", "rustc-semver", ] [[package]] -name = "clru" -version = "0.6.1" +name = "codespan-reporting" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8191fa7302e03607ff0e237d4246cc043ff5b3cb9409d995172ba3bea16b807" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] [[package]] name = "collect-license-metadata" @@ -951,9 +745,9 @@ dependencies = [ [[package]] name = "compiletest_rs" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70489bbb718aea4f92e5f48f2e3b5be670c2051de30e57cb6e5377b4aa08b372" +checksum = "e2731272cf25196735df1b52ab5bcba22cf9f99455626c4c8dc092bd5f7f66d0" dependencies = [ "diff", "filetime", @@ -972,29 +766,12 @@ dependencies = [ "winapi", ] -[[package]] -name = "concolor" -version = "0.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b90f9dcd9490a97db91a85ccd79e38a87e14323f0bb824659ee3274e9143ba37" -dependencies = [ - "atty", - "bitflags", - "concolor-query 0.1.0", -] - [[package]] name = "concolor-override" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a855d4a1978dc52fb0536a04d384c2c0c1aa273597f08b77c8c4d3b2eec6037f" -[[package]] -name = "concolor-query" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82a90734b3d5dcf656e7624cca6bce9c3a90ee11f900e80141a7427ccfb3d317" - [[package]] name = "concolor-query" version = "0.3.3" @@ -1004,21 +781,6 @@ dependencies = [ "windows-sys 0.45.0", ] -[[package]] -name = "const-oid" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cec318a675afcb6a1ea1d4340e2d377e56e47c266f28043ceccbf4412ddfdd3b" - -[[package]] -name = "content_inspector" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7bda66e858c683005a53a9a60c69a4aca7eeaa45d124526e389f7aec8e62f38" -dependencies = [ - "memchr", -] - [[package]] name = "convert_case" version = "0.4.0" @@ -1033,21 +795,11 @@ dependencies = [ "rand_xorshift", ] -[[package]] -name = "core-foundation" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b5ed8e7e76c45974e15e41bfa8d5b0483cd90191639e01d8f5f1e606299d3fb" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" -version = "0.8.0" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a21fa21941700a3cd8fcb4091f361a6a712fac632f85d9f487cc892045d55c6" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "coverage_test_macros" @@ -1062,18 +814,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crates-io" -version = "0.36.0" -dependencies = [ - "anyhow", - "curl", - "percent-encoding", - "serde", - "serde_json", - "url", -] - [[package]] name = "crc32fast" version = "1.3.2" @@ -1126,18 +866,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crypto-bigint" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" -dependencies = [ - "generic-array", - "rand_core", - "subtle", - "zeroize", -] - [[package]] name = "crypto-common" version = "0.1.6" @@ -1158,22 +886,6 @@ dependencies = [ "quote", ] -[[package]] -name = "ct-codecs" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3b7eb4404b8195a9abb6356f4ac07d8ba267045c8d6d220ac4dc992e6cc75df" - -[[package]] -name = "ctor" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" -dependencies = [ - "quote", - "syn 1.0.102", -] - [[package]] name = "curl" version = "0.4.44" @@ -1197,7 +909,6 @@ checksum = "14d05c10f541ae6f3bc5b3d923c20001f47db7d5f0b2bc6ad16490133842db79" dependencies = [ "cc", "libc", - "libnghttp2-sys", "libz-sys", "openssl-sys", "pkg-config", @@ -1205,6 +916,50 @@ dependencies = [ "winapi", ] +[[package]] +name = "cxx" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn 2.0.8", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.8", +] + [[package]] name = "datafrog" version = "2.0.1" @@ -1217,18 +972,7 @@ version = "0.1.70" dependencies = [ "itertools", "quote", - "syn 1.0.102", -] - -[[package]] -name = "der" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" -dependencies = [ - "const-oid", - "pem-rfc7468", - "zeroize", + "syn 2.0.8", ] [[package]] @@ -1269,7 +1013,6 @@ checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer", "crypto-common", - "subtle", ] [[package]] @@ -1350,33 +1093,6 @@ dependencies = [ "rustc-std-workspace-core", ] -[[package]] -name = "dunce" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c" - -[[package]] -name = "ecdsa" -version = "0.14.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" -dependencies = [ - "der", - "elliptic-curve", - "rfc6979", - "signature", -] - -[[package]] -name = "ed25519-compact" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a3d382e8464107391c8706b4c14b087808ecb909f6c15c34114bc42e53a9e4c" -dependencies = [ - "getrandom", -] - [[package]] name = "either" version = "1.6.0" @@ -1395,28 +1111,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "elliptic-curve" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" -dependencies = [ - "base16ct", - "crypto-bigint", - "der", - "digest", - "ff", - "generic-array", - "group", - "hkdf", - "pem-rfc7468", - "pkcs8", - "rand_core", - "sec1", - "subtle", - "zeroize", -] - [[package]] name = "elsa" version = "1.7.1" @@ -1476,13 +1170,13 @@ dependencies = [ [[package]] name = "errno" -version = "0.2.8" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -1546,22 +1240,6 @@ dependencies = [ "instant", ] -[[package]] -name = "ff" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" -dependencies = [ - "rand_core", - "subtle", -] - -[[package]] -name = "fiat-crypto" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a214f5bb88731d436478f3ae1f8a277b62124089ba9fb67f4f93fb100ef73c90" - [[package]] name = "filetime" version = "0.2.20" @@ -1582,14 +1260,11 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" [[package]] name = "flate2" -version = "1.0.23" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ - "cfg-if", "crc32fast", - "libc", - "libz-sys", "miniz_oxide", ] @@ -1633,21 +1308,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.0.1" @@ -1773,16 +1433,6 @@ dependencies = [ "slab", ] -[[package]] -name = "fwdansi" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c1f5787fe85505d1f7777268db5103d80a7a374d2316a7ce262e57baf8f208" -dependencies = [ - "memchr", - "termcolor", -] - [[package]] name = "generate-copyright" version = "0.1.0" @@ -1820,10 +1470,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi", - "wasm-bindgen", ] [[package]] @@ -1832,592 +1480,20 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" dependencies = [ - "compiler_builtins", "fallible-iterator", "indexmap", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", "stable_deref_trait", ] [[package]] -name = "git2" -version = "0.17.0" +name = "gimli" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89511277159354bea13ae1e53e0c9ab85ba1b20d7e91618fa30e6bc5566857fb" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" dependencies = [ - "bitflags", - "libc", - "libgit2-sys", - "log", - "openssl-probe", - "openssl-sys", - "url", -] - -[[package]] -name = "git2-curl" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f8b7432b72928cff76f69e59ed5327f94a52763731e71274960dee72fe5f8c" -dependencies = [ - "curl", - "git2", - "log", - "url", -] - -[[package]] -name = "gix" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dabfac58aecb4a38cdd2568de66eb1f0d968fd6726f5a80cb8bea7944ef10cc0" -dependencies = [ - "gix-actor", - "gix-attributes", - "gix-config", - "gix-credentials", - "gix-date", - "gix-diff", - "gix-discover", - "gix-features", - "gix-glob", - "gix-hash", - "gix-hashtable", - "gix-index", - "gix-lock", - "gix-mailmap", - "gix-object", - "gix-odb", - "gix-pack", - "gix-path", - "gix-prompt", - "gix-protocol", - "gix-ref", - "gix-refspec", - "gix-revision", - "gix-sec", - "gix-tempfile", - "gix-transport", - "gix-traverse", - "gix-url", - "gix-validate", - "gix-worktree", - "log", - "once_cell", - "prodash", - "signal-hook", - "smallvec", - "thiserror", - "unicode-normalization", -] - -[[package]] -name = "gix-actor" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc22b0cdc52237667c301dd7cdc6ead8f8f73c9f824e9942c8ebd6b764f6c0bf" -dependencies = [ - "bstr 1.3.0", - "btoi", - "gix-date", - "itoa", - "nom", - "thiserror", -] - -[[package]] -name = "gix-attributes" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2231a25934a240d0a4b6f4478401c73ee81d8be52de0293eedbc172334abf3e1" -dependencies = [ - "bstr 1.3.0", - "gix-features", - "gix-glob", - "gix-path", - "gix-quote", - "thiserror", - "unicode-bom", -] - -[[package]] -name = "gix-bitmap" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "024bca0c7187517bda5ea24ab148c9ca8208dd0c3e2bea88cdb2008f91791a6d" -dependencies = [ - "thiserror", -] - -[[package]] -name = "gix-chunk" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0d39583cab06464b8bf73b3f1707458270f0e7383cb24c3c9c1a16e6f792978" -dependencies = [ - "thiserror", -] - -[[package]] -name = "gix-command" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2c6f75c1e0f924de39e750880a6e21307194bb1ab773efe3c7d2d787277f8ab" -dependencies = [ - "bstr 1.3.0", -] - -[[package]] -name = "gix-config" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52c62e26ce11f607712e4f49a0a192ed87675d30187fd61be070abbd607d12f1" -dependencies = [ - "bstr 1.3.0", - "gix-config-value", - "gix-features", - "gix-glob", - "gix-path", - "gix-ref", - "gix-sec", - "memchr", - "nom", - "once_cell", - "smallvec", - "thiserror", - "unicode-bom", -] - -[[package]] -name = "gix-config-value" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d4a4ba0531e46fe558459557a5b29fb86c3e4b2666c1c0861d93c7c678331" -dependencies = [ - "bitflags", - "bstr 1.3.0", - "gix-path", - "libc", - "thiserror", -] - -[[package]] -name = "gix-credentials" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be32b5fe339a31b8e53fa854081dc914c45020dcb64637f3c21baf69c96fc1b" -dependencies = [ - "bstr 1.3.0", - "gix-command", - "gix-config-value", - "gix-path", - "gix-prompt", - "gix-sec", - "gix-url", - "thiserror", -] - -[[package]] -name = "gix-date" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96271912ce39822501616f177dea7218784e6c63be90d5f36322ff3a722aae2" -dependencies = [ - "bstr 1.3.0", - "itoa", - "thiserror", - "time 0.3.17", -] - -[[package]] -name = "gix-diff" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585b0834d4b6791a848637c4e109545fda9b0f29b591ba55edb33ceda6e7856b" -dependencies = [ - "gix-hash", - "gix-object", - "imara-diff", - "thiserror", -] - -[[package]] -name = "gix-discover" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91c204adba5ebd211c74735cbb65817d277e154486bac0dffa3701f163b80350" -dependencies = [ - "bstr 1.3.0", - "dunce", - "gix-hash", - "gix-path", - "gix-ref", - "gix-sec", - "thiserror", -] - -[[package]] -name = "gix-features" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6a9dfa7b3c1a99315203e8b97f8f99f3bd95731590607abeaa5ca31bc41fe3" -dependencies = [ - "bytes", - "crc32fast", - "crossbeam-channel", - "flate2", - "gix-hash", - "libc", - "once_cell", - "parking_lot 0.12.1", - "prodash", - "sha1_smol", - "thiserror", - "walkdir", -] - -[[package]] -name = "gix-glob" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93e43efd776bc543f46f0fd0ca3d920c37af71a764a16f2aebd89765e9ff2993" -dependencies = [ - "bitflags", - "bstr 1.3.0", -] - -[[package]] -name = "gix-hash" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0c5a9f4d621d4f4ea046bb331df5c746ca735b8cae5b234cc2be70ee4dbef0" -dependencies = [ - "hex", - "thiserror", -] - -[[package]] -name = "gix-hashtable" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9609c1b8f36f12968e6a6098f7cdb52004f7d42d570f47a2d6d7c16612f19acb" -dependencies = [ - "gix-hash", - "hashbrown 0.13.1", - "parking_lot 0.12.1", -] - -[[package]] -name = "gix-index" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c12caf7886c7ba06f2b28835cdc2be1dca86bd047d00299d2d49e707ce1c2616" -dependencies = [ - "bitflags", - "bstr 1.3.0", - "btoi", - "filetime", - "gix-bitmap", - "gix-features", - "gix-hash", - "gix-lock", - "gix-object", - "gix-traverse", - "itoa", - "memmap2 0.5.10", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-lock" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66119ff8a4a395d0ea033fef718bc85f8b4f0855874f4ce1e005fc16cfe1f66e" -dependencies = [ - "fastrand", - "gix-tempfile", - "thiserror", -] - -[[package]] -name = "gix-mailmap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b66aea5e52875cd4915f4957a6f4b75831a36981e2ec3f5fad9e370e444fe1a" -dependencies = [ - "bstr 1.3.0", - "gix-actor", - "thiserror", -] - -[[package]] -name = "gix-object" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df068db9180ee935fbb70504848369e270bdcb576b05c0faa8b9fd3b86fc017" -dependencies = [ - "bstr 1.3.0", - "btoi", - "gix-actor", - "gix-features", - "gix-hash", - "gix-validate", - "hex", - "itoa", - "nom", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-odb" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9a5f9e1afbd509761977a2ea02869cedaaba500b4e783deb2e4de5179a55a80" -dependencies = [ - "arc-swap", - "gix-features", - "gix-hash", - "gix-object", - "gix-pack", - "gix-path", - "gix-quote", - "parking_lot 0.12.1", - "tempfile", - "thiserror", -] - -[[package]] -name = "gix-pack" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51db84e1459a8022e518d40a8778028d793dbb28e4d35c9a5eaf92658fb0775" -dependencies = [ - "clru", - "gix-chunk", - "gix-diff", - "gix-features", - "gix-hash", - "gix-hashtable", - "gix-object", - "gix-path", - "gix-tempfile", - "gix-traverse", - "memmap2 0.5.10", - "parking_lot 0.12.1", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-packetline" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d63e5e5a9a92d4fc6b63ff9d94954d25c779ce25c98d5bbe2e4399aa42f7073c" -dependencies = [ - "bstr 1.3.0", - "hex", - "thiserror", -] - -[[package]] -name = "gix-path" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6c104a66dec149cb8f7aaafc6ab797654cf82d67f050fd0cb7e7294e328354b" -dependencies = [ - "bstr 1.3.0", - "thiserror", -] - -[[package]] -name = "gix-prompt" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20cebf73229debaa82574c4fd20dcaf00fa8d4bfce823a862c4e990d7a0b5b4" -dependencies = [ - "gix-command", - "gix-config-value", - "nix", - "parking_lot 0.12.1", - "thiserror", -] - -[[package]] -name = "gix-protocol" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d372ab11d5d28ac21800e3f1a6603a67c1ead57f6f5fab07e1e73e960f331c1" -dependencies = [ - "bstr 1.3.0", - "btoi", - "gix-credentials", - "gix-features", - "gix-hash", - "gix-transport", - "maybe-async", - "nom", - "thiserror", -] - -[[package]] -name = "gix-quote" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a282f5a8d9ee0b09ec47390ac727350c48f2f5c76d803cd8da6b3e7ad56e0bcb" -dependencies = [ - "bstr 1.3.0", - "btoi", - "thiserror", -] - -[[package]] -name = "gix-ref" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90a0ed29e581f04b904ecd0c32b11f33b8209b5a0af9c43f415249a4f2fba632" -dependencies = [ - "gix-actor", - "gix-features", - "gix-hash", - "gix-lock", - "gix-object", - "gix-path", - "gix-tempfile", - "gix-validate", - "memmap2 0.5.10", - "nom", - "thiserror", -] - -[[package]] -name = "gix-refspec" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aba332462bda2e8efeae4302b39a6ed01ad56ef772fd5b7ef197cf2798294d65" -dependencies = [ - "bstr 1.3.0", - "gix-hash", - "gix-revision", - "gix-validate", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-revision" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed98e4a0254953c64bc913bd23146a1de662067d5cf974cbdde396958b39e5b0" -dependencies = [ - "bstr 1.3.0", - "gix-date", - "gix-hash", - "gix-hashtable", - "gix-object", - "thiserror", -] - -[[package]] -name = "gix-sec" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ffa5bf0772f9b01de501c035b6b084cf9b8bb07dec41e3afc6a17336a65f47" -dependencies = [ - "bitflags", - "dirs", - "gix-path", - "libc", - "windows 0.43.0", -] - -[[package]] -name = "gix-tempfile" -version = "4.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88751f247234b1f73c8e8056fd835a0999b04e596e052302cb71186005dc4b27" -dependencies = [ - "libc", - "once_cell", - "parking_lot 0.12.1", - "signal-hook", - "signal-hook-registry", - "tempfile", -] - -[[package]] -name = "gix-transport" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d633947b36a2fbbc089195bdc71621158f1660c2ff2a6b12b0279c16e2f764bc" -dependencies = [ - "base64", - "bstr 1.3.0", - "curl", - "gix-command", - "gix-credentials", - "gix-features", - "gix-packetline", - "gix-quote", - "gix-sec", - "gix-url", - "thiserror", -] - -[[package]] -name = "gix-traverse" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd9a4a07bb22168dc79c60e1a6a41919d198187ca83d8a5940ad8d7122a45df3" -dependencies = [ - "gix-hash", - "gix-hashtable", - "gix-object", - "thiserror", -] - -[[package]] -name = "gix-url" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "044072b7ce8601b62dcec841b92129f5cc677072823324121b395d766ac5f528" -dependencies = [ - "bstr 1.3.0", - "gix-features", - "gix-path", - "home", - "thiserror", - "url", -] - -[[package]] -name = "gix-validate" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b69ddb780ea1465255e66818d75b7098371c58dbc9560da4488a44b9f5c7e443" -dependencies = [ - "bstr 1.3.0", - "thiserror", -] - -[[package]] -name = "gix-worktree" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cb9af6e56152953d8fe113c4f9d7cf60cf7a982362711e9200a255579b49cb" -dependencies = [ - "bstr 1.3.0", - "gix-attributes", - "gix-features", - "gix-glob", - "gix-hash", - "gix-index", - "gix-object", - "gix-path", - "io-close", - "thiserror", + "compiler_builtins", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", ] [[package]] @@ -2439,17 +1515,6 @@ dependencies = [ "regex", ] -[[package]] -name = "group" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" -dependencies = [ - "ff", - "rand_core", - "subtle", -] - [[package]] name = "gsgdt" version = "0.1.2" @@ -2459,21 +1524,6 @@ dependencies = [ "serde", ] -[[package]] -name = "handlebars" -version = "3.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4498fc115fa7d34de968184e473529abb40eeb6be8bc5f7faba3d08c316cb3e3" -dependencies = [ - "log", - "pest", - "pest_derive", - "quick-error 2.0.1", - "serde", - "serde_json", - "walkdir", -] - [[package]] name = "handlebars" version = "4.3.3" @@ -2541,33 +1591,6 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" -[[package]] -name = "hkdf" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" -dependencies = [ - "hmac", -] - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - -[[package]] -name = "home" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2456aef2e6b6a9784192ae780c0f15bc57df0e918585282325e8c8ac27737654" -dependencies = [ - "winapi", -] - [[package]] name = "html-checker" version = "0.1.0" @@ -2590,22 +1613,13 @@ dependencies = [ "syn 1.0.102", ] -[[package]] -name = "http-auth" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b40b39d66c28829a0cf4d09f7e139ff8201f7500a5083732848ed3b4b4d850" -dependencies = [ - "memchr", -] - [[package]] name = "humantime" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" dependencies = [ - "quick-error 1.2.3", + "quick-error", ] [[package]] @@ -2614,6 +1628,30 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c1ad908cc71012b7bea4d0c53ba96a8cba9962f048fa68d143376143d863b7a" +[[package]] +name = "iana-time-zone" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows 0.48.0", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "icu_list" version = "1.1.0" @@ -2714,30 +1752,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "im-rc" -version = "15.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe" -dependencies = [ - "bitmaps", - "rand_core", - "rand_xoshiro", - "sized-chunks", - "typenum", - "version_check", -] - -[[package]] -name = "imara-diff" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e98c1d0ad70fc91b8b9654b1f33db55e59579d3b3de2bffdced0fdb810570cb8" -dependencies = [ - "ahash 0.8.2", - "hashbrown 0.12.3", -] - [[package]] name = "indenter" version = "0.3.3" @@ -2805,16 +1819,6 @@ dependencies = [ "unic-langid", ] -[[package]] -name = "io-close" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cadcf447f06744f8ce713d2d6239bb5bde2c357a452397a9ed90c625da390bc" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "io-lifetimes" version = "1.0.3" @@ -2827,14 +1831,14 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ "hermit-abi 0.3.0", "io-lifetimes", "rustix", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -2873,9 +1877,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] @@ -2933,9 +1937,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.140" +version = "0.2.142" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" +checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" dependencies = [ "rustc-std-workspace-core", ] @@ -2952,27 +1956,13 @@ dependencies = [ [[package]] name = "libffi-sys" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc65067b78c0fc069771e8b9a9e02df71e08858bec92c1f101377c67b9dca7c7" +checksum = "f36115160c57e8529781b4183c2bb51fdc1f6d6d1ed345591d84be7703befb3c" dependencies = [ "cc", ] -[[package]] -name = "libgit2-sys" -version = "0.15.0+1.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "032e537ae4dd4e50c877f258dc55fcd0657b5021f454094a425bb6bcc9edea4c" -dependencies = [ - "cc", - "libc", - "libssh2-sys", - "libz-sys", - "openssl-sys", - "pkg-config", -] - [[package]] name = "libloading" version = "0.7.1" @@ -2989,35 +1979,11 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" -[[package]] -name = "libnghttp2-sys" -version = "0.1.4+1.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03624ec6df166e79e139a2310ca213283d6b3c30810c54844f307086d4488df1" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "libssh2-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee" -dependencies = [ - "cc", - "libc", - "libz-sys", - "openssl-sys", - "pkg-config", - "vcpkg", -] - [[package]] name = "libz-sys" -version = "1.1.3" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" +checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" dependencies = [ "cc", "libc", @@ -3025,6 +1991,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + [[package]] name = "linkchecker" version = "0.1.0" @@ -3050,9 +2025,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.1.4" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" +checksum = "36eb31c1778188ae1e64398743890d0877fef36d11521ac60406b42016e8c2cf" [[package]] name = "litemap" @@ -3135,17 +2110,6 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -[[package]] -name = "maybe-async" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f1b8c13cb1f814b634a96b2c725449fe7ed464a7b8781de8688be5ffbd3f305" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.102", -] - [[package]] name = "md-5" version = "0.10.0" @@ -3168,7 +2132,7 @@ dependencies = [ "clap_complete", "elasticlunr-rs", "env_logger 0.10.0", - "handlebars 4.3.3", + "handlebars", "log", "memchr", "once_cell", @@ -3179,23 +2143,10 @@ dependencies = [ "serde_json", "shlex", "tempfile", - "toml 0.5.7", + "toml", "topological-sort", ] -[[package]] -name = "mdman" -version = "0.1.0" -dependencies = [ - "anyhow", - "handlebars 3.5.5", - "pretty_assertions", - "pulldown-cmark", - "same-file", - "serde_json", - "url", -] - [[package]] name = "measureme" version = "10.1.0" @@ -3203,7 +2154,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbdc226fa10994e8f66a4d2f6f000148bc563a1c671b6dcd2135737018033d8a" dependencies = [ "log", - "memmap2 0.2.1", + "memmap2", "parking_lot 0.11.2", "perf-event-open-sys", "rustc-hash", @@ -3229,15 +2180,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memmap2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" -dependencies = [ - "libc", -] - [[package]] name = "memoffset" version = "0.7.1" @@ -3277,9 +2219,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[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", "compiler_builtins", @@ -3339,18 +2281,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" -[[package]] -name = "nix" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" -dependencies = [ - "bitflags", - "cfg-if", - "libc", - "static_assertions", -] - [[package]] name = "nom" version = "7.1.0" @@ -3362,21 +2292,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "nom8" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" -dependencies = [ - "memchr", -] - -[[package]] -name = "normalize-line-endings" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" - [[package]] name = "num-integer" version = "0.1.43" @@ -3406,38 +2321,20 @@ dependencies = [ "libc", ] -[[package]] -name = "num_threads" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" -dependencies = [ - "libc", -] - -[[package]] -name = "object" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" -dependencies = [ - "compiler_builtins", - "memchr", - "rustc-std-workspace-alloc", - "rustc-std-workspace-core", -] - [[package]] name = "object" version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d864c91689fdc196779b98dba0aceac6118594c2df6ee5d943eb6a8df4d107a" dependencies = [ + "compiler_builtins", "crc32fast", "flate2", "hashbrown 0.13.1", "indexmap", "memchr", + "rustc-std-workspace-alloc", + "rustc-std-workspace-core", ] [[package]] @@ -3451,9 +2348,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.16.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "opener" @@ -3465,123 +2362,36 @@ dependencies = [ "winapi", ] -[[package]] -name = "openssl" -version = "0.10.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d2f106ab837a24e03672c59b1239669a0596406ff657c3c0835b6b7f0f35a33" -dependencies = [ - "bitflags", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.8", -] - [[package]] name = "openssl-probe" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" -[[package]] -name = "openssl-src" -version = "111.25.0+1.1.1t" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3173cd3626c43e3854b1b727422a276e568d9ec5fe8cec197822cf52cfb743d6" -dependencies = [ - "cc", -] - [[package]] name = "openssl-sys" -version = "0.9.84" +version = "0.9.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a20eace9dc2d82904039cb76dcf50fb1a0bba071cfd1629720b5d6f1ddba0fa" +checksum = "8e17f59264b2809d77ae94f0e1ebabc434773f370d6ca667bd223ea10e06cc7e" dependencies = [ "cc", "libc", - "openssl-src", "pkg-config", "vcpkg", ] -[[package]] -name = "ordered-float" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87" -dependencies = [ - "num-traits", -] - -[[package]] -name = "orion" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2baf7fd2e326e3895c681176788dd227fcd8369350e53c570592d8563fecbb6" -dependencies = [ - "fiat-crypto", - "subtle", - "zeroize", -] - -[[package]] -name = "os_info" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5209b2162b2c140df493a93689e04f8deab3a67634f5bc7a553c0a98e5b8d399" -dependencies = [ - "log", - "serde", - "winapi", -] - [[package]] name = "os_str_bytes" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" -[[package]] -name = "output_vt100" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" -dependencies = [ - "winapi", -] - [[package]] name = "owo-colors" version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" -[[package]] -name = "p384" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" -dependencies = [ - "ecdsa", - "elliptic-curve", - "sha2", -] - [[package]] name = "packed_simd_2" version = "0.3.8" @@ -3663,42 +2473,12 @@ dependencies = [ "windows-sys 0.42.0", ] -[[package]] -name = "pasetors" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed20c4c21d893414f42e0cbfebe8a8036b5ae9b0264611fb6504e395eda6ceec" -dependencies = [ - "ct-codecs", - "ed25519-compact", - "getrandom", - "orion", - "p384", - "rand_core", - "regex", - "serde", - "serde_json", - "sha2", - "subtle", - "time 0.3.17", - "zeroize", -] - [[package]] name = "pathdiff" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" -[[package]] -name = "pem-rfc7468" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac" -dependencies = [ - "base64ct", -] - [[package]] name = "percent-encoding" version = "2.1.0" @@ -3818,16 +2598,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkcs8" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" -dependencies = [ - "der", - "spki", -] - [[package]] name = "pkg-config" version = "0.3.25" @@ -3857,28 +2627,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -[[package]] -name = "pretty_assertions" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" -dependencies = [ - "ctor", - "diff", - "output_vt100", - "yansi", -] - -[[package]] -name = "pretty_env_logger" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" -dependencies = [ - "env_logger 0.7.1", - "log", -] - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -3926,15 +2674,6 @@ dependencies = [ "std", ] -[[package]] -name = "prodash" -version = "23.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d73c6b64cb5b99eb63ca97d378685712617ec0172ff5c04cd47a489d3e2c51f8" -dependencies = [ - "parking_lot 0.12.1", -] - [[package]] name = "profiler_builtins" version = "0.0.0" @@ -3976,12 +2715,6 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" -[[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - [[package]] name = "quine-mc_cluskey" version = "0.2.4" @@ -4148,22 +2881,10 @@ dependencies = [ "walkdir", ] -[[package]] -name = "rfc6979" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" -dependencies = [ - "crypto-bigint", - "hmac", - "zeroize", -] - [[package]] name = "rls" version = "2.0.0" dependencies = [ - "rustc-workspace-hack", "serde", "serde_json", ] @@ -4275,22 +2996,8 @@ dependencies = [ [[package]] name = "rustc-workspace-hack" version = "1.0.0" -dependencies = [ - "bstr 0.2.17", - "clap 3.2.20", - "getrandom", - "hashbrown 0.12.3", - "libc", - "libz-sys", - "once_cell", - "rand", - "regex", - "serde_json", - "smallvec", - "syn 1.0.102", - "url", - "winapi", -] +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb" [[package]] name = "rustc_abi" @@ -4346,6 +3053,7 @@ dependencies = [ "rustc_ast_pretty", "rustc_data_structures", "rustc_errors", + "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_macros", @@ -4369,6 +3077,7 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", + "rustc_fluent_macro", "rustc_macros", "rustc_parse", "rustc_session", @@ -4396,6 +3105,7 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", + "rustc_fluent_macro", "rustc_lexer", "rustc_macros", "rustc_serialize", @@ -4421,9 +3131,9 @@ dependencies = [ "either", "itertools", "polonius-engine", - "rustc_const_eval", "rustc_data_structures", "rustc_errors", + "rustc_fluent_macro", "rustc_graphviz", "rustc_hir", "rustc_index", @@ -4453,6 +3163,7 @@ dependencies = [ "rustc_errors", "rustc_expand", "rustc_feature", + "rustc_fluent_macro", "rustc_lexer", "rustc_lint_defs", "rustc_macros", @@ -4474,13 +3185,14 @@ dependencies = [ "cstr", "libc", "measureme", - "object 0.30.1", + "object", "rustc-demangle", "rustc_ast", "rustc_attr", "rustc_codegen_ssa", "rustc_data_structures", "rustc_errors", + "rustc_fluent_macro", "rustc_fs_util", "rustc_hir", "rustc_index", @@ -4496,7 +3208,6 @@ dependencies = [ "serde", "serde_json", "smallvec", - "tempfile", "tracing", ] @@ -4510,7 +3221,7 @@ dependencies = [ "itertools", "jobserver", "libc", - "object 0.30.1", + "object", "pathdiff", "regex", "rustc_arena", @@ -4518,6 +3229,7 @@ dependencies = [ "rustc_attr", "rustc_data_structures", "rustc_errors", + "rustc_fluent_macro", "rustc_fs_util", "rustc_hir", "rustc_incremental", @@ -4550,6 +3262,7 @@ dependencies = [ "rustc_attr", "rustc_data_structures", "rustc_errors", + "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_infer", @@ -4568,7 +3281,7 @@ dependencies = [ name = "rustc_data_structures" version = "0.0.0" dependencies = [ - "arrayvec 0.7.0", + "arrayvec", "bitflags", "cfg-if", "elsa", @@ -4578,7 +3291,7 @@ dependencies = [ "jobserver", "libc", "measureme", - "memmap2 0.2.1", + "memmap2", "parking_lot 0.11.2", "rustc-hash", "rustc-rayon", @@ -4587,9 +3300,7 @@ dependencies = [ "rustc_index", "rustc_macros", "rustc_serialize", - "serde_json", "smallvec", - "stable_deref_trait", "stacker", "tempfile", "thin-vec", @@ -4624,6 +3335,7 @@ dependencies = [ "rustc_errors", "rustc_expand", "rustc_feature", + "rustc_fluent_macro", "rustc_hir", "rustc_hir_analysis", "rustc_hir_pretty", @@ -4672,6 +3384,7 @@ dependencies = [ "intl-memoizer", "rustc_baked_icu_data", "rustc_data_structures", + "rustc_fluent_macro", "rustc_macros", "rustc_serialize", "rustc_span", @@ -4688,6 +3401,7 @@ dependencies = [ "rustc_ast_pretty", "rustc_data_structures", "rustc_error_messages", + "rustc_fluent_macro", "rustc_hir", "rustc_lint_defs", "rustc_macros", @@ -4716,6 +3430,7 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", + "rustc_fluent_macro", "rustc_lexer", "rustc_lint_defs", "rustc_macros", @@ -4736,6 +3451,19 @@ dependencies = [ "rustc_span", ] +[[package]] +name = "rustc_fluent_macro" +version = "0.1.0" +dependencies = [ + "annotate-snippets", + "fluent-bundle", + "fluent-syntax", + "proc-macro2", + "quote", + "syn 2.0.8", + "unic-langid", +] + [[package]] name = "rustc_fs_util" version = "0.0.0" @@ -4772,10 +3500,11 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", + "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_infer", - "rustc_lint", + "rustc_lint_defs", "rustc_macros", "rustc_middle", "rustc_session", @@ -4784,7 +3513,6 @@ dependencies = [ "rustc_trait_selection", "rustc_type_ir", "smallvec", - "thin-vec", "tracing", ] @@ -4806,6 +3534,7 @@ dependencies = [ "rustc_ast", "rustc_data_structures", "rustc_errors", + "rustc_fluent_macro", "rustc_graphviz", "rustc_hir", "rustc_hir_analysis", @@ -4833,6 +3562,7 @@ dependencies = [ "rustc_ast", "rustc_data_structures", "rustc_errors", + "rustc_fluent_macro", "rustc_fs_util", "rustc_graphviz", "rustc_hir", @@ -4849,7 +3579,7 @@ dependencies = [ name = "rustc_index" version = "0.0.0" dependencies = [ - "arrayvec 0.7.0", + "arrayvec", "rustc_macros", "rustc_serialize", "smallvec", @@ -4861,6 +3591,7 @@ version = "0.0.0" dependencies = [ "rustc_data_structures", "rustc_errors", + "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_macros", @@ -4891,6 +3622,7 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_expand", + "rustc_fluent_macro", "rustc_fs_util", "rustc_hir", "rustc_hir_analysis", @@ -4917,7 +3649,6 @@ dependencies = [ "rustc_trait_selection", "rustc_traits", "rustc_ty_utils", - "smallvec", "tracing", ] @@ -4940,6 +3671,7 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", + "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_infer", @@ -4993,14 +3725,10 @@ dependencies = [ name = "rustc_macros" version = "0.1.0" dependencies = [ - "annotate-snippets", - "fluent-bundle", - "fluent-syntax", "proc-macro2", "quote", "syn 2.0.8", "synstructure 0.13.0", - "unic-langid", ] [[package]] @@ -5016,6 +3744,7 @@ dependencies = [ "rustc_errors", "rustc_expand", "rustc_feature", + "rustc_fluent_macro", "rustc_fs_util", "rustc_hir", "rustc_hir_pretty", @@ -5027,7 +3756,6 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_type_ir", - "smallvec", "snap", "tempfile", "tracing", @@ -5053,6 +3781,7 @@ dependencies = [ "rustc_error_messages", "rustc_errors", "rustc_feature", + "rustc_fluent_macro", "rustc_graphviz", "rustc_hir", "rustc_index", @@ -5078,6 +3807,7 @@ dependencies = [ "rustc_ast", "rustc_data_structures", "rustc_errors", + "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_infer", @@ -5101,6 +3831,7 @@ dependencies = [ "rustc_ast", "rustc_data_structures", "rustc_errors", + "rustc_fluent_macro", "rustc_graphviz", "rustc_hir", "rustc_index", @@ -5144,6 +3875,7 @@ version = "0.0.0" dependencies = [ "rustc_data_structures", "rustc_errors", + "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_macros", @@ -5153,7 +3885,6 @@ dependencies = [ "rustc_target", "serde", "serde_json", - "smallvec", "tracing", ] @@ -5167,6 +3898,7 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", + "rustc_fluent_macro", "rustc_lexer", "rustc_macros", "rustc_session", @@ -5197,6 +3929,7 @@ dependencies = [ "rustc_errors", "rustc_expand", "rustc_feature", + "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_lexer", @@ -5217,6 +3950,7 @@ dependencies = [ "libloading", "rustc_ast", "rustc_errors", + "rustc_fluent_macro", "rustc_lint", "rustc_macros", "rustc_metadata", @@ -5232,6 +3966,7 @@ dependencies = [ "rustc_attr", "rustc_data_structures", "rustc_errors", + "rustc_fluent_macro", "rustc_hir", "rustc_hir_analysis", "rustc_macros", @@ -5268,11 +4003,11 @@ version = "0.0.0" dependencies = [ "parking_lot 0.11.2", "rustc-rayon-core", - "rustc_arena", "rustc_ast", "rustc_data_structures", "rustc_errors", "rustc_feature", + "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_macros", @@ -5300,6 +4035,7 @@ dependencies = [ "rustc_errors", "rustc_expand", "rustc_feature", + "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_macros", @@ -5333,9 +4069,9 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_feature", + "rustc_fluent_macro", "rustc_fs_util", "rustc_hir", - "rustc_index", "rustc_lint_defs", "rustc_macros", "rustc_serialize", @@ -5384,6 +4120,7 @@ dependencies = [ "rustc-demangle", "rustc_data_structures", "rustc_errors", + "rustc_fluent_macro", "rustc_hir", "rustc_macros", "rustc_middle", @@ -5403,7 +4140,6 @@ dependencies = [ "rustc_data_structures", "rustc_feature", "rustc_fs_util", - "rustc_index", "rustc_macros", "rustc_serialize", "rustc_span", @@ -5421,11 +4157,11 @@ checksum = "8ba09476327c4b70ccefb6180f046ef588c26a24cf5d269a9feba316eb4f029f" name = "rustc_trait_selection" version = "0.0.0" dependencies = [ - "itertools", "rustc_ast", "rustc_attr", "rustc_data_structures", "rustc_errors", + "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_infer", @@ -5452,7 +4188,6 @@ dependencies = [ "rustc_ast", "rustc_data_structures", "rustc_hir", - "rustc_index", "rustc_infer", "rustc_middle", "rustc_span", @@ -5483,6 +4218,7 @@ version = "0.0.0" dependencies = [ "rustc_data_structures", "rustc_errors", + "rustc_fluent_macro", "rustc_hir", "rustc_index", "rustc_infer", @@ -5521,7 +4257,7 @@ dependencies = [ name = "rustdoc" version = "0.0.0" dependencies = [ - "arrayvec 0.7.0", + "arrayvec", "askama", "expect-test", "itertools", @@ -5606,7 +4342,7 @@ dependencies = [ "serde_json", "term", "thiserror", - "toml 0.5.7", + "toml", "unicode-segmentation", "unicode-width", "unicode_categories", @@ -5614,16 +4350,16 @@ dependencies = [ [[package]] name = "rustix" -version = "0.36.5" +version = "0.37.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588" +checksum = "2aae838e49b3d63e9274e1c01833cc8139d3fec468c3b84688c628f44b1ae11d" dependencies = [ "bitflags", "errno", "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -5670,41 +4406,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] -name = "sec1" -version = "0.3.0" +name = "scratch" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" -dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", -] - -[[package]] -name = "security-framework" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1759c2e3c8580017a484a7ac56d3abc5a6c1feadf88db2f3633f12ae4268c69" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f99b9d5e26d2a71633cc4f2ebae7cc9f874044e0c351a27e17892d76dce5678b" -dependencies = [ - "core-foundation-sys", - "libc", -] +checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" [[package]] name = "self_cell" @@ -5730,16 +4435,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-value" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" -dependencies = [ - "ordered-float", - "serde", -] - [[package]] name = "serde_derive" version = "1.0.159" @@ -5751,15 +4446,6 @@ dependencies = [ "syn 2.0.8", ] -[[package]] -name = "serde_ignored" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c2c7d39d14f2f2ea82239de71594782f186fd03501ac81f0ce08e674819ff2f" -dependencies = [ - "serde", -] - [[package]] name = "serde_json" version = "1.0.85" @@ -5772,15 +4458,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_spanned" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" -dependencies = [ - "serde", -] - [[package]] name = "sha1" version = "0.10.5" @@ -5792,12 +4469,6 @@ dependencies = [ "digest", ] -[[package]] -name = "sha1_smol" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" - [[package]] name = "sha2" version = "0.10.6" @@ -5830,57 +4501,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42a568c8f2cd051a4d283bd6eb0343ac214c1b0f1ac19f93e1175b2dee38c73d" -[[package]] -name = "signal-hook" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" -dependencies = [ - "digest", - "rand_core", -] - -[[package]] -name = "similar" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e24979f63a11545f5f2c60141afe249d4f19f84581ea2138065e400941d83d3" - [[package]] name = "siphasher" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7" -[[package]] -name = "sized-chunks" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e65d6a9f13cd78f361ea5a2cf53a45d67cdda421ba0316b9be101560f3d207" -dependencies = [ - "bitmaps", - "typenum", -] - [[package]] name = "slab" version = "0.4.2" @@ -5899,30 +4525,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831" -[[package]] -name = "snapbox" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "827c00e91b15e2674d8a5270bae91f898693cbf9561cbb58d8eaa31974597293" -dependencies = [ - "concolor", - "content_inspector", - "dunce", - "filetime", - "normalize-line-endings", - "similar", - "snapbox-macros", - "tempfile", - "walkdir", - "yansi", -] - -[[package]] -name = "snapbox-macros" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a253e6f894cfa440cba00600a249fa90869d8e0ec45ab274a456e043a0ce8f2" - [[package]] name = "socket2" version = "0.4.1" @@ -5947,9 +4549,9 @@ dependencies = [ [[package]] name = "spdx-rs" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3c02f6eb7e7b4100c272f685a9ccaccaab302324e8c7ec3e2ee72340fb29ff3" +checksum = "6b1ec09829bf2d82c175c121b20de11ffab2def83bd55979002099b1f9956c9b" dependencies = [ "chrono", "log", @@ -5962,16 +4564,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "spki" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" -dependencies = [ - "base64ct", - "der", -] - [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -6012,7 +4604,7 @@ dependencies = [ "hermit-abi 0.3.0", "libc", "miniz_oxide", - "object 0.29.0", + "object", "panic_abort", "panic_unwind", "profiler_builtins", @@ -6061,15 +4653,6 @@ dependencies = [ "quote", ] -[[package]] -name = "strip-ansi-escapes" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "011cbb39cf7c1f62871aea3cc46e5817b0937b49e9447370c93cacbe93a766d8" -dependencies = [ - "vte", -] - [[package]] name = "strsim" version = "0.10.0" @@ -6096,10 +4679,13 @@ dependencies = [ ] [[package]] -name = "subtle" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" +name = "suggest-tests" +version = "0.1.0" +dependencies = [ + "build_helper", + "glob", + "once_cell", +] [[package]] name = "syn" @@ -6205,12 +4791,12 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb20089a8ba2b69debd491f8d2d023761cbf196e999218c591fa1e7e15a21907" +checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" dependencies = [ "rustix", - "windows-sys 0.42.0", + "windows-sys 0.48.0", ] [[package]] @@ -6286,9 +4872,9 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da8fbf660a019b6bf11ea95762041464aa9099cc293b6a66d77cea5107619671" dependencies = [ - "gimli", + "gimli 0.26.2", "hashbrown 0.12.3", - "object 0.30.1", + "object", "tracing", ] @@ -6314,7 +4900,7 @@ dependencies = [ name = "tidy" version = "0.1.0" dependencies = [ - "cargo-platform 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo-platform", "cargo_metadata 0.15.3", "ignore", "lazy_static", @@ -6329,45 +4915,6 @@ dependencies = [ name = "tier-check" version = "0.1.0" -[[package]] -name = "time" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "time" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" -dependencies = [ - "itoa", - "libc", - "num_threads", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" - -[[package]] -name = "time-macros" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" -dependencies = [ - "time-core", -] - [[package]] name = "tinystr" version = "0.7.1" @@ -6414,40 +4961,6 @@ dependencies = [ "serde", ] -[[package]] -name = "toml" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7afcae9e3f0fe2c370fd4657108972cbb2fa9db1b9f84849cefd80741b01cb6" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.19.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6a7712b49e1775fb9a7b998de6635b299237f48b404dde71704f2e0e7f37e5" -dependencies = [ - "indexmap", - "nom8", - "serde", - "serde_spanned", - "toml_datetime", -] - [[package]] name = "topological-sort" version = "0.2.2" @@ -6584,11 +5097,12 @@ checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" [[package]] name = "ui_test" -version = "0.5.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54ddb6f31025943e2f9d59237f433711c461a43d9415974c3eb3a4902edc1c1f" +checksum = "3e10f5f88ce8c331a388deda1e6e2bd533c73ca89cc5f539a3df02ed35c8efba" dependencies = [ "bstr 1.3.0", + "cargo-platform", "cargo_metadata 0.15.3", "color-eyre", "colored", @@ -6597,6 +5111,7 @@ dependencies = [ "lazy_static", "regex", "rustc_version", + "rustfix", "serde", "serde_json", "tempfile", @@ -6711,12 +5226,6 @@ dependencies = [ "matches", ] -[[package]] -name = "unicode-bom" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63ec69f541d875b783ca40184d655f2927c95f0bffd486faa83cd3ac3529ec32" - [[package]] name = "unicode-ident" version = "1.0.5" @@ -6832,9 +5341,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "0.8.2" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +checksum = "5b55a3fef2a1e3b3a00ce878640918820d3c51081576ac657d23af9fc7928fdb" dependencies = [ "getrandom", ] @@ -6857,27 +5366,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "vte" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cbce692ab4ca2f1f3047fcf732430249c0e971bfdd2b234cf2c47ad93af5983" -dependencies = [ - "arrayvec 0.5.2", - "utf8parse", - "vte_generate_state_changes", -] - -[[package]] -name = "vte_generate_state_changes" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff" -dependencies = [ - "proc-macro2", - "quote", -] - [[package]] name = "walkdir" version = "2.3.2" @@ -6902,9 +5390,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -6912,9 +5400,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log", @@ -6927,9 +5415,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6937,9 +5425,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", @@ -6950,9 +5438,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "winapi" @@ -6985,28 +5473,22 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.43.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04662ed0e3e5630dfa9b26e4cb823b817f1a9addda855d973a9458c236556244" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - [[package]] name = "windows" version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25" dependencies = [ - "windows-targets", + "windows-targets 0.42.2", +] + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.0", ] [[package]] @@ -7015,13 +5497,13 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] @@ -7030,7 +5512,16 @@ version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows-targets", + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", ] [[package]] @@ -7039,13 +5530,28 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", ] [[package]] @@ -7054,42 +5560,84 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + [[package]] name = "windows_i686_gnu" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + [[package]] name = "windows_i686_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + [[package]] name = "writeable" version = "0.5.1" @@ -7134,12 +5682,6 @@ dependencies = [ "linked-hash-map", ] -[[package]] -name = "yansi" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" - [[package]] name = "yansi-term" version = "0.1.2" @@ -7194,12 +5736,6 @@ dependencies = [ "synstructure 0.12.6", ] -[[package]] -name = "zeroize" -version = "1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" - [[package]] name = "zerovec" version = "0.9.2" diff --git a/Cargo.toml b/Cargo.toml index 15cbb2659c9b..a497d7321e02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,12 +22,6 @@ members = [ "src/tools/remote-test-server", "src/tools/rust-installer", "src/tools/rust-demangler", - "src/tools/cargo", - "src/tools/cargo/crates/credential/cargo-credential-1password", - "src/tools/cargo/crates/credential/cargo-credential-macos-keychain", - "src/tools/cargo/crates/credential/cargo-credential-wincred", - "src/tools/cargo/crates/mdman", - # "src/tools/cargo/crates/resolver-tests", "src/tools/rustdoc", "src/tools/rls", "src/tools/rustfmt", @@ -44,6 +38,7 @@ members = [ "src/tools/lld-wrapper", "src/tools/collect-license-metadata", "src/tools/generate-copyright", + "src/tools/suggest-tests", ] exclude = [ @@ -105,10 +100,6 @@ miniz_oxide.debug = 0 object.debug = 0 [patch.crates-io] -# See comments in `src/tools/rustc-workspace-hack/README.md` for what's going on -# here -rustc-workspace-hack = { path = 'src/tools/rustc-workspace-hack' } - # See comments in `library/rustc-std-workspace-core/README.md` for what's going on # here rustc-std-workspace-core = { path = 'library/rustc-std-workspace-core' } diff --git a/README.md b/README.md index c19e129a9207..41b135972af1 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,8 @@ Read ["Installation"] from [The Book]. The Rust build system uses a Python script called `x.py` to build the compiler, which manages the bootstrapping process. It lives at the root of the project. +It also uses a file named `config.toml` to determine various configuration settings for the build. +You can see a full list of options in `config.example.toml`. The `x.py` command can be run directly on most Unix systems in the following format: @@ -85,6 +87,8 @@ See [the rustc-dev-guide for more info][sysllvm]. ### Building on a Unix-like system +#### Build steps + 1. Clone the [source] with `git`: ```sh @@ -96,18 +100,13 @@ See [the rustc-dev-guide for more info][sysllvm]. 2. Configure the build settings: - The Rust build system uses a file named `config.toml` in the root of the - source tree to determine various configuration settings for the build. - Set up the defaults intended for distros to get started. You can see a full - list of options in `config.example.toml`. - ```sh - printf 'profile = "user" \nchangelog-seen = 2 \n' > config.toml + ./configure ``` If you plan to use `x.py install` to create an installation, it is recommended that you set the `prefix` value in the `[install]` section to a - directory. + directory: `./configure --set install.prefix=` 3. Build and install: @@ -117,12 +116,25 @@ See [the rustc-dev-guide for more info][sysllvm]. When complete, `./x.py install` will place several programs into `$PREFIX/bin`: `rustc`, the Rust compiler, and `rustdoc`, the - API-documentation tool. If you've set `profile = "user"` or - `build.extended = true`, it will also include [Cargo], Rust's package - manager. + API-documentation tool. By default, it will also include [Cargo], Rust's package manager. + You can disable this behavior by passing `--set build.extended=false` to `./configure`. [Cargo]: https://github.com/rust-lang/cargo +#### Configure and Make + +This project provides a configure script and makefile (the latter of which just invokes `x.py`). +`./configure` is the recommended way to programatically generate a `config.toml`. `make` is not +recommended (we suggest using `x.py` directly), but it is supported and we try not to break it +unnecessarily. + +```sh +./configure +make && sudo make install +``` + +`configure` generates a `config.toml` which can also be used with normal `x.py` invocations. + ### Building on Windows On Windows, we suggest using [winget] to install dependencies by running the @@ -186,7 +198,7 @@ toolchain. 4. Navigate to Rust's source code (or clone it), then build it: ```sh - ./x.py build && ./x.py install + python x.py setup user && python x.py build && python x.py install ``` #### MSVC @@ -204,6 +216,7 @@ With these dependencies installed, you can build the compiler in a `cmd.exe` shell with: ```sh +python x.py setup user python x.py build ``` @@ -232,21 +245,7 @@ Windows build triples are: The build triple can be specified by either specifying `--build=` when invoking `x.py` commands, or by creating a `config.toml` file (as described in -[Installing from Source](#installing-from-source)), and modifying the `build` -option under the `[build]` section. - -### Configure and Make - -While it's not the recommended build system, this project also provides a -configure script and makefile (the latter of which just invokes `x.py`). - -```sh -./configure -make && sudo make install -``` - -`configure` generates a `config.toml` which can also be used with normal `x.py` -invocations. +[Building on a Unix-like system](#building-on-a-unix-like-system)), and passing `--set build.build=` to `./configure`. ## Building Documentation diff --git a/RELEASES.md b/RELEASES.md index b923f87abfd4..e72905c15bd2 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,109 @@ +Version 1.69.0 (2023-04-20) +========================== + + + +Language +-------- + +- [Deriving built-in traits on packed structs works with `Copy` fields.](https://github.com/rust-lang/rust/pull/104429/) +- [Stabilize the `cmpxchg16b` target feature on x86 and x86_64.](https://github.com/rust-lang/rust/pull/106774/) +- [Improve analysis of trait bounds for associated types.](https://github.com/rust-lang/rust/pull/103695/) +- [Allow associated types to be used as union fields.](https://github.com/rust-lang/rust/pull/106938/) +- [Allow `Self: Autotrait` bounds on dyn-safe trait methods.](https://github.com/rust-lang/rust/pull/107082/) +- [Treat `str` as containing `[u8]` for auto trait purposes.](https://github.com/rust-lang/rust/pull/107941/) + + + +Compiler +-------- + +- [Upgrade `*-pc-windows-gnu` on CI to mingw-w64 v10 and GCC 12.2.](https://github.com/rust-lang/rust/pull/100178/) +- [Rework min_choice algorithm of member constraints.](https://github.com/rust-lang/rust/pull/105300/) +- [Support `true` and `false` as boolean flags in compiler arguments.](https://github.com/rust-lang/rust/pull/107043/) +- [Default `repr(C)` enums to `c_int` size.](https://github.com/rust-lang/rust/pull/107592/) + + + +Libraries +--------- + +- [Implement the unstable `DispatchFromDyn` for cell types, allowing downstream experimentation with custom method receivers.](https://github.com/rust-lang/rust/pull/97373/) +- [Document that `fmt::Arguments::as_str()` may return `Some(_)` in more cases after optimization, subject to change.](https://github.com/rust-lang/rust/pull/106823/) +- [Implement `AsFd` and `AsRawFd` for `Rc`.](https://github.com/rust-lang/rust/pull/107317/) + + + +Stabilized APIs +--------------- + +- [`CStr::from_bytes_until_nul`](https://doc.rust-lang.org/stable/core/ffi/struct.CStr.html#method.from_bytes_until_nul) +- [`core::ffi::FromBytesUntilNulError`](https://doc.rust-lang.org/stable/core/ffi/struct.FromBytesUntilNulError.html) + +These APIs are now stable in const contexts: + +- [`SocketAddr::new`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.new) +- [`SocketAddr::ip`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.ip) +- [`SocketAddr::port`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.port) +- [`SocketAddr::is_ipv4`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.is_ipv4) +- [`SocketAddr::is_ipv6`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.is_ipv6) +- [`SocketAddrV4::new`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV4.html#method.new) +- [`SocketAddrV4::ip`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV4.html#method.ip) +- [`SocketAddrV4::port`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV4.html#method.port) +- [`SocketAddrV6::new`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.new) +- [`SocketAddrV6::ip`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.ip) +- [`SocketAddrV6::port`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.port) +- [`SocketAddrV6::flowinfo`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.flowinfo) +- [`SocketAddrV6::scope_id`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.scope_id) + + + +Cargo +----- + +- [Cargo now suggests `cargo fix` or `cargo clippy --fix` when compilation warnings are auto-fixable.](https://github.com/rust-lang/cargo/pull/11558/) +- [Cargo now suggests `cargo add` if you try to install a library crate.](https://github.com/rust-lang/cargo/pull/11410/) +- [Cargo now sets the `CARGO_BIN_NAME` environment variable also for binary examples.](https://github.com/rust-lang/cargo/pull/11705/) + + + +Rustdoc +----- + +- [Vertically compact trait bound formatting.](https://github.com/rust-lang/rust/pull/102842/) +- [Only include stable lints in `rustdoc::all` group.](https://github.com/rust-lang/rust/pull/106316/) +- [Compute maximum Levenshtein distance based on the query.](https://github.com/rust-lang/rust/pull/107141/) +- [Remove inconsistently-present sidebar tooltips.](https://github.com/rust-lang/rust/pull/107490/) +- [Search by macro when query ends with `!`.](https://github.com/rust-lang/rust/pull/108143/) + + + +Compatibility Notes +------------------- + +- [The `rust-analysis` component from `rustup` now only contains a warning placeholder.](https://github.com/rust-lang/rust/pull/101841/) This was primarily intended for RLS, and the corresponding `-Zsave-analysis` flag has been removed from the compiler as well. +- [Unaligned references to packed fields are now a hard error.](https://github.com/rust-lang/rust/pull/102513/) This has been a warning since 1.53, and denied by default with a future-compatibility warning since 1.62. +- [Update the minimum external LLVM to 14.](https://github.com/rust-lang/rust/pull/107573/) +- [Cargo now emits errors on invalid characters in a registry token.](https://github.com/rust-lang/cargo/pull/11600/) +- [When `default-features` is set to false of a workspace dependency, and an inherited dependency of a member has `default-features = true`, Cargo will enable default features of that dependency.](https://github.com/rust-lang/cargo/pull/11409/) +- [Cargo denies `CARGO_HOME` in the `[env]` configuration table. Cargo itself doesn't pick up this value, but recursive calls to cargo would, which was not intended.](https://github.com/rust-lang/cargo/pull/11644/) +- [Debuginfo for build dependencies is now off if not explicitly set. This is expected to improve the overall build time.](https://github.com/rust-lang/cargo/pull/11252/) +- [The Rust distribution no longer always includes rustdoc](https://github.com/rust-lang/rust/pull/106886) + If `tools = [...]` is set in config.toml, we will respect a missing rustdoc in that list. By + default rustdoc remains included. To retain the prior behavior explicitly add `"rustdoc"` to the + list. + + + +Internal Changes +---------------- + +These changes do not affect any public interfaces of Rust, but they represent +significant improvements to the performance or internals of rustc and related +tools. + +- [Move `format_args!()` into AST (and expand it during AST lowering)](https://github.com/rust-lang/rust/pull/106745/) + Version 1.68.2 (2023-03-28) =========================== @@ -861,7 +967,7 @@ Compatibility Notes - [rustdoc: doctests are now run on unexported `macro_rules!` macros, matching other private items][96630] - [rustdoc: Remove .woff font files][96279] - [Enforce Copy bounds for repeat elements while considering lifetimes][95819] -- [Windows: Fix potentinal unsoundness by aborting if `File` reads or writes cannot +- [Windows: Fix potential unsoundness by aborting if `File` reads or writes cannot complete synchronously][95469]. Internal Changes @@ -1692,10 +1798,10 @@ Libraries - [impl Default, Copy, Clone for std::io::Sink and std::io::Empty][rust#86744] - [`impl From<[(K, V); N]>` for all collections.][rust#84111] - [Remove `P: Unpin` bound on impl Future for Pin.][rust#81363] -- [Treat invalid environment variable names as non-existent.][rust#86183] +- [Treat invalid environment variable names as nonexistent.][rust#86183] Previously, the environment functions would panic if given a variable name with an internal null character or equal sign (`=`). Now, these functions will - just treat such names as non-existent variables, since the OS cannot represent + just treat such names as nonexistent variables, since the OS cannot represent the existence of a variable with such a name. Stabilised APIs @@ -1888,7 +1994,7 @@ Compatibility Notes kinds of errors could be categorised [into newer more specific `ErrorKind` variants][79965], and that they do not represent a user error. - [Using environment variable names with `process::Command` on Windows now - behaves as expected.][85270] Previously using envionment variables with + behaves as expected.][85270] Previously using environment variables with `Command` would cause them to be ASCII-uppercased. - [Rustdoc will now warn on using rustdoc lints that aren't prefixed with `rustdoc::`][86849] @@ -6265,7 +6371,7 @@ eg. `static MINUTE: Duration = Duration::from_secs(60);` Cargo ----- -- [`cargo new` no longer removes `rust` or `rs` prefixs/suffixs.][cargo/5013] +- [`cargo new` no longer removes `rust` or `rs` prefixes/suffixes.][cargo/5013] - [`cargo new` now defaults to creating a binary crate, instead of a library crate.][cargo/5029] diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index c863acde7b03..b4597d5bc784 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -1,4 +1,5 @@ use super::*; +use std::fmt::Write; use std::{borrow::Borrow, cmp, iter, ops::Bound}; #[cfg(feature = "randomize")] @@ -49,219 +50,60 @@ pub trait LayoutCalculator { repr: &ReprOptions, kind: StructKind, ) -> Option { - let pack = repr.pack; - let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align }; - let mut inverse_memory_index: IndexVec = fields.indices().collect(); - let optimize = !repr.inhibit_struct_field_reordering_opt(); - if optimize { - let end = - if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() }; - let optimizing = &mut inverse_memory_index.raw[..end]; - let effective_field_align = |layout: Layout<'_>| { - if let Some(pack) = pack { - // return the packed alignment in bytes - layout.align().abi.min(pack).bytes() - } else { - // returns log2(effective-align). - // This is ok since `pack` applies to all fields equally. - // The calculation assumes that size is an integer multiple of align, except for ZSTs. - // - // group [u8; 4] with align-4 or [u8; 6] with align-2 fields - layout.align().abi.bytes().max(layout.size().bytes()).trailing_zeros() as u64 - } - }; + let layout = univariant(self, dl, fields, repr, kind, NicheBias::Start); + // Enums prefer niches close to the beginning or the end of the variants so that other (smaller) + // data-carrying variants can be packed into the space after/before the niche. + // If the default field ordering does not give us a niche at the front then we do a second + // run and bias niches to the right and then check which one is closer to one of the struct's + // edges. + if let Some(layout) = &layout { + if let Some(niche) = layout.largest_niche { + let head_space = niche.offset.bytes(); + let niche_length = niche.value.size(dl).bytes(); + let tail_space = layout.size.bytes() - head_space - niche_length; - // If `-Z randomize-layout` was enabled for the type definition we can shuffle - // the field ordering to try and catch some code making assumptions about layouts - // we don't guarantee - if repr.can_randomize_type_layout() && cfg!(feature = "randomize") { - #[cfg(feature = "randomize")] - { - // `ReprOptions.layout_seed` is a deterministic seed that we can use to - // randomize field ordering with - let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed); + // This may end up doing redundant work if the niche is already in the last field + // (e.g. a trailing bool) and there is tail padding. But it's non-trivial to get + // the unpadded size so we try anyway. + if fields.len() > 1 && head_space != 0 && tail_space > 0 { + let alt_layout = univariant(self, dl, fields, repr, kind, NicheBias::End) + .expect("alt layout should always work"); + let niche = alt_layout + .largest_niche + .expect("alt layout should have a niche like the regular one"); + let alt_head_space = niche.offset.bytes(); + let alt_niche_len = niche.value.size(dl).bytes(); + let alt_tail_space = alt_layout.size.bytes() - alt_head_space - alt_niche_len; - // Shuffle the ordering of the fields - optimizing.shuffle(&mut rng); - } - // Otherwise we just leave things alone and actually optimize the type's fields - } else { - match kind { - StructKind::AlwaysSized | StructKind::MaybeUnsized => { - optimizing.sort_by_key(|&x| { - // Place ZSTs first to avoid "interesting offsets", - // especially with only one or two non-ZST fields. - // Then place largest alignments first, largest niches within an alignment group last - let f = fields[x]; - let niche_size = f.largest_niche().map_or(0, |n| n.available(dl)); - (!f.0.is_zst(), cmp::Reverse(effective_field_align(f)), niche_size) - }); - } + debug_assert_eq!(layout.size.bytes(), alt_layout.size.bytes()); - StructKind::Prefixed(..) => { - // Sort in ascending alignment so that the layout stays optimal - // regardless of the prefix. - // And put the largest niche in an alignment group at the end - // so it can be used as discriminant in jagged enums - optimizing.sort_by_key(|&x| { - let f = fields[x]; - let niche_size = f.largest_niche().map_or(0, |n| n.available(dl)); - (effective_field_align(f), niche_size) - }); + let prefer_alt_layout = + alt_head_space > head_space && alt_head_space > tail_space; + + debug!( + "sz: {}, default_niche_at: {}+{}, default_tail_space: {}, alt_niche_at/head_space: {}+{}, alt_tail: {}, num_fields: {}, better: {}\n\ + layout: {}\n\ + alt_layout: {}\n", + layout.size.bytes(), + head_space, + niche_length, + tail_space, + alt_head_space, + alt_niche_len, + alt_tail_space, + layout.fields.count(), + prefer_alt_layout, + format_field_niches(&layout, &fields, &dl), + format_field_niches(&alt_layout, &fields, &dl), + ); + + if prefer_alt_layout { + return Some(alt_layout); } } - - // FIXME(Kixiron): We can always shuffle fields within a given alignment class - // regardless of the status of `-Z randomize-layout` } } - // inverse_memory_index holds field indices by increasing memory offset. - // That is, if field 5 has offset 0, the first element of inverse_memory_index is 5. - // We now write field offsets to the corresponding offset slot; - // field 5 with offset 0 puts 0 in offsets[5]. - // At the bottom of this function, we invert `inverse_memory_index` to - // produce `memory_index` (see `invert_mapping`). - let mut sized = true; - let mut offsets = IndexVec::from_elem(Size::ZERO, &fields); - let mut offset = Size::ZERO; - let mut largest_niche = None; - let mut largest_niche_available = 0; - if let StructKind::Prefixed(prefix_size, prefix_align) = kind { - let prefix_align = - if let Some(pack) = pack { prefix_align.min(pack) } else { prefix_align }; - align = align.max(AbiAndPrefAlign::new(prefix_align)); - offset = prefix_size.align_to(prefix_align); - } - for &i in &inverse_memory_index { - let field = &fields[i]; - if !sized { - self.delay_bug(&format!( - "univariant: field #{} comes after unsized field", - offsets.len(), - )); - } - - if field.0.is_unsized() { - sized = false; - } - - // Invariant: offset < dl.obj_size_bound() <= 1<<61 - let field_align = if let Some(pack) = pack { - field.align().min(AbiAndPrefAlign::new(pack)) - } else { - field.align() - }; - offset = offset.align_to(field_align.abi); - align = align.max(field_align); - - debug!("univariant offset: {:?} field: {:#?}", offset, field); - offsets[i] = offset; - - if let Some(mut niche) = field.largest_niche() { - let available = niche.available(dl); - if available > largest_niche_available { - largest_niche_available = available; - niche.offset += offset; - largest_niche = Some(niche); - } - } - - offset = offset.checked_add(field.size(), dl)?; - } - if let Some(repr_align) = repr.align { - align = align.max(AbiAndPrefAlign::new(repr_align)); - } - debug!("univariant min_size: {:?}", offset); - let min_size = offset; - // As stated above, inverse_memory_index holds field indices by increasing offset. - // This makes it an already-sorted view of the offsets vec. - // To invert it, consider: - // If field 5 has offset 0, offsets[0] is 5, and memory_index[5] should be 0. - // Field 5 would be the first element, so memory_index is i: - // Note: if we didn't optimize, it's already right. - let memory_index = if optimize { - inverse_memory_index.invert_bijective_mapping() - } else { - debug_assert!(inverse_memory_index.iter().copied().eq(fields.indices())); - inverse_memory_index.into_iter().map(FieldIdx::as_u32).collect() - }; - let size = min_size.align_to(align.abi); - let mut abi = Abi::Aggregate { sized }; - // Unpack newtype ABIs and find scalar pairs. - if sized && size.bytes() > 0 { - // All other fields must be ZSTs. - let mut non_zst_fields = fields.iter_enumerated().filter(|&(_, f)| !f.0.is_zst()); - - match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) { - // We have exactly one non-ZST field. - (Some((i, field)), None, None) => { - // Field fills the struct and it has a scalar or scalar pair ABI. - if offsets[i].bytes() == 0 - && align.abi == field.align().abi - && size == field.size() - { - match field.abi() { - // For plain scalars, or vectors of them, we can't unpack - // newtypes for `#[repr(C)]`, as that affects C ABIs. - Abi::Scalar(_) | Abi::Vector { .. } if optimize => { - abi = field.abi(); - } - // But scalar pairs are Rust-specific and get - // treated as aggregates by C ABIs anyway. - Abi::ScalarPair(..) => { - abi = field.abi(); - } - _ => {} - } - } - } - - // Two non-ZST fields, and they're both scalars. - (Some((i, a)), Some((j, b)), None) => { - match (a.abi(), b.abi()) { - (Abi::Scalar(a), Abi::Scalar(b)) => { - // Order by the memory placement, not source order. - let ((i, a), (j, b)) = if offsets[i] < offsets[j] { - ((i, a), (j, b)) - } else { - ((j, b), (i, a)) - }; - let pair = self.scalar_pair(a, b); - let pair_offsets = match pair.fields { - FieldsShape::Arbitrary { ref offsets, ref memory_index } => { - assert_eq!(memory_index.raw, [0, 1]); - offsets - } - _ => panic!(), - }; - if offsets[i] == pair_offsets[FieldIdx::from_usize(0)] - && offsets[j] == pair_offsets[FieldIdx::from_usize(1)] - && align == pair.align - && size == pair.size - { - // We can use `ScalarPair` only when it matches our - // already computed layout (including `#[repr(C)]`). - abi = pair.abi; - } - } - _ => {} - } - } - - _ => {} - } - } - if fields.iter().any(|f| f.abi().is_uninhabited()) { - abi = Abi::Uninhabited; - } - Some(LayoutS { - variants: Variants::Single { index: FIRST_VARIANT }, - fields: FieldsShape::Arbitrary { offsets, memory_index }, - abi, - largest_niche, - align, - size, - }) + layout } fn layout_of_never_type(&self) -> LayoutS { @@ -461,8 +303,8 @@ pub trait LayoutCalculator { let all_indices = variants.indices(); let needs_disc = |index: VariantIdx| index != largest_variant_index && !absent(&variants[index]); - let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap().index() - ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap().index(); + let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap() + ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap(); let count = niche_variants.size_hint().1.unwrap() as u128; @@ -560,8 +402,7 @@ pub trait LayoutCalculator { tag: niche_scalar, tag_encoding: TagEncoding::Niche { untagged_variant: largest_variant_index, - niche_variants: (VariantIdx::new(*niche_variants.start()) - ..=VariantIdx::new(*niche_variants.end())), + niche_variants, niche_start, }, tag_field: 0, @@ -934,3 +775,323 @@ pub trait LayoutCalculator { }) } } + +/// Determines towards which end of a struct layout optimizations will try to place the best niches. +enum NicheBias { + Start, + End, +} + +fn univariant( + this: &(impl LayoutCalculator + ?Sized), + dl: &TargetDataLayout, + fields: &IndexSlice>, + repr: &ReprOptions, + kind: StructKind, + niche_bias: NicheBias, +) -> Option { + let pack = repr.pack; + let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align }; + let mut inverse_memory_index: IndexVec = fields.indices().collect(); + let optimize = !repr.inhibit_struct_field_reordering_opt(); + if optimize && fields.len() > 1 { + let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() }; + let optimizing = &mut inverse_memory_index.raw[..end]; + + // If `-Z randomize-layout` was enabled for the type definition we can shuffle + // the field ordering to try and catch some code making assumptions about layouts + // we don't guarantee + if repr.can_randomize_type_layout() && cfg!(feature = "randomize") { + #[cfg(feature = "randomize")] + { + // `ReprOptions.layout_seed` is a deterministic seed that we can use to + // randomize field ordering with + let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed.as_u64()); + + // Shuffle the ordering of the fields + optimizing.shuffle(&mut rng); + } + // Otherwise we just leave things alone and actually optimize the type's fields + } else { + let max_field_align = fields.iter().map(|f| f.align().abi.bytes()).max().unwrap_or(1); + let largest_niche_size = fields + .iter() + .filter_map(|f| f.largest_niche()) + .map(|n| n.available(dl)) + .max() + .unwrap_or(0); + + // Calculates a sort key to group fields by their alignment or possibly some size-derived + // pseudo-alignment. + let alignment_group_key = |layout: Layout<'_>| { + if let Some(pack) = pack { + // return the packed alignment in bytes + layout.align().abi.min(pack).bytes() + } else { + // returns log2(effective-align). + // This is ok since `pack` applies to all fields equally. + // The calculation assumes that size is an integer multiple of align, except for ZSTs. + // + let align = layout.align().abi.bytes(); + let size = layout.size().bytes(); + let niche_size = layout.largest_niche().map(|n| n.available(dl)).unwrap_or(0); + // group [u8; 4] with align-4 or [u8; 6] with align-2 fields + let size_as_align = align.max(size).trailing_zeros(); + let size_as_align = if largest_niche_size > 0 { + match niche_bias { + // Given `A(u8, [u8; 16])` and `B(bool, [u8; 16])` we want to bump the array + // to the front in the first case (for aligned loads) but keep the bool in front + // in the second case for its niches. + NicheBias::Start => max_field_align.trailing_zeros().min(size_as_align), + // When moving niches towards the end of the struct then for + // A((u8, u8, u8, bool), (u8, bool, u8)) we want to keep the first tuple + // in the align-1 group because its bool can be moved closer to the end. + NicheBias::End if niche_size == largest_niche_size => { + align.trailing_zeros() + } + NicheBias::End => size_as_align, + } + } else { + size_as_align + }; + size_as_align as u64 + } + }; + + match kind { + StructKind::AlwaysSized | StructKind::MaybeUnsized => { + // Currently `LayoutS` only exposes a single niche so sorting is usually sufficient + // to get one niche into the preferred position. If it ever supported multiple niches + // then a more advanced pick-and-pack approach could provide better results. + // But even for the single-niche cache it's not optimal. E.g. for + // A(u32, (bool, u8), u16) it would be possible to move the bool to the front + // but it would require packing the tuple together with the u16 to build a 4-byte + // group so that the u32 can be placed after it without padding. This kind + // of packing can't be achieved by sorting. + optimizing.sort_by_key(|&x| { + let f = fields[x]; + let field_size = f.size().bytes(); + let niche_size = f.largest_niche().map_or(0, |n| n.available(dl)); + let niche_size_key = match niche_bias { + // large niche first + NicheBias::Start => !niche_size, + // large niche last + NicheBias::End => niche_size, + }; + let inner_niche_offset_key = match niche_bias { + NicheBias::Start => f.largest_niche().map_or(0, |n| n.offset.bytes()), + NicheBias::End => f.largest_niche().map_or(0, |n| { + !(field_size - n.value.size(dl).bytes() - n.offset.bytes()) + }), + }; + + ( + // Place ZSTs first to avoid "interesting offsets", especially with only one + // or two non-ZST fields. This helps Scalar/ScalarPair layouts. + !f.0.is_zst(), + // Then place largest alignments first. + cmp::Reverse(alignment_group_key(f)), + // Then prioritize niche placement within alignment group according to + // `niche_bias_start`. + niche_size_key, + // Then among fields with equally-sized niches prefer the ones + // closer to the start/end of the field. + inner_niche_offset_key, + ) + }); + } + + StructKind::Prefixed(..) => { + // Sort in ascending alignment so that the layout stays optimal + // regardless of the prefix. + // And put the largest niche in an alignment group at the end + // so it can be used as discriminant in jagged enums + optimizing.sort_by_key(|&x| { + let f = fields[x]; + let niche_size = f.largest_niche().map_or(0, |n| n.available(dl)); + (alignment_group_key(f), niche_size) + }); + } + } + + // FIXME(Kixiron): We can always shuffle fields within a given alignment class + // regardless of the status of `-Z randomize-layout` + } + } + // inverse_memory_index holds field indices by increasing memory offset. + // That is, if field 5 has offset 0, the first element of inverse_memory_index is 5. + // We now write field offsets to the corresponding offset slot; + // field 5 with offset 0 puts 0 in offsets[5]. + // At the bottom of this function, we invert `inverse_memory_index` to + // produce `memory_index` (see `invert_mapping`). + let mut sized = true; + let mut offsets = IndexVec::from_elem(Size::ZERO, &fields); + let mut offset = Size::ZERO; + let mut largest_niche = None; + let mut largest_niche_available = 0; + if let StructKind::Prefixed(prefix_size, prefix_align) = kind { + let prefix_align = + if let Some(pack) = pack { prefix_align.min(pack) } else { prefix_align }; + align = align.max(AbiAndPrefAlign::new(prefix_align)); + offset = prefix_size.align_to(prefix_align); + } + for &i in &inverse_memory_index { + let field = &fields[i]; + if !sized { + this.delay_bug(&format!( + "univariant: field #{} comes after unsized field", + offsets.len(), + )); + } + + if field.0.is_unsized() { + sized = false; + } + + // Invariant: offset < dl.obj_size_bound() <= 1<<61 + let field_align = if let Some(pack) = pack { + field.align().min(AbiAndPrefAlign::new(pack)) + } else { + field.align() + }; + offset = offset.align_to(field_align.abi); + align = align.max(field_align); + + debug!("univariant offset: {:?} field: {:#?}", offset, field); + offsets[i] = offset; + + if let Some(mut niche) = field.largest_niche() { + let available = niche.available(dl); + // Pick up larger niches. + let prefer_new_niche = match niche_bias { + NicheBias::Start => available > largest_niche_available, + // if there are several niches of the same size then pick the last one + NicheBias::End => available >= largest_niche_available, + }; + if prefer_new_niche { + largest_niche_available = available; + niche.offset += offset; + largest_niche = Some(niche); + } + } + + offset = offset.checked_add(field.size(), dl)?; + } + if let Some(repr_align) = repr.align { + align = align.max(AbiAndPrefAlign::new(repr_align)); + } + debug!("univariant min_size: {:?}", offset); + let min_size = offset; + // As stated above, inverse_memory_index holds field indices by increasing offset. + // This makes it an already-sorted view of the offsets vec. + // To invert it, consider: + // If field 5 has offset 0, offsets[0] is 5, and memory_index[5] should be 0. + // Field 5 would be the first element, so memory_index is i: + // Note: if we didn't optimize, it's already right. + let memory_index = if optimize { + inverse_memory_index.invert_bijective_mapping() + } else { + debug_assert!(inverse_memory_index.iter().copied().eq(fields.indices())); + inverse_memory_index.into_iter().map(FieldIdx::as_u32).collect() + }; + let size = min_size.align_to(align.abi); + let mut abi = Abi::Aggregate { sized }; + // Unpack newtype ABIs and find scalar pairs. + if sized && size.bytes() > 0 { + // All other fields must be ZSTs. + let mut non_zst_fields = fields.iter_enumerated().filter(|&(_, f)| !f.0.is_zst()); + + match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) { + // We have exactly one non-ZST field. + (Some((i, field)), None, None) => { + // Field fills the struct and it has a scalar or scalar pair ABI. + if offsets[i].bytes() == 0 && align.abi == field.align().abi && size == field.size() + { + match field.abi() { + // For plain scalars, or vectors of them, we can't unpack + // newtypes for `#[repr(C)]`, as that affects C ABIs. + Abi::Scalar(_) | Abi::Vector { .. } if optimize => { + abi = field.abi(); + } + // But scalar pairs are Rust-specific and get + // treated as aggregates by C ABIs anyway. + Abi::ScalarPair(..) => { + abi = field.abi(); + } + _ => {} + } + } + } + + // Two non-ZST fields, and they're both scalars. + (Some((i, a)), Some((j, b)), None) => { + match (a.abi(), b.abi()) { + (Abi::Scalar(a), Abi::Scalar(b)) => { + // Order by the memory placement, not source order. + let ((i, a), (j, b)) = if offsets[i] < offsets[j] { + ((i, a), (j, b)) + } else { + ((j, b), (i, a)) + }; + let pair = this.scalar_pair(a, b); + let pair_offsets = match pair.fields { + FieldsShape::Arbitrary { ref offsets, ref memory_index } => { + assert_eq!(memory_index.raw, [0, 1]); + offsets + } + _ => panic!(), + }; + if offsets[i] == pair_offsets[FieldIdx::from_usize(0)] + && offsets[j] == pair_offsets[FieldIdx::from_usize(1)] + && align == pair.align + && size == pair.size + { + // We can use `ScalarPair` only when it matches our + // already computed layout (including `#[repr(C)]`). + abi = pair.abi; + } + } + _ => {} + } + } + + _ => {} + } + } + if fields.iter().any(|f| f.abi().is_uninhabited()) { + abi = Abi::Uninhabited; + } + Some(LayoutS { + variants: Variants::Single { index: FIRST_VARIANT }, + fields: FieldsShape::Arbitrary { offsets, memory_index }, + abi, + largest_niche, + align, + size, + }) +} + +fn format_field_niches( + layout: &LayoutS, + fields: &IndexSlice>, + dl: &TargetDataLayout, +) -> String { + let mut s = String::new(); + for i in layout.fields.index_by_increasing_offset() { + let offset = layout.fields.offset(i); + let f = fields[i.into()]; + write!(s, "[o{}a{}s{}", offset.bytes(), f.align().abi.bytes(), f.size().bytes()).unwrap(); + if let Some(n) = f.largest_niche() { + write!( + s, + " n{}b{}s{}", + n.offset.bytes(), + n.available(dl).ilog2(), + n.value.size(dl).bytes() + ) + .unwrap(); + } + write!(s, "] ").unwrap(); + } + s +} diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index b0c0ee942ea8..d01a9b003042 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -9,9 +9,10 @@ use std::str::FromStr; use bitflags::bitflags; use rustc_data_structures::intern::Interned; +use rustc_data_structures::stable_hasher::Hash64; #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::StableOrd; -use rustc_index::vec::{Idx, IndexSlice, IndexVec}; +use rustc_index::{IndexSlice, IndexVec}; #[cfg(feature = "nightly")] use rustc_macros::HashStable_Generic; #[cfg(feature = "nightly")] @@ -77,12 +78,12 @@ pub struct ReprOptions { pub flags: ReprFlags, /// The seed to be used for randomizing a type's layout /// - /// Note: This could technically be a `[u8; 16]` (a `u128`) which would + /// Note: This could technically be a `Hash128` which would /// be the "most accurate" hash as it'd encompass the item and crate /// hash without loss, but it does pay the price of being larger. - /// Everything's a tradeoff, a `u64` seed should be sufficient for our + /// Everything's a tradeoff, a 64-bit seed should be sufficient for our /// purposes (primarily `-Z randomize-layout`) - pub field_shuffle_seed: u64, + pub field_shuffle_seed: Hash64, } impl ReprOptions { @@ -665,15 +666,12 @@ impl Align { format!("`{}` is too large", align) } - let mut bytes = align; - let mut pow2: u8 = 0; - while (bytes & 1) == 0 { - pow2 += 1; - bytes >>= 1; - } - if bytes != 1 { + let tz = align.trailing_zeros(); + if align != (1 << tz) { return Err(not_power_of_2(align)); } + + let pow2 = tz as u8; if pow2 > Self::MAX.pow2 { return Err(too_large(align)); } diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 345e058e1134..6e15f06a76de 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -20,6 +20,7 @@ #![feature(rustc_attrs)] #![cfg_attr(test, feature(test))] #![feature(strict_provenance)] +#![deny(unsafe_op_in_unsafe_fn)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] #![allow(clippy::mut_from_ref)] // Arena allocators are one of the places where this pattern is fine. @@ -74,19 +75,27 @@ impl ArenaChunk { #[inline] unsafe fn new(capacity: usize) -> ArenaChunk { ArenaChunk { - storage: NonNull::new(Box::into_raw(Box::new_uninit_slice(capacity))).unwrap(), + storage: NonNull::from(Box::leak(Box::new_uninit_slice(capacity))), entries: 0, } } /// Destroys this arena chunk. + /// + /// # Safety + /// + /// The caller must ensure that `len` elements of this chunk have been initialized. #[inline] unsafe fn destroy(&mut self, len: usize) { // The branch on needs_drop() is an -O1 performance optimization. - // Without the branch, dropping TypedArena takes linear time. + // Without the branch, dropping TypedArena takes linear time. if mem::needs_drop::() { - let slice = &mut *(self.storage.as_mut()); - ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut slice[..len])); + // SAFETY: The caller must ensure that `len` elements of this chunk have + // been initialized. + unsafe { + let slice = self.storage.as_mut(); + ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut slice[..len])); + } } } @@ -104,7 +113,7 @@ impl ArenaChunk { // A pointer as large as possible for zero-sized elements. ptr::invalid_mut(!0) } else { - self.start().add((*self.storage.as_ptr()).len()) + self.start().add(self.storage.len()) } } } @@ -255,7 +264,9 @@ impl TypedArena { self.ensure_capacity(len); let start_ptr = self.ptr.get(); - self.ptr.set(start_ptr.add(len)); + // SAFETY: `self.ensure_capacity` makes sure that there is enough space + // for `len` elements. + unsafe { self.ptr.set(start_ptr.add(len)) }; start_ptr } @@ -288,7 +299,7 @@ impl TypedArena { // If the previous chunk's len is less than HUGE_PAGE // bytes, then this chunk will be least double the previous // chunk's size. - new_cap = (*last_chunk.storage.as_ptr()).len().min(HUGE_PAGE / elem_size / 2); + new_cap = last_chunk.storage.len().min(HUGE_PAGE / elem_size / 2); new_cap *= 2; } else { new_cap = PAGE / elem_size; @@ -396,7 +407,7 @@ impl DroplessArena { // If the previous chunk's len is less than HUGE_PAGE // bytes, then this chunk will be least double the previous // chunk's size. - new_cap = (*last_chunk.storage.as_ptr()).len().min(HUGE_PAGE / 2); + new_cap = last_chunk.storage.len().min(HUGE_PAGE / 2); new_cap *= 2; } else { new_cap = PAGE; @@ -483,6 +494,10 @@ impl DroplessArena { } } + /// # Safety + /// + /// The caller must ensure that `mem` is valid for writes up to + /// `size_of::() * len`. #[inline] unsafe fn write_from_iter>( &self, @@ -494,13 +509,18 @@ impl DroplessArena { // Use a manual loop since LLVM manages to optimize it better for // slice iterators loop { - let value = iter.next(); - if i >= len || value.is_none() { - // We only return as many items as the iterator gave us, even - // though it was supposed to give us `len` - return slice::from_raw_parts_mut(mem, i); + // SAFETY: The caller must ensure that `mem` is valid for writes up to + // `size_of::() * len`. + unsafe { + match iter.next() { + Some(value) if i < len => mem.add(i).write(value), + Some(_) | None => { + // We only return as many items as the iterator gave us, even + // though it was supposed to give us `len` + return slice::from_raw_parts_mut(mem, i); + } + } } - ptr::write(mem.add(i), value.unwrap()); i += 1; } } diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index df1a716755b4..3ed342ce48b4 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1271,6 +1271,7 @@ impl Expr { ExprKind::Continue(..) => ExprPrecedence::Continue, ExprKind::Ret(..) => ExprPrecedence::Ret, ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm, + ExprKind::OffsetOf(..) => ExprPrecedence::OffsetOf, ExprKind::MacCall(..) => ExprPrecedence::Mac, ExprKind::Struct(..) => ExprPrecedence::Struct, ExprKind::Repeat(..) => ExprPrecedence::Repeat, @@ -1298,17 +1299,17 @@ impl Expr { /// To a first-order approximation, is this a pattern? pub fn is_approximately_pattern(&self) -> bool { - match &self.peel_parens().kind { + matches!( + &self.peel_parens().kind, ExprKind::Array(_) - | ExprKind::Call(_, _) - | ExprKind::Tup(_) - | ExprKind::Lit(_) - | ExprKind::Range(_, _, _) - | ExprKind::Underscore - | ExprKind::Path(_, _) - | ExprKind::Struct(_) => true, - _ => false, - } + | ExprKind::Call(_, _) + | ExprKind::Tup(_) + | ExprKind::Lit(_) + | ExprKind::Range(_, _, _) + | ExprKind::Underscore + | ExprKind::Path(_, _) + | ExprKind::Struct(_) + ) } } @@ -1469,6 +1470,9 @@ pub enum ExprKind { /// Output of the `asm!()` macro. InlineAsm(P), + /// Output of the `offset_of!()` macro. + OffsetOf(P, P<[Ident]>), + /// A macro invocation; pre-expansion. MacCall(P), @@ -2972,7 +2976,7 @@ pub enum ItemKind { } impl ItemKind { - pub fn article(&self) -> &str { + pub fn article(&self) -> &'static str { use ItemKind::*; match self { Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..) @@ -2981,7 +2985,7 @@ impl ItemKind { } } - pub fn descr(&self) -> &str { + pub fn descr(&self) -> &'static str { match self { ItemKind::ExternCrate(..) => "extern crate", ItemKind::Use(..) => "`use` import", diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index c4771115cacf..e6c4db9e2ae5 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -10,15 +10,10 @@ use crate::tokenstream::{DelimSpan, Spacing, TokenTree}; use crate::tokenstream::{LazyAttrTokenStream, TokenStream}; use crate::util::comments; use crate::util::literal::escape_string_symbol; -use rustc_data_structures::sync::WorkerLocal; use rustc_index::bit_set::GrowableBitSet; use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; -use std::cell::Cell; use std::iter; -#[cfg(debug_assertions)] -use std::ops::BitXor; -#[cfg(debug_assertions)] use std::sync::atomic::{AtomicU32, Ordering}; use thin_vec::{thin_vec, ThinVec}; @@ -40,39 +35,16 @@ impl MarkedAttrs { } } -pub struct AttrIdGenerator(WorkerLocal>); - -#[cfg(debug_assertions)] -static MAX_ATTR_ID: AtomicU32 = AtomicU32::new(u32::MAX); +pub struct AttrIdGenerator(AtomicU32); impl AttrIdGenerator { pub fn new() -> Self { - // We use `(index as u32).reverse_bits()` to initialize the - // starting value of AttrId in each worker thread. - // The `index` is the index of the worker thread. - // This ensures that the AttrId generated in each thread is unique. - AttrIdGenerator(WorkerLocal::new(|index| { - let index: u32 = index.try_into().unwrap(); - - #[cfg(debug_assertions)] - { - let max_id = ((index + 1).next_power_of_two() - 1).bitxor(u32::MAX).reverse_bits(); - MAX_ATTR_ID.fetch_min(max_id, Ordering::Release); - } - - Cell::new(index.reverse_bits()) - })) + AttrIdGenerator(AtomicU32::new(0)) } pub fn mk_attr_id(&self) -> AttrId { - let id = self.0.get(); - - // Ensure the assigned attr_id does not overlap the bits - // representing the number of threads. - #[cfg(debug_assertions)] - assert!(id <= MAX_ATTR_ID.load(Ordering::Acquire)); - - self.0.set(id + 1); + let id = self.0.fetch_add(1, Ordering::Relaxed); + assert!(id != u32::MAX); AttrId::from_u32(id) } } diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs index 23c32fa96ca4..b07ed1d1c741 100644 --- a/compiler/rustc_ast/src/lib.rs +++ b/compiler/rustc_ast/src/lib.rs @@ -10,7 +10,6 @@ )] #![feature(associated_type_bounds)] #![feature(box_patterns)] -#![feature(const_default_impls)] #![feature(const_trait_impl)] #![feature(if_let_guard)] #![feature(let_chains)] diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 694d31d8f1fd..99f1f4bd9685 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1456,6 +1456,12 @@ pub fn noop_visit_expr( } ExprKind::InlineAsm(asm) => vis.visit_inline_asm(asm), ExprKind::FormatArgs(fmt) => vis.visit_format_args(fmt), + ExprKind::OffsetOf(container, fields) => { + vis.visit_ty(container); + for field in fields.iter_mut() { + vis.visit_ident(field); + } + } ExprKind::MacCall(mac) => vis.visit_mac_call(mac), ExprKind::Struct(se) => { let StructExpr { qself, path, fields, rest } = se.deref_mut(); diff --git a/compiler/rustc_ast/src/node_id.rs b/compiler/rustc_ast/src/node_id.rs index daa82996b3d1..d16741757d1f 100644 --- a/compiler/rustc_ast/src/node_id.rs +++ b/compiler/rustc_ast/src/node_id.rs @@ -9,14 +9,14 @@ rustc_index::newtype_index! { /// /// [`DefId`]: rustc_span::def_id::DefId #[debug_format = "NodeId({})"] - pub struct NodeId {} + pub struct NodeId { + /// The [`NodeId`] used to represent the root of the crate. + const CRATE_NODE_ID = 0; + } } rustc_data_structures::define_id_collections!(NodeMap, NodeSet, NodeMapEntry, NodeId); -/// The [`NodeId`] used to represent the root of the crate. -pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0); - /// When parsing and at the beginning of doing expansions, we initially give all AST nodes /// this dummy AST [`NodeId`]. Then, during a later phase of expansion, we renumber them /// to have small, positive IDs. diff --git a/compiler/rustc_ast/src/ptr.rs b/compiler/rustc_ast/src/ptr.rs index 4b2850336a03..0140fb752bf9 100644 --- a/compiler/rustc_ast/src/ptr.rs +++ b/compiler/rustc_ast/src/ptr.rs @@ -126,7 +126,8 @@ impl> Encodable for P { } impl P<[T]> { - pub const fn new() -> P<[T]> { + // FIXME(const-hack) make this const again + pub fn new() -> P<[T]> { P { ptr: Box::default() } } diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index 3893875e9a40..24b4bd8623f0 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -269,6 +269,7 @@ pub enum ExprPrecedence { Index, Try, InlineAsm, + OffsetOf, Mac, FormatArgs, @@ -335,7 +336,8 @@ impl ExprPrecedence { | ExprPrecedence::Try | ExprPrecedence::InlineAsm | ExprPrecedence::Mac - | ExprPrecedence::FormatArgs => PREC_POSTFIX, + | ExprPrecedence::FormatArgs + | ExprPrecedence::OffsetOf => PREC_POSTFIX, // Never need parens ExprPrecedence::Array diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index ac9b321b71c6..8a6b5d5c9052 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -909,6 +909,12 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { ExprKind::Paren(subexpression) => visitor.visit_expr(subexpression), ExprKind::InlineAsm(asm) => visitor.visit_inline_asm(asm), ExprKind::FormatArgs(f) => visitor.visit_format_args(f), + ExprKind::OffsetOf(container, fields) => { + visitor.visit_ty(container); + for &field in fields { + visitor.visit_ident(field); + } + } ExprKind::Yield(optional_expression) => { walk_list!(visitor, visit_expr, optional_expression); } diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index eb2e82d7988c..6b0da2565050 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -12,6 +12,7 @@ rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } +rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_index = { path = "../rustc_index" } rustc_middle = { path = "../rustc_middle" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 1b1c4765bc07..7a0a7da96957 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -121,12 +121,16 @@ impl<'hir> LoweringContext<'_, 'hir> { LitKind::Err } }; - hir::ExprKind::Lit(respan(self.lower_span(e.span), lit_kind)) + let lit = self.arena.alloc(respan(self.lower_span(e.span), lit_kind)); + hir::ExprKind::Lit(lit) + } + ExprKind::IncludedBytes(bytes) => { + let lit = self.arena.alloc(respan( + self.lower_span(e.span), + LitKind::ByteStr(bytes.clone(), StrStyle::Cooked), + )); + hir::ExprKind::Lit(lit) } - ExprKind::IncludedBytes(bytes) => hir::ExprKind::Lit(respan( - self.lower_span(e.span), - LitKind::ByteStr(bytes.clone(), StrStyle::Cooked), - )), ExprKind::Cast(expr, ty) => { let expr = self.lower_expr(expr); let ty = @@ -285,6 +289,13 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm)) } ExprKind::FormatArgs(fmt) => self.lower_format_args(e.span, fmt), + ExprKind::OffsetOf(container, fields) => hir::ExprKind::OffsetOf( + self.lower_ty( + container, + &mut ImplTraitContext::Disallowed(ImplTraitPosition::OffsetOf), + ), + self.arena.alloc_from_iter(fields.iter().map(|&ident| self.lower_ident(ident))), + ), ExprKind::Struct(se) => { let rest = match &se.rest { StructRest::Base(e) => Some(self.lower_expr(e)), @@ -847,13 +858,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let awaitee_arm = self.arm(awaitee_pat, loop_expr); // `match ::std::future::IntoFuture::into_future() { ... }` - let into_future_span = self.mark_span_with_reason( - DesugaringKind::Await, - dot_await_span, - self.allow_into_future.clone(), - ); let into_future_expr = self.expr_call_lang_item_fn( - into_future_span, + span, hir::LangItem::IntoFutureIntoFuture, arena_vec![self; expr], Some(expr_hir_id), @@ -1746,40 +1752,31 @@ impl<'hir> LoweringContext<'_, 'hir> { } pub(super) fn expr_usize(&mut self, sp: Span, value: usize) -> hir::Expr<'hir> { - self.expr( - sp, - hir::ExprKind::Lit(hir::Lit { - span: sp, - node: ast::LitKind::Int( - value as u128, - ast::LitIntType::Unsigned(ast::UintTy::Usize), - ), - }), - ) + let lit = self.arena.alloc(hir::Lit { + span: sp, + node: ast::LitKind::Int(value as u128, ast::LitIntType::Unsigned(ast::UintTy::Usize)), + }); + self.expr(sp, hir::ExprKind::Lit(lit)) } pub(super) fn expr_u32(&mut self, sp: Span, value: u32) -> hir::Expr<'hir> { - self.expr( - sp, - hir::ExprKind::Lit(hir::Lit { - span: sp, - node: ast::LitKind::Int(value.into(), ast::LitIntType::Unsigned(ast::UintTy::U32)), - }), - ) + let lit = self.arena.alloc(hir::Lit { + span: sp, + node: ast::LitKind::Int(value.into(), ast::LitIntType::Unsigned(ast::UintTy::U32)), + }); + self.expr(sp, hir::ExprKind::Lit(lit)) } pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> { - self.expr(sp, hir::ExprKind::Lit(hir::Lit { span: sp, node: ast::LitKind::Char(value) })) + let lit = self.arena.alloc(hir::Lit { span: sp, node: ast::LitKind::Char(value) }); + self.expr(sp, hir::ExprKind::Lit(lit)) } pub(super) fn expr_str(&mut self, sp: Span, value: Symbol) -> hir::Expr<'hir> { - self.expr( - sp, - hir::ExprKind::Lit(hir::Lit { - span: sp, - node: ast::LitKind::Str(value, ast::StrStyle::Cooked), - }), - ) + let lit = self + .arena + .alloc(hir::Lit { span: sp, node: ast::LitKind::Str(value, ast::StrStyle::Cooked) }); + self.expr(sp, hir::ExprKind::Lit(lit)) } pub(super) fn expr_call_mut( diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index c41bdc440935..c081162ea146 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -186,7 +186,7 @@ enum ArgumentType { /// Generates: /// /// ```text -/// ::new_…(arg) +/// ::new_…(arg) /// ``` fn make_argument<'hir>( ctx: &mut LoweringContext<'_, 'hir>, @@ -220,19 +220,19 @@ fn make_argument<'hir>( /// Generates: /// /// ```text -/// ::Is(…) +/// ::Is(…) /// ``` /// /// or /// /// ```text -/// ::Param(…) +/// ::Param(…) /// ``` /// /// or /// /// ```text -/// ::Implied +/// ::Implied /// ``` fn make_count<'hir>( ctx: &mut LoweringContext<'_, 'hir>, @@ -278,13 +278,13 @@ fn make_count<'hir>( /// Generates /// /// ```text -/// ::…, // alignment +/// ::…, // alignment /// …u32, // flags -/// , // width -/// , // precision +/// , // width +/// , // precision /// ) /// ``` fn make_format_spec<'hir>( @@ -327,7 +327,7 @@ fn make_format_spec<'hir>( None => sym::Unknown, }, ); - // This needs to match `FlagV1` in library/core/src/fmt/mod.rs. + // This needs to match `Flag` in library/core/src/fmt/rt.rs. let flags: u32 = ((sign == Some(FormatSign::Plus)) as u32) | ((sign == Some(FormatSign::Minus)) as u32) << 1 | (alternate as u32) << 2 @@ -438,7 +438,7 @@ fn expand_format_args<'hir>( // If the args array contains exactly all the original arguments once, // in order, we can use a simple array instead of a `match` construction. // However, if there's a yield point in any argument except the first one, - // we don't do this, because an ArgumentV1 cannot be kept across yield points. + // we don't do this, because an Argument cannot be kept across yield points. // // This is an optimization, speeding up compilation about 1-2% in some cases. // See https://github.com/rust-lang/rust/pull/106770#issuecomment-1380790609 @@ -449,9 +449,9 @@ fn expand_format_args<'hir>( let args = if use_simple_array { // Generate: // &[ - // ::new_display(&arg0), - // ::new_lower_hex(&arg1), - // ::new_debug(&arg2), + // ::new_display(&arg0), + // ::new_lower_hex(&arg1), + // ::new_debug(&arg2), // … // ] let elements: Vec<_> = arguments @@ -477,9 +477,9 @@ fn expand_format_args<'hir>( // Generate: // &match (&arg0, &arg1, &…) { // args => [ - // ::new_display(args.0), - // ::new_lower_hex(args.1), - // ::new_debug(args.0), + // ::new_display(args.0), + // ::new_lower_hex(args.1), + // ::new_debug(args.0), // … // ] // } diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index f7fe0d771a13..2e66c81eb0d0 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -5,7 +5,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_hir::definitions; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::*; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_index::{Idx, IndexVec}; use rustc_middle::span_bug; use rustc_session::Session; use rustc_span::source_map::SourceMap; diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index f89e254a2f54..3d154a93fb2d 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -12,7 +12,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::PredicateOrigin; -use rustc_index::vec::{Idx, IndexSlice, IndexVec}; +use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::source_map::DesugaringKind; @@ -83,15 +83,14 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { impl_trait_bounds: Vec::new(), allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()), allow_gen_future: Some([sym::gen_future, sym::closure_track_caller][..].into()), - allow_into_future: Some([sym::into_future][..].into()), generics_def_id_map: Default::default(), }; lctx.with_hir_id_owner(owner, |lctx| f(lctx)); for (def_id, info) in lctx.children { - self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); - debug_assert!(matches!(self.owners[def_id], hir::MaybeOwner::Phantom)); - self.owners[def_id] = info; + let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); + debug_assert!(matches!(owner, hir::MaybeOwner::Phantom)); + *owner = info; } } @@ -99,8 +98,8 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { &mut self, def_id: LocalDefId, ) -> hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>> { - self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); - if let hir::MaybeOwner::Phantom = self.owners[def_id] { + let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); + if let hir::MaybeOwner::Phantom = owner { let node = self.ast_index[def_id]; match node { AstOwner::NonOwner => {} @@ -138,12 +137,10 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { // Evaluate with the lifetimes in `params` in-scope. // This is used to track which lifetimes have already been defined, // and which need to be replicated when lowering an async fn. - match parent_hir.node().expect_item().kind { - hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => { - lctx.is_in_trait_impl = of_trait.is_some(); - } - _ => {} - }; + + if let hir::ItemKind::Impl(impl_) = parent_hir.node().expect_item().kind { + lctx.is_in_trait_impl = impl_.of_trait.is_some(); + } match ctxt { AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)), @@ -445,7 +442,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ItemKind::MacroDef(MacroDef { body, macro_rules }) => { let body = P(self.lower_delim_args(body)); let macro_kind = self.resolver.decl_macro_kind(self.local_def_id(id)); - hir::ItemKind::Macro(ast::MacroDef { body, macro_rules: *macro_rules }, macro_kind) + let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules }); + hir::ItemKind::Macro(macro_def, macro_kind) } ItemKind::MacCall(..) => { panic!("`TyMac` should have been expanded by now") diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index f7ae96b7c4a3..b5b28bf8e31e 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -55,13 +55,13 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::{ DiagnosticArgFromDisplay, DiagnosticMessage, Handler, StashKey, SubdiagnosticMessage, }; +use rustc_fluent_macro::fluent_messages; use rustc_hir as hir; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::definitions::DefPathData; use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate}; -use rustc_index::vec::{Idx, IndexSlice, IndexVec}; -use rustc_macros::fluent_messages; +use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_middle::{ span_bug, ty::{ResolverAstLowering, TyCtxt}, @@ -136,7 +136,6 @@ struct LoweringContext<'a, 'hir> { allow_try_trait: Option>, allow_gen_future: Option>, - allow_into_future: Option>, /// Mapping from generics `def_id`s to TAIT generics `def_id`s. /// For each captured lifetime (e.g., 'a), we create a new lifetime parameter that is a generic @@ -283,6 +282,7 @@ enum ImplTraitPosition { FieldTy, Cast, ImplSelf, + OffsetOf, } impl std::fmt::Display for ImplTraitPosition { @@ -313,6 +313,7 @@ impl std::fmt::Display for ImplTraitPosition { ImplTraitPosition::FieldTy => "field types", ImplTraitPosition::Cast => "cast types", ImplTraitPosition::ImplSelf => "impl headers", + ImplTraitPosition::OffsetOf => "`offset_of!` params", }; write!(f, "{name}") @@ -332,10 +333,7 @@ enum FnDeclKind { impl FnDeclKind { fn param_impl_trait_allowed(&self) -> bool { - match self { - FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => true, - _ => false, - } + matches!(self, FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait) } fn return_impl_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool { @@ -371,8 +369,8 @@ fn index_crate<'a>( krate: &'a Crate, ) -> IndexVec> { let mut indexer = Indexer { node_id_to_def_id, index: IndexVec::new() }; - indexer.index.ensure_contains_elem(CRATE_DEF_ID, || AstOwner::NonOwner); - indexer.index[CRATE_DEF_ID] = AstOwner::Crate(krate); + *indexer.index.ensure_contains_elem(CRATE_DEF_ID, || AstOwner::NonOwner) = + AstOwner::Crate(krate); visit::walk_crate(&mut indexer, krate); return indexer.index; @@ -389,22 +387,21 @@ fn index_crate<'a>( fn visit_item(&mut self, item: &'a ast::Item) { let def_id = self.node_id_to_def_id[&item.id]; - self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner); - self.index[def_id] = AstOwner::Item(item); + *self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) = AstOwner::Item(item); visit::walk_item(self, item) } fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: visit::AssocCtxt) { let def_id = self.node_id_to_def_id[&item.id]; - self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner); - self.index[def_id] = AstOwner::AssocItem(item, ctxt); + *self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) = + AstOwner::AssocItem(item, ctxt); visit::walk_assoc_item(self, item, ctxt); } fn visit_foreign_item(&mut self, item: &'a ast::ForeignItem) { let def_id = self.node_id_to_def_id[&item.id]; - self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner); - self.index[def_id] = AstOwner::ForeignItem(item); + *self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) = + AstOwner::ForeignItem(item); visit::walk_foreign_item(self, item); } } diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml index 8bd212073a65..eb7361235207 100644 --- a/compiler/rustc_ast_passes/Cargo.toml +++ b/compiler/rustc_ast_passes/Cargo.toml @@ -12,6 +12,7 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } rustc_macros = { path = "../rustc_macros" } +rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_parse = { path = "../rustc_parse" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index a349fe6a3c44..ffca37ae9d5f 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -231,7 +231,7 @@ ast_passes_feature_on_non_nightly = `#![feature]` may not be used on the {$chann .suggestion = remove the attribute .stable_since = the feature `{$name}` has been stable since `{$since}` and no longer requires an attribute to enable -ast_passes_incompatbile_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed +ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed .help = remove one of these features ast_passes_show_span = {$msg} diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 27bbd237961a..1732865f0bb6 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -677,7 +677,7 @@ impl AddToDiagnostic for StableFeature { } #[derive(Diagnostic)] -#[diag(ast_passes_incompatbile_features)] +#[diag(ast_passes_incompatible_features)] #[help] pub struct IncompatibleFeatures { #[primary_span] diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index e2c666604b3c..7db413c5bbd4 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -13,7 +13,7 @@ #![deny(rustc::diagnostic_outside_of_impl)] use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_macros::fluent_messages; +use rustc_fluent_macro::fluent_messages; pub mod ast_validation; mod errors; diff --git a/compiler/rustc_ast_pretty/src/pp.rs b/compiler/rustc_ast_pretty/src/pp.rs index c93022308a37..7ab8c3eaba22 100644 --- a/compiler/rustc_ast_pretty/src/pp.rs +++ b/compiler/rustc_ast_pretty/src/pp.rs @@ -360,7 +360,7 @@ impl Printer { fn check_stack(&mut self, mut depth: usize) { while let Some(&index) = self.scan_stack.back() { - let mut entry = &mut self.buf[index]; + let entry = &mut self.buf[index]; match entry.token { Token::Begin(_) => { if depth == 0 { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 776bf54244ed..aeb0c7620204 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -549,6 +549,26 @@ impl<'a> State<'a> { self.end(); self.pclose(); } + ast::ExprKind::OffsetOf(container, fields) => { + // FIXME: This should have its own syntax, distinct from a macro invocation. + self.word("offset_of!"); + self.popen(); + self.rbox(0, Inconsistent); + self.print_type(container); + self.word(","); + self.space(); + + if let Some((&first, rest)) = fields.split_first() { + self.print_ident(first); + + for &field in rest { + self.word("."); + self.print_ident(field); + } + } + + self.end(); + } ast::ExprKind::MacCall(m) => self.print_mac(m), ast::ExprKind::Paren(e) => { self.popen(); diff --git a/compiler/rustc_attr/Cargo.toml b/compiler/rustc_attr/Cargo.toml index 6349ddf31d10..2c4c3a0c2635 100644 --- a/compiler/rustc_attr/Cargo.toml +++ b/compiler/rustc_attr/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_serialize = { path = "../rustc_serialize" } rustc_errors = { path = "../rustc_errors" } +rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_span = { path = "../rustc_span" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_feature = { path = "../rustc_feature" } diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs index 49818c14f275..cfed2acfb3a4 100644 --- a/compiler/rustc_attr/src/lib.rs +++ b/compiler/rustc_attr/src/lib.rs @@ -12,7 +12,7 @@ extern crate rustc_macros; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_macros::fluent_messages; +use rustc_fluent_macro::fluent_messages; mod builtin; mod session_diagnostics; diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml index 87c113f3e30b..56a9deb6aab1 100644 --- a/compiler/rustc_borrowck/Cargo.toml +++ b/compiler/rustc_borrowck/Cargo.toml @@ -15,12 +15,12 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_graphviz = { path = "../rustc_graphviz" } rustc_hir = { path = "../rustc_hir" } +rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } -rustc_const_eval = { path = "../rustc_const_eval" } rustc_mir_dataflow = { path = "../rustc_mir_dataflow" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl index a3b6b5e8138b..0b8123c97036 100644 --- a/compiler/rustc_borrowck/messages.ftl +++ b/compiler/rustc_borrowck/messages.ftl @@ -56,18 +56,6 @@ borrowck_returned_lifetime_short = borrowck_used_impl_require_static = the used `impl` has a `'static` requirement -borrowck_capture_kind_label = - capture is {$kind_desc} because of use here - -borrowck_var_borrow_by_use_place_in_generator = - borrow occurs due to use of {$place} in closure in generator - -borrowck_var_borrow_by_use_place_in_closure = - borrow occurs due to use of {$place} in closure - -borrowck_var_borrow_by_use_place = - borrow occurs due to use of {$place} - borrowck_borrow_due_to_use_generator = borrow occurs due to use in generator @@ -101,12 +89,63 @@ borrowck_capture_mut = borrowck_capture_move = capture is moved because of use here +borrowck_var_borrow_by_use_place_in_generator = + {$is_single_var -> + *[true] borrow occurs + [false] borrows occur + } due to use of {$place} in generator + +borrowck_var_borrow_by_use_place_in_closure = + {$is_single_var -> + *[true] borrow occurs + [false] borrows occur + } due to use of {$place} in closure + +borrowck_var_borrow_by_use_in_generator = + borrow occurs due to use in generator + +borrowck_var_borrow_by_use_in_closure = + borrow occurs due to use in closure + borrowck_var_move_by_use_place_in_generator = move occurs due to use of {$place} in generator borrowck_var_move_by_use_place_in_closure = move occurs due to use of {$place} in closure +borrowck_var_move_by_use_in_generator = + move occurs due to use in generator + +borrowck_var_move_by_use_in_closure = + move occurs due to use in closure + +borrowck_partial_var_move_by_use_in_generator = + variable {$is_partial -> + [true] partially moved + *[false] moved + } due to use in generator + +borrowck_partial_var_move_by_use_in_closure = + variable {$is_partial -> + [true] partially moved + *[false] moved + } due to use in closure + +borrowck_var_first_borrow_by_use_place_in_generator = + first borrow occurs due to use of {$place} in generator + +borrowck_var_first_borrow_by_use_place_in_closure = + first borrow occurs due to use of {$place} in closure + +borrowck_var_second_borrow_by_use_place_in_generator = + second borrow occurs due to use of {$place} in generator + +borrowck_var_second_borrow_by_use_place_in_closure = + second borrow occurs due to use of {$place} in closure + +borrowck_var_mutable_borrow_by_use_place_in_closure = + mutable borrow occurs due to use of {$place} in closure + borrowck_cannot_move_when_borrowed = cannot move out of {$place -> [value] value @@ -127,3 +166,90 @@ borrowck_opaque_type_non_generic_param = [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type *[other] this generic parameter must be used with a generic {$kind} parameter } + +borrowck_moved_due_to_call = + {$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this {$is_loop_message -> + [true] call, in previous iteration of loop + *[false] call + } + +borrowck_moved_due_to_usage_in_operator = + {$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to usage in {$is_loop_message -> + [true] operator, in previous iteration of loop + *[false] operator + } + +borrowck_moved_due_to_implicit_into_iter_call = + {$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this implicit call to {$is_loop_message -> + [true] `.into_iter()`, in previous iteration of loop + *[false] `.into_iter()` + } + +borrowck_moved_due_to_method_call = + {$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this method {$is_loop_message -> + [true] call, in previous iteration of loop + *[false] call + } + +borrowck_value_moved_here = + value {$is_partial -> + [true] partially moved + *[false] moved + } {$is_move_msg -> + [true] into closure here + *[false] here + }{$is_loop_message -> + [true] , in previous iteration of loop + *[false] {""} + } + +borrowck_consider_borrow_type_contents = + help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents + +borrowck_moved_a_fn_once_in_call = + this value implements `FnOnce`, which causes it to be moved when called + +borrowck_calling_operator_moves_lhs = + calling this operator moves the left-hand side + +borrowck_func_take_self_moved_place = + `{$func}` takes ownership of the receiver `self`, which moves {$place_name} + +borrowck_suggest_iterate_over_slice = + consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop + +borrowck_suggest_create_freash_reborrow = + consider reborrowing the `Pin` instead of moving it + +borrowck_value_capture_here = + value captured {$is_within -> + [true] here by generator + *[false] here + } + +borrowck_move_out_place_here = + {$place} is moved here + +borrowck_closure_invoked_twice = + closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment + +borrowck_closure_moved_twice = + closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment + +borrowck_ty_no_impl_copy = + {$is_partial_move -> + [true] partial move + *[false] move + } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 2bbb9618dbf0..acca1a1477f2 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -469,6 +469,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { } #[rustc_lint_diagnostics] + #[track_caller] pub(crate) fn struct_span_err_with_code>( &self, sp: S, diff --git a/compiler/rustc_borrowck/src/constraints/graph.rs b/compiler/rustc_borrowck/src/constraints/graph.rs index f5a34cb0561b..8b7d9ec2cd67 100644 --- a/compiler/rustc_borrowck/src/constraints/graph.rs +++ b/compiler/rustc_borrowck/src/constraints/graph.rs @@ -1,5 +1,5 @@ use rustc_data_structures::graph; -use rustc_index::vec::IndexVec; +use rustc_index::IndexVec; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::{RegionVid, VarianceDiagInfo}; use rustc_span::DUMMY_SP; diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs index d2d9779dbea4..315886bbe29b 100644 --- a/compiler/rustc_borrowck/src/constraints/mod.rs +++ b/compiler/rustc_borrowck/src/constraints/mod.rs @@ -2,7 +2,7 @@ #![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::graph::scc::Sccs; -use rustc_index::vec::{IndexSlice, IndexVec}; +use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::{RegionVid, VarianceDiagInfo}; use rustc_span::Span; diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index cb1a65222237..3451b7db8caa 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -3,10 +3,10 @@ //! This file provides API for compiler consumers. use rustc_hir::def_id::LocalDefId; -use rustc_index::vec::IndexSlice; +use rustc_index::IndexSlice; use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; use rustc_middle::mir::Body; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::TyCtxt; pub use super::{ facts::{AllFacts as PoloniusInput, RustcFacts}, @@ -28,12 +28,9 @@ pub use super::{ /// that shows how to do this at `tests/run-make/obtain-borrowck/`. /// /// * Polonius is highly unstable, so expect regular changes in its signature or other details. -pub fn get_body_with_borrowck_facts( - tcx: TyCtxt<'_>, - def: ty::WithOptConstParam, -) -> BodyWithBorrowckFacts<'_> { +pub fn get_body_with_borrowck_facts(tcx: TyCtxt<'_>, def: LocalDefId) -> BodyWithBorrowckFacts<'_> { let (input_body, promoted) = tcx.mir_promoted(def); - let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def.did)).build(); + let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def)).build(); let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexSlice<_, _> = &promoted.borrow(); *super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap() diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs index 9e9f0b4b4ad0..6259722b6940 100644 --- a/compiler/rustc_borrowck/src/def_use.rs +++ b/compiler/rustc_borrowck/src/def_use.rs @@ -52,12 +52,16 @@ pub fn categorize(context: PlaceContext) -> Option { PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow) | PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow) | + // `PlaceMention` and `AscribeUserType` both evaluate the place, which must not + // contain dangling references. + PlaceContext::NonUse(NonUseContext::PlaceMention) | + PlaceContext::NonUse(NonUseContext::AscribeUserTy) | + PlaceContext::MutatingUse(MutatingUseContext::AddressOf) | PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) | PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) | - PlaceContext::NonUse(NonUseContext::AscribeUserTy) | PlaceContext::MutatingUse(MutatingUseContext::Retag) => Some(DefUse::Use), @@ -72,8 +76,6 @@ pub fn categorize(context: PlaceContext) -> Option { PlaceContext::MutatingUse(MutatingUseContext::Drop) => Some(DefUse::Drop), - // This statement exists to help unsafeck. It does not require the place to be live. - PlaceContext::NonUse(NonUseContext::PlaceMention) => None, // Debug info is neither def nor use. PlaceContext::NonUse(NonUseContext::VarDebugInfo) => None, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 75a3dd0c0f3d..ac84188a35fb 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1,5 +1,6 @@ +use std::iter; + use either::Either; -use rustc_const_eval::util::CallKind; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{ @@ -9,8 +10,8 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_block, walk_expr, Visitor}; use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem}; -use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::ObligationCause; +use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, @@ -18,20 +19,19 @@ use rustc_middle::mir::{ ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm, }; use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty}; +use rustc_middle::util::CallKind; use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex}; use rustc_span::def_id::LocalDefId; use rustc_span::hygiene::DesugaringKind; -use rustc_span::symbol::{kw, sym}; +use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::ObligationCtxt; use crate::borrow_set::TwoPhaseActivation; use crate::borrowck_errors; - use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead; -use crate::diagnostics::find_all_local_uses; -use crate::diagnostics::mutability_errors::mut_borrow_of_mutable_ref; +use crate::diagnostics::{find_all_local_uses, CapturedMessageOpt}; use crate::{ borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf, InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind, @@ -183,13 +183,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let move_spans = self.move_spans(moved_place.as_ref(), move_out.source); let move_span = move_spans.args_or_use(); - let move_msg = if move_spans.for_closure() { " into closure" } else { "" }; + let is_move_msg = move_spans.for_closure(); - let loop_message = if location == move_out.source || move_site.traversed_back_edge { - ", in previous iteration of loop" - } else { - "" - }; + let is_loop_message = location == move_out.source || move_site.traversed_back_edge; if location == move_out.source { is_loop_move = true; @@ -206,17 +202,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); } + let msg_opt = CapturedMessageOpt { + is_partial_move, + is_loop_message, + is_move_msg, + is_loop_move, + maybe_reinitialized_locations_is_empty: maybe_reinitialized_locations + .is_empty(), + }; self.explain_captures( &mut err, span, move_span, move_spans, *moved_place, - partially_str, - loop_message, - move_msg, - is_loop_move, - maybe_reinitialized_locations.is_empty(), + msg_opt, ); } seen_spans.insert(move_span); @@ -282,12 +282,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } if needs_note { - let span = if let Some(local) = place.as_local() { - Some(self.body.local_decls[local].source_info.span) + if let Some(local) = place.as_local() { + let span = self.body.local_decls[local].source_info.span; + err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { + is_partial_move, + ty, + place: ¬e_msg, + span, + }); } else { - None + err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Note { + is_partial_move, + ty, + place: ¬e_msg, + }); }; - self.note_type_does_not_implement_copy(&mut err, ¬e_msg, ty, span, partial_str); } if let UseSpans::FnSelfUse { @@ -633,11 +642,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else { return false; }; - // Regions are already solved, so we must use a fresh InferCtxt, - // but the type has region variables, so erase those. - tcx.infer_ctxt() - .build() - .type_implements_trait(default_trait, [tcx.erase_regions(ty)], param_env) + self.infcx + .type_implements_trait(default_trait, [ty], param_env) .must_apply_modulo_regions() }; @@ -696,7 +702,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .copied() .find_map(find_fn_kind_from_did), ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => tcx - .bound_explicit_item_bounds(def_id) + .explicit_item_bounds(def_id) .subst_iter_copied(tcx, substs) .find_map(find_fn_kind_from_did), ty::Closure(_, substs) => match substs.as_closure().kind() { @@ -730,13 +736,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn suggest_cloning(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) { let tcx = self.infcx.tcx; // Try to find predicates on *generic params* that would allow copying `ty` - let infcx = tcx.infer_ctxt().build(); - if let Some(clone_trait_def) = tcx.lang_items().clone_trait() - && infcx + && self.infcx .type_implements_trait( clone_trait_def, - [tcx.erase_regions(ty)], + [ty], self.param_env, ) .must_apply_modulo_regions() @@ -760,12 +764,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .and_then(|def_id| tcx.hir().get_generics(def_id)) else { return; }; // Try to find predicates on *generic params* that would allow copying `ty` - let infcx = tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new(&infcx); + let ocx = ObligationCtxt::new(&self.infcx); let copy_did = tcx.require_lang_item(LangItem::Copy, Some(span)); let cause = ObligationCause::misc(span, self.mir_def_id()); - ocx.register_bound(cause, self.param_env, infcx.tcx.erase_regions(ty), copy_did); + ocx.register_bound(cause, self.param_env, ty, copy_did); let errors = ocx.select_all_or_error(); // Only emit suggestion if all required predicates are on generic @@ -827,11 +830,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_spans.var_path_only_subdiag(&mut err, crate::InitializationRequiringAction::Borrow); - move_spans.var_span_label( - &mut err, - format!("move occurs due to use{}", move_spans.describe()), - "moved", - ); + move_spans.var_subdiag(None, &mut err, None, |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => MoveUseInGenerator { var_span }, + None => MoveUseInClosure { var_span }, + } + }); self.explain_why_borrow_contains_point(location, borrow, None) .add_explanation_to_diagnostic( @@ -868,13 +873,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_span, &self.describe_any_place(borrow.borrowed_place.as_ref()), ); - borrow_spans.var_subdiag(&mut err, Some(borrow.kind), |kind, var_span| { + borrow_spans.var_subdiag(None, &mut err, Some(borrow.kind), |kind, var_span| { use crate::session_diagnostics::CaptureVarCause::*; let place = &borrow.borrowed_place; let desc_place = self.describe_any_place(place.as_ref()); match kind { - Some(_) => BorrowUsePlaceGenerator { place: desc_place, var_span }, - None => BorrowUsePlaceClosure { place: desc_place, var_span }, + Some(_) => { + BorrowUsePlaceGenerator { place: desc_place, var_span, is_single_var: true } + } + None => BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: true }, } }); @@ -946,7 +953,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &msg_borrow, None, ); - self.suggest_binding_for_closure_capture_self( + self.suggest_binding_for_closure_capture_self(&mut err, &issued_spans); + self.suggest_using_closure_argument_instead_of_capture( &mut err, issued_borrow.borrowed_place, &issued_spans, @@ -969,6 +977,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { place, issued_borrow.borrowed_place, ); + self.suggest_using_closure_argument_instead_of_capture( + &mut err, + issued_borrow.borrowed_place, + &issued_spans, + ); err } @@ -988,16 +1001,26 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { immutable_section_description, "mutably borrow", ); - borrow_spans.var_span_label( + borrow_spans.var_subdiag( + None, &mut err, - format!( - "borrow occurs due to use of {}{}", - desc_place, - borrow_spans.describe(), - ), - "immutable", + Some(BorrowKind::Unique), + |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => BorrowUsePlaceGenerator { + place: desc_place, + var_span, + is_single_var: true, + }, + None => BorrowUsePlaceClosure { + place: desc_place, + var_span, + is_single_var: true, + }, + } + }, ); - return err; } else { first_borrow_desc = "immutable "; @@ -1070,32 +1093,48 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; if issued_spans == borrow_spans { - borrow_spans.var_span_label( - &mut err, - format!("borrows occur due to use of {}{}", desc_place, borrow_spans.describe(),), - gen_borrow_kind.describe_mutability(), - ); + borrow_spans.var_subdiag(None, &mut err, Some(gen_borrow_kind), |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => BorrowUsePlaceGenerator { + place: desc_place, + var_span, + is_single_var: false, + }, + None => { + BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false } + } + } + }); } else { - let borrow_place = &issued_borrow.borrowed_place; - let borrow_place_desc = self.describe_any_place(borrow_place.as_ref()); - issued_spans.var_span_label( + issued_spans.var_subdiag( + Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic), &mut err, - format!( - "first borrow occurs due to use of {}{}", - borrow_place_desc, - issued_spans.describe(), - ), - issued_borrow.kind.describe_mutability(), + Some(issued_borrow.kind), + |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + let borrow_place = &issued_borrow.borrowed_place; + let borrow_place_desc = self.describe_any_place(borrow_place.as_ref()); + match kind { + Some(_) => { + FirstBorrowUsePlaceGenerator { place: borrow_place_desc, var_span } + } + None => FirstBorrowUsePlaceClosure { place: borrow_place_desc, var_span }, + } + }, ); - borrow_spans.var_span_label( + borrow_spans.var_subdiag( + Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic), &mut err, - format!( - "second borrow occurs due to use of {}{}", - desc_place, - borrow_spans.describe(), - ), - gen_borrow_kind.describe_mutability(), + Some(gen_borrow_kind), + |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => SecondBorrowUsePlaceGenerator { place: desc_place, var_span }, + None => SecondBorrowUsePlaceClosure { place: desc_place, var_span }, + } + }, ); } @@ -1229,23 +1268,161 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - fn suggest_binding_for_closure_capture_self( + /// Suggest using closure argument instead of capture. + /// + /// For example: + /// ```ignore (illustrative) + /// struct S; + /// + /// impl S { + /// fn call(&mut self, f: impl Fn(&mut Self)) { /* ... */ } + /// fn x(&self) {} + /// } + /// + /// let mut v = S; + /// v.call(|this: &mut S| v.x()); + /// // ^\ ^-- help: try using the closure argument: `this` + /// // *-- error: cannot borrow `v` as mutable because it is also borrowed as immutable + /// ``` + fn suggest_using_closure_argument_instead_of_capture( &self, err: &mut Diagnostic, borrowed_place: Place<'tcx>, issued_spans: &UseSpans<'tcx>, + ) { + let &UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return }; + let tcx = self.infcx.tcx; + let hir = tcx.hir(); + + // Get the type of the local that we are trying to borrow + let local = borrowed_place.local; + let local_ty = self.body.local_decls[local].ty; + + // Get the body the error happens in + let Some(body_id) = hir.get(self.mir_hir_id()).body_id() else { return }; + + let body_expr = hir.body(body_id).value; + + struct ClosureFinder<'hir> { + hir: rustc_middle::hir::map::Map<'hir>, + borrow_span: Span, + res: Option<(&'hir hir::Expr<'hir>, &'hir hir::Closure<'hir>)>, + /// The path expression with the `borrow_span` span + error_path: Option<(&'hir hir::Expr<'hir>, &'hir hir::QPath<'hir>)>, + } + impl<'hir> Visitor<'hir> for ClosureFinder<'hir> { + type NestedFilter = OnlyBodies; + + fn nested_visit_map(&mut self) -> Self::Map { + self.hir + } + + fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) { + if let hir::ExprKind::Path(qpath) = &ex.kind + && ex.span == self.borrow_span + { + self.error_path = Some((ex, qpath)); + } + + if let hir::ExprKind::Closure(closure) = ex.kind + && ex.span.contains(self.borrow_span) + // To support cases like `|| { v.call(|this| v.get()) }` + // FIXME: actually support such cases (need to figure out how to move from the capture place to original local) + && self.res.as_ref().map_or(true, |(prev_res, _)| prev_res.span.contains(ex.span)) + { + self.res = Some((ex, closure)); + } + + hir::intravisit::walk_expr(self, ex); + } + } + + // Find the closure that most tightly wraps `capture_kind_span` + let mut finder = + ClosureFinder { hir, borrow_span: capture_kind_span, res: None, error_path: None }; + finder.visit_expr(body_expr); + let Some((closure_expr, closure)) = finder.res else { return }; + + let typeck_results = tcx.typeck(self.mir_def_id()); + + // Check that the parent of the closure is a method call, + // with receiver matching with local's type (modulo refs) + let parent = hir.parent_id(closure_expr.hir_id); + if let hir::Node::Expr(parent) = hir.get(parent) { + if let hir::ExprKind::MethodCall(_, recv, ..) = parent.kind { + let recv_ty = typeck_results.expr_ty(recv); + + if recv_ty.peel_refs() != local_ty { + return; + } + } + } + + // Get closure's arguments + let ty::Closure(_, substs) = typeck_results.expr_ty(closure_expr).kind() else { /* hir::Closure can be a generator too */ return }; + let sig = substs.as_closure().sig(); + let tupled_params = + tcx.erase_late_bound_regions(sig.inputs().iter().next().unwrap().map_bound(|&b| b)); + let ty::Tuple(params) = tupled_params.kind() else { return }; + + // Find the first argument with a matching type, get its name + let Some((_, this_name)) = params + .iter() + .zip(hir.body_param_names(closure.body)) + .find(|(param_ty, name)|{ + // FIXME: also support deref for stuff like `Rc` arguments + param_ty.peel_refs() == local_ty && name != &Ident::empty() + }) + else { return }; + + let spans; + if let Some((_path_expr, qpath)) = finder.error_path + && let hir::QPath::Resolved(_, path) = qpath + && let hir::def::Res::Local(local_id) = path.res + { + // Find all references to the problematic variable in this closure body + + struct VariableUseFinder { + local_id: hir::HirId, + spans: Vec, + } + impl<'hir> Visitor<'hir> for VariableUseFinder { + fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) { + if let hir::ExprKind::Path(qpath) = &ex.kind + && let hir::QPath::Resolved(_, path) = qpath + && let hir::def::Res::Local(local_id) = path.res + && local_id == self.local_id + { + self.spans.push(ex.span); + } + + hir::intravisit::walk_expr(self, ex); + } + } + + let mut finder = VariableUseFinder { local_id, spans: Vec::new() }; + finder.visit_expr(hir.body(closure.body).value); + + spans = finder.spans; + } else { + spans = vec![capture_kind_span]; + } + + err.multipart_suggestion( + "try using the closure argument", + iter::zip(spans, iter::repeat(this_name.to_string())).collect(), + Applicability::MaybeIncorrect, + ); + } + + fn suggest_binding_for_closure_capture_self( + &self, + err: &mut Diagnostic, + issued_spans: &UseSpans<'tcx>, ) { let UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return }; let hir = self.infcx.tcx.hir(); - // check whether the borrowed place is capturing `self` by mut reference - let local = borrowed_place.local; - let Some(_) = self - .body - .local_decls - .get(local) - .map(|l| mut_borrow_of_mutable_ref(l, self.local_names[local])) else { return }; - struct ExpressionFinder<'hir> { capture_span: Span, closure_change_spans: Vec, @@ -1731,9 +1908,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.span_label(borrow_span, "borrowed value does not live long enough"); err.span_label(drop_span, format!("`{}` dropped here while still borrowed", name)); - let within = if borrow_spans.for_generator() { " by generator" } else { "" }; - - borrow_spans.args_span_label(&mut err, format!("value captured here{}", within)); + borrow_spans.args_subdiag(&mut err, |args_span| { + crate::session_diagnostics::CaptureArgLabel::Capture { + is_within: borrow_spans.for_generator(), + args_span, + } + }); explanation.add_explanation_to_diagnostic( self.infcx.tcx, @@ -1947,9 +2127,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { None, ); - let within = if borrow_spans.for_generator() { " by generator" } else { "" }; - - borrow_spans.args_span_label(&mut err, format!("value captured here{}", within)); + borrow_spans.args_subdiag(&mut err, |args_span| { + crate::session_diagnostics::CaptureArgLabel::Capture { + is_within: borrow_spans.for_generator(), + args_span, + } + }); err } @@ -2029,7 +2212,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let tcx = self.infcx.tcx; let return_ty = self.regioncx.universal_regions().unnormalized_output_ty; - let return_ty = tcx.erase_regions(return_ty); // to avoid panics if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) @@ -2382,11 +2564,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { section, "assign", ); - loan_spans.var_span_label( - &mut err, - format!("borrow occurs due to use{}", loan_spans.describe()), - loan.kind.describe_mutability(), - ); + + loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => BorrowUseInGenerator { var_span }, + None => BorrowUseInClosure { var_span }, + } + }); self.buffer_error(err); @@ -2396,11 +2581,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place); - loan_spans.var_span_label( - &mut err, - format!("borrow occurs due to use{}", loan_spans.describe()), - loan.kind.describe_mutability(), - ); + loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => BorrowUseInGenerator { var_span }, + None => BorrowUseInClosure { var_span }, + } + }); self.explain_why_borrow_contains_point(location, loan, None).add_explanation_to_diagnostic( self.infcx.tcx, @@ -2424,7 +2611,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Some((method_did, method_substs)), ) = ( &self.body[loan.reserve_location.block].terminator, - rustc_const_eval::util::find_self_call( + rustc_middle::util::find_self_call( tcx, self.body, loan.assigned_place.local, diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 8860395e71c8..f995c3165a91 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -3,7 +3,7 @@ use rustc_errors::{Applicability, Diagnostic}; use rustc_hir as hir; use rustc_hir::intravisit::Visitor; -use rustc_index::vec::IndexSlice; +use rustc_index::IndexSlice; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::mir::{ Body, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location, Operand, Place, diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 110354a20d83..4243ec214b09 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1,13 +1,16 @@ //! Borrow checker diagnostics. +use crate::session_diagnostics::{ + CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause, + CaptureVarKind, CaptureVarPathUseCause, OnClosureNote, +}; use itertools::Itertools; -use rustc_const_eval::util::{call_kind, CallDesugaringKind}; use rustc_errors::{Applicability, Diagnostic}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::GeneratorKind; -use rustc_index::vec::IndexSlice; -use rustc_infer::infer::{LateBoundRegionConversionTime, TyCtxtInferExt}; +use rustc_index::IndexSlice; +use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ AggregateKind, Constant, FakeReadCause, Local, LocalInfo, LocalKind, Location, Operand, Place, @@ -15,6 +18,7 @@ use rustc_middle::mir::{ }; use rustc_middle::ty::print::Print; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; +use rustc_middle::util::{call_kind, CallDesugaringKind}; use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult}; use rustc_span::def_id::LocalDefId; use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP}; @@ -45,7 +49,7 @@ pub(crate) use mutability_errors::AccessKind; pub(crate) use outlives_suggestion::OutlivesSuggestionBuilder; pub(crate) use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors}; pub(crate) use region_name::{RegionName, RegionNameSource}; -pub(crate) use rustc_const_eval::util::CallKind; +pub(crate) use rustc_middle::util::CallKind; pub(super) struct DescribePlaceOpt { pub including_downcast: bool, @@ -117,13 +121,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind() { let did = did.expect_local(); if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) { - diag.span_note( - *span, - &format!( - "closure cannot be invoked more than once because it moves the \ - variable `{}` out of its environment", - ty::place_to_string_for_capture(self.infcx.tcx, hir_place) - ), + diag.eager_subdiagnostic( + &self.infcx.tcx.sess.parse_sess.span_diagnostic, + OnClosureNote::InvokedTwice { + place_name: &ty::place_to_string_for_capture( + self.infcx.tcx, + hir_place, + ), + span: *span, + }, ); return true; } @@ -137,13 +143,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind() { let did = did.expect_local(); if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) { - diag.span_note( - *span, - &format!( - "closure cannot be moved more than once as it is not `Copy` due to \ - moving the variable `{}` out of its environment", - ty::place_to_string_for_capture(self.infcx.tcx, hir_place) - ), + diag.eager_subdiagnostic( + &self.infcx.tcx.sess.parse_sess.span_diagnostic, + OnClosureNote::MovedTwice { + place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place), + span: *span, + }, ); return true; } @@ -380,25 +385,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - /// Add a note that a type does not implement `Copy` - pub(super) fn note_type_does_not_implement_copy( - &self, - err: &mut Diagnostic, - place_desc: &str, - ty: Ty<'tcx>, - span: Option, - move_prefix: &str, - ) { - let message = format!( - "{move_prefix}move occurs because {place_desc} has type `{ty}`, which does not implement the `Copy` trait", - ); - if let Some(span) = span { - err.span_label(span, message); - } else { - err.note(&message); - } - } - pub(super) fn borrowed_content_source( &self, deref_base: PlaceRef<'tcx>, @@ -582,9 +568,13 @@ impl UseSpans<'_> { } /// Add a span label to the arguments of the closure, if it exists. - pub(super) fn args_span_label(self, err: &mut Diagnostic, message: impl Into) { + pub(super) fn args_subdiag( + self, + err: &mut Diagnostic, + f: impl FnOnce(Span) -> CaptureArgLabel, + ) { if let UseSpans::ClosureUse { args_span, .. } = self { - err.span_label(args_span, message); + err.subdiagnostic(f(args_span)); } } @@ -595,8 +585,8 @@ impl UseSpans<'_> { err: &mut Diagnostic, action: crate::InitializationRequiringAction, ) { - use crate::session_diagnostics::CaptureVarPathUseCause::*; use crate::InitializationRequiringAction::*; + use CaptureVarPathUseCause::*; if let UseSpans::ClosureUse { generator_kind, path_span, .. } = self { match generator_kind { Some(_) => { @@ -619,34 +609,14 @@ impl UseSpans<'_> { } } - /// Add a span label to the use of the captured variable, if it exists. - pub(super) fn var_span_label( - self, - err: &mut Diagnostic, - message: impl Into, - kind_desc: impl Into, - ) { - if let UseSpans::ClosureUse { capture_kind_span, path_span, .. } = self { - if capture_kind_span == path_span { - err.span_label(capture_kind_span, message); - } else { - let capture_kind_label = - format!("capture is {} because of use here", kind_desc.into()); - let path_label = message; - err.span_label(capture_kind_span, capture_kind_label); - err.span_label(path_span, path_label); - } - } - } - /// Add a subdiagnostic to the use of the captured variable, if it exists. pub(super) fn var_subdiag( self, + handler: Option<&rustc_errors::Handler>, err: &mut Diagnostic, kind: Option, - f: impl Fn(Option, Span) -> crate::session_diagnostics::CaptureVarCause, + f: impl FnOnce(Option, Span) -> CaptureVarCause, ) { - use crate::session_diagnostics::CaptureVarKind::*; if let UseSpans::ClosureUse { generator_kind, capture_kind_span, path_span, .. } = self { if capture_kind_span != path_span { err.subdiagnostic(match kind { @@ -654,17 +624,21 @@ impl UseSpans<'_> { rustc_middle::mir::BorrowKind::Shared | rustc_middle::mir::BorrowKind::Shallow | rustc_middle::mir::BorrowKind::Unique => { - Immute { kind_span: capture_kind_span } + CaptureVarKind::Immut { kind_span: capture_kind_span } } rustc_middle::mir::BorrowKind::Mut { .. } => { - Mut { kind_span: capture_kind_span } + CaptureVarKind::Mut { kind_span: capture_kind_span } } }, - None => Move { kind_span: capture_kind_span }, + None => CaptureVarKind::Move { kind_span: capture_kind_span }, }); }; - err.subdiagnostic(f(generator_kind, path_span)); + let diag = f(generator_kind, path_span); + match handler { + Some(hd) => err.eager_subdiagnostic(hd, diag), + None => err.subdiagnostic(diag), + }; } } @@ -684,20 +658,6 @@ impl UseSpans<'_> { } } - /// Describe the span associated with a use of a place. - pub(super) fn describe(&self) -> &str { - match *self { - UseSpans::ClosureUse { generator_kind, .. } => { - if generator_kind.is_some() { - " in generator" - } else { - " in closure" - } - } - _ => "", - } - } - pub(super) fn or_else(self, if_other: F) -> Self where F: FnOnce() -> Self, @@ -788,6 +748,15 @@ impl<'tcx> BorrowedContentSource<'tcx> { } } +///helper struct for explain_captures() +struct CapturedMessageOpt { + is_partial_move: bool, + is_loop_message: bool, + is_move_msg: bool, + is_loop_move: bool, + maybe_reinitialized_locations_is_empty: bool, +} + impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Finds the spans associated to a move or copy of move_place at location. pub(super) fn move_spans( @@ -874,7 +843,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }) = &self.body[location.block].terminator { let Some((method_did, method_substs)) = - rustc_const_eval::util::find_self_call( + rustc_middle::util::find_self_call( self.infcx.tcx, &self.body, target_temp, @@ -1027,12 +996,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { move_span: Span, move_spans: UseSpans<'tcx>, moved_place: Place<'tcx>, - partially_str: &str, - loop_message: &str, - move_msg: &str, - is_loop_move: bool, - maybe_reinitialized_locations_is_empty: bool, + msg_opt: CapturedMessageOpt, ) { + let CapturedMessageOpt { + is_partial_move: is_partial, + is_loop_message, + is_move_msg, + is_loop_move, + maybe_reinitialized_locations_is_empty, + } = msg_opt; if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } = move_spans { let place_name = self .describe_place(moved_place.as_ref()) @@ -1042,30 +1014,26 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { CallKind::FnCall { fn_trait_id, .. } if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() => { - err.span_label( + err.subdiagnostic(CaptureReasonLabel::Call { fn_call_span, - &format!( - "{place_name} {partially_str}moved due to this call{loop_message}", - ), - ); - err.span_note( - var_span, - "this value implements `FnOnce`, which causes it to be moved when called", - ); + place_name: &place_name, + is_partial, + is_loop_message, + }); + err.subdiagnostic(CaptureReasonNote::FnOnceMoveInCall { var_span }); } CallKind::Operator { self_arg, .. } => { let self_arg = self_arg.unwrap(); - err.span_label( + err.subdiagnostic(CaptureReasonLabel::OperatorUse { fn_call_span, - &format!( - "{place_name} {partially_str}moved due to usage in operator{loop_message}", - ), - ); + place_name: &place_name, + is_partial, + is_loop_message, + }); if self.fn_self_span_reported.insert(fn_span) { - err.span_note( - self_arg.span, - "calling this operator moves the left-hand side", - ); + err.subdiagnostic(CaptureReasonNote::LhsMoveByOperator { + span: self_arg.span, + }); } } CallKind::Normal { self_arg, desugaring, method_did, method_substs } => { @@ -1074,35 +1042,27 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring { let ty = moved_place.ty(self.body, tcx).ty; let suggest = match tcx.get_diagnostic_item(sym::IntoIterator) { - Some(def_id) => { - let infcx = self.infcx.tcx.infer_ctxt().build(); - type_known_to_meet_bound_modulo_regions( - &infcx, - self.param_env, - tcx.mk_imm_ref(tcx.lifetimes.re_erased, tcx.erase_regions(ty)), - def_id, - ) - } + Some(def_id) => type_known_to_meet_bound_modulo_regions( + &self.infcx, + self.param_env, + tcx.mk_imm_ref(tcx.lifetimes.re_erased, ty), + def_id, + ), _ => false, }; if suggest { - err.span_suggestion_verbose( - move_span.shrink_to_lo(), - &format!( - "consider iterating over a slice of the `{ty}`'s content to \ - avoid moving into the `for` loop", - ), - "&", - Applicability::MaybeIncorrect, - ); + err.subdiagnostic(CaptureReasonSuggest::IterateSlice { + ty, + span: move_span.shrink_to_lo(), + }); } - err.span_label( + err.subdiagnostic(CaptureReasonLabel::ImplicitCall { fn_call_span, - &format!( - "{place_name} {partially_str}moved due to this implicit call to `.into_iter()`{loop_message}", - ), - ); + place_name: &place_name, + is_partial, + is_loop_message, + }); // If the moved place was a `&mut` ref, then we can // suggest to reborrow it where it was moved, so it // will still be valid by the time we get to the usage. @@ -1125,34 +1085,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } } else { - err.span_label( + err.subdiagnostic(CaptureReasonLabel::MethodCall { fn_call_span, - &format!( - "{place_name} {partially_str}moved due to this method call{loop_message}", - ), - ); - - let infcx = tcx.infer_ctxt().build(); + place_name: &place_name, + is_partial, + is_loop_message, + }); // Erase and shadow everything that could be passed to the new infcx. - let ty = tcx.erase_regions(moved_place.ty(self.body, tcx).ty); - let method_substs = tcx.erase_regions(method_substs); + let ty = moved_place.ty(self.body, tcx).ty; if let ty::Adt(def, substs) = ty.kind() && Some(def.did()) == tcx.lang_items().pin_type() && let ty::Ref(_, _, hir::Mutability::Mut) = substs.type_at(0).kind() - && let self_ty = infcx.instantiate_binder_with_fresh_vars( + && let self_ty = self.infcx.instantiate_binder_with_fresh_vars( fn_call_span, LateBoundRegionConversionTime::FnCall, tcx.fn_sig(method_did).subst(tcx, method_substs).input(0), ) - && infcx.can_eq(self.param_env, ty, self_ty) + && self.infcx.can_eq(self.param_env, ty, self_ty) { - err.span_suggestion_verbose( - fn_call_span.shrink_to_lo(), - "consider reborrowing the `Pin` instead of moving it", - "as_mut().".to_string(), - Applicability::MaybeIncorrect, - ); + err.eager_subdiagnostic( + &self.infcx.tcx.sess.parse_sess.span_diagnostic, + CaptureReasonSuggest::FreshReborrow { + span: fn_call_span.shrink_to_lo(), + }); } if let Some(clone_trait) = tcx.lang_items().clone_trait() && let trait_ref = tcx.mk_trait_ref(clone_trait, [ty]) @@ -1162,7 +1118,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.param_env, ty::Binder::dummy(trait_ref), ) - && infcx.predicate_must_hold_modulo_regions(&o) + && self.infcx.predicate_must_hold_modulo_regions(&o) { err.span_suggestion_verbose( fn_call_span.shrink_to_lo(), @@ -1177,10 +1133,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // error messages. if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) { let func = tcx.def_path_str(method_did); - err.span_note( - self_arg.span, - &format!("`{func}` takes ownership of the receiver `self`, which moves {place_name}") - ); + err.subdiagnostic(CaptureReasonNote::FuncTakeSelf { + func, + place_name, + span: self_arg.span, + }); } let parent_did = tcx.parent(method_did); let parent_self_ty = @@ -1194,30 +1151,28 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result)) }); if is_option_or_result && maybe_reinitialized_locations_is_empty { - err.span_label( - var_span, - "help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents", - ); + err.subdiagnostic(CaptureReasonLabel::BorrowContent { var_span }); } } // Other desugarings takes &self, which cannot cause a move _ => {} } } else { - if move_span != span || !loop_message.is_empty() { - err.span_label( + if move_span != span || is_loop_message { + err.subdiagnostic(CaptureReasonLabel::MovedHere { move_span, - format!("value {partially_str}moved{move_msg} here{loop_message}"), - ); + is_partial, + is_move_msg, + is_loop_message, + }); } // If the move error occurs due to a loop, don't show // another message for the same span - if loop_message.is_empty() { - move_spans.var_span_label( - err, - format!("variable {partially_str}moved due to use{}", move_spans.describe()), - "moved", - ); + if !is_loop_message { + move_spans.var_subdiag(None, err, None, |kind, var_span| match kind { + Some(_) => CaptureVarCause::PartialMoveUseInGenerator { var_span, is_partial }, + None => CaptureVarCause::PartialMoveUseInClosure { var_span, is_partial }, + }) } } } diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 3662bec0c763..67af96a71e30 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -6,6 +6,7 @@ use rustc_mir_dataflow::move_paths::{ }; use rustc_span::{BytePos, Span}; +use crate::diagnostics::CapturedMessageOpt; use crate::diagnostics::{DescribePlaceOpt, UseSpans}; use crate::prefixes::PrefixSet; use crate::MirBorrowckCtxt; @@ -397,10 +398,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } }; + let msg_opt = CapturedMessageOpt { + is_partial_move: false, + is_loop_message: false, + is_move_msg: false, + is_loop_move: false, + maybe_reinitialized_locations_is_empty: true, + }; if let Some(use_spans) = use_spans { - self.explain_captures( - &mut err, span, span, use_spans, move_place, "", "", "", false, true, - ); + self.explain_captures(&mut err, span, span, use_spans, move_place, msg_opt); } err } @@ -416,13 +422,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { None => "value".to_string(), }; - self.note_type_does_not_implement_copy( - err, - &place_desc, - place_ty, - Some(span), - "", - ); + err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { + is_partial_move: false, + ty: place_ty, + place: &place_desc, + span, + }); } else { binds_to.sort(); binds_to.dedup(); @@ -444,9 +449,19 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Some(desc) => format!("`{desc}`"), None => "value".to_string(), }; - self.note_type_does_not_implement_copy(err, &place_desc, place_ty, Some(span), ""); + err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { + is_partial_move: false, + ty: place_ty, + place: &place_desc, + span, + }); - use_spans.args_span_label(err, format!("{place_desc} is moved here")); + use_spans.args_subdiag(err, |args_span| { + crate::session_diagnostics::CaptureArgLabel::MoveOutPlace { + place: place_desc, + args_span, + } + }); } } } @@ -534,13 +549,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } if binds_to.len() == 1 { - self.note_type_does_not_implement_copy( - err, - &format!("`{}`", self.local_names[*local].unwrap()), - bind_to.ty, - Some(binding_span), - "", - ); + let place_desc = &format!("`{}`", self.local_names[*local].unwrap()); + err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { + is_partial_move: false, + ty: bind_to.ty, + place: &place_desc, + span: binding_span, + }); } } diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 9d9040096504..e3d81194ac81 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -15,8 +15,8 @@ use rustc_span::{sym, BytePos, Span}; use rustc_target::abi::FieldIdx; use crate::diagnostics::BorrowedContentSource; +use crate::util::FindAssignments; use crate::MirBorrowckCtxt; -use rustc_const_eval::util::collect_writes::FindAssignments; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub(crate) enum AccessKind { @@ -231,14 +231,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } if suggest { - borrow_spans.var_span_label( - &mut err, - format!( - "mutable borrow occurs due to use of {} in closure", - self.describe_any_place(access_place.as_ref()), - ), - "mutable", - ); + borrow_spans.var_subdiag( + None, + &mut err, + Some(mir::BorrowKind::Mut { allow_two_phase_borrow: false }), + |_kind, var_span| { + let place = self.describe_any_place(access_place.as_ref()); + crate::session_diagnostics::CaptureVarCause::MutableBorrowUsePlaceClosure { + place, + var_span, + } + }, + ); } borrow_span } @@ -1143,7 +1147,7 @@ pub fn mut_borrow_of_mutable_ref(local_decl: &LocalDecl<'_>, local_name: Option< // suggest removing the `&mut`. // // Deliberately fall into this case for all implicit self types, - // so that we don't fall in to the next case with them. + // so that we don't fall into the next case with them. kind == hir::ImplicitSelfKind::MutRef } _ if Some(kw::SelfLower) == local_name => { @@ -1231,7 +1235,7 @@ fn suggest_ampmut<'tcx>( } } - let (suggestability, highlight_span) = match opt_ty_info { + let (suggestibility, highlight_span) = match opt_ty_info { // if this is a variable binding with an explicit type, // try to highlight that for the suggestion. Some(ty_span) => (true, ty_span), @@ -1252,7 +1256,7 @@ fn suggest_ampmut<'tcx>( let ty_mut = local_decl.ty.builtin_deref(true).unwrap(); assert_eq!(ty_mut.mutbl, hir::Mutability::Not); ( - suggestability, + suggestibility, highlight_span, if local_decl.ty.is_ref() { format!("&mut {}", ty_mut.ty) diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs index 376415e3d320..98418e2372f0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs @@ -3,7 +3,7 @@ use crate::region_infer::RegionInferenceContext; use crate::Upvar; -use rustc_index::vec::{Idx, IndexSlice}; +use rustc_index::IndexSlice; use rustc_middle::mir::{Body, Local}; use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_span::source_map::Span; @@ -117,7 +117,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { argument_index: usize, ) -> (Option, Span) { let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs(); - let argument_local = Local::new(implicit_inputs + argument_index + 1); + let argument_local = Local::from_usize(implicit_inputs + argument_index + 1); debug!("get_argument_name_and_span_for_region: argument_local={argument_local:?}"); let argument_name = local_names[argument_local]; diff --git a/compiler/rustc_borrowck/src/facts.rs b/compiler/rustc_borrowck/src/facts.rs index 02ffb51fbb7e..87fad9a355d3 100644 --- a/compiler/rustc_borrowck/src/facts.rs +++ b/compiler/rustc_borrowck/src/facts.rs @@ -4,7 +4,6 @@ use crate::location::{LocationIndex, LocationTable}; use crate::BorrowIndex; use polonius_engine::AllFacts as PoloniusFacts; use polonius_engine::Atom; -use rustc_index::vec::Idx; use rustc_middle::mir::Local; use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_mir_dataflow::move_paths::MovePathIndex; @@ -93,13 +92,13 @@ impl AllFactsExt for AllFacts { impl Atom for BorrowIndex { fn index(self) -> usize { - Idx::index(self) + self.as_usize() } } impl Atom for LocationIndex { fn index(self) -> usize { - Idx::index(self) + self.as_usize() } } diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index 498d254da653..06986f848bfe 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -79,7 +79,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { } // Only relevant for mir typeck StatementKind::AscribeUserType(..) - // Only relevant for unsafeck + // Only relevant for liveness and unsafeck | StatementKind::PlaceMention(..) // Doesn't have any language semantics | StatementKind::Coverage(..) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index a4b285a34fa4..6900729d671a 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -20,14 +20,14 @@ extern crate tracing; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::graph::dominators::Dominators; use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticMessage, SubdiagnosticMessage}; +use rustc_fluent_macro::fluent_messages; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_index::bit_set::ChunkedBitSet; -use rustc_index::vec::{IndexSlice, IndexVec}; +use rustc_index::{IndexSlice, IndexVec}; use rustc_infer::infer::{ DefiningAnchor, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt, }; -use rustc_macros::fluent_messages; use rustc_middle::mir::{ traversal, Body, ClearCrossCrate, Local, Location, Mutability, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, VarDebugInfoContents, @@ -88,6 +88,7 @@ mod session_diagnostics; mod type_check; mod universal_regions; mod used_muts; +mod util; /// A public API provided for the Rust compiler consumers. pub mod consumers; @@ -118,24 +119,12 @@ impl<'tcx> TyCtxtConsts<'tcx> { } pub fn provide(providers: &mut Providers) { - *providers = Providers { - mir_borrowck: |tcx, did| { - if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) { - tcx.mir_borrowck_const_arg(def) - } else { - mir_borrowck(tcx, ty::WithOptConstParam::unknown(did)) - } - }, - mir_borrowck_const_arg: |tcx, (did, param_did)| { - mir_borrowck(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) }) - }, - ..*providers - }; + *providers = Providers { mir_borrowck, ..*providers }; } -fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> &BorrowCheckResult<'_> { +fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { let (input_body, promoted) = tcx.mir_promoted(def); - debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id())); + debug!("run query mir_borrowck: {}", tcx.def_path_str(def)); if input_body.borrow().should_skip() { debug!("Skipping borrowck because of injected body"); @@ -149,7 +138,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> &Bor return tcx.arena.alloc(result); } - let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner; + let hir_owner = tcx.hir().local_def_id_to_hir_id(def).owner; let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build(); @@ -166,19 +155,19 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> &Bor /// If `return_body_with_facts` is true, then return the body with non-erased /// region ids on which the borrow checking was performed together with Polonius /// facts. -#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.with_opt_param().as_local().unwrap()), level = "debug")] +#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.def_id()), level = "debug")] fn do_mir_borrowck<'tcx>( infcx: &InferCtxt<'tcx>, input_body: &Body<'tcx>, input_promoted: &IndexSlice>, return_body_with_facts: bool, ) -> (BorrowCheckResult<'tcx>, Option>>) { - let def = input_body.source.with_opt_param().as_local().unwrap(); + let def = input_body.source.def_id().expect_local(); debug!(?def); let tcx = infcx.tcx; let infcx = BorrowckInferCtxt::new(infcx); - let param_env = tcx.param_env(def.did); + let param_env = tcx.param_env(def); let mut local_names = IndexVec::from_elem(None, &input_body.local_decls); for var_debug_info in &input_body.var_debug_info { @@ -206,7 +195,7 @@ fn do_mir_borrowck<'tcx>( errors.set_tainted_by_errors(e); } let upvars: Vec<_> = tcx - .closure_captures(def.did) + .closure_captures(def) .iter() .map(|&captured_place| { let capture = captured_place.info.capture_kind; @@ -248,7 +237,7 @@ fn do_mir_borrowck<'tcx>( .iterate_to_fixpoint() .into_results_cursor(&body); - let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(def.did).is_fn_or_closure(); + let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(def).is_fn_or_closure(); let borrow_set = Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data)); @@ -528,7 +517,7 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> { where F: Fn() -> RegionCtxt, { - let next_region = self.infcx.next_nll_region_var(origin.clone()); + let next_region = self.infcx.next_nll_region_var(origin); let vid = next_region.as_var(); if cfg!(debug_assertions) && !self.inside_canonicalization_ctxt() { @@ -676,7 +665,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx } // Only relevant for mir typeck StatementKind::AscribeUserType(..) - // Only relevant for unsafeck + // Only relevant for liveness and unsafeck | StatementKind::PlaceMention(..) // Doesn't have any language semantics | StatementKind::Coverage(..) @@ -946,6 +935,7 @@ enum InitializationRequiringAction { PartialAssignment, } +#[derive(Debug)] struct RootPlace<'tcx> { place_local: Local, place_projection: &'tcx [PlaceElem<'tcx>], @@ -1859,11 +1849,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // is allowed, remove this match arm. ty::Adt(..) | ty::Tuple(..) => { check_parent_of_field(self, location, place_base, span, flow_state); - - // rust-lang/rust#21232, #54499, #54986: during period where we reject - // partial initialization, do not complain about unnecessary `mut` on - // an attempt to do a partial initialization. - self.used_mut.insert(place.local); } _ => {} @@ -1951,6 +1936,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { (prefix, base, span), mpi, ); + + // rust-lang/rust#21232, #54499, #54986: during period where we reject + // partial initialization, do not complain about unnecessary `mut` on + // an attempt to do a partial initialization. + this.used_mut.insert(base.local); } } } diff --git a/compiler/rustc_borrowck/src/location.rs b/compiler/rustc_borrowck/src/location.rs index 288b7d85be2d..0e669abfd14a 100644 --- a/compiler/rustc_borrowck/src/location.rs +++ b/compiler/rustc_borrowck/src/location.rs @@ -1,6 +1,6 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -use rustc_index::vec::{Idx, IndexVec}; +use rustc_index::IndexVec; use rustc_middle::mir::{BasicBlock, Body, Location}; /// Maps between a MIR Location, which identifies a particular @@ -50,19 +50,19 @@ impl LocationTable { } pub fn all_points(&self) -> impl Iterator { - (0..self.num_points).map(LocationIndex::new) + (0..self.num_points).map(LocationIndex::from_usize) } pub fn start_index(&self, location: Location) -> LocationIndex { let Location { block, statement_index } = location; let start_index = self.statements_before_block[block]; - LocationIndex::new(start_index + statement_index * 2) + LocationIndex::from_usize(start_index + statement_index * 2) } pub fn mid_index(&self, location: Location) -> LocationIndex { let Location { block, statement_index } = location; let start_index = self.statements_before_block[block]; - LocationIndex::new(start_index + statement_index * 2 + 1) + LocationIndex::from_usize(start_index + statement_index * 2 + 1) } pub fn to_location(&self, index: LocationIndex) -> RichLocation { diff --git a/compiler/rustc_borrowck/src/member_constraints.rs b/compiler/rustc_borrowck/src/member_constraints.rs index f637e6a95ac6..842e90080582 100644 --- a/compiler/rustc_borrowck/src/member_constraints.rs +++ b/compiler/rustc_borrowck/src/member_constraints.rs @@ -2,7 +2,7 @@ #![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxIndexMap; -use rustc_index::vec::{IndexSlice, IndexVec}; +use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::infer::MemberConstraint; use rustc_middle::ty::{self, Ty}; use rustc_span::Span; @@ -221,7 +221,7 @@ fn append_list( ) { let mut p = target_list; loop { - let mut r = &mut constraints[p]; + let r = &mut constraints[p]; match r.next_constraint { Some(q) => p = q, None => { diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 59a3ab3189d7..5f1bcb27ea79 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -4,11 +4,11 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_hir::def_id::LocalDefId; -use rustc_index::vec::IndexSlice; +use rustc_index::IndexSlice; use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere}; use rustc_middle::mir::{ - BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, - Promoted, + Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted, + START_BLOCK, }; use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt}; use rustc_span::symbol::sym; @@ -61,7 +61,7 @@ pub(crate) fn replace_regions_in_mir<'tcx>( body: &mut Body<'tcx>, promoted: &mut IndexSlice>, ) -> UniversalRegions<'tcx> { - let def = body.source.with_opt_param().as_local().unwrap(); + let def = body.source.def_id().expect_local(); debug!(?def); @@ -94,8 +94,8 @@ fn populate_polonius_move_facts( } } - let fn_entry_start = location_table - .start_index(Location { block: BasicBlock::from_u32(0u32), statement_index: 0 }); + let fn_entry_start = + location_table.start_index(Location { block: START_BLOCK, statement_index: 0 }); // initialized_at for init in move_data.inits.iter() { @@ -235,7 +235,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>( // Create the region inference context, taking ownership of the // region inference data that was contained in `infcx`, and the // base constraints generated by the type-check. - let var_origins = infcx.take_region_var_origins(); + let var_origins = infcx.get_region_var_origins(); let MirTypeckRegionConstraints { placeholder_indices, placeholder_index_to_region: _, diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 729f3dbff3b4..65573c71f14a 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -7,7 +7,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::graph::scc::Sccs; use rustc_errors::Diagnostic; use rustc_hir::def_id::CRATE_DEF_ID; -use rustc_index::vec::{IndexSlice, IndexVec}; +use rustc_index::{IndexSlice, IndexVec}; use rustc_infer::infer::outlives::test_type_match; use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq}; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin}; diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index 8132800f107a..193e20601152 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -4,8 +4,8 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_index::bit_set::SparseBitMatrix; use rustc_index::interval::IntervalSet; use rustc_index::interval::SparseIntervalMatrix; -use rustc_index::vec::Idx; -use rustc_index::vec::IndexVec; +use rustc_index::Idx; +use rustc_index::IndexVec; use rustc_middle::mir::{BasicBlock, Body, Location}; use rustc_middle::ty::{self, RegionVid}; use std::fmt::Debug; diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index 94ce29dfe519..22de7549e940 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -1,7 +1,7 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] use crate::BorrowckInferCtxt; -use rustc_index::vec::IndexSlice; +use rustc_index::IndexSlice; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::mir::visit::{MutVisitor, TyContext}; use rustc_middle::mir::Constant; diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index a3678929099d..bb95101845f3 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -184,7 +184,7 @@ pub(crate) enum CaptureVarPathUseCause { #[derive(Subdiagnostic)] pub(crate) enum CaptureVarKind { #[label(borrowck_capture_immute)] - Immute { + Immut { #[primary_span] kind_span: Span, }, @@ -204,16 +204,80 @@ pub(crate) enum CaptureVarKind { pub(crate) enum CaptureVarCause { #[label(borrowck_var_borrow_by_use_place_in_generator)] BorrowUsePlaceGenerator { + is_single_var: bool, place: String, #[primary_span] var_span: Span, }, #[label(borrowck_var_borrow_by_use_place_in_closure)] BorrowUsePlaceClosure { + is_single_var: bool, place: String, #[primary_span] var_span: Span, }, + #[label(borrowck_var_borrow_by_use_in_generator)] + BorrowUseInGenerator { + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_borrow_by_use_in_closure)] + BorrowUseInClosure { + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_move_by_use_in_generator)] + MoveUseInGenerator { + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_move_by_use_in_closure)] + MoveUseInClosure { + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_first_borrow_by_use_place_in_generator)] + FirstBorrowUsePlaceGenerator { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_first_borrow_by_use_place_in_closure)] + FirstBorrowUsePlaceClosure { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_second_borrow_by_use_place_in_generator)] + SecondBorrowUsePlaceGenerator { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_second_borrow_by_use_place_in_closure)] + SecondBorrowUsePlaceClosure { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_mutable_borrow_by_use_place_in_closure)] + MutableBorrowUsePlaceClosure { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_partial_var_move_by_use_in_generator)] + PartialMoveUseInGenerator { + #[primary_span] + var_span: Span, + is_partial: bool, + }, + #[label(borrowck_partial_var_move_by_use_in_closure)] + PartialMoveUseInClosure { + #[primary_span] + var_span: Span, + is_partial: bool, + }, } #[derive(Diagnostic)] @@ -239,3 +303,144 @@ pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> { #[label] pub param_span: Span, } + +#[derive(Subdiagnostic)] +pub(crate) enum CaptureReasonLabel<'a> { + #[label(borrowck_moved_due_to_call)] + Call { + #[primary_span] + fn_call_span: Span, + place_name: &'a str, + is_partial: bool, + is_loop_message: bool, + }, + #[label(borrowck_moved_due_to_usage_in_operator)] + OperatorUse { + #[primary_span] + fn_call_span: Span, + place_name: &'a str, + is_partial: bool, + is_loop_message: bool, + }, + #[label(borrowck_moved_due_to_implicit_into_iter_call)] + ImplicitCall { + #[primary_span] + fn_call_span: Span, + place_name: &'a str, + is_partial: bool, + is_loop_message: bool, + }, + #[label(borrowck_moved_due_to_method_call)] + MethodCall { + #[primary_span] + fn_call_span: Span, + place_name: &'a str, + is_partial: bool, + is_loop_message: bool, + }, + #[label(borrowck_value_moved_here)] + MovedHere { + #[primary_span] + move_span: Span, + is_partial: bool, + is_move_msg: bool, + is_loop_message: bool, + }, + #[label(borrowck_consider_borrow_type_contents)] + BorrowContent { + #[primary_span] + var_span: Span, + }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum CaptureReasonNote { + #[note(borrowck_moved_a_fn_once_in_call)] + FnOnceMoveInCall { + #[primary_span] + var_span: Span, + }, + #[note(borrowck_calling_operator_moves_lhs)] + LhsMoveByOperator { + #[primary_span] + span: Span, + }, + #[note(borrowck_func_take_self_moved_place)] + FuncTakeSelf { + func: String, + place_name: String, + #[primary_span] + span: Span, + }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum CaptureReasonSuggest<'tcx> { + #[suggestion( + borrowck_suggest_iterate_over_slice, + applicability = "maybe-incorrect", + code = "&", + style = "verbose" + )] + IterateSlice { + ty: Ty<'tcx>, + #[primary_span] + span: Span, + }, + #[suggestion( + borrowck_suggest_create_freash_reborrow, + applicability = "maybe-incorrect", + code = "as_mut().", + style = "verbose" + )] + FreshReborrow { + #[primary_span] + span: Span, + }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum CaptureArgLabel { + #[label(borrowck_value_capture_here)] + Capture { + is_within: bool, + #[primary_span] + args_span: Span, + }, + #[label(borrowck_move_out_place_here)] + MoveOutPlace { + place: String, + #[primary_span] + args_span: Span, + }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum OnClosureNote<'a> { + #[note(borrowck_closure_invoked_twice)] + InvokedTwice { + place_name: &'a str, + #[primary_span] + span: Span, + }, + #[note(borrowck_closure_moved_twice)] + MovedTwice { + place_name: &'a str, + #[primary_span] + span: Span, + }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum TypeNoCopy<'a, 'tcx> { + #[label(borrowck_ty_no_impl_copy)] + Label { + is_partial_move: bool, + ty: Ty<'tcx>, + place: &'a str, + #[primary_span] + span: Span, + }, + #[note(borrowck_ty_no_impl_copy)] + Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str }, +} diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 17e702eb8c52..9250b8d3eaf2 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -7,7 +7,6 @@ //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and //! contain revealed `impl Trait` values). -use rustc_index::vec::Idx; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; @@ -83,7 +82,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } // In MIR, argument N is stored in local N+1. - let local = Local::new(argument_index + 1); + let local = Local::from_usize(argument_index + 1); let mir_input_ty = body.local_decls[local].ty; diff --git a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs index 2c387edfef07..a9ca94567878 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs @@ -1,5 +1,5 @@ use rustc_data_structures::vec_linked_list as vll; -use rustc_index::vec::IndexVec; +use rustc_index::IndexVec; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{Body, Local, Location}; diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 375eca1b29d3..d5e50a61b032 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -14,7 +14,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_hir::lang_items::LangItem; -use rustc_index::vec::{IndexSlice, IndexVec}; +use rustc_index::{IndexSlice, IndexVec}; use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::region_constraints::RegionConstraintData; @@ -394,7 +394,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { self.cx.ascribe_user_type( constant.literal.ty(), UserType::TypeOf( - uv.def.did, + uv.def, UserSubsts { substs: uv.substs, user_self_ty: None }, ), locations.span(&self.cx.body), @@ -1766,7 +1766,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let Some(uv) = maybe_uneval { if uv.promoted.is_none() { let tcx = self.tcx(); - let def_id = uv.def.def_id_for_type_of(); + let def_id = uv.def; if tcx.def_kind(def_id) == DefKind::InlineConst { let def_id = def_id.expect_local(); let predicates = @@ -2306,7 +2306,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Rvalue::AddressOf(..) | Rvalue::ThreadLocalRef(..) | Rvalue::Len(..) - | Rvalue::Discriminant(..) => {} + | Rvalue::Discriminant(..) + | Rvalue::NullaryOp(NullOp::OffsetOf(..), _) => {} } } diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 70fddb1057c0..3f7f23df8d92 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -19,7 +19,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::BodyOwnerKind; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_index::IndexVec; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt}; @@ -226,7 +226,7 @@ impl<'tcx> UniversalRegions<'tcx> { /// known between those regions. pub fn new( infcx: &BorrowckInferCtxt<'_, 'tcx>, - mir_def: ty::WithOptConstParam, + mir_def: LocalDefId, param_env: ty::ParamEnv<'tcx>, ) -> Self { UniversalRegionsBuilder { infcx, mir_def, param_env }.build() @@ -289,7 +289,7 @@ impl<'tcx> UniversalRegions<'tcx> { /// Returns an iterator over all the RegionVids corresponding to /// universally quantified free regions. pub fn universal_regions(&self) -> impl Iterator { - (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::new) + (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize) } /// Returns `true` if `r` is classified as an local region. @@ -388,7 +388,7 @@ impl<'tcx> UniversalRegions<'tcx> { struct UniversalRegionsBuilder<'cx, 'tcx> { infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>, - mir_def: ty::WithOptConstParam, + mir_def: LocalDefId, param_env: ty::ParamEnv<'tcx>, } @@ -417,12 +417,12 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let mut indices = self.compute_indices(fr_static, defining_ty); debug!("build: indices={:?}", indices); - let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.did.to_def_id()); + let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.to_def_id()); // If this is a 'root' body (not a closure/generator/inline const), then // there are no extern regions, so the local regions start at the same // position as the (empty) sub-list of extern regions - let first_local_index = if self.mir_def.did.to_def_id() == typeck_root_def_id { + let first_local_index = if self.mir_def.to_def_id() == typeck_root_def_id { first_extern_index } else { // If this is a closure, generator, or inline-const, then the late-bound regions from the enclosing @@ -433,7 +433,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { // } for_each_late_bound_region_in_recursive_scope( self.infcx.tcx, - self.infcx.tcx.local_parent(self.mir_def.did), + self.infcx.tcx.local_parent(self.mir_def), |r| { debug!(?r); if !indices.indices.contains_key(&r) { @@ -462,13 +462,13 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let inputs_and_output = self.infcx.replace_bound_regions_with_nll_infer_vars( FR, - self.mir_def.did, + self.mir_def, bound_inputs_and_output, &mut indices, ); // Converse of above, if this is a function/closure then the late-bound regions declared on its // signature are local. - for_each_late_bound_region_in_item(self.infcx.tcx, self.mir_def.did, |r| { + for_each_late_bound_region_in_item(self.infcx.tcx, self.mir_def, |r| { debug!(?r); if !indices.indices.contains_key(&r) { let region_vid = { @@ -492,7 +492,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { if self.infcx.tcx.fn_sig(def_id).skip_binder().c_variadic() { let va_list_did = self.infcx.tcx.require_lang_item( LangItem::VaList, - Some(self.infcx.tcx.def_span(self.mir_def.did)), + Some(self.infcx.tcx.def_span(self.mir_def)), ); let reg_vid = self @@ -544,11 +544,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { /// see `DefiningTy` for details. fn defining_ty(&self) -> DefiningTy<'tcx> { let tcx = self.infcx.tcx; - let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id()); + let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id()); - match tcx.hir().body_owner_kind(self.mir_def.did) { + match tcx.hir().body_owner_kind(self.mir_def) { BodyOwnerKind::Closure | BodyOwnerKind::Fn => { - let defining_ty = tcx.type_of(self.mir_def.def_id_for_type_of()).subst_identity(); + let defining_ty = tcx.type_of(self.mir_def).subst_identity(); debug!("defining_ty (pre-replacement): {:?}", defining_ty); @@ -562,9 +562,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { } ty::FnDef(def_id, substs) => DefiningTy::FnDef(def_id, substs), _ => span_bug!( - tcx.def_span(self.mir_def.did), + tcx.def_span(self.mir_def), "expected defining type for `{:?}`: `{:?}`", - self.mir_def.did, + self.mir_def, defining_ty ), } @@ -572,10 +572,10 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { BodyOwnerKind::Const | BodyOwnerKind::Static(..) => { let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id); - if self.mir_def.did.to_def_id() == typeck_root_def_id { + if self.mir_def.to_def_id() == typeck_root_def_id { let substs = self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_substs); - DefiningTy::Const(self.mir_def.did.to_def_id(), substs) + DefiningTy::Const(self.mir_def.to_def_id(), substs) } else { // FIXME this line creates a dependency between borrowck and typeck. // @@ -587,15 +587,15 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { // below), so that `type_of(inline_const_def_id).substs(substs)` uses the // proper type with NLL infer vars. let ty = tcx - .typeck(self.mir_def.did) - .node_type(tcx.local_def_id_to_hir_id(self.mir_def.did)); + .typeck(self.mir_def) + .node_type(tcx.local_def_id_to_hir_id(self.mir_def)); let substs = InlineConstSubsts::new( tcx, InlineConstSubstsParts { parent_substs: identity_substs, ty }, ) .substs; let substs = self.infcx.replace_free_regions_with_nll_infer_vars(FR, substs); - DefiningTy::InlineConst(self.mir_def.did.to_def_id(), substs) + DefiningTy::InlineConst(self.mir_def.to_def_id(), substs) } } } @@ -611,7 +611,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { defining_ty: DefiningTy<'tcx>, ) -> UniversalRegionIndices<'tcx> { let tcx = self.infcx.tcx; - let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id()); + let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id()); let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id); let fr_substs = match defining_ty { DefiningTy::Closure(_, substs) @@ -647,7 +647,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let tcx = self.infcx.tcx; match defining_ty { DefiningTy::Closure(def_id, substs) => { - assert_eq!(self.mir_def.did.to_def_id(), def_id); + assert_eq!(self.mir_def.to_def_id(), def_id); let closure_sig = substs.as_closure().sig(); let inputs_and_output = closure_sig.inputs_and_output(); let bound_vars = tcx.mk_bound_variable_kinds_from_iter( @@ -682,7 +682,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { } DefiningTy::Generator(def_id, substs, movability) => { - assert_eq!(self.mir_def.did.to_def_id(), def_id); + assert_eq!(self.mir_def.to_def_id(), def_id); let resume_ty = substs.as_generator().resume_ty(); let output = substs.as_generator().return_ty(); let generator_ty = tcx.mk_generator(def_id, substs, movability); @@ -700,14 +700,14 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { DefiningTy::Const(def_id, _) => { // For a constant body, there are no inputs, and one // "output" (the type of the constant). - assert_eq!(self.mir_def.did.to_def_id(), def_id); - let ty = tcx.type_of(self.mir_def.def_id_for_type_of()).subst_identity(); + assert_eq!(self.mir_def.to_def_id(), def_id); + let ty = tcx.type_of(self.mir_def).subst_identity(); let ty = indices.fold_to_region_vids(tcx, ty); ty::Binder::dummy(tcx.mk_type_list(&[ty])) } DefiningTy::InlineConst(def_id, substs) => { - assert_eq!(self.mir_def.did.to_def_id(), def_id); + assert_eq!(self.mir_def.to_def_id(), def_id); let ty = substs.as_inline_const().ty(); ty::Binder::dummy(tcx.mk_type_list(&[ty])) } diff --git a/compiler/rustc_const_eval/src/util/collect_writes.rs b/compiler/rustc_borrowck/src/util/collect_writes.rs similarity index 100% rename from compiler/rustc_const_eval/src/util/collect_writes.rs rename to compiler/rustc_borrowck/src/util/collect_writes.rs diff --git a/compiler/rustc_borrowck/src/util/mod.rs b/compiler/rustc_borrowck/src/util/mod.rs new file mode 100644 index 000000000000..7377d4de7274 --- /dev/null +++ b/compiler/rustc_borrowck/src/util/mod.rs @@ -0,0 +1,3 @@ +mod collect_writes; + +pub use collect_writes::FindAssignments; diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index 336e14ef9663..5f6441660e3b 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -17,6 +17,7 @@ rustc_feature = { path = "../rustc_feature" } rustc_lexer = { path = "../rustc_lexer" } rustc_lint_defs = { path = "../rustc_lint_defs" } rustc_macros = { path = "../rustc_macros" } +rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_parse_format = { path = "../rustc_parse_format" } rustc_parse = { path = "../rustc_parse" } rustc_session = { path = "../rustc_session" } diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 83dc1ac50e55..74049406426e 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -149,3 +149,25 @@ builtin_macros_format_pos_mismatch = {$n} positional {$n -> [one] argument *[more] arguments } in format string, but {$desc} + +builtin_macros_offset_of_expected_field = expected field + +builtin_macros_offset_of_expected_two_args = expected 2 arguments + +builtin_macros_test_case_non_item = `#[test_case]` attribute is only allowed on items + +builtin_macros_test_bad_fn = {$kind} functions cannot be used for tests + .label = `{$kind}` because of this + +builtin_macros_asm_explicit_register_name = explicit register arguments cannot have names + +builtin_macros_asm_mutually_exclusive = the `{$opt1}` and `{$opt2}` options are mutually exclusive + +builtin_macros_asm_pure_combine = the `pure` option must be combined with either `nomem` or `readonly` + +builtin_macros_asm_pure_no_output = asm with the `pure` option must have at least one output + +builtin_macros_asm_modifier_invalid = asm template modifier must be a single character + +builtin_macros_test_runner_invalid = `test_runner` argument must be a path +builtin_macros_test_runner_nargs = `#![test_runner(..)]` accepts exactly 1 argument diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 8c1579baacb0..bcdd58a09016 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -15,6 +15,8 @@ use rustc_span::{InnerSpan, Span}; use rustc_target::asm::InlineAsmArch; use smallvec::smallvec; +use crate::errors; + pub struct AsmArgs { pub templates: Vec>, pub operands: Vec<(ast::InlineAsmOperand, Span)>, @@ -205,7 +207,7 @@ pub fn parse_asm_args<'a>( // of the argument available. if explicit_reg { if name.is_some() { - diag.struct_span_err(span, "explicit register arguments cannot have names").emit(); + diag.emit_err(errors::AsmExplicitRegisterName { span }); } args.reg_args.insert(slot); } else if let Some(name) = name { @@ -240,25 +242,19 @@ pub fn parse_asm_args<'a>( && args.options.contains(ast::InlineAsmOptions::READONLY) { let spans = args.options_spans.clone(); - diag.struct_span_err(spans, "the `nomem` and `readonly` options are mutually exclusive") - .emit(); + diag.emit_err(errors::AsmMutuallyExclusive { spans, opt1: "nomem", opt2: "readonly" }); } if args.options.contains(ast::InlineAsmOptions::PURE) && args.options.contains(ast::InlineAsmOptions::NORETURN) { let spans = args.options_spans.clone(); - diag.struct_span_err(spans, "the `pure` and `noreturn` options are mutually exclusive") - .emit(); + diag.emit_err(errors::AsmMutuallyExclusive { spans, opt1: "pure", opt2: "noreturn" }); } if args.options.contains(ast::InlineAsmOptions::PURE) && !args.options.intersects(ast::InlineAsmOptions::NOMEM | ast::InlineAsmOptions::READONLY) { let spans = args.options_spans.clone(); - diag.struct_span_err( - spans, - "the `pure` option must be combined with either `nomem` or `readonly`", - ) - .emit(); + diag.emit_err(errors::AsmPureCombine { spans }); } let mut have_real_output = false; @@ -285,11 +281,7 @@ pub fn parse_asm_args<'a>( } } if args.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output { - diag.struct_span_err( - args.options_spans.clone(), - "asm with the `pure` option must have at least one output", - ) - .emit(); + diag.emit_err(errors::AsmPureNoOutput { spans: args.options_spans.clone() }); } if args.options.contains(ast::InlineAsmOptions::NORETURN) && !outputs_sp.is_empty() { let err = diag @@ -705,11 +697,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option Context<'cx, 'a> { | ExprKind::If(_, _, _) | ExprKind::IncludedBytes(..) | ExprKind::InlineAsm(_) + | ExprKind::OffsetOf(_, _) | ExprKind::Let(_, _, _) | ExprKind::Lit(_) | ExprKind::Loop(_, _, _) diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 630f9b87bc3e..b146988a3c23 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -551,3 +551,71 @@ pub(crate) struct FormatPositionalMismatch { #[subdiagnostic] pub(crate) highlight: SingleLabelManySpans, } + +#[derive(Diagnostic)] +#[diag(builtin_macros_test_case_non_item)] +pub(crate) struct TestCaseNonItem { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_test_bad_fn)] +pub(crate) struct TestBadFn { + #[primary_span] + pub(crate) span: Span, + #[label] + pub(crate) cause: Span, + pub(crate) kind: &'static str, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_asm_explicit_register_name)] +pub(crate) struct AsmExplicitRegisterName { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_asm_mutually_exclusive)] +pub(crate) struct AsmMutuallyExclusive { + #[primary_span] + pub(crate) spans: Vec, + pub(crate) opt1: &'static str, + pub(crate) opt2: &'static str, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_asm_pure_combine)] +pub(crate) struct AsmPureCombine { + #[primary_span] + pub(crate) spans: Vec, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_asm_pure_no_output)] +pub(crate) struct AsmPureNoOutput { + #[primary_span] + pub(crate) spans: Vec, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_asm_modifier_invalid)] +pub(crate) struct AsmModifierInvalid { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_test_runner_invalid)] +pub(crate) struct TestRunnerInvalid { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_test_runner_nargs)] +pub(crate) struct TestRunnerNargs { + #[primary_span] + pub(crate) span: Span, +} diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index f0fc61d7c4f2..f17df5b0a83c 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -141,13 +141,7 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult< args: args .named_args() .iter() - .filter_map(|a| { - if let Some(ident) = a.kind.ident() { - Some((a, ident)) - } else { - None - } - }) + .filter_map(|a| a.kind.ident().map(|ident| (a, ident))) .map(|(arg, n)| n.span.to(arg.expr.span)) .collect(), }); diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 37fbd03a6a21..8f86ef44aa3a 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -24,7 +24,7 @@ use crate::deriving::*; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind}; use rustc_expand::proc_macro::BangProcMacro; -use rustc_macros::fluent_messages; +use rustc_fluent_macro::fluent_messages; use rustc_span::symbol::sym; mod alloc_error_handler; @@ -45,6 +45,7 @@ mod format; mod format_foreign; mod global_allocator; mod log_syntax; +mod offset_of; mod source_util; mod test; mod trace_macros; @@ -92,6 +93,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { line: source_util::expand_line, log_syntax: log_syntax::expand_log_syntax, module_path: source_util::expand_mod, + offset_of: offset_of::expand_offset_of, option_env: env::expand_option_env, core_panic: edition_panic::expand_panic, std_panic: edition_panic::expand_panic, diff --git a/compiler/rustc_builtin_macros/src/offset_of.rs b/compiler/rustc_builtin_macros/src/offset_of.rs new file mode 100644 index 000000000000..0ef3e000e414 --- /dev/null +++ b/compiler/rustc_builtin_macros/src/offset_of.rs @@ -0,0 +1,99 @@ +use rustc_ast as ast; +use rustc_ast::ptr::P; +use rustc_ast::token; +use rustc_ast::tokenstream::TokenStream; +use rustc_errors::PResult; +use rustc_expand::base::{self, *}; +use rustc_macros::Diagnostic; +use rustc_parse::parser::Parser; +use rustc_span::{symbol::Ident, Span}; + +#[derive(Diagnostic)] +#[diag(builtin_macros_offset_of_expected_field)] +struct ExpectedField { + #[primary_span] + span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_offset_of_expected_two_args)] +struct ExpectedTwoArgs { + #[primary_span] + span: Span, +} + +fn parse_field<'a>(cx: &ExtCtxt<'a>, p: &mut Parser<'a>) -> PResult<'a, Ident> { + let token = p.token.uninterpolate(); + let field = match token.kind { + token::Ident(name, _) => Ident::new(name, token.span), + token::Literal(token::Lit { kind: token::Integer, symbol, suffix: None }) => { + Ident::new(symbol, token.span) + } + _ => return Err(cx.create_err(ExpectedField { span: p.token.span })), + }; + + p.bump(); + + Ok(field) +} + +fn parse_args<'a>( + cx: &mut ExtCtxt<'a>, + sp: Span, + tts: TokenStream, +) -> PResult<'a, (P, P<[Ident]>)> { + let mut p = cx.new_parser_from_tts(tts); + + let container = p.parse_ty()?; + + p.expect(&token::Comma)?; + + if p.eat(&token::Eof) { + return Err(cx.create_err(ExpectedTwoArgs { span: sp })); + } + + let mut fields = Vec::new(); + + loop { + let field = parse_field(cx, &mut p)?; + fields.push(field); + + if p.eat(&token::Dot) { + continue; + } + + p.eat(&token::Comma); + + if !p.eat(&token::Eof) { + return Err(cx.create_err(ExpectedTwoArgs { span: sp })); + } + + break; + } + + Ok((container, fields.into())) +} + +pub fn expand_offset_of<'cx>( + cx: &'cx mut ExtCtxt<'_>, + sp: Span, + tts: TokenStream, +) -> Box { + match parse_args(cx, sp, tts) { + Ok((container, fields)) => { + let expr = P(ast::Expr { + id: ast::DUMMY_NODE_ID, + kind: ast::ExprKind::OffsetOf(container, fields), + span: sp, + attrs: ast::AttrVec::new(), + tokens: None, + }); + + MacEager::expr(expr) + } + Err(mut err) => { + err.emit(); + DummyResult::any(sp) + } + } +} diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 79d8be2484b5..49ee276af4e6 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -1,3 +1,4 @@ +use crate::errors; /// The expansion from a test function to the appropriate test struct for libtest /// Ideally, this code would be in libtest but for efficiency and error messages it lives here. use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute}; @@ -40,12 +41,7 @@ pub fn expand_test_case( unreachable!() }, _ => { - ecx.struct_span_err( - anno_item.span(), - "`#[test_case]` attribute is only allowed on items", - ) - .emit(); - + ecx.emit_err(errors::TestCaseNonItem { span: anno_item.span() }); return vec![]; } }; @@ -533,15 +529,11 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { match &i.kind { ast::ItemKind::Fn(box ast::Fn { sig, generics, .. }) => { if let ast::Unsafe::Yes(span) = sig.header.unsafety { - sd.struct_span_err(i.span, "unsafe functions cannot be used for tests") - .span_label(span, "`unsafe` because of this") - .emit(); + sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "unsafe" }); return false; } if let ast::Async::Yes { span, .. } = sig.header.asyncness { - sd.struct_span_err(i.span, "async functions cannot be used for tests") - .span_label(span, "`async` because of this") - .emit(); + sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" }); return false; } diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 80f497333a63..be4ba66c082a 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -19,6 +19,8 @@ use tracing::debug; use std::{iter, mem}; +use crate::errors; + #[derive(Clone)] struct Test { span: Span, @@ -385,11 +387,11 @@ fn get_test_runner(sd: &rustc_errors::Handler, krate: &ast::Crate) -> Option match single.meta_item() { Some(meta_item) if meta_item.is_word() => return Some(meta_item.path.clone()), _ => { - sd.struct_span_err(span, "`test_runner` argument must be a path").emit(); + sd.emit_err(errors::TestRunnerInvalid { span }); } }, _ => { - sd.struct_span_err(span, "`#![test_runner(..)]` accepts exactly 1 argument").emit(); + sd.emit_err(errors::TestRunnerNargs { span }); } } None diff --git a/compiler/rustc_codegen_cranelift/.github/actions/github-release/README.md b/compiler/rustc_codegen_cranelift/.github/actions/github-release/README.md new file mode 100644 index 000000000000..c70ba8f49538 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/.github/actions/github-release/README.md @@ -0,0 +1,18 @@ +# github-release + +An action used to publish GitHub releases for `wasmtime`. + +As of the time of this writing there's a few actions floating around which +perform github releases but they all tend to have their set of drawbacks. +Additionally nothing handles deleting releases which we need for our rolling +`dev` release. + +To handle all this this action rolls-its-own implementation using the +actions/toolkit repository and packages published there. These run in a Docker +container and take various inputs to orchestrate the release from the build. + +More comments can be found in `main.js`. + +Testing this is really hard. If you want to try though run `npm install` and +then `node main.js`. You'll have to configure a bunch of env vars though to get +anything reasonably working. diff --git a/compiler/rustc_codegen_cranelift/.github/actions/github-release/action.yml b/compiler/rustc_codegen_cranelift/.github/actions/github-release/action.yml new file mode 100644 index 000000000000..36e5209f50c3 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/.github/actions/github-release/action.yml @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +name: 'rustc_codegen_cranelift github releases' +description: 'rustc_codegen_cranelift github releases' +inputs: + token: + description: '' + required: true + files: + description: '' + required: true +runs: + using: 'node16' + main: 'main.js' diff --git a/compiler/rustc_codegen_cranelift/.github/actions/github-release/main.js b/compiler/rustc_codegen_cranelift/.github/actions/github-release/main.js new file mode 100644 index 000000000000..6fcfca34ea77 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/.github/actions/github-release/main.js @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +const core = require('@actions/core'); +const path = require("path"); +const fs = require("fs"); +const github = require('@actions/github'); +const glob = require('glob'); + +function sleep(milliseconds) { + return new Promise(resolve => setTimeout(resolve, milliseconds)) +} + +async function runOnce() { + // Load all our inputs and env vars. Note that `getInput` reads from `INPUT_*` + const files = core.getInput('files'); + const token = core.getInput('token'); + const slug = process.env.GITHUB_REPOSITORY; + const owner = slug.split('/')[0]; + const repo = slug.split('/')[1]; + const sha = process.env.GITHUB_SHA; + let name = 'dev'; + if (process.env.GITHUB_REF.startsWith('refs/tags/v')) { + name = process.env.GITHUB_REF.substring(10); + } + + core.info(`files: ${files}`); + core.info(`name: ${name}`); + core.info(`token: ${token}`); + + const octokit = github.getOctokit(token); + + // For the `dev` release we may need to update the tag to point to the new + // commit on this branch. All other names should already have tags associated + // with them. + if (name == 'dev') { + let tag = null; + try { + tag = await octokit.request("GET /repos/:owner/:repo/git/refs/tags/:name", { owner, repo, name }); + core.info(`found existing tag`); + console.log("tag: ", JSON.stringify(tag.data, null, 2)); + } catch (e) { + // ignore if this tag doesn't exist + core.info(`no existing tag found`); + } + + if (tag === null || tag.data.object.sha !== sha) { + core.info(`updating existing tag or creating new one`); + + try { + core.info(`updating dev tag`); + await octokit.rest.git.updateRef({ + owner, + repo, + ref: 'tags/dev', + sha, + force: true, + }); + } catch (e) { + console.log("ERROR: ", JSON.stringify(e.data, null, 2)); + core.info(`creating dev tag`); + try { + await octokit.rest.git.createRef({ + owner, + repo, + ref: 'refs/tags/dev', + sha, + }); + } catch (e) { + // we might race with others, so assume someone else has created the + // tag by this point. + console.log("failed to create tag: ", JSON.stringify(e.data, null, 2)); + } + } + + console.log("double-checking tag is correct"); + tag = await octokit.request("GET /repos/:owner/:repo/git/refs/tags/:name", { owner, repo, name }); + if (tag.data.object.sha !== sha) { + console.log("tag: ", JSON.stringify(tag.data, null, 2)); + throw new Error("tag didn't work"); + } + } else { + core.info(`existing tag works`); + } + } + + // Delete a previous release + try { + core.info(`fetching release`); + let release = await octokit.rest.repos.getReleaseByTag({ owner, repo, tag: name }); + console.log("found release: ", JSON.stringify(release.data, null, 2)); + await octokit.rest.repos.deleteRelease({ + owner, + repo, + release_id: release.data.id, + }); + console.log("deleted release"); + } catch (e) { + console.log("ERROR: ", JSON.stringify(e, null, 2)); + } + + console.log("creating a release"); + let release = await octokit.rest.repos.createRelease({ + owner, + repo, + tag_name: name, + prerelease: name === 'dev', + }); + + // Delete all assets from a previous run + for (const asset of release.data.assets) { + console.log(`deleting prior asset ${asset.id}`); + await octokit.rest.repos.deleteReleaseAsset({ + owner, + repo, + asset_id: asset.id, + }); + } + + // Upload all the relevant assets for this release as just general blobs. + for (const file of glob.sync(files)) { + const size = fs.statSync(file).size; + const name = path.basename(file); + core.info(`upload ${file}`); + await octokit.rest.repos.uploadReleaseAsset({ + data: fs.createReadStream(file), + headers: { 'content-length': size, 'content-type': 'application/octet-stream' }, + name, + url: release.data.upload_url, + }); + } +} + +async function run() { + const retries = 10; + for (let i = 0; i < retries; i++) { + try { + await runOnce(); + break; + } catch (e) { + if (i === retries - 1) + throw e; + logError(e); + console.log("RETRYING after 10s"); + await sleep(10000) + } + } +} + +function logError(e) { + console.log("ERROR: ", e.message); + try { + console.log(JSON.stringify(e, null, 2)); + } catch (e) { + // ignore json errors for now + } + console.log(e.stack); +} + +run().catch(err => { + logError(err); + core.setFailed(err.message); +}); diff --git a/compiler/rustc_codegen_cranelift/.github/actions/github-release/package-lock.json b/compiler/rustc_codegen_cranelift/.github/actions/github-release/package-lock.json new file mode 100644 index 000000000000..dd3b2a048f09 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/.github/actions/github-release/package-lock.json @@ -0,0 +1,571 @@ +{ + "name": "rustc_codegen_cranelift-github-release", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "rustc_codegen_cranelift-github-release", + "version": "0.0.0", + "dependencies": { + "@actions/core": "^1.9.1", + "@actions/github": "^5.1.0", + "glob": "^7.1.5" + } + }, + "node_modules/@actions/core": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", + "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", + "dependencies": { + "@actions/http-client": "^2.0.1", + "uuid": "^8.3.2" + } + }, + "node_modules/@actions/github": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz", + "integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==", + "dependencies": { + "@actions/http-client": "^2.0.1", + "@octokit/core": "^3.6.0", + "@octokit/plugin-paginate-rest": "^2.17.0", + "@octokit/plugin-rest-endpoint-methods": "^5.13.0" + } + }, + "node_modules/@actions/http-client": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz", + "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==", + "dependencies": { + "tunnel": "^0.0.6" + } + }, + "node_modules/@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "dependencies": { + "@octokit/types": "^6.0.3" + } + }, + "node_modules/@octokit/core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", + "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", + "dependencies": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.3", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "dependencies": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "dependencies": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "12.11.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "2.21.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", + "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", + "dependencies": { + "@octokit/types": "^6.40.0" + }, + "peerDependencies": { + "@octokit/core": ">=2" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", + "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", + "dependencies": { + "@octokit/types": "^6.39.0", + "deprecation": "^2.3.1" + }, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/request": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", + "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", + "dependencies": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "dependencies": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "node_modules/@octokit/types": { + "version": "6.41.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", + "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", + "dependencies": { + "@octokit/openapi-types": "^12.11.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + } + }, + "dependencies": { + "@actions/core": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", + "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", + "requires": { + "@actions/http-client": "^2.0.1", + "uuid": "^8.3.2" + } + }, + "@actions/github": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz", + "integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==", + "requires": { + "@actions/http-client": "^2.0.1", + "@octokit/core": "^3.6.0", + "@octokit/plugin-paginate-rest": "^2.17.0", + "@octokit/plugin-rest-endpoint-methods": "^5.13.0" + } + }, + "@actions/http-client": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz", + "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==", + "requires": { + "tunnel": "^0.0.6" + } + }, + "@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "requires": { + "@octokit/types": "^6.0.3" + } + }, + "@octokit/core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", + "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", + "requires": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.3", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "requires": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "requires": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/openapi-types": { + "version": "12.11.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" + }, + "@octokit/plugin-paginate-rest": { + "version": "2.21.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", + "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", + "requires": { + "@octokit/types": "^6.40.0" + } + }, + "@octokit/plugin-rest-endpoint-methods": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", + "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", + "requires": { + "@octokit/types": "^6.39.0", + "deprecation": "^2.3.1" + } + }, + "@octokit/request": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", + "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", + "requires": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "requires": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "@octokit/types": { + "version": "6.41.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", + "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", + "requires": { + "@octokit/openapi-types": "^12.11.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" + }, + "universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + } + } +} diff --git a/compiler/rustc_codegen_cranelift/.github/actions/github-release/package.json b/compiler/rustc_codegen_cranelift/.github/actions/github-release/package.json new file mode 100644 index 000000000000..d9c23f8873ec --- /dev/null +++ b/compiler/rustc_codegen_cranelift/.github/actions/github-release/package.json @@ -0,0 +1,11 @@ +{ + "name": "rustc_codegen_cranelift-github-release", + "version": "0.0.0", + "license": "Apache-2.0 WITH LLVM-exception", + "main": "main.js", + "dependencies": { + "@actions/core": "^1.9.1", + "@actions/github": "^5.1.0", + "glob": "^7.1.5" + } +} diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml b/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml index 5f5510a57965..3c40555669cb 100644 --- a/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml +++ b/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml @@ -45,13 +45,6 @@ jobs: if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu' run: rustup set default-host x86_64-pc-windows-gnu - - name: Use sparse cargo registry - run: | - cat >> ~/.cargo/config.toml <> ~/.cargo/config.toml <> ~/.cargo/config.toml <> ~/.cargo/config.toml <> ~/.cargo/config.toml <> ~/.cargo/config.toml < Self { + fn new(dirs: Dirs, mut target_compiler: Compiler, is_native: bool) -> Self { if let Ok(rustflags) = env::var("RUSTFLAGS") { target_compiler.rustflags.push(' '); target_compiler.rustflags.push_str(&rustflags); @@ -297,7 +304,7 @@ impl TestRunner { Self { is_native, jit_supported, dirs, target_compiler } } - pub fn run_testsuite(&self, tests: &[TestCase]) { + fn run_testsuite(&self, tests: &[TestCase]) { for TestCase { config, cmd } in tests { let (tag, testname) = config.split_once('.').unwrap(); let tag = tag.to_uppercase(); @@ -382,7 +389,7 @@ impl TestRunner { spawn_and_wait(self.rustc_command(args)); } - fn run_out_command<'a>(&self, name: &str, args: &[&str]) { + fn run_out_command(&self, name: &str, args: &[&str]) { let mut full_cmd = vec![]; // Prepend the RUN_WRAPPER's diff --git a/compiler/rustc_codegen_cranelift/example/alloc_example.rs b/compiler/rustc_codegen_cranelift/example/alloc_example.rs index 4ede2fe4efe8..d994e2fbc0ae 100644 --- a/compiler/rustc_codegen_cranelift/example/alloc_example.rs +++ b/compiler/rustc_codegen_cranelift/example/alloc_example.rs @@ -18,7 +18,7 @@ extern "C" { } #[panic_handler] -fn panic_handler(_: &core::panic::PanicInfo) -> ! { +fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! { core::intrinsics::abort(); } diff --git a/compiler/rustc_codegen_cranelift/example/arbitrary_self_types_pointers_and_wrappers.rs b/compiler/rustc_codegen_cranelift/example/arbitrary_self_types_pointers_and_wrappers.rs index d270fec6b711..f7edfa960a22 100644 --- a/compiler/rustc_codegen_cranelift/example/arbitrary_self_types_pointers_and_wrappers.rs +++ b/compiler/rustc_codegen_cranelift/example/arbitrary_self_types_pointers_and_wrappers.rs @@ -3,8 +3,8 @@ #![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)] use std::{ - ops::{Deref, CoerceUnsized, DispatchFromDyn}, marker::Unsize, + ops::{CoerceUnsized, Deref, DispatchFromDyn}, }; struct Ptr(Box); @@ -33,7 +33,6 @@ impl Deref for Wrapper { impl, U> CoerceUnsized> for Wrapper {} impl, U> DispatchFromDyn> for Wrapper {} - trait Trait { // This method isn't object-safe yet. Unsized by-value `self` is object-safe (but not callable // without unsized_locals), but wrappers around `Self` currently are not. diff --git a/compiler/rustc_codegen_cranelift/example/dst-field-align.rs b/compiler/rustc_codegen_cranelift/example/dst-field-align.rs index 6c338e99912e..22fc6ff33e33 100644 --- a/compiler/rustc_codegen_cranelift/example/dst-field-align.rs +++ b/compiler/rustc_codegen_cranelift/example/dst-field-align.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] struct Foo { a: u16, - b: T + b: T, } trait Bar { @@ -10,58 +10,57 @@ trait Bar { } impl Bar for usize { - fn get(&self) -> usize { *self } + fn get(&self) -> usize { + *self + } } struct Baz { - a: T + a: T, } struct HasDrop { ptr: Box, - data: T + data: T, } fn main() { // Test that zero-offset works properly - let b : Baz = Baz { a: 7 }; + let b: Baz = Baz { a: 7 }; assert_eq!(b.a.get(), 7); - let b : &Baz = &b; + let b: &Baz = &b; assert_eq!(b.a.get(), 7); // Test that the field is aligned properly - let f : Foo = Foo { a: 0, b: 11 }; + let f: Foo = Foo { a: 0, b: 11 }; assert_eq!(f.b.get(), 11); - let ptr1 : *const u8 = &f.b as *const _ as *const u8; + let ptr1: *const u8 = &f.b as *const _ as *const u8; - let f : &Foo = &f; - let ptr2 : *const u8 = &f.b as *const _ as *const u8; + let f: &Foo = &f; + let ptr2: *const u8 = &f.b as *const _ as *const u8; assert_eq!(f.b.get(), 11); // The pointers should be the same assert_eq!(ptr1, ptr2); // Test that nested DSTs work properly - let f : Foo> = Foo { a: 0, b: Foo { a: 1, b: 17 }}; + let f: Foo> = Foo { a: 0, b: Foo { a: 1, b: 17 } }; assert_eq!(f.b.b.get(), 17); - let f : &Foo> = &f; + let f: &Foo> = &f; assert_eq!(f.b.b.get(), 17); // Test that get the pointer via destructuring works - let f : Foo = Foo { a: 0, b: 11 }; - let f : &Foo = &f; + let f: Foo = Foo { a: 0, b: 11 }; + let f: &Foo = &f; let &Foo { a: _, b: ref bar } = f; assert_eq!(bar.get(), 11); // Make sure that drop flags don't screw things up - let d : HasDrop> = HasDrop { - ptr: Box::new(0), - data: Baz { a: [1,2,3,4] } - }; - assert_eq!([1,2,3,4], d.data.a); + let d: HasDrop> = HasDrop { ptr: Box::new(0), data: Baz { a: [1, 2, 3, 4] } }; + assert_eq!([1, 2, 3, 4], d.data.a); - let d : &HasDrop> = &d; - assert_eq!(&[1,2,3,4], &d.data.a); + let d: &HasDrop> = &d; + assert_eq!(&[1, 2, 3, 4], &d.data.a); } diff --git a/compiler/rustc_codegen_cranelift/example/example.rs b/compiler/rustc_codegen_cranelift/example/example.rs index d5c122bf681f..885e55bc7642 100644 --- a/compiler/rustc_codegen_cranelift/example/example.rs +++ b/compiler/rustc_codegen_cranelift/example/example.rs @@ -11,11 +11,7 @@ pub fn abc(a: u8) -> u8 { } pub fn bcd(b: bool, a: u8) -> u8 { - if b { - a * 2 - } else { - a * 3 - } + if b { a * 2 } else { a * 3 } } pub fn call() { diff --git a/compiler/rustc_codegen_cranelift/example/issue-72793.rs b/compiler/rustc_codegen_cranelift/example/issue-72793.rs index b1bb9b8e1e73..166b00600438 100644 --- a/compiler/rustc_codegen_cranelift/example/issue-72793.rs +++ b/compiler/rustc_codegen_cranelift/example/issue-72793.rs @@ -2,7 +2,9 @@ #![feature(type_alias_impl_trait)] -trait T { type Item; } +trait T { + type Item; +} type Alias<'a> = impl T; diff --git a/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs b/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs index 039100696331..6f39c5edcad2 100644 --- a/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs +++ b/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs @@ -40,10 +40,7 @@ impl ListImpl { } } -pub static A: ListImpl = ListImpl { - len: 3, - data: [5, 6, 7], -}; +pub static A: ListImpl = ListImpl { len: 3, data: [5, 6, 7] }; pub static A_REF: &'static List = A.as_list(); pub static A_TAIL_OFFSET: isize = tail_offset(A.as_list()); diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs index 73b83b89f6d9..ea97e9f060e0 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs @@ -37,13 +37,13 @@ impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} pub trait DispatchFromDyn {} // &T -> &U -impl<'a, T: ?Sized+Unsize, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {} +impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {} // &mut T -> &mut U -impl<'a, T: ?Sized+Unsize, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {} +impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut T {} // *const T -> *const U -impl, U: ?Sized> DispatchFromDyn<*const U> for *const T {} +impl, U: ?Sized> DispatchFromDyn<*const U> for *const T {} // *mut T -> *mut U -impl, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {} +impl, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {} impl, U: ?Sized> DispatchFromDyn> for Box {} #[lang = "receiver"] @@ -288,7 +288,6 @@ impl PartialEq for u32 { } } - impl PartialEq for u64 { fn eq(&self, other: &u64) -> bool { (*self) == (*other) @@ -361,7 +360,7 @@ impl PartialEq for *const T { } } -impl PartialEq for Option { +impl PartialEq for Option { fn eq(&self, other: &Self) -> bool { match (self, other) { (Some(lhs), Some(rhs)) => *lhs == *rhs, @@ -472,7 +471,20 @@ pub fn panic(_msg: &'static str) -> ! { #[track_caller] fn panic_bounds_check(index: usize, len: usize) -> ! { unsafe { - libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index); + libc::printf( + "index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, + len, + index, + ); + intrinsics::abort(); + } +} + +#[lang = "panic_cannot_unwind"] +#[track_caller] +fn panic_cannot_unwind() -> ! { + unsafe { + libc::puts("panic in a function that cannot unwind\n\0" as *const str as *const i8); intrinsics::abort(); } } @@ -599,7 +611,7 @@ pub mod libc { // functions. legacy_stdio_definitions.lib which provides the printf wrapper functions as normal // symbols to link against. #[cfg_attr(unix, link(name = "c"))] - #[cfg_attr(target_env="msvc", link(name="legacy_stdio_definitions"))] + #[cfg_attr(target_env = "msvc", link(name = "legacy_stdio_definitions"))] extern "C" { pub fn printf(format: *const i8, ...) -> i32; } @@ -638,7 +650,7 @@ impl Index for [T] { } } -extern { +extern "C" { type VaListImpl; } @@ -648,23 +660,33 @@ pub struct VaList<'a>(&'a mut VaListImpl); #[rustc_builtin_macro] #[rustc_macro_transparency = "semitransparent"] -pub macro stringify($($t:tt)*) { /* compiler built-in */ } +pub macro stringify($($t:tt)*) { + /* compiler built-in */ +} #[rustc_builtin_macro] #[rustc_macro_transparency = "semitransparent"] -pub macro file() { /* compiler built-in */ } +pub macro file() { + /* compiler built-in */ +} #[rustc_builtin_macro] #[rustc_macro_transparency = "semitransparent"] -pub macro line() { /* compiler built-in */ } +pub macro line() { + /* compiler built-in */ +} #[rustc_builtin_macro] #[rustc_macro_transparency = "semitransparent"] -pub macro cfg() { /* compiler built-in */ } +pub macro cfg() { + /* compiler built-in */ +} #[rustc_builtin_macro] #[rustc_macro_transparency = "semitransparent"] -pub macro global_asm() { /* compiler built-in */ } +pub macro global_asm() { + /* compiler built-in */ +} pub static A_STATIC: u8 = 42; @@ -676,7 +698,7 @@ struct PanicLocation { } #[no_mangle] -#[cfg(not(windows))] +#[cfg(not(all(windows, target_env = "gnu")))] pub fn get_tls() -> u8 { #[thread_local] static A: u8 = 42; diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index 6ad3268e70dd..5a55aa215bfd 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -319,7 +319,7 @@ fn main() { from_decimal_string(); - #[cfg(not(any(jit, windows)))] + #[cfg(all(not(jit), not(all(windows, target_env = "gnu"))))] test_tls(); #[cfg(all(not(jit), target_arch = "x86_64", any(target_os = "linux", target_os = "darwin")))] @@ -524,6 +524,7 @@ pub enum E1 { // Computing the discriminant used to be done using the niche type (here `u8`, // from the `bool` field of `V1`), overflowing for variants with large enough // indices (`V3` and `V4`), causing them to be interpreted as other variants. +#[rustfmt::skip] pub enum E2 { V1 { f: bool }, diff --git a/compiler/rustc_codegen_cranelift/example/mod_bench.rs b/compiler/rustc_codegen_cranelift/example/mod_bench.rs index e3e8a3c2d6ab..f15e48acc41e 100644 --- a/compiler/rustc_codegen_cranelift/example/mod_bench.rs +++ b/compiler/rustc_codegen_cranelift/example/mod_bench.rs @@ -3,15 +3,15 @@ #[cfg_attr(unix, link(name = "c"))] #[cfg_attr(target_env = "msvc", link(name = "msvcrt"))] -extern {} +extern "C" {} #[panic_handler] -fn panic_handler(_: &core::panic::PanicInfo) -> ! { +fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! { core::intrinsics::abort(); } -#[lang="eh_personality"] -fn eh_personality(){} +#[lang = "eh_personality"] +fn eh_personality() {} // Required for rustc_codegen_llvm #[no_mangle] diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs index e34b35d5c4a8..ab4045d11a66 100644 --- a/compiler/rustc_codegen_cranelift/example/std_example.rs +++ b/compiler/rustc_codegen_cranelift/example/std_example.rs @@ -1,4 +1,4 @@ -#![feature(core_intrinsics, generators, generator_trait, is_sorted)] +#![feature(core_intrinsics, generators, generator_trait, is_sorted, repr_simd)] #[cfg(target_arch = "x86_64")] use std::arch::x86_64::*; @@ -56,7 +56,10 @@ fn main() { assert_eq!(0b0000000000000000000000000010000010000000000000000000000000000000_0000000000100000000000000000000000001000000000000100000000000000u128.leading_zeros(), 26); assert_eq!(0b0000000000000000000000000010000000000000000000000000000000000000_0000000000000000000000000000000000001000000000000000000010000000u128.trailing_zeros(), 7); - assert_eq!(core::intrinsics::saturating_sub(0, -170141183460469231731687303715884105728i128), 170141183460469231731687303715884105727i128); + assert_eq!( + core::intrinsics::saturating_sub(0, -170141183460469231731687303715884105728i128), + 170141183460469231731687303715884105727i128 + ); std::hint::black_box(std::hint::black_box(7571400400375753350092698930310845914i128) * 10); assert!(0i128.checked_div(2i128).is_some()); @@ -113,7 +116,9 @@ fn main() { Box::pin(move |mut _task_context| { yield (); - }).as_mut().resume(0); + }) + .as_mut() + .resume(0); #[derive(Copy, Clone)] enum Nums { @@ -148,12 +153,20 @@ fn main() { enum Never {} } + + foo(I64X2(0, 0)); } fn panic(_: u128) { panic!(); } +#[repr(simd)] +struct I64X2(i64, i64); + +#[allow(improper_ctypes_definitions)] +extern "C" fn foo(_a: I64X2) {} + #[cfg(target_arch = "x86_64")] #[target_feature(enable = "sse2")] unsafe fn test_simd() { @@ -168,7 +181,10 @@ unsafe fn test_simd() { let (zero0, zero1) = std::mem::transmute::<_, (u64, u64)>(x); assert_eq!((zero0, zero1), (0, 0)); assert_eq!(std::mem::transmute::<_, [u16; 8]>(or), [7, 7, 7, 7, 7, 7, 7, 7]); - assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_eq), [0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff]); + assert_eq!( + std::mem::transmute::<_, [u16; 8]>(cmp_eq), + [0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff] + ); assert_eq!(std::mem::transmute::<_, [u16; 8]>(cmp_lt), [0, 0, 0, 0, 0, 0, 0, 0]); test_mm_slli_si128(); @@ -182,6 +198,7 @@ unsafe fn test_simd() { test_mm_extract_epi8(); test_mm_insert_epi16(); + #[rustfmt::skip] let mask1 = _mm_movemask_epi8(dbg!(_mm_setr_epi8(255u8 as i8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))); assert_eq!(mask1, 1); } @@ -343,7 +360,7 @@ fn test_checked_mul() { #[derive(PartialEq)] enum LoopState { Continue(()), - Break(()) + Break(()), } pub enum Instruction { diff --git a/compiler/rustc_codegen_cranelift/example/subslice-patterns-const-eval.rs b/compiler/rustc_codegen_cranelift/example/subslice-patterns-const-eval.rs index 2cb84786f56d..3c8789166639 100644 --- a/compiler/rustc_codegen_cranelift/example/subslice-patterns-const-eval.rs +++ b/compiler/rustc_codegen_cranelift/example/subslice-patterns-const-eval.rs @@ -19,7 +19,9 @@ macro_rules! n { // This macro has an unused variable so that it can be repeated base on the // number of times a repeated variable (`$e` in `z`) occurs. macro_rules! zed { - ($e:expr) => { Z } + ($e:expr) => { + Z + }; } macro_rules! z { @@ -32,12 +34,14 @@ macro_rules! z { macro_rules! compare_evaluation { ($e:expr, $t:ty $(,)?) => {{ const CONST_EVAL: $t = $e; - const fn const_eval() -> $t { $e } + const fn const_eval() -> $t { + $e + } static CONST_EVAL2: $t = const_eval(); let runtime_eval = $e; assert_eq!(CONST_EVAL, runtime_eval); assert_eq!(CONST_EVAL2, runtime_eval); - }} + }}; } // Repeat `$test`, substituting the given macro variables with the given @@ -65,6 +69,7 @@ macro_rules! repeat { } } +#[rustfmt::skip] fn main() { repeat! { ($arr $Ty); n, N; z, Z: diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index 2236a6ca1552..59ad80c3207d 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-03-15" +channel = "nightly-2023-04-29" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs b/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs index 939a1f1ca590..e2db7d03a9d3 100644 --- a/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs +++ b/compiler/rustc_codegen_cranelift/scripts/cargo-clif.rs @@ -64,7 +64,7 @@ fn main() { }; #[cfg(unix)] - Command::new("cargo").args(args).exec(); + panic!("Failed to spawn cargo: {}", Command::new("cargo").args(args).exec()); #[cfg(not(unix))] std::process::exit( diff --git a/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs b/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs index b9bba7f2e084..ab496a4a6844 100644 --- a/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs +++ b/compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs @@ -15,22 +15,24 @@ fn main() { env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX, ); - let mut args = std::env::args_os().skip(1).collect::>(); + let passed_args = std::env::args_os().skip(1).collect::>(); + let mut args = vec![]; args.push(OsString::from("-Cpanic=abort")); args.push(OsString::from("-Zpanic-abort-tests")); let mut codegen_backend_arg = OsString::from("-Zcodegen-backend="); codegen_backend_arg.push(cg_clif_dylib_path); args.push(codegen_backend_arg); - if !args.contains(&OsString::from("--sysroot")) { + if !passed_args.contains(&OsString::from("--sysroot")) { args.push(OsString::from("--sysroot")); args.push(OsString::from(sysroot.to_str().unwrap())); } + args.extend(passed_args); // Ensure that the right toolchain is used env::set_var("RUSTUP_TOOLCHAIN", env!("TOOLCHAIN_NAME")); #[cfg(unix)] - Command::new("rustc").args(args).exec(); + panic!("Failed to spawn rustc: {}", Command::new("rustc").args(args).exec()); #[cfg(not(unix))] std::process::exit( diff --git a/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs b/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs index 167631eaf7ee..545844446c50 100644 --- a/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs +++ b/compiler/rustc_codegen_cranelift/scripts/rustdoc-clif.rs @@ -15,22 +15,24 @@ fn main() { env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX, ); - let mut args = std::env::args_os().skip(1).collect::>(); + let passed_args = std::env::args_os().skip(1).collect::>(); + let mut args = vec![]; args.push(OsString::from("-Cpanic=abort")); args.push(OsString::from("-Zpanic-abort-tests")); let mut codegen_backend_arg = OsString::from("-Zcodegen-backend="); codegen_backend_arg.push(cg_clif_dylib_path); args.push(codegen_backend_arg); - if !args.contains(&OsString::from("--sysroot")) { + if !passed_args.contains(&OsString::from("--sysroot")) { args.push(OsString::from("--sysroot")); args.push(OsString::from(sysroot.to_str().unwrap())); } + args.extend(passed_args); // Ensure that the right toolchain is used env::set_var("RUSTUP_TOOLCHAIN", env!("TOOLCHAIN_NAME")); #[cfg(unix)] - Command::new("rustdoc").args(args).exec(); + panic!("Failed to spawn rustdoc: {}", Command::new("rustdoc").args(args).exec()); #[cfg(not(unix))] std::process::exit( diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index 20dcb4cf34d2..1329d3ea076b 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -10,7 +10,8 @@ pushd rust command -v rg >/dev/null 2>&1 || cargo install ripgrep -rm -r tests/ui/{extern/,unsized-locals/,lto/,linkage*} || true +# FIXME add needs-asm-support to all tests in tests/ui/asm +rm -r tests/ui/{unsized-locals/,lto/,linkage*} || true for test in $(rg --files-with-matches "lto|// needs-asm-support|// needs-unwind" tests/{codegen-units,ui,incremental}); do rm $test done @@ -27,13 +28,24 @@ rm tests/ui/parser/unclosed-delimiter-in-dep.rs # submodule contains //~ERROR # ================ # requires stack unwinding +# FIXME add needs-unwind to these tests rm tests/incremental/change_crate_dep_kind.rs rm tests/incremental/issue-80691-bad-eval-cache.rs # -Cpanic=abort causes abort instead of exit(101) +rm -r tests/run-make/c-unwind-abi-catch-lib-panic +rm -r tests/run-make/c-unwind-abi-catch-panic +rm -r tests/run-make/debug-assertions +rm -r tests/run-make/foreign-double-unwind +rm -r tests/run-make/foreign-exceptions +rm -r tests/run-make/foreign-rust-exceptions +rm -r tests/run-make/libtest-json +rm -r tests/run-make/static-unwinding # requires compiling with -Cpanic=unwind rm -r tests/ui/macros/rfc-2011-nicer-assert-messages/ rm -r tests/run-make/test-benches rm tests/ui/test-attrs/test-type.rs +rm -r tests/run-make/const_fn_mir +rm -r tests/run-make/intrinsic-unreachable # vendor intrinsics rm tests/ui/sse2.rs # cpuid not supported, so sse2 not detected @@ -49,6 +61,7 @@ rm tests/incremental/hashes/statics.rs # same # variadic arguments rm tests/ui/abi/mir/mir_codegen_calls_variadic.rs # requires float varargs rm tests/ui/abi/variadic-ffi.rs # requires callee side vararg support +rm -r tests/run-make/c-link-to-rust-va-list-fn # requires callee side vararg support # unsized locals rm -r tests/run-pass-valgrind/unsized-locals @@ -59,6 +72,19 @@ rm tests/ui/target-feature/missing-plusminus.rs # error not implemented rm tests/ui/fn/dyn-fn-alignment.rs # wants a 256 byte alignment rm -r tests/run-make/emit-named-files # requires full --emit support rm -r tests/run-make/repr128-dwarf # debuginfo test +rm -r tests/run-make/split-debuginfo # same +rm -r tests/run-make/symbols-include-type-name # --emit=asm not supported +rm -r tests/run-make/target-specs # i686 not supported by Cranelift +rm -r tests/run-make/mismatching-target-triples # same +rm -r tests/run-make/use-extern-for-plugins # same + +# requires LTO +rm -r tests/run-make/cdylib +rm -r tests/run-make/issue-14500 +rm -r tests/run-make/issue-64153 +rm -r tests/run-make/codegen-options-parsing +rm -r tests/run-make/lto-* +rm -r tests/run-make/reproducible-build-2 # optimization tests # ================== @@ -70,7 +96,14 @@ rm -r tests/run-make/fmt-write-bloat/ # tests an optimization # backend specific tests # ====================== rm tests/incremental/thinlto/cgu_invalidated_when_import_{added,removed}.rs # requires LLVM +rm -r tests/run-make/cross-lang-lto # same +rm -r tests/run-make/issue-7349 # same +rm -r tests/run-make/sepcomp-inlining # same +rm -r tests/run-make/sepcomp-separate # same +rm -r tests/run-make/sepcomp-cci-copies # same +rm -r tests/run-make/volatile-intrinsics # same rm tests/ui/abi/stack-protector.rs # requires stack protector support +rm -r tests/run-make/emit-stack-sizes # requires support for -Z emit-stack-sizes # giving different but possibly correct results # ============================================= @@ -95,13 +128,12 @@ rm tests/ui/proc-macro/no-missing-docs.rs # same rm tests/ui/rust-2018/proc-macro-crate-in-paths.rs # same rm tests/ui/proc-macro/allowed-signatures.rs # same +# rustdoc-clif passes extra args, suppressing the help message when no args are passed +rm -r tests/run-make/issue-88756-default-output + # doesn't work due to the way the rustc test suite is invoked. # should work when using ./x.py test the way it is intended # ============================================================ -rm -r tests/run-make/emit-shared-files # requires the rustdoc executable in dist/bin/ -rm -r tests/run-make/unstable-flag-required # same -rm -r tests/run-make/rustdoc-* # same -rm -r tests/run-make/issue-88756-default-output # same rm -r tests/run-make/remap-path-prefix-dwarf # requires llvm-dwarfdump rm -r tests/ui/consts/missing_span_in_backtrace.rs # expects sysroot source to be elsewhere @@ -112,17 +144,41 @@ rm tests/incremental/spike-neg2.rs # same rm tests/ui/simd/intrinsic/generic-reduction-pass.rs # simd_reduce_add_unordered doesn't accept an accumulator for integer vectors -rm tests/ui/simd/intrinsic/generic-as.rs # crash when accessing vector type field (#1318) rm tests/ui/simd/simd-bitmask.rs # crash +rm -r tests/run-make/issue-51671 # wrong filename given in case of --emit=obj +rm -r tests/run-make/issue-30063 # same +rm -r tests/run-make/multiple-emits # same +rm -r tests/run-make/output-type-permutations # same +rm -r tests/run-make/used # same + # bugs in the test suite # ====================== rm tests/ui/backtrace.rs # TODO warning -rm tests/ui/simple_global_asm.rs # TODO add needs-asm-support rm tests/ui/process/nofile-limit.rs # TODO some AArch64 linking issue rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd +cp ../dist/bin/rustdoc-clif ../dist/bin/rustdoc # some tests expect bin/rustdoc to exist + +# prevent $(RUSTDOC) from picking up the sysroot built by x.py. It conflicts with the one used by +# rustdoc-clif +cat <) { @@ -91,35 +89,7 @@ pub(super) fn add_local_place_comments<'tcx>( largest_niche: _, } = layout.0.0; - let (kind, extra) = match *place.inner() { - CPlaceInner::Var(place_local, var) => { - assert_eq!(local, place_local); - ("ssa", Cow::Owned(format!(",var={}", var.index()))) - } - CPlaceInner::VarPair(place_local, var1, var2) => { - assert_eq!(local, place_local); - ("ssa", Cow::Owned(format!("var=({}, {})", var1.index(), var2.index()))) - } - CPlaceInner::VarLane(_local, _var, _lane) => unreachable!(), - CPlaceInner::Addr(ptr, meta) => { - let meta = if let Some(meta) = meta { - Cow::Owned(format!("meta={}", meta)) - } else { - Cow::Borrowed("") - }; - match ptr.debug_base_and_offset() { - (crate::pointer::PointerBase::Addr(addr), offset) => { - ("reuse", format!("storage={}{}{}", addr, offset, meta).into()) - } - (crate::pointer::PointerBase::Stack(stack_slot), offset) => { - ("stack", format!("storage={}{}{}", stack_slot, offset, meta).into()) - } - (crate::pointer::PointerBase::Dangling(align), offset) => { - ("zst", format!("align={},offset={}", align.bytes(), offset).into()) - } - } - } - }; + let (kind, extra) = place.debug_comment(); fx.add_global_comment(format!( "{:<5} {:5} {:30} {:4}b {}, {}{}{}", diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 91c085d3d698..e533afcfaa94 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -70,7 +70,7 @@ pub(crate) fn get_function_sig<'tcx>( default_call_conv: CallConv, inst: Instance<'tcx>, ) -> Signature { - assert!(!inst.substs.needs_infer()); + assert!(!inst.substs.has_infer()); clif_sig_from_fn_abi( tcx, default_call_conv, @@ -605,9 +605,9 @@ pub(crate) fn codegen_drop<'tcx>( // | ... | // \-------/ // - let (ptr, vtable) = drop_place.to_ptr_maybe_unsized(); + let (ptr, vtable) = drop_place.to_ptr_unsized(); let ptr = ptr.get_addr(fx); - let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable.unwrap()); + let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable); // FIXME(eddyb) perhaps move some of this logic into // `Instance::resolve_drop_in_place`? diff --git a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs index e5ad31eb9484..d847e524f8cf 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs @@ -84,7 +84,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { attrs )], Abi::Vector { .. } => { - let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout).unwrap(); + let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout); smallvec![AbiParam::new(vector_ty)] } _ => unreachable!("{:?}", self.layout.abi), @@ -135,7 +135,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { (None, vec![AbiParam::new(scalar_to_clif_type(tcx, scalar))]) } Abi::Vector { .. } => { - let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout).unwrap(); + let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout); (None, vec![AbiParam::new(vector_ty)]) } _ => unreachable!("{:?}", self.layout.abi), diff --git a/compiler/rustc_codegen_cranelift/src/abi/returning.rs b/compiler/rustc_codegen_cranelift/src/abi/returning.rs index 6d3e8eda276a..14e54d5ee381 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/returning.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/returning.rs @@ -9,7 +9,7 @@ use smallvec::{smallvec, SmallVec}; /// this adds an extra parameter pointing to where the return value needs to be stored. pub(super) fn codegen_return_param<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, - ssa_analyzed: &rustc_index::vec::IndexVec, + ssa_analyzed: &rustc_index::IndexSlice, block_params_iter: &mut impl Iterator, ) -> CPlace<'tcx> { let (ret_place, ret_param): (_, SmallVec<[_; 2]>) = match fx.fn_abi.as_ref().unwrap().ret.mode { @@ -63,11 +63,11 @@ pub(super) fn codegen_with_call_return_arg<'tcx>( let (ret_temp_place, return_ptr) = match ret_arg_abi.mode { PassMode::Ignore => (None, None), PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => { - if matches!(ret_place.inner(), CPlaceInner::Addr(_, None)) { + if let Some(ret_ptr) = ret_place.try_to_ptr() { // This is an optimization to prevent unnecessary copies of the return value when // the return place is already a memory place as opposed to a register. // This match arm can be safely removed. - (None, Some(ret_place.to_ptr().get_addr(fx))) + (None, Some(ret_ptr.get_addr(fx))) } else { let place = CPlace::new_stack_slot(fx, ret_arg_abi.layout); (Some(place), Some(place.to_ptr().get_addr(fx))) diff --git a/compiler/rustc_codegen_cranelift/src/analyze.rs b/compiler/rustc_codegen_cranelift/src/analyze.rs index 54d5c1c2ae9e..359d581c1535 100644 --- a/compiler/rustc_codegen_cranelift/src/analyze.rs +++ b/compiler/rustc_codegen_cranelift/src/analyze.rs @@ -2,7 +2,7 @@ use crate::prelude::*; -use rustc_index::vec::IndexVec; +use rustc_index::IndexVec; use rustc_middle::mir::StatementKind::*; use rustc_middle::ty::Ty; diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index f5301f9f7f10..a259a4f30b27 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -1,7 +1,7 @@ //! Codegen of a single function use rustc_ast::InlineAsmOptions; -use rustc_index::vec::IndexVec; +use rustc_index::IndexVec; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -28,7 +28,7 @@ pub(crate) fn codegen_fn<'tcx>( module: &mut dyn Module, instance: Instance<'tcx>, ) -> CodegenedFunction { - debug_assert!(!instance.substs.needs_infer()); + debug_assert!(!instance.substs.has_infer()); let symbol_name = tcx.symbol_name(instance).name.to_string(); let _timer = tcx.prof.generic_activity_with_arg("codegen fn", &*symbol_name); @@ -141,16 +141,6 @@ pub(crate) fn compile_fn( context.clear(); context.func = codegened_func.func; - // If the return block is not reachable, then the SSA builder may have inserted an `iconst.i128` - // instruction, which doesn't have an encoding. - context.compute_cfg(); - context.compute_domtree(); - context.eliminate_unreachable_code(module.isa()).unwrap(); - context.dce(module.isa()).unwrap(); - // Some Cranelift optimizations expect the domtree to not yet be computed and as such don't - // invalidate it when it would change. - context.domtree.clear(); - #[cfg(any())] // This is never true let _clif_guard = { use std::fmt::Write; @@ -182,27 +172,6 @@ pub(crate) fn compile_fn( cx.profiler.generic_activity("define function").run(|| { context.want_disasm = cx.should_write_ir; module.define_function(codegened_func.func_id, context).unwrap(); - - if cx.profiler.enabled() { - let mut recording_args = false; - cx.profiler - .generic_activity_with_arg_recorder( - "define function (clif pass timings)", - |recorder| { - let pass_times = cranelift_codegen::timing::take_current(); - // Replace newlines with | as measureme doesn't allow control characters like - // newlines inside strings. - recorder.record_arg(format!("{}", pass_times).replace('\n', " | ")); - recording_args = true; - }, - ) - .run(|| { - if recording_args { - // Wait a tiny bit to ensure chrome's profiler doesn't hide the event - std::thread::sleep(std::time::Duration::from_nanos(2)) - } - }); - } }); if cx.should_write_ir { @@ -216,7 +185,7 @@ pub(crate) fn compile_fn( &clif_comments, ); - if let Some(disasm) = &context.compiled_code().unwrap().disasm { + if let Some(disasm) = &context.compiled_code().unwrap().vcode { crate::pretty_clif::write_ir_file( &cx.output_filenames, &format!("{}.vcode", codegened_func.symbol_name), @@ -524,13 +493,14 @@ fn codegen_stmt<'tcx>( fx.set_debug_loc(stmt.source_info); - #[cfg(any())] // This is never true match &stmt.kind { StatementKind::StorageLive(..) | StatementKind::StorageDead(..) => {} // Those are not very useful _ => { if fx.clif_comments.enabled() { let inst = fx.bcx.func.layout.last_inst(cur_block).unwrap(); - fx.add_comment(inst, format!("{:?}", stmt)); + with_no_trimmed_paths!({ + fx.add_comment(inst, format!("{:?}", stmt)); + }); } } } @@ -715,11 +685,11 @@ fn codegen_stmt<'tcx>( } Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), ref operand, _to_ty) => { let operand = codegen_operand(fx, operand); - operand.unsize_value(fx, lval); + crate::unsize::coerce_unsized_into(fx, operand, lval); } Rvalue::Cast(CastKind::DynStar, ref operand, _) => { let operand = codegen_operand(fx, operand); - operand.coerce_dyn_star(fx, lval); + crate::unsize::coerce_dyn_star(fx, operand, lval); } Rvalue::Cast(CastKind::Transmute, ref operand, _to_ty) => { let operand = codegen_operand(fx, operand); @@ -781,14 +751,20 @@ fn codegen_stmt<'tcx>( let operand = operand.load_scalar(fx); lval.write_cvalue(fx, CValue::by_val(operand, box_layout)); } - Rvalue::NullaryOp(null_op, ty) => { + Rvalue::NullaryOp(ref null_op, ty) => { assert!(lval.layout().ty.is_sized(fx.tcx, ParamEnv::reveal_all())); let layout = fx.layout_of(fx.monomorphize(ty)); let val = match null_op { NullOp::SizeOf => layout.size.bytes(), NullOp::AlignOf => layout.align.abi.bytes(), + NullOp::OffsetOf(fields) => { + layout.offset_of_subfield(fx, fields.iter().map(|f| f.index())).bytes() + } }; - let val = CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), val.into()); + let val = CValue::by_val( + fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(val).unwrap()), + fx.layout_of(fx.tcx.types.usize), + ); lval.write_cvalue(fx, val); } Rvalue::Aggregate(ref kind, ref operands) => { @@ -863,9 +839,7 @@ fn codegen_array_len<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, place: CPlace<'tcx let len = fx.monomorphize(len).eval_target_usize(fx.tcx, ParamEnv::reveal_all()) as i64; fx.bcx.ins().iconst(fx.pointer_type, len) } - ty::Slice(_elem_ty) => { - place.to_ptr_maybe_unsized().1.expect("Length metadata for slice place") - } + ty::Slice(_elem_ty) => place.to_ptr_unsized().1, _ => bug!("Rvalue::Len({:?})", place), } } @@ -919,8 +893,7 @@ pub(crate) fn codegen_place<'tcx>( ty::Slice(elem_ty) => { assert!(from_end, "slice subslices should be `from_end`"); let elem_layout = fx.layout_of(*elem_ty); - let (ptr, len) = cplace.to_ptr_maybe_unsized(); - let len = len.unwrap(); + let (ptr, len) = cplace.to_ptr_unsized(); cplace = CPlace::for_ptr_with_extra( ptr.offset_i64(fx, elem_layout.size.bytes() as i64 * (from as i64)), fx.bcx.ins().iadd_imm(len, -(from as i64 + to as i64)), diff --git a/compiler/rustc_codegen_cranelift/src/cast.rs b/compiler/rustc_codegen_cranelift/src/cast.rs index 032d1151041d..6bf3a866ba46 100644 --- a/compiler/rustc_codegen_cranelift/src/cast.rs +++ b/compiler/rustc_codegen_cranelift/src/cast.rs @@ -103,7 +103,7 @@ pub(crate) fn clif_int_or_float_cast( vec![AbiParam::new(types::I64X2)], &[from], )[0]; - // FIXME use bitcast instead of store to get from i64x2 to i128 + // FIXME(bytecodealliance/wasmtime#6104) use bitcast instead of store to get from i64x2 to i128 let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { kind: StackSlotKind::ExplicitSlot, size: 16, diff --git a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs index f674ce776a68..f751d8c179db 100644 --- a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs +++ b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs @@ -7,7 +7,6 @@ use crate::prelude::*; pub(crate) fn maybe_codegen<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, bin_op: BinOp, - checked: bool, lhs: CValue<'tcx>, rhs: CValue<'tcx>, ) -> Option> { @@ -22,47 +21,97 @@ pub(crate) fn maybe_codegen<'tcx>( let is_signed = type_sign(lhs.layout().ty); match bin_op { - BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => { - assert!(!checked); - None + BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => None, + BinOp::Add | BinOp::Sub => None, + BinOp::Mul => { + let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)]; + let ret_val = fx.lib_call( + "__multi3", + vec![AbiParam::new(types::I128), AbiParam::new(types::I128)], + vec![AbiParam::new(types::I128)], + &args, + )[0]; + Some(CValue::by_val( + ret_val, + fx.layout_of(if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }), + )) } - BinOp::Add | BinOp::Sub if !checked => None, - BinOp::Mul if !checked || is_signed => { - if !checked { + BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"), + BinOp::Div | BinOp::Rem => { + let name = match (bin_op, is_signed) { + (BinOp::Div, false) => "__udivti3", + (BinOp::Div, true) => "__divti3", + (BinOp::Rem, false) => "__umodti3", + (BinOp::Rem, true) => "__modti3", + _ => unreachable!(), + }; + if fx.tcx.sess.target.is_like_windows { + let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)]; + let ret = fx.lib_call( + name, + vec![AbiParam::new(types::I128), AbiParam::new(types::I128)], + vec![AbiParam::new(types::I64X2)], + &args, + )[0]; + // FIXME(bytecodealliance/wasmtime#6104) use bitcast instead of store to get from i64x2 to i128 + let ret_place = CPlace::new_stack_slot(fx, lhs.layout()); + ret_place.to_ptr().store(fx, ret, MemFlags::trusted()); + Some(ret_place.to_cvalue(fx)) + } else { let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)]; let ret_val = fx.lib_call( - "__multi3", + name, vec![AbiParam::new(types::I128), AbiParam::new(types::I128)], vec![AbiParam::new(types::I128)], &args, )[0]; - Some(CValue::by_val( - ret_val, - fx.layout_of(if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }), - )) - } else { - let out_ty = fx.tcx.mk_tup(&[lhs.layout().ty, fx.tcx.types.bool]); - let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32)); - let lhs = lhs.load_scalar(fx); - let rhs = rhs.load_scalar(fx); - let oflow_ptr = oflow.to_ptr().get_addr(fx); - let res = fx.lib_call_unadjusted( - "__muloti4", - vec![ - AbiParam::new(types::I128), - AbiParam::new(types::I128), - AbiParam::new(fx.pointer_type), - ], - vec![AbiParam::new(types::I128)], - &[lhs, rhs, oflow_ptr], - )[0]; - let oflow = oflow.to_cvalue(fx).load_scalar(fx); - let oflow = fx.bcx.ins().ireduce(types::I8, oflow); - Some(CValue::by_val_pair(res, oflow, fx.layout_of(out_ty))) + Some(CValue::by_val(ret_val, lhs.layout())) } } + BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => None, + BinOp::Shl | BinOp::Shr => None, + } +} + +pub(crate) fn maybe_codegen_checked<'tcx>( + fx: &mut FunctionCx<'_, '_, 'tcx>, + bin_op: BinOp, + lhs: CValue<'tcx>, + rhs: CValue<'tcx>, +) -> Option> { + if lhs.layout().ty != fx.tcx.types.u128 + && lhs.layout().ty != fx.tcx.types.i128 + && rhs.layout().ty != fx.tcx.types.u128 + && rhs.layout().ty != fx.tcx.types.i128 + { + return None; + } + + let is_signed = type_sign(lhs.layout().ty); + + match bin_op { + BinOp::BitAnd | BinOp::BitOr | BinOp::BitXor => unreachable!(), + BinOp::Mul if is_signed => { + let out_ty = fx.tcx.mk_tup(&[lhs.layout().ty, fx.tcx.types.bool]); + let oflow = CPlace::new_stack_slot(fx, fx.layout_of(fx.tcx.types.i32)); + let lhs = lhs.load_scalar(fx); + let rhs = rhs.load_scalar(fx); + let oflow_ptr = oflow.to_ptr().get_addr(fx); + let res = fx.lib_call_unadjusted( + "__muloti4", + vec![ + AbiParam::new(types::I128), + AbiParam::new(types::I128), + AbiParam::new(fx.pointer_type), + ], + vec![AbiParam::new(types::I128)], + &[lhs, rhs, oflow_ptr], + )[0]; + let oflow = oflow.to_cvalue(fx).load_scalar(fx); + let oflow = fx.bcx.ins().ireduce(types::I8, oflow); + Some(CValue::by_val_pair(res, oflow, fx.layout_of(out_ty))) + } BinOp::Add | BinOp::Sub | BinOp::Mul => { - assert!(checked); let out_ty = fx.tcx.mk_tup(&[lhs.layout().ty, fx.tcx.types.bool]); let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty)); let param_types = vec![ @@ -83,42 +132,8 @@ pub(crate) fn maybe_codegen<'tcx>( Some(out_place.to_cvalue(fx)) } BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"), - BinOp::Div | BinOp::Rem => { - assert!(!checked); - let name = match (bin_op, is_signed) { - (BinOp::Div, false) => "__udivti3", - (BinOp::Div, true) => "__divti3", - (BinOp::Rem, false) => "__umodti3", - (BinOp::Rem, true) => "__modti3", - _ => unreachable!(), - }; - if fx.tcx.sess.target.is_like_windows { - let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)]; - let ret = fx.lib_call( - name, - vec![AbiParam::new(types::I128), AbiParam::new(types::I128)], - vec![AbiParam::new(types::I64X2)], - &args, - )[0]; - // FIXME use bitcast instead of store to get from i64x2 to i128 - let ret_place = CPlace::new_stack_slot(fx, lhs.layout()); - ret_place.to_ptr().store(fx, ret, MemFlags::trusted()); - Some(ret_place.to_cvalue(fx)) - } else { - let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)]; - let ret_val = fx.lib_call( - name, - vec![AbiParam::new(types::I128), AbiParam::new(types::I128)], - vec![AbiParam::new(types::I128)], - &args, - )[0]; - Some(CValue::by_val(ret_val, lhs.layout())) - } - } - BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => { - assert!(!checked); - None - } - BinOp::Shl | BinOp::Shr => None, + BinOp::Div | BinOp::Rem => unreachable!(), + BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => unreachable!(), + BinOp::Shl | BinOp::Shr => unreachable!(), } } diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index d39bf700035f..30f4cf4473c6 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -2,7 +2,7 @@ use cranelift_codegen::isa::TargetFrontendConfig; use gimli::write::FileId; use rustc_data_structures::sync::Lrc; -use rustc_index::vec::IndexVec; +use rustc_index::IndexVec; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, }; @@ -72,19 +72,6 @@ fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { - let (element, count) = match &tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().abi - { - Abi::Vector { element, count } => (*element, *count), - _ => unreachable!(), - }; - - match scalar_to_clif_type(tcx, element).by(u32::try_from(count).unwrap()) { - // Cranelift currently only implements icmp for 128bit vectors. - Some(vector_ty) if vector_ty.bits() == 128 => vector_ty, - _ => return None, - } - } ty::Param(_) => bug!("ty param {:?}", ty), _ => return None, }) @@ -96,12 +83,7 @@ fn clif_pair_type_from_ty<'tcx>( ) -> Option<(types::Type, types::Type)> { Some(match ty.kind() { ty::Tuple(types) if types.len() == 2 => { - let a = clif_type_from_ty(tcx, types[0])?; - let b = clif_type_from_ty(tcx, types[1])?; - if a.is_vector() || b.is_vector() { - return None; - } - (a, b) + (clif_type_from_ty(tcx, types[0])?, clif_type_from_ty(tcx, types[1])?) } ty::RawPtr(TypeAndMut { ty: pointee_ty, mutbl: _ }) | ty::Ref(_, pointee_ty, _) => { if has_ptr_meta(tcx, *pointee_ty) { @@ -431,7 +413,11 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { // Note: must be kept in sync with get_caller_location from cg_ssa pub(crate) fn get_caller_location(&mut self, mut source_info: mir::SourceInfo) -> CValue<'tcx> { - let span_to_caller_location = |fx: &mut FunctionCx<'_, '_, 'tcx>, span: Span| { + let span_to_caller_location = |fx: &mut FunctionCx<'_, '_, 'tcx>, mut span: Span| { + // Remove `Inlined` marks as they pollute `expansion_cause`. + while span.is_inlined() { + span.remove_mark(); + } let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span); let caller = fx.tcx.sess.source_map().lookup_char_pos(topmost.lo()); let const_loc = fx.tcx.const_caller_location(( diff --git a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs index 203219a8a754..54df04f8c2c4 100644 --- a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs +++ b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs @@ -25,8 +25,18 @@ impl ConcurrencyLimiter { .clone() .into_helper_thread(move |token| { let mut state = state_helper.lock().unwrap(); - state.add_new_token(token.unwrap()); - available_token_condvar_helper.notify_one(); + match token { + Ok(token) => { + state.add_new_token(token); + available_token_condvar_helper.notify_one(); + } + Err(err) => { + state.poison(format!("failed to acquire jobserver token: {}", err)); + // Notify all threads waiting for a token to give them a chance to + // gracefully exit. + available_token_condvar_helper.notify_all(); + } + } }) .unwrap(); ConcurrencyLimiter { @@ -37,16 +47,31 @@ impl ConcurrencyLimiter { } } - pub(super) fn acquire(&mut self) -> ConcurrencyLimiterToken { + pub(super) fn acquire(&mut self, handler: &rustc_errors::Handler) -> ConcurrencyLimiterToken { let mut state = self.state.lock().unwrap(); loop { state.assert_invariants(); - if state.try_start_job() { - return ConcurrencyLimiterToken { - state: self.state.clone(), - available_token_condvar: self.available_token_condvar.clone(), - }; + match state.try_start_job() { + Ok(true) => { + return ConcurrencyLimiterToken { + state: self.state.clone(), + available_token_condvar: self.available_token_condvar.clone(), + }; + } + Ok(false) => {} + Err(err) => { + // An error happened when acquiring the token. Raise it as fatal error. + // Make sure to drop the mutex guard first to prevent poisoning the mutex. + drop(state); + if let Some(err) = err { + handler.fatal(&err).raise(); + } else { + // The error was already emitted, but compilation continued. Raise a silent + // fatal error. + rustc_errors::FatalError.raise(); + } + } } self.helper_thread.as_mut().unwrap().request_token(); @@ -100,13 +125,22 @@ mod state { pending_jobs: usize, active_jobs: usize, + poisoned: bool, + stored_error: Option, + // None is used to represent the implicit token, Some to represent explicit tokens tokens: Vec>, } impl ConcurrencyLimiterState { pub(super) fn new(pending_jobs: usize) -> Self { - ConcurrencyLimiterState { pending_jobs, active_jobs: 0, tokens: vec![None] } + ConcurrencyLimiterState { + pending_jobs, + active_jobs: 0, + poisoned: false, + stored_error: None, + tokens: vec![None], + } } pub(super) fn assert_invariants(&self) { @@ -127,14 +161,18 @@ mod state { self.drop_excess_capacity(); } - pub(super) fn try_start_job(&mut self) -> bool { + pub(super) fn try_start_job(&mut self) -> Result> { + if self.poisoned { + return Err(self.stored_error.take()); + } + if self.active_jobs < self.tokens.len() { // Using existing token self.job_started(); - return true; + return Ok(true); } - false + Ok(false) } pub(super) fn job_started(&mut self) { @@ -161,6 +199,11 @@ mod state { self.assert_invariants(); } + pub(super) fn poison(&mut self, error: String) { + self.poisoned = true; + self.stored_error = Some(error); + } + fn drop_excess_capacity(&mut self) { self.assert_invariants(); diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index e87f4e258911..bf5d29c16f66 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -91,7 +91,7 @@ pub(crate) fn eval_mir_constant<'tcx>( ), }, ConstantKind::Unevaluated(mir::UnevaluatedConst { def, .. }, _) - if fx.tcx.is_static(def.did) => + if fx.tcx.is_static(def) => { span_bug!(constant.span, "MIR constant refers to static"); } @@ -159,6 +159,8 @@ pub(crate) fn codegen_const_value<'tcx>( _ => unreachable!(), }; + // FIXME avoid this extra copy to the stack and directly write to the final + // destination let place = CPlace::new_stack_slot(fx, layout); place.to_ptr().store(fx, val, MemFlags::trusted()); place.to_cvalue(fx) diff --git a/compiler/rustc_codegen_cranelift/src/discriminant.rs b/compiler/rustc_codegen_cranelift/src/discriminant.rs index f740945a03c3..670384663e83 100644 --- a/compiler/rustc_codegen_cranelift/src/discriminant.rs +++ b/compiler/rustc_codegen_cranelift/src/discriminant.rs @@ -103,7 +103,6 @@ pub(crate) fn codegen_get_discriminant<'tcx>( } }; - let cast_to_size = dest_layout.layout.size(); let cast_to = fx.clif_type(dest_layout.ty).unwrap(); // Read the tag/niche-encoded discriminant from memory. @@ -122,21 +121,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>( dest.write_cvalue(fx, res); } TagEncoding::Niche { untagged_variant, ref niche_variants, niche_start } => { - let tag_size = tag_scalar.size(fx); - let max_unsigned = tag_size.unsigned_int_max(); - let max_signed = tag_size.signed_int_max() as u128; - let min_signed = max_signed + 1; let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32(); - let niche_end = niche_start.wrapping_add(relative_max as u128) & max_unsigned; - let range = tag_scalar.valid_range(fx); - - let sle = |lhs: u128, rhs: u128| -> bool { - // Signed and unsigned comparisons give the same results, - // except that in signed comparisons an integer with the - // sign bit set is less than one with the sign bit clear. - // Toggle the sign bit to do a signed comparison. - (lhs ^ min_signed) <= (rhs ^ min_signed) - }; // We have a subrange `niche_start..=niche_end` inside `range`. // If the value of the tag is inside this subrange, it's a @@ -153,45 +138,6 @@ pub(crate) fn codegen_get_discriminant<'tcx>( // } // However, we will likely be able to emit simpler code. - // Find the least and greatest values in `range`, considered - // both as signed and unsigned. - let (low_unsigned, high_unsigned) = - if range.start <= range.end { (range.start, range.end) } else { (0, max_unsigned) }; - let (low_signed, high_signed) = if sle(range.start, range.end) { - (range.start, range.end) - } else { - (min_signed, max_signed) - }; - - let niches_ule = niche_start <= niche_end; - let niches_sle = sle(niche_start, niche_end); - let cast_smaller = cast_to_size <= tag_size; - - // In the algorithm above, we can change - // cast(relative_tag) + niche_variants.start() - // into - // cast(tag + (niche_variants.start() - niche_start)) - // if either the casted type is no larger than the original - // type, or if the niche values are contiguous (in either the - // signed or unsigned sense). - let can_incr = cast_smaller || niches_ule || niches_sle; - - let data_for_boundary_niche = || -> Option<(IntCC, u128)> { - if !can_incr { - None - } else if niche_start == low_unsigned { - Some((IntCC::UnsignedLessThanOrEqual, niche_end)) - } else if niche_end == high_unsigned { - Some((IntCC::UnsignedGreaterThanOrEqual, niche_start)) - } else if niche_start == low_signed { - Some((IntCC::SignedLessThanOrEqual, niche_end)) - } else if niche_end == high_signed { - Some((IntCC::SignedGreaterThanOrEqual, niche_start)) - } else { - None - } - }; - let (is_niche, tagged_discr, delta) = if relative_max == 0 { // Best case scenario: only one tagged variant. This will // likely become just a comparison and a jump. @@ -206,41 +152,6 @@ pub(crate) fn codegen_get_discriminant<'tcx>( let tagged_discr = fx.bcx.ins().iconst(cast_to, niche_variants.start().as_u32() as i64); (is_niche, tagged_discr, 0) - } else if let Some((predicate, constant)) = data_for_boundary_niche() { - // The niche values are either the lowest or the highest in - // `range`. We can avoid the first subtraction in the - // algorithm. - // The algorithm is now this: - // is_niche = tag <= niche_end - // discr = if is_niche { - // cast(tag + (niche_variants.start() - niche_start)) - // } else { - // untagged_variant - // } - // (the first line may instead be tag >= niche_start, - // and may be a signed or unsigned comparison) - // The arithmetic must be done before the cast, so we can - // have the correct wrapping behavior. See issue #104519 for - // the consequences of getting this wrong. - let is_niche = codegen_icmp_imm(fx, predicate, tag, constant as i128); - let delta = (niche_variants.start().as_u32() as u128).wrapping_sub(niche_start); - let incr_tag = if delta == 0 { - tag - } else { - let delta = match fx.bcx.func.dfg.value_type(tag) { - types::I128 => { - let lsb = fx.bcx.ins().iconst(types::I64, delta as u64 as i64); - let msb = fx.bcx.ins().iconst(types::I64, (delta >> 64) as u64 as i64); - fx.bcx.ins().iconcat(lsb, msb) - } - ty => fx.bcx.ins().iconst(ty, delta as i64), - }; - fx.bcx.ins().iadd(tag, delta) - }; - - let cast_tag = clif_intcast(fx, incr_tag, cast_to, !niches_ule); - - (is_niche, cast_tag, 0) } else { // The special cases don't apply, so we'll have to go with // the general algorithm. diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 3e2e2af96886..0e6c6ad95aa1 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -324,6 +324,10 @@ fn module_codegen( OngoingModuleCodegen::Async(std::thread::spawn(move || { cx.profiler.clone().verbose_generic_activity_with_arg("compile functions", &*cgu_name).run( || { + cranelift_codegen::timing::set_thread_profiler(Box::new(super::MeasuremeProfiler( + cx.profiler.clone(), + ))); + let mut cached_context = Context::new(); for codegened_func in codegened_functions { crate::base::compile_fn( @@ -407,7 +411,7 @@ pub(crate) fn run_aot( backend_config.clone(), global_asm_config.clone(), cgu.name(), - concurrency_limiter.acquire(), + concurrency_limiter.acquire(tcx.sess.diagnostic()), ), module_codegen, Some(rustc_middle::dep_graph::hash_result), diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index f6a48e3257bc..3118105a4e2d 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -224,6 +224,10 @@ pub(crate) fn codegen_and_compile_fn<'tcx>( module: &mut dyn Module, instance: Instance<'tcx>, ) { + cranelift_codegen::timing::set_thread_profiler(Box::new(super::MeasuremeProfiler( + cx.profiler.clone(), + ))); + tcx.prof.generic_activity("codegen and compile fn").run(|| { let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name)); diff --git a/compiler/rustc_codegen_cranelift/src/driver/mod.rs b/compiler/rustc_codegen_cranelift/src/driver/mod.rs index d09d3a529759..5c52c9c18adf 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/mod.rs @@ -4,6 +4,7 @@ //! [`codegen_fn`]: crate::base::codegen_fn //! [`codegen_static`]: crate::constant::codegen_static +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_middle::mir::mono::{Linkage as RLinkage, MonoItem, Visibility}; use crate::prelude::*; @@ -39,3 +40,31 @@ fn predefine_mono_items<'tcx>( } }); } + +struct MeasuremeProfiler(SelfProfilerRef); + +struct TimingGuard { + profiler: std::mem::ManuallyDrop, + inner: Option>, +} + +impl Drop for TimingGuard { + fn drop(&mut self) { + self.inner.take(); + unsafe { + std::mem::ManuallyDrop::drop(&mut self.profiler); + } + } +} + +impl cranelift_codegen::timing::Profiler for MeasuremeProfiler { + fn start_pass(&self, pass: cranelift_codegen::timing::Pass) -> Box { + let mut timing_guard = + TimingGuard { profiler: std::mem::ManuallyDrop::new(self.0.clone()), inner: None }; + timing_guard.inner = Some( + unsafe { &*(&*timing_guard.profiler as &SelfProfilerRef as *const SelfProfilerRef) } + .generic_activity(pass.description()), + ); + Box::new(timing_guard) + } +} diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index a74f8ffa23d4..63a1f6959dda 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -104,7 +104,6 @@ pub(crate) fn compile_global_asm( return Ok(None); } - // FIXME fix linker error on macOS if cfg!(not(feature = "inline_asm")) { return Err( "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift" diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 03f2a65fccad..539f8c103dbd 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -51,17 +51,13 @@ fn report_atomic_type_validation_error<'tcx>( fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); } -pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> Option { +pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> Type { let (element, count) = match layout.abi { Abi::Vector { element, count } => (element, count), _ => unreachable!(), }; - match scalar_to_clif_type(tcx, element).by(u32::try_from(count).unwrap()) { - // Cranelift currently only implements icmp for 128bit vectors. - Some(vector_ty) if vector_ty.bits() == 128 => Some(vector_ty), - _ => None, - } + scalar_to_clif_type(tcx, element).by(u32::try_from(count).unwrap()).unwrap() } fn simd_for_each_lane<'tcx>( @@ -534,7 +530,7 @@ fn codegen_regular_intrinsic_call<'tcx>( // The only difference between offset and arith_offset is regarding UB. Because Cranelift // doesn't have UB both are codegen'ed the same way - sym::offset | sym::arith_offset => { + sym::arith_offset => { intrinsic_args!(fx, args => (base, offset); intrinsic); let offset = offset.load_scalar(fx); @@ -1107,8 +1103,8 @@ fn codegen_regular_intrinsic_call<'tcx>( fx.bcx.ins().call_indirect(f_sig, f, &[data]); - let layout = ret.layout(); - let ret_val = CValue::const_val(fx, layout, ty::ScalarInt::null(layout.size)); + let layout = fx.layout_of(fx.tcx.types.i32); + let ret_val = CValue::by_val(fx.bcx.ins().iconst(types::I32, 0), layout); ret.write_cvalue(fx, ret_val); } diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index 6f54a8d49c86..264b578c168b 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -253,7 +253,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( } ret.write_cvalue(fx, base); - let ret_lane = ret.place_field(fx, FieldIdx::new(idx.try_into().unwrap())); + let ret_lane = ret.place_lane(fx, idx.try_into().unwrap()); ret_lane.write_cvalue(fx, val); } diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 8cc7f6c34b02..f0b399ae2808 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -90,7 +90,7 @@ mod prelude { pub(crate) use rustc_data_structures::fx::FxHashMap; - pub(crate) use rustc_index::vec::Idx; + pub(crate) use rustc_index::Idx; pub(crate) use cranelift_codegen::ir::condcodes::{FloatCC, IntCC}; pub(crate) use cranelift_codegen::ir::function::Function; @@ -110,7 +110,7 @@ mod prelude { pub(crate) use crate::common::*; pub(crate) use crate::debuginfo::{DebugContext, UnwindContext}; pub(crate) use crate::pointer::Pointer; - pub(crate) use crate::value_and_place::{CPlace, CPlaceInner, CValue}; + pub(crate) use crate::value_and_place::{CPlace, CValue}; } struct PrintOnPanic String>(F); diff --git a/compiler/rustc_codegen_cranelift/src/num.rs b/compiler/rustc_codegen_cranelift/src/num.rs index 1357b7be1e09..ba53e01c7a21 100644 --- a/compiler/rustc_codegen_cranelift/src/num.rs +++ b/compiler/rustc_codegen_cranelift/src/num.rs @@ -118,7 +118,7 @@ pub(crate) fn codegen_int_binop<'tcx>( ); } - if let Some(res) = crate::codegen_i128::maybe_codegen(fx, bin_op, false, in_lhs, in_rhs) { + if let Some(res) = crate::codegen_i128::maybe_codegen(fx, bin_op, in_lhs, in_rhs) { return res; } @@ -173,7 +173,7 @@ pub(crate) fn codegen_checked_int_binop<'tcx>( let lhs = in_lhs.load_scalar(fx); let rhs = in_rhs.load_scalar(fx); - if let Some(res) = crate::codegen_i128::maybe_codegen(fx, bin_op, true, in_lhs, in_rhs) { + if let Some(res) = crate::codegen_i128::maybe_codegen_checked(fx, bin_op, in_lhs, in_rhs) { return res; } diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs index e0a081c9d498..27e21183c556 100644 --- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs +++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs @@ -7,48 +7,51 @@ //! test compile //! target x86_64 //! -//! function u0:0(i64, i64, i64) system_v { -//! ; symbol _ZN119_$LT$example..IsNotEmpty$u20$as$u20$mini_core..FnOnce$LT$$LP$$RF$$u27$a$u20$$RF$$u27$b$u20$$u5b$u16$u5d$$C$$RP$$GT$$GT$9call_once17he85059d5e6a760a0E -//! ; instance Instance { def: Item(DefId(0/0:29 ~ example[8787]::{{impl}}[0]::call_once[0])), substs: [ReErased, ReErased] } -//! ; sig ([IsNotEmpty, (&&[u16],)]; c_variadic: false)->(u8, u8) +//! function u0:22(i64) -> i8, i8 system_v { +//! ; symbol _ZN97_$LT$example..IsNotEmpty$u20$as$u20$mini_core..FnOnce$LT$$LP$$RF$$RF$$u5b$u16$u5d$$C$$RP$$GT$$GT$9call_once17hd517c453d67c0915E +//! ; instance Instance { def: Item(WithOptConstParam { did: DefId(0:42 ~ example[4e51]::{impl#0}::call_once), const_param_did: None }), substs: [ReErased, ReErased] } +//! ; abi FnAbi { args: [ArgAbi { layout: TyAndLayout { ty: IsNotEmpty, layout: Layout { size: Size(0 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: Align(8 bytes) }, abi: Aggregate { sized: true }, fields: Arbitrary { offsets: [], memory_index: [] }, largest_niche: None, variants: Single { index: 0 } } }, mode: Ignore }, ArgAbi { layout: TyAndLayout { ty: &&[u16], layout: Layout { size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(8 bytes), pref: Align(8 bytes) }, abi: Scalar(Initialized { value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), fields: Primitive, largest_niche: Some(Niche { offset: Size(0 bytes), value: Pointer(AddressSpace(0)), valid_range: 1..=18446744073709551615 }), variants: Single { index: 0 } } }, mode: Direct(ArgAttributes { regular: NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some(Align(8 bytes)) }) }], ret: ArgAbi { layout: TyAndLayout { ty: (u8, u8), layout: Layout { size: Size(2 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: Align(8 bytes) }, abi: ScalarPair(Initialized { value: Int(I8, false), valid_range: 0..=255 }, Initialized { value: Int(I8, false), valid_range: 0..=255 }), fields: Arbitrary { offsets: [Size(0 bytes), Size(1 bytes)], memory_index: [0, 1] }, largest_niche: None, variants: Single { index: 0 } } }, mode: Pair(ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }, ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }) }, c_variadic: false, fixed_count: 1, conv: Rust, can_unwind: false } //! -//! ; ssa {_2: NOT_SSA, _4: NOT_SSA, _0: NOT_SSA, _3: (empty), _1: NOT_SSA} -//! ; msg loc.idx param pass mode ssa flags ty -//! ; ret _0 = v0 ByRef NOT_SSA (u8, u8) -//! ; arg _1 = v1 ByRef NOT_SSA IsNotEmpty -//! ; arg _2.0 = v2 ByVal(types::I64) NOT_SSA &&[u16] +//! ; kind loc.idx param pass mode ty +//! ; ssa _0 (u8, u8) 2b 1, 8 var=(0, 1) +//! ; ret _0 - Pair(ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }, ArgAttributes { regular: NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: None }) (u8, u8) +//! ; arg _1 - Ignore IsNotEmpty +//! ; arg _2.0 = v0 Direct(ArgAttributes { regular: NonNull | NoUndef, arg_ext: None, pointee_size: Size(0 bytes), pointee_align: Some(Align(8 bytes)) }) &&[u16] //! -//! ss0 = explicit_slot 0 ; _1: IsNotEmpty size=0 align=1,8 -//! ss1 = explicit_slot 8 ; _2: (&&[u16],) size=8 align=8,8 -//! ss2 = explicit_slot 8 ; _4: (&&[u16],) size=8 align=8,8 -//! sig0 = (i64, i64, i64) system_v -//! sig1 = (i64, i64, i64) system_v -//! fn0 = colocated u0:6 sig1 ; Instance { def: Item(DefId(0/0:31 ~ example[8787]::{{impl}}[1]::call_mut[0])), substs: [ReErased, ReErased] } +//! ; kind local ty size align (abi,pref) +//! ; zst _1 IsNotEmpty 0b 1, 8 align=8,offset= +//! ; stack _2 (&&[u16],) 8b 8, 8 storage=ss0 +//! ; ssa _3 &mut IsNotEmpty 8b 8, 8 var=2 //! -//! block0(v0: i64, v1: i64, v2: i64): -//! v3 = stack_addr.i64 ss0 -//! v4 = stack_addr.i64 ss1 -//! store v2, v4 -//! v5 = stack_addr.i64 ss2 +//! ss0 = explicit_slot 16 +//! sig0 = (i64, i64) -> i8, i8 system_v +//! fn0 = colocated u0:23 sig0 ; Instance { def: Item(WithOptConstParam { did: DefId(0:46 ~ example[4e51]::{impl#1}::call_mut), const_param_did: None }), substs: [ReErased, ReErased] } +//! +//! block0(v0: i64): +//! nop +//! ; write_cvalue: Addr(Pointer { base: Stack(ss0), offset: Offset32(0) }, None): &&[u16] <- ByVal(v0): &&[u16] +//! stack_store v0, ss0 //! jump block1 //! //! block1: //! nop //! ; _3 = &mut _1 -//! ; _4 = _2 -//! v6 = load.i64 v4 -//! store v6, v5 +//! v1 = iconst.i64 8 +//! ; write_cvalue: Var(_3, var2): &mut IsNotEmpty <- ByVal(v1): &mut IsNotEmpty //! ; -//! ; _0 = const mini_core::FnMut::call_mut(move _3, move _4) -//! v7 = load.i64 v5 -//! call fn0(v0, v3, v7) +//! ; _0 = >::call_mut(move _3, _2) +//! v2 = stack_load.i64 ss0 +//! v3, v4 = call fn0(v1, v2) ; v1 = 8 +//! v5 -> v3 +//! v6 -> v4 +//! ; write_cvalue: VarPair(_0, var0, var1): (u8, u8) <- ByValPair(v3, v4): (u8, u8) //! jump block2 //! //! block2: //! nop //! ; //! ; return -//! return +//! return v5, v6 //! } //! ``` diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index 1b69862ce2ca..c964d1ac5e0d 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -2,8 +2,8 @@ use crate::prelude::*; +use cranelift_codegen::entity::EntityRef; use cranelift_codegen::ir::immediates::Offset32; -use cranelift_codegen::ir::{InstructionData, Opcode}; fn codegen_field<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, @@ -214,17 +214,7 @@ impl<'tcx> CValue<'tcx> { ) -> CValue<'tcx> { let layout = self.1; match self.0 { - CValueInner::ByVal(val) => match layout.abi { - Abi::Vector { element: _, count } => { - let count = u8::try_from(count).expect("SIMD type with more than 255 lanes???"); - let field = u8::try_from(field.index()).unwrap(); - assert!(field < count); - let lane = fx.bcx.ins().extractlane(val, field); - let field_layout = layout.field(&*fx, usize::from(field)); - CValue::by_val(lane, field_layout) - } - _ => unreachable!("value_field for ByVal with abi {:?}", layout.abi), - }, + CValueInner::ByVal(_) => unreachable!(), CValueInner::ByValPair(val1, val2) => match layout.abi { Abi::ScalarPair(_, _) => { let val = match field.as_u32() { @@ -258,16 +248,7 @@ impl<'tcx> CValue<'tcx> { let lane_layout = fx.layout_of(lane_ty); assert!(lane_idx < lane_count); match self.0 { - CValueInner::ByVal(val) => match layout.abi { - Abi::Vector { element: _, count: _ } => { - assert!(lane_count <= u8::MAX.into(), "SIMD type with more than 255 lanes???"); - let lane_idx = u8::try_from(lane_idx).unwrap(); - let lane = fx.bcx.ins().extractlane(val, lane_idx); - CValue::by_val(lane, lane_layout) - } - _ => unreachable!("value_lane for ByVal with abi {:?}", layout.abi), - }, - CValueInner::ByValPair(_, _) => unreachable!(), + CValueInner::ByVal(_) | CValueInner::ByValPair(_, _) => unreachable!(), CValueInner::ByRef(ptr, None) => { let field_offset = lane_layout.size * lane_idx; let field_ptr = ptr.offset_i64(fx, i64::try_from(field_offset.bytes()).unwrap()); @@ -277,14 +258,6 @@ impl<'tcx> CValue<'tcx> { } } - pub(crate) fn unsize_value(self, fx: &mut FunctionCx<'_, '_, 'tcx>, dest: CPlace<'tcx>) { - crate::unsize::coerce_unsized_into(fx, self, dest); - } - - pub(crate) fn coerce_dyn_star(self, fx: &mut FunctionCx<'_, '_, 'tcx>, dest: CPlace<'tcx>) { - crate::unsize::coerce_dyn_star(fx, self, dest); - } - /// If `ty` is signed, `const_val` must already be sign extended. pub(crate) fn const_val( fx: &mut FunctionCx<'_, '_, 'tcx>, @@ -345,10 +318,9 @@ pub(crate) struct CPlace<'tcx> { } #[derive(Debug, Copy, Clone)] -pub(crate) enum CPlaceInner { +enum CPlaceInner { Var(Local, Variable), VarPair(Local, Variable, Variable), - VarLane(Local, Variable, u8), Addr(Pointer, Option), } @@ -357,10 +329,6 @@ impl<'tcx> CPlace<'tcx> { self.layout } - pub(crate) fn inner(&self) -> &CPlaceInner { - &self.inner - } - pub(crate) fn new_stack_slot( fx: &mut FunctionCx<'_, '_, 'tcx>, layout: TyAndLayout<'tcx>, @@ -442,12 +410,6 @@ impl<'tcx> CPlace<'tcx> { //fx.bcx.set_val_label(val2, cranelift_codegen::ir::ValueLabel::new(var2.index())); CValue::by_val_pair(val1, val2, layout) } - CPlaceInner::VarLane(_local, var, lane) => { - let val = fx.bcx.use_var(var); - //fx.bcx.set_val_label(val, cranelift_codegen::ir::ValueLabel::new(var.index())); - let val = fx.bcx.ins().extractlane(val, lane); - CValue::by_val(val, layout) - } CPlaceInner::Addr(ptr, extra) => { if let Some(extra) = extra { CValue::by_ref_unsized(ptr, extra, layout) @@ -458,21 +420,56 @@ impl<'tcx> CPlace<'tcx> { } } - #[track_caller] - pub(crate) fn to_ptr(self) -> Pointer { - match self.to_ptr_maybe_unsized() { - (ptr, None) => ptr, - (_, Some(_)) => bug!("Expected sized cplace, found {:?}", self), + pub(crate) fn debug_comment(self) -> (&'static str, String) { + match self.inner { + CPlaceInner::Var(_local, var) => ("ssa", format!("var={}", var.index())), + CPlaceInner::VarPair(_local, var1, var2) => { + ("ssa", format!("var=({}, {})", var1.index(), var2.index())) + } + CPlaceInner::Addr(ptr, meta) => { + let meta = + if let Some(meta) = meta { format!(",meta={}", meta) } else { String::new() }; + match ptr.debug_base_and_offset() { + (crate::pointer::PointerBase::Addr(addr), offset) => { + ("reuse", format!("storage={}{}{}", addr, offset, meta)) + } + (crate::pointer::PointerBase::Stack(stack_slot), offset) => { + ("stack", format!("storage={}{}{}", stack_slot, offset, meta)) + } + (crate::pointer::PointerBase::Dangling(align), offset) => { + ("zst", format!("align={},offset={}", align.bytes(), offset)) + } + } + } } } #[track_caller] - pub(crate) fn to_ptr_maybe_unsized(self) -> (Pointer, Option) { + pub(crate) fn to_ptr(self) -> Pointer { match self.inner { - CPlaceInner::Addr(ptr, extra) => (ptr, extra), - CPlaceInner::Var(_, _) - | CPlaceInner::VarPair(_, _, _) - | CPlaceInner::VarLane(_, _, _) => bug!("Expected CPlace::Addr, found {:?}", self), + CPlaceInner::Addr(ptr, None) => ptr, + CPlaceInner::Addr(_, Some(_)) => bug!("Expected sized cplace, found {:?}", self), + CPlaceInner::Var(_, _) | CPlaceInner::VarPair(_, _, _) => { + bug!("Expected CPlace::Addr, found {:?}", self) + } + } + } + + #[track_caller] + pub(crate) fn to_ptr_unsized(self) -> (Pointer, Value) { + match self.inner { + CPlaceInner::Addr(ptr, Some(extra)) => (ptr, extra), + CPlaceInner::Addr(_, None) | CPlaceInner::Var(_, _) | CPlaceInner::VarPair(_, _, _) => { + bug!("Expected unsized cplace, found {:?}", self) + } + } + } + + pub(crate) fn try_to_ptr(self) -> Option { + match self.inner { + CPlaceInner::Var(_, _) | CPlaceInner::VarPair(_, _, _) => None, + CPlaceInner::Addr(ptr, None) => Some(ptr), + CPlaceInner::Addr(_, Some(_)) => bug!("Expected sized cplace, found {:?}", self), } } @@ -496,7 +493,7 @@ impl<'tcx> CPlace<'tcx> { from: CValue<'tcx>, method: &'static str, ) { - fn transmute_value<'tcx>( + fn transmute_scalar<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, var: Variable, data: Value, @@ -520,7 +517,7 @@ impl<'tcx> CPlace<'tcx> { | (types::F64, types::I64) => codegen_bitcast(fx, dst_ty, data), _ if src_ty.is_vector() && dst_ty.is_vector() => codegen_bitcast(fx, dst_ty, data), _ if src_ty.is_vector() || dst_ty.is_vector() => { - // FIXME do something more efficient for transmutes between vectors and integers. + // FIXME(bytecodealliance/wasmtime#6104) do something more efficient for transmutes between vectors and integers. let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { kind: StackSlotKind::ExplicitSlot, // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to @@ -554,7 +551,7 @@ impl<'tcx> CPlace<'tcx> { format!( "{}: {:?}: {:?} <- {:?}: {:?}", method, - self.inner(), + self.inner, self.layout().ty, from.0, from.layout().ty @@ -563,32 +560,11 @@ impl<'tcx> CPlace<'tcx> { } let dst_layout = self.layout(); - let to_ptr = match self.inner { + match self.inner { CPlaceInner::Var(_local, var) => { - if let ty::Array(element, len) = dst_layout.ty.kind() { - // Can only happen for vector types - let len = u32::try_from(len.eval_target_usize(fx.tcx, ParamEnv::reveal_all())) - .unwrap(); - let vector_ty = fx.clif_type(*element).unwrap().by(len).unwrap(); - - let data = match from.0 { - CValueInner::ByRef(ptr, None) => { - let mut flags = MemFlags::new(); - flags.set_notrap(); - ptr.load(fx, vector_ty, flags) - } - CValueInner::ByVal(_) - | CValueInner::ByValPair(_, _) - | CValueInner::ByRef(_, Some(_)) => bug!("array should be ByRef"), - }; - - fx.bcx.def_var(var, data); - return; - } let data = CValue(from.0, dst_layout).load_scalar(fx); let dst_ty = fx.clif_type(self.layout().ty).unwrap(); - transmute_value(fx, var, data, dst_ty); - return; + transmute_scalar(fx, var, data, dst_ty); } CPlaceInner::VarPair(_local, var1, var2) => { let (data1, data2) = if from.layout().ty == dst_layout.ty { @@ -599,80 +575,61 @@ impl<'tcx> CPlace<'tcx> { CValue(CValueInner::ByRef(ptr, None), dst_layout).load_scalar_pair(fx) }; let (dst_ty1, dst_ty2) = fx.clif_pair_type(self.layout().ty).unwrap(); - transmute_value(fx, var1, data1, dst_ty1); - transmute_value(fx, var2, data2, dst_ty2); - return; + transmute_scalar(fx, var1, data1, dst_ty1); + transmute_scalar(fx, var2, data2, dst_ty2); } - CPlaceInner::VarLane(_local, var, lane) => { - let data = from.load_scalar(fx); - - // First get the old vector - let vector = fx.bcx.use_var(var); - //fx.bcx.set_val_label(vector, cranelift_codegen::ir::ValueLabel::new(var.index())); - - // Next insert the written lane into the vector - let vector = fx.bcx.ins().insertlane(vector, data, lane); - - // Finally write the new vector - //fx.bcx.set_val_label(vector, cranelift_codegen::ir::ValueLabel::new(var.index())); - fx.bcx.def_var(var, vector); - - return; - } - CPlaceInner::Addr(ptr, None) => { + CPlaceInner::Addr(_, Some(_)) => bug!("Can't write value to unsized place {:?}", self), + CPlaceInner::Addr(to_ptr, None) => { if dst_layout.size == Size::ZERO || dst_layout.abi == Abi::Uninhabited { return; } - ptr - } - CPlaceInner::Addr(_, Some(_)) => bug!("Can't write value to unsized place {:?}", self), - }; - let mut flags = MemFlags::new(); - flags.set_notrap(); - match from.layout().abi { - // FIXME make Abi::Vector work too - Abi::Scalar(_) => { - let val = from.load_scalar(fx); - to_ptr.store(fx, val, flags); - return; - } - Abi::ScalarPair(a_scalar, b_scalar) => { - let (value, extra) = from.load_scalar_pair(fx); - let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar); - to_ptr.store(fx, value, flags); - to_ptr.offset(fx, b_offset).store(fx, extra, flags); - return; - } - _ => {} - } + let mut flags = MemFlags::new(); + flags.set_notrap(); + match from.layout().abi { + Abi::Scalar(_) => { + let val = from.load_scalar(fx); + to_ptr.store(fx, val, flags); + return; + } + Abi::ScalarPair(a_scalar, b_scalar) => { + let (value, extra) = from.load_scalar_pair(fx); + let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar); + to_ptr.store(fx, value, flags); + to_ptr.offset(fx, b_offset).store(fx, extra, flags); + return; + } + _ => {} + } - match from.0 { - CValueInner::ByVal(val) => { - to_ptr.store(fx, val, flags); + match from.0 { + CValueInner::ByVal(val) => { + to_ptr.store(fx, val, flags); + } + CValueInner::ByValPair(_, _) => { + bug!("Non ScalarPair abi {:?} for ByValPair CValue", dst_layout.abi); + } + CValueInner::ByRef(from_ptr, None) => { + let from_addr = from_ptr.get_addr(fx); + let to_addr = to_ptr.get_addr(fx); + let src_layout = from.1; + let size = dst_layout.size.bytes(); + let src_align = src_layout.align.abi.bytes() as u8; + let dst_align = dst_layout.align.abi.bytes() as u8; + fx.bcx.emit_small_memory_copy( + fx.target_config, + to_addr, + from_addr, + size, + dst_align, + src_align, + true, + flags, + ); + } + CValueInner::ByRef(_, Some(_)) => todo!(), + } } - CValueInner::ByValPair(_, _) => { - bug!("Non ScalarPair abi {:?} for ByValPair CValue", dst_layout.abi); - } - CValueInner::ByRef(from_ptr, None) => { - let from_addr = from_ptr.get_addr(fx); - let to_addr = to_ptr.get_addr(fx); - let src_layout = from.1; - let size = dst_layout.size.bytes(); - let src_align = src_layout.align.abi.bytes() as u8; - let dst_align = dst_layout.align.abi.bytes() as u8; - fx.bcx.emit_small_memory_copy( - fx.target_config, - to_addr, - from_addr, - size, - dst_align, - src_align, - true, - flags, - ); - } - CValueInner::ByRef(_, Some(_)) => todo!(), } } @@ -692,40 +649,6 @@ impl<'tcx> CPlace<'tcx> { let layout = self.layout(); match self.inner { - CPlaceInner::Var(local, var) => match layout.ty.kind() { - ty::Array(_, _) => { - // Can only happen for vector types - return CPlace { - inner: CPlaceInner::VarLane(local, var, field.as_u32().try_into().unwrap()), - layout: layout.field(fx, field.as_u32().try_into().unwrap()), - }; - } - ty::Adt(adt_def, substs) if layout.ty.is_simd() => { - let f0 = &adt_def.non_enum_variant().fields[FieldIdx::from_u32(0)]; - let f0_ty = f0.ty(fx.tcx, substs); - - match f0_ty.kind() { - ty::Array(_, _) => { - assert_eq!(field.as_u32(), 0); - return CPlace { - inner: CPlaceInner::Var(local, var), - layout: layout.field(fx, field.as_u32().try_into().unwrap()), - }; - } - _ => { - return CPlace { - inner: CPlaceInner::VarLane( - local, - var, - field.as_u32().try_into().unwrap(), - ), - layout: layout.field(fx, field.as_u32().try_into().unwrap()), - }; - } - } - } - _ => {} - }, CPlaceInner::VarPair(local, var1, var2) => { let layout = layout.field(&*fx, field.index()); @@ -738,7 +661,12 @@ impl<'tcx> CPlace<'tcx> { _ => {} } - let (base, extra) = self.to_ptr_maybe_unsized(); + let (base, extra) = match self.inner { + CPlaceInner::Addr(ptr, extra) => (ptr, extra), + CPlaceInner::Var(_, _) | CPlaceInner::VarPair(_, _, _) => { + bug!("Expected CPlace::Addr, found {:?}", self) + } + }; let (field_ptr, field_layout) = codegen_field(fx, base, extra, layout, field); if field_layout.is_unsized() { @@ -767,15 +695,8 @@ impl<'tcx> CPlace<'tcx> { assert!(lane_idx < lane_count); match self.inner { - CPlaceInner::Var(local, var) => { - assert!(matches!(layout.abi, Abi::Vector { .. })); - CPlace { - inner: CPlaceInner::VarLane(local, var, lane_idx.try_into().unwrap()), - layout: lane_layout, - } - } + CPlaceInner::Var(_, _) => unreachable!(), CPlaceInner::VarPair(_, _, _) => unreachable!(), - CPlaceInner::VarLane(_, _, _) => unreachable!(), CPlaceInner::Addr(ptr, None) => { let field_offset = lane_layout.size * lane_idx; let field_ptr = ptr.offset_i64(fx, i64::try_from(field_offset.bytes()).unwrap()); @@ -794,34 +715,13 @@ impl<'tcx> CPlace<'tcx> { ty::Array(elem_ty, _) => { let elem_layout = fx.layout_of(*elem_ty); match self.inner { - CPlaceInner::Var(local, var) => { - // This is a hack to handle `vector_val.0[1]`. It doesn't allow dynamic - // indexing. - let lane_idx = match fx.bcx.func.dfg.insts - [fx.bcx.func.dfg.value_def(index).unwrap_inst()] - { - InstructionData::UnaryImm { opcode: Opcode::Iconst, imm } => imm, - _ => bug!( - "Dynamic indexing into a vector type is not supported: {self:?}[{index}]" - ), - }; - return CPlace { - inner: CPlaceInner::VarLane( - local, - var, - lane_idx.bits().try_into().unwrap(), - ), - layout: elem_layout, - }; - } CPlaceInner::Addr(addr, None) => (elem_layout, addr), - CPlaceInner::Addr(_, Some(_)) - | CPlaceInner::VarPair(_, _, _) - | CPlaceInner::VarLane(_, _, _) => bug!("Can't index into {self:?}"), + CPlaceInner::Var(_, _) + | CPlaceInner::Addr(_, Some(_)) + | CPlaceInner::VarPair(_, _, _) => bug!("Can't index into {self:?}"), } - // FIXME use VarLane in case of Var with simd type } - ty::Slice(elem_ty) => (fx.layout_of(*elem_ty), self.to_ptr_maybe_unsized().0), + ty::Slice(elem_ty) => (fx.layout_of(*elem_ty), self.to_ptr_unsized().0), _ => bug!("place_index({:?})", self.layout().ty), }; @@ -846,12 +746,8 @@ impl<'tcx> CPlace<'tcx> { layout: TyAndLayout<'tcx>, ) -> CValue<'tcx> { if has_ptr_meta(fx.tcx, self.layout().ty) { - let (ptr, extra) = self.to_ptr_maybe_unsized(); - CValue::by_val_pair( - ptr.get_addr(fx), - extra.expect("unsized type without metadata"), - layout, - ) + let (ptr, extra) = self.to_ptr_unsized(); + CValue::by_val_pair(ptr.get_addr(fx), extra, layout) } else { CValue::by_val(self.to_ptr().get_addr(fx), layout) } diff --git a/compiler/rustc_codegen_cranelift/y.rs b/compiler/rustc_codegen_cranelift/y.rs index fd825d02e355..a68a10500f50 100755 --- a/compiler/rustc_codegen_cranelift/y.rs +++ b/compiler/rustc_codegen_cranelift/y.rs @@ -3,10 +3,14 @@ # This block is ignored by rustc set -e echo "[BUILD] y.rs" 1>&2 -rustc $0 -o ${0/.rs/.bin} -Cdebuginfo=1 --edition 2021 -Cpanic=abort +rustc $0 -o ${0/.rs/.bin} -Cdebuginfo=1 --edition 2021 exec ${0/.rs/.bin} $@ */ +#![warn(rust_2018_idioms)] +#![warn(unused_lifetimes)] +#![warn(unreachable_pub)] + //! The build system for cg_clif //! //! # Manual compilation diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 65de02b35671..738cdb6f119f 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -593,6 +593,8 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister { InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r", InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w", InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a", InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d", @@ -667,6 +669,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl InlineAsmRegClass::Avr(_) => unimplemented!(), InlineAsmRegClass::Bpf(_) => unimplemented!(), InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => cx.type_i32(), @@ -804,6 +808,7 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option } } InlineAsmRegClass::Hexagon(_) => None, + InlineAsmRegClass::LoongArch(_) => None, InlineAsmRegClass::Mips(_) => None, InlineAsmRegClass::Nvptx(_) => None, InlineAsmRegClass::PowerPC(_) => None, diff --git a/compiler/rustc_codegen_gcc/src/callee.rs b/compiler/rustc_codegen_gcc/src/callee.rs index ba1e86562089..433b2585f82a 100644 --- a/compiler/rustc_codegen_gcc/src/callee.rs +++ b/compiler/rustc_codegen_gcc/src/callee.rs @@ -17,7 +17,7 @@ use crate::context::CodegenCx; pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) -> Function<'gcc> { let tcx = cx.tcx(); - assert!(!instance.substs.needs_infer()); + assert!(!instance.substs.has_infer()); assert!(!instance.substs.has_escaping_bound_vars()); let sym = tcx.symbol_name(instance).name; diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 0b661505acc0..1cabb05de975 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -27,6 +27,7 @@ extern crate rustc_attr; extern crate rustc_codegen_ssa; extern crate rustc_data_structures; extern crate rustc_errors; +extern crate rustc_fluent_macro; extern crate rustc_hir; extern crate rustc_macros; extern crate rustc_metadata; @@ -76,7 +77,7 @@ use rustc_codegen_ssa::target_features::supported_target_features; use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, Handler, SubdiagnosticMessage}; -use rustc_macros::fluent_messages; +use rustc_fluent_macro::fluent_messages; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs index c1f6340866ca..342b830cedb1 100644 --- a/compiler/rustc_codegen_gcc/src/mono_item.rs +++ b/compiler/rustc_codegen_gcc/src/mono_item.rs @@ -31,7 +31,7 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> { #[cfg_attr(not(feature="master"), allow(unused_variables))] fn predefine_fn(&self, instance: Instance<'tcx>, linkage: Linkage, visibility: Visibility, symbol_name: &str) { - assert!(!instance.substs.needs_infer()); + assert!(!instance.substs.has_infer()); let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); self.linkage.set(base::linkage_to_gcc(linkage)); diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index a7ba2f8b6953..5e750d91b825 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -22,6 +22,7 @@ rustc_attr = { path = "../rustc_attr" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } +rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } @@ -35,6 +36,5 @@ rustc_target = { path = "../rustc_target" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } -tempfile = "3.2.0" serde = { version = "1", features = [ "derive" ]} serde_json = "1" diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 1a3865360a3c..98d5b3599d96 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -236,6 +236,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { InlineAsmArch::Nvptx64 => {} InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {} InlineAsmArch::Hexagon => {} + InlineAsmArch::LoongArch64 => {} InlineAsmArch::Mips | InlineAsmArch::Mips64 => {} InlineAsmArch::S390x => {} InlineAsmArch::SpirV => {} @@ -633,6 +634,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "w", InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f", InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "r", InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f", InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h", @@ -719,6 +722,7 @@ fn modifier_to_llvm( } } InlineAsmRegClass::Hexagon(_) => None, + InlineAsmRegClass::LoongArch(_) => None, InlineAsmRegClass::Mips(_) => None, InlineAsmRegClass::Nvptx(_) => None, InlineAsmRegClass::PowerPC(_) => None, @@ -803,6 +807,8 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &' cx.type_vector(cx.type_i64(), 2) } InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => cx.type_i16(), diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index 6ee2a05ffd7b..30a0cf1d0191 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -27,7 +27,7 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> debug!("get_fn(instance={:?})", instance); - assert!(!instance.substs.needs_infer()); + assert!(!instance.substs.has_infer()); assert!(!instance.substs.has_escaping_bound_vars()); if let Some(&llfn) = cx.instances.borrow().get(&instance) { diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 4f8b5abd9010..9127fba388ba 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -10,7 +10,7 @@ use crate::value::Value; use rustc_ast::Mutability; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::*; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher}; use rustc_hir::def_id::DefId; use rustc_middle::bug; use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar}; @@ -261,7 +261,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { let hash = self.tcx.with_stable_hashing_context(|mut hcx| { let mut hasher = StableHasher::new(); alloc.hash_stable(&mut hcx, &mut hasher); - hasher.finish::() + hasher.finish::() }); llvm::set_value_name(value, format!("alloc_{hash:032x}").as_bytes()); } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index 99e4ded62f1a..2f910c37d610 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::{self, Instance}; use rustc_session::config::DebugInfo; use rustc_index::bit_set::BitSet; -use rustc_index::vec::Idx; +use rustc_index::Idx; /// Produces DIScope DIEs for each MIR Scope which has variables defined in it. // FIXME(eddyb) almost all of this should be in `rustc_codegen_ssa::mir::debuginfo`. diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index ff2b005d7576..aaf5dbd9930c 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -22,9 +22,9 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_, bx.const_bitcast(get_or_insert_gdb_debug_scripts_section_global(bx), bx.type_i8p()); // Load just the first byte as that's all that's necessary to force // LLVM to keep around the reference to the global. - let volative_load_instruction = bx.volatile_load(bx.type_i8(), gdb_debug_scripts_section); + let volatile_load_instruction = bx.volatile_load(bx.type_i8(), gdb_debug_scripts_section); unsafe { - llvm::LLVMSetAlignment(volative_load_instruction, 1); + llvm::LLVMSetAlignment(volatile_load_instruction, 1); } } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 21a0a60b012a..25fe3cb265d7 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -29,7 +29,6 @@ use rustc_hir::def::CtorKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; -use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{ self, AdtKind, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt, Visibility, }; @@ -1182,12 +1181,12 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>( let names = get_parameter_names(cx, generics); let template_params: SmallVec<_> = iter::zip(substs, names) .filter_map(|(kind, name)| { - if let GenericArgKind::Type(ty) = kind.unpack() { + kind.as_type().map(|ty| { let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); let actual_type_di_node = type_di_node(cx, actual_type); let name = name.as_str(); - Some(unsafe { + unsafe { llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( DIB(cx), None, @@ -1195,10 +1194,8 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>( name.len(), actual_type_di_node, ) - }) - } else { - None - } + } + }) }) .collect(); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index 69443b9b828e..ecb0912d3288 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -6,7 +6,7 @@ use rustc_codegen_ssa::{ traits::ConstMethods, }; -use rustc_index::vec::IndexVec; +use rustc_index::IndexVec; use rustc_middle::{ bug, ty::{ @@ -62,7 +62,7 @@ const SINGLE_VARIANT_VIRTUAL_DISR: u64 = 0; /// In CPP-like mode, we generate a union with a field for each variant and an /// explicit tag field. The field of each variant has a struct type -/// that encodes the discrimiant of the variant and it's data layout. +/// that encodes the discriminant of the variant and it's data layout. /// The union also has a nested enumeration type that is only used for encoding /// variant names in an efficient way. Its enumerator values do _not_ correspond /// to the enum's discriminant values. diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 55a217f59f91..9e0e847a1556 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -3,7 +3,7 @@ use rustc_codegen_ssa::debuginfo::{ wants_c_like_enum_debuginfo, }; use rustc_hir::def::CtorKind; -use rustc_index::vec::IndexSlice; +use rustc_index::IndexSlice; use rustc_middle::{ bug, mir::{GeneratorLayout, GeneratorSavedLocal}, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index d56c414cf651..2e9f89f41969 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -21,12 +21,13 @@ use rustc_codegen_ssa::debuginfo::type_names; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind}; use rustc_codegen_ssa::traits::*; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::stable_hasher::Hash128; use rustc_data_structures::sync::Lrc; use rustc_hir::def_id::{DefId, DefIdMap}; -use rustc_index::vec::IndexVec; +use rustc_index::IndexVec; use rustc_middle::mir; use rustc_middle::ty::layout::LayoutOf; -use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; +use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeVisitableExt}; use rustc_session::config::{self, DebugInfo}; use rustc_session::Session; @@ -61,7 +62,7 @@ pub struct CodegenUnitDebugContext<'ll, 'tcx> { llcontext: &'ll llvm::Context, llmod: &'ll llvm::Module, builder: &'ll mut DIBuilder<'ll>, - created_files: RefCell, &'ll DIFile>>, + created_files: RefCell, &'ll DIFile>>, type_map: metadata::TypeMap<'ll, 'tcx>, namespace_map: RefCell>, @@ -460,12 +461,12 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { let names = get_parameter_names(cx, generics); iter::zip(substs, names) .filter_map(|(kind, name)| { - if let GenericArgKind::Type(ty) = kind.unpack() { + kind.as_type().map(|ty| { let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); let actual_type_metadata = type_di_node(cx, actual_type); let name = name.as_str(); - Some(unsafe { + unsafe { Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( DIB(cx), None, @@ -473,10 +474,8 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { name.len(), actual_type_metadata, )) - }) - } else { - None - } + } + }) }) .collect() } else { @@ -516,7 +515,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { ty::Adt(def, ..) if !def.is_box() => { // Again, only create type information if full debuginfo is enabled if cx.sess().opts.debuginfo == DebugInfo::Full - && !impl_self_ty.needs_subst() + && !impl_self_ty.has_param() { Some(type_di_node(cx, impl_self_ty)) } else { diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 3f77ea77effe..8305a0a4c286 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -34,7 +34,7 @@ use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::{CodegenResults, CompiledModule}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{DiagnosticMessage, ErrorGuaranteed, FatalError, Handler, SubdiagnosticMessage}; -use rustc_macros::fluent_messages; +use rustc_fluent_macro::fluent_messages; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::ty::query::Providers; @@ -69,7 +69,7 @@ mod declare; mod errors; mod intrinsic; -// The following is a work around that replaces `pub mod llvm;` and that fixes issue 53912. +// The following is a workaround that replaces `pub mod llvm;` and that fixes issue 53912. #[path = "llvm/mod.rs"] mod llvm_; pub mod llvm { diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 09f3fe021650..c95148013eb7 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -552,6 +552,7 @@ pub enum ArchiveKind { K_BSD, K_DARWIN, K_COFF, + K_AIXBIG, } // LLVMRustThinLTOData diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index f820e7523712..4f5cc575da6e 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -137,6 +137,7 @@ impl FromStr for ArchiveKind { "bsd" => Ok(ArchiveKind::K_BSD), "darwin" => Ok(ArchiveKind::K_DARWIN), "coff" => Ok(ArchiveKind::K_COFF), + "aix_big" => Ok(ArchiveKind::K_AIXBIG), _ => Err(()), } } diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index d0ae36349df1..59bdc60830f8 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -48,7 +48,7 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> { visibility: Visibility, symbol_name: &str, ) { - assert!(!instance.substs.needs_infer()); + assert!(!instance.substs.has_infer()); let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); let lldecl = self.declare_fn(symbol_name, fn_abi); diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index c55991e00d3a..a421535c9b46 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -7,12 +7,11 @@ edition = "2021" test = false [dependencies] -ar_archive_writer = "0.1.1" +ar_archive_writer = "0.1.3" bitflags = "1.2.1" cc = "1.0.69" itertools = "0.10.1" tracing = "0.1" -libc = "0.2.50" jobserver = "0.1.22" tempfile = "3.2" thorin-dwp = "0.4" @@ -29,6 +28,7 @@ rustc_span = { path = "../rustc_span" } rustc_middle = { path = "../rustc_middle" } rustc_type_ir = { path = "../rustc_type_ir" } rustc_attr = { path = "../rustc_attr" } +rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } @@ -42,6 +42,9 @@ rustc_query_system = { path = "../rustc_query_system" } rustc_target = { path = "../rustc_target" } rustc_session = { path = "../rustc_session" } +[target.'cfg(unix)'.dependencies] +libc = "0.2.50" + [dependencies.object] version = "0.30.1" default-features = false diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 243be0e1f70e..375fdec10075 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -148,7 +148,7 @@ codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` fa codegen_ssa_unable_to_run_dsymutil = unable to run `dsymutil`: {$error} -codegen_ssa_stripping_debu_info_failed = stripping debug info with `{$util}` failed: {$status} +codegen_ssa_stripping_debug_info_failed = stripping debug info with `{$util}` failed: {$status} .note = {$output} codegen_ssa_unable_to_run = unable to run `{$util}`: {$error} @@ -291,3 +291,16 @@ codegen_ssa_invalid_monomorphization_unsupported_cast = invalid monomorphization codegen_ssa_invalid_monomorphization_unsupported_operation = invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}` codegen_ssa_invalid_monomorphization_expected_vector_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type + +codegen_ssa_invalid_no_sanitize = invalid argument for `no_sanitize` + .note = expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread` + +codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]` + .note = the attribute requires exactly one argument + +codegen_ssa_illegal_link_ordinal_format = illegal ordinal format in `link_ordinal` + .note = an unsuffixed integer value, e.g., `1`, is expected + +codegen_ssa_target_feature_safe_trait = `#[target_feature(..)]` cannot be applied to safe trait method + .label = cannot be applied to safe trait method + .label_def = not an `unsafe` function diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 66ec8f5f57d2..1c464b3eca49 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -233,6 +233,7 @@ impl<'a> ArArchiveBuilder<'a> { "bsd" => ArchiveKind::Bsd, "darwin" => ArchiveKind::Darwin, "coff" => ArchiveKind::Coff, + "aix_big" => ArchiveKind::AixBig, kind => { self.sess.emit_fatal(UnknownArchiveKind { kind }); } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 02e21e74fadc..eecfe13bb3ee 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -349,7 +349,10 @@ fn link_rlib<'a>( let NativeLibKind::Static { bundle: None | Some(true), whole_archive } = lib.kind else { continue; }; - if whole_archive == Some(true) && !codegen_results.crate_info.feature_packed_bundled_libs { + if whole_archive == Some(true) + && flavor == RlibFlavor::Normal + && !codegen_results.crate_info.feature_packed_bundled_libs + { sess.emit_err(errors::IncompatibleLinkingModifiers); } if flavor == RlibFlavor::Normal && let Some(filename) = lib.filename { diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index d0fd3cd76667..8f2f829c17c1 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -333,7 +333,7 @@ fn exported_symbols_provider_local( match *mono_item { MonoItem::Fn(Instance { def: InstanceDef::Item(def), substs }) => { if substs.non_erasable_generics().next().is_some() { - let symbol = ExportedSymbol::Generic(def.did, substs); + let symbol = ExportedSymbol::Generic(def, substs); symbols.push(( symbol, SymbolExportInfo { diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 2dda4cd16941..c80347448cbb 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -872,7 +872,7 @@ fn execute_copy_from_cache_work_item( let load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| { let source_file = in_incr_comp_dir(&incr_comp_session_dir, saved_path); debug!( - "copying pre-existing module `{}` from {:?} to {}", + "copying preexisting module `{}` from {:?} to {}", module.name, source_file, output_path.display() diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 8542bab689d6..5bd42622f2c3 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -14,6 +14,7 @@ use rustc_span::symbol::Ident; use rustc_span::{sym, Span}; use rustc_target::spec::{abi, SanitizerSet}; +use crate::errors; use crate::target_features::from_target_feature; use crate::{errors::ExpectedUsedSymbol, target_features::check_target_feature_trait_unsafe}; @@ -156,7 +157,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { None => { // Unfortunately, unconditionally using `llvm.used` causes // issues in handling `.init_array` with the gold linker, - // but using `llvm.compiler.used` caused a nontrival amount + // but using `llvm.compiler.used` caused a nontrivial amount // of unintentional ecosystem breakage -- particularly on // Mach-O targets. // @@ -334,10 +335,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { codegen_fn_attrs.no_sanitize |= SanitizerSet::HWADDRESS } _ => { - tcx.sess - .struct_span_err(item.span(), "invalid argument for `no_sanitize`") - .note("expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`") - .emit(); + tcx.sess.emit_err(errors::InvalidNoSanitize { span: item.span() }); } } } @@ -608,10 +606,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option { let sole_meta_list = match meta_item_list { Some([item]) => item.lit(), Some(_) => { - tcx.sess - .struct_span_err(attr.span, "incorrect number of arguments to `#[link_ordinal]`") - .note("the attribute requires exactly one argument") - .emit(); + tcx.sess.emit_err(errors::InvalidLinkOrdinalNargs { span: attr.span }); return None; } _ => None, @@ -642,10 +637,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option { None } } else { - tcx.sess - .struct_span_err(attr.span, "illegal ordinal format in `link_ordinal`") - .note("an unsuffixed integer value, e.g., `1`, is expected") - .emit(); + tcx.sess.emit_err(errors::InvalidLinkOrdinalFormat { span: attr.span }); None } } diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs index 1ea13040072e..e4da3b8de051 100644 --- a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs +++ b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs @@ -1,6 +1,6 @@ pub use super::ffi::*; -use rustc_index::vec::{IndexSlice, IndexVec}; +use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::coverage::{ CodeRegion, CounterValueReference, ExpressionOperandId, InjectedExpressionId, InjectedExpressionIndex, MappedExpressionIndex, Op, diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index f2469fde3b65..03f33d8d8aa7 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -12,7 +12,7 @@ // * `"` is treated as the start of a string. use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher}; use rustc_hir::def_id::DefId; use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData}; use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Mutability}; @@ -675,8 +675,7 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S hcx.while_hashing_spans(false, |hcx| { ct.to_valtree().hash_stable(hcx, &mut hasher) }); - let hash: u64 = hasher.finish(); - hash + hasher.finish::() }); if cpp_like_debuginfo(tcx) { diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 66e7e314f79d..cf4893b82265 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -424,7 +424,7 @@ pub struct UnableToRunDsymutil { } #[derive(Diagnostic)] -#[diag(codegen_ssa_stripping_debu_info_failed)] +#[diag(codegen_ssa_stripping_debug_info_failed)] #[note] pub struct StrippingDebugInfoFailed<'a> { pub util: &'a str, @@ -981,3 +981,37 @@ impl IntoDiagnosticArg for ExpectedPointerMutability { } } } + +#[derive(Diagnostic)] +#[diag(codegen_ssa_invalid_no_sanitize)] +#[note] +pub struct InvalidNoSanitize { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_invalid_link_ordinal_nargs)] +#[note] +pub struct InvalidLinkOrdinalNargs { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_illegal_link_ordinal_format)] +#[note] +pub struct InvalidLinkOrdinalFormat { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_target_feature_safe_trait)] +pub struct TargetFeatureSafeTrait { + #[primary_span] + #[label] + pub span: Span, + #[label(codegen_ssa_label_def)] + pub def: Span, +} diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 0ab12314b3c8..26d55618b490 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -25,8 +25,8 @@ use rustc_ast as ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; +use rustc_fluent_macro::fluent_messages; use rustc_hir::def_id::CrateNum; -use rustc_macros::fluent_messages; use rustc_middle::dep_graph::WorkProduct; use rustc_middle::middle::dependency_format::Dependencies; use rustc_middle::middle::exported_symbols::SymbolExportKind; diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs index 2421acab4715..81b49afb8839 100644 --- a/compiler/rustc_codegen_ssa/src/meth.rs +++ b/compiler/rustc_codegen_ssa/src/meth.rs @@ -67,10 +67,10 @@ impl<'a, 'tcx> VirtualIndex { /// ref of the type. fn expect_dyn_trait_in_self(ty: Ty<'_>) -> ty::PolyExistentialTraitRef<'_> { for arg in ty.peel_refs().walk() { - if let GenericArgKind::Type(ty) = arg.unpack() { - if let ty::Dynamic(data, _, _) = ty.kind() { - return data.principal().expect("expected principal trait object"); - } + if let GenericArgKind::Type(ty) = arg.unpack() + && let ty::Dynamic(data, _, _) = ty.kind() + { + return data.principal().expect("expected principal trait object"); } } diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 115a41050d2a..0334c7ff1326 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -5,7 +5,7 @@ use super::FunctionCx; use crate::traits::*; use rustc_data_structures::graph::dominators::Dominators; use rustc_index::bit_set::BitSet; -use rustc_index::vec::{IndexSlice, IndexVec}; +use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::traversal; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{self, Location, TerminatorKind}; diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index dd86977817fb..a0a8246be152 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -12,7 +12,6 @@ use crate::MemFlags; use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::lang_items::LangItem; -use rustc_index::vec::Idx; use rustc_middle::mir::{self, AssertKind, SwitchTargets}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; @@ -369,7 +368,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if self.fn_abi.c_variadic { // The `VaList` "spoofed" argument is just after all the real arguments. let va_list_arg_idx = self.fn_abi.args.len(); - match self.locals[mir::Local::new(1 + va_list_arg_idx)] { + match self.locals[mir::Local::from_usize(1 + va_list_arg_idx)] { LocalRef::Place(va_list) => { bx.va_end(va_list.llval); } diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index d049bafb821b..4e5e2dd5d506 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -1,5 +1,5 @@ use crate::traits::*; -use rustc_index::vec::IndexVec; +use rustc_index::IndexVec; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir; use rustc_middle::ty; @@ -494,6 +494,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue }; if let Ok(operand) = self.eval_mir_constant_to_operand(bx, &c) { + self.set_debug_loc(bx, var.source_info); let base = Self::spill_operand_to_stack( &operand, Some(var.name.to_string()), diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 7af7fc92dbce..1479242f23a6 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -135,13 +135,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .unwrap(); OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx) } - sym::offset => { - let ty = substs.type_at(0); - let layout = bx.layout_of(ty); - let ptr = args[0].immediate(); - let offset = args[1].immediate(); - bx.inbounds_gep(bx.backend_type(layout), ptr, &[offset]) - } sym::arith_offset => { let ty = substs.type_at(0); let layout = bx.layout_of(ty); diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 3dadb33c9691..f706ecea9751 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -9,7 +9,7 @@ use rustc_target::abi::call::{FnAbi, PassMode}; use std::iter; use rustc_index::bit_set::BitSet; -use rustc_index::vec::IndexVec; +use rustc_index::IndexVec; use self::debuginfo::{FunctionDebugContext, PerLocalVarDebugInfo}; use self::place::PlaceRef; @@ -152,7 +152,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, instance: Instance<'tcx>, ) { - assert!(!instance.substs.needs_infer()); + assert!(!instance.substs.has_infer()); let llfn = cx.get_fn(instance); @@ -304,7 +304,17 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bug!("spread argument isn't a tuple?!"); }; - let place = PlaceRef::alloca(bx, bx.layout_of(arg_ty)); + let layout = bx.layout_of(arg_ty); + + // FIXME: support unsized params in "rust-call" ABI + if layout.is_unsized() { + span_bug!( + arg_decl.source_info.span, + "\"rust-call\" ABI does not support unsized params", + ); + } + + let place = PlaceRef::alloca(bx, layout); for i in 0..tupled_arg_tys.len() { let arg = &fx.fn_abi.args[idx]; idx += 1; diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 1633cfef19d2..a58a61cd567f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -211,7 +211,6 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { ) -> V { let dl = &bx.tcx().data_layout; let cast_to_layout = bx.cx().layout_of(cast_to); - let cast_to_size = cast_to_layout.layout.size(); let cast_to = bx.cx().immediate_backend_type(cast_to_layout); if self.layout.abi.is_uninhabited() { return bx.cx().const_poison(cast_to); @@ -261,21 +260,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { _ => (tag_imm, bx.cx().immediate_backend_type(tag_op.layout)), }; - let tag_size = tag_scalar.size(bx.cx()); - let max_unsigned = tag_size.unsigned_int_max(); - let max_signed = tag_size.signed_int_max() as u128; - let min_signed = max_signed + 1; let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32(); - let niche_end = niche_start.wrapping_add(relative_max as u128) & max_unsigned; - let range = tag_scalar.valid_range(bx.cx()); - - let sle = |lhs: u128, rhs: u128| -> bool { - // Signed and unsigned comparisons give the same results, - // except that in signed comparisons an integer with the - // sign bit set is less than one with the sign bit clear. - // Toggle the sign bit to do a signed comparison. - (lhs ^ min_signed) <= (rhs ^ min_signed) - }; // We have a subrange `niche_start..=niche_end` inside `range`. // If the value of the tag is inside this subrange, it's a @@ -291,49 +276,6 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { // untagged_variant // } // However, we will likely be able to emit simpler code. - - // Find the least and greatest values in `range`, considered - // both as signed and unsigned. - let (low_unsigned, high_unsigned) = if range.start <= range.end { - (range.start, range.end) - } else { - (0, max_unsigned) - }; - let (low_signed, high_signed) = if sle(range.start, range.end) { - (range.start, range.end) - } else { - (min_signed, max_signed) - }; - - let niches_ule = niche_start <= niche_end; - let niches_sle = sle(niche_start, niche_end); - let cast_smaller = cast_to_size <= tag_size; - - // In the algorithm above, we can change - // cast(relative_tag) + niche_variants.start() - // into - // cast(tag + (niche_variants.start() - niche_start)) - // if either the casted type is no larger than the original - // type, or if the niche values are contiguous (in either the - // signed or unsigned sense). - let can_incr = cast_smaller || niches_ule || niches_sle; - - let data_for_boundary_niche = || -> Option<(IntPredicate, u128)> { - if !can_incr { - None - } else if niche_start == low_unsigned { - Some((IntPredicate::IntULE, niche_end)) - } else if niche_end == high_unsigned { - Some((IntPredicate::IntUGE, niche_start)) - } else if niche_start == low_signed { - Some((IntPredicate::IntSLE, niche_end)) - } else if niche_end == high_signed { - Some((IntPredicate::IntSGE, niche_start)) - } else { - None - } - }; - let (is_niche, tagged_discr, delta) = if relative_max == 0 { // Best case scenario: only one tagged variant. This will // likely become just a comparison and a jump. @@ -349,40 +291,6 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { let tagged_discr = bx.cx().const_uint(cast_to, niche_variants.start().as_u32() as u64); (is_niche, tagged_discr, 0) - } else if let Some((predicate, constant)) = data_for_boundary_niche() { - // The niche values are either the lowest or the highest in - // `range`. We can avoid the first subtraction in the - // algorithm. - // The algorithm is now this: - // is_niche = tag <= niche_end - // discr = if is_niche { - // cast(tag + (niche_variants.start() - niche_start)) - // } else { - // untagged_variant - // } - // (the first line may instead be tag >= niche_start, - // and may be a signed or unsigned comparison) - // The arithmetic must be done before the cast, so we can - // have the correct wrapping behavior. See issue #104519 for - // the consequences of getting this wrong. - let is_niche = - bx.icmp(predicate, tag, bx.cx().const_uint_big(tag_llty, constant)); - let delta = (niche_variants.start().as_u32() as u128).wrapping_sub(niche_start); - let incr_tag = if delta == 0 { - tag - } else { - bx.add(tag, bx.cx().const_uint_big(tag_llty, delta)) - }; - - let cast_tag = if cast_smaller { - bx.intcast(incr_tag, cast_to, false) - } else if niches_ule { - bx.zext(incr_tag, cast_to) - } else { - bx.sext(incr_tag, cast_to) - }; - - (is_niche, cast_tag, 0) } else { // The special cases don't apply, so we'll have to go with // the general algorithm. diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index d88226f5db05..64452472eeca 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -12,6 +12,7 @@ use rustc_middle::mir::Operand; use rustc_middle::ty::cast::{CastTy, IntTy}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt}; +use rustc_session::config::OptLevel; use rustc_span::source_map::{Span, DUMMY_SP}; use rustc_target::abi::{self, FIRST_VARIANT}; @@ -231,10 +232,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (ScalarOrZst::Scalar(in_scalar), ScalarOrZst::Scalar(out_scalar)) if in_scalar.size(self.cx) == out_scalar.size(self.cx) => { + let operand_bty = bx.backend_type(operand.layout); let cast_bty = bx.backend_type(cast); - Some(OperandValue::Immediate( - self.transmute_immediate(bx, imm, in_scalar, out_scalar, cast_bty), - )) + Some(OperandValue::Immediate(self.transmute_immediate( + bx, + imm, + in_scalar, + operand_bty, + out_scalar, + cast_bty, + ))) } _ => None, } @@ -250,11 +257,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { && in_a.size(self.cx) == out_a.size(self.cx) && in_b.size(self.cx) == out_b.size(self.cx) { + let in_a_ibty = bx.scalar_pair_element_backend_type(operand.layout, 0, false); + let in_b_ibty = bx.scalar_pair_element_backend_type(operand.layout, 1, false); let out_a_ibty = bx.scalar_pair_element_backend_type(cast, 0, false); let out_b_ibty = bx.scalar_pair_element_backend_type(cast, 1, false); Some(OperandValue::Pair( - self.transmute_immediate(bx, imm_a, in_a, out_a, out_a_ibty), - self.transmute_immediate(bx, imm_b, in_b, out_b, out_b_ibty), + self.transmute_immediate(bx, imm_a, in_a, in_a_ibty, out_a, out_a_ibty), + self.transmute_immediate(bx, imm_b, in_b, in_b_ibty, out_b, out_b_ibty), )) } else { None @@ -273,6 +282,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx: &mut Bx, mut imm: Bx::Value, from_scalar: abi::Scalar, + from_backend_ty: Bx::Type, to_scalar: abi::Scalar, to_backend_ty: Bx::Type, ) -> Bx::Value { @@ -280,6 +290,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { use abi::Primitive::*; imm = bx.from_immediate(imm); + + // When scalars are passed by value, there's no metadata recording their + // valid ranges. For example, `char`s are passed as just `i32`, with no + // way for LLVM to know that they're 0x10FFFF at most. Thus we assume + // the range of the input value too, not just the output range. + self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty); + imm = match (from_scalar.primitive(), to_scalar.primitive()) { (Int(..) | F32 | F64, Int(..) | F32 | F64) => bx.bitcast(imm, to_backend_ty), (Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty), @@ -294,10 +311,55 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.bitcast(int_imm, to_backend_ty) } }; + self.assume_scalar_range(bx, imm, to_scalar, to_backend_ty); imm = bx.to_immediate_scalar(imm, to_scalar); imm } + fn assume_scalar_range( + &self, + bx: &mut Bx, + imm: Bx::Value, + scalar: abi::Scalar, + backend_ty: Bx::Type, + ) { + if matches!(self.cx.sess().opts.optimize, OptLevel::No | OptLevel::Less) + // For now, the critical niches are all over `Int`eger values. + // Should floating-point values or pointers ever get more complex + // niches, then this code will probably want to handle them too. + || !matches!(scalar.primitive(), abi::Primitive::Int(..)) + || scalar.is_always_valid(self.cx) + { + return; + } + + let abi::WrappingRange { start, end } = scalar.valid_range(self.cx); + + if start <= end { + if start > 0 { + let low = bx.const_uint_big(backend_ty, start); + let cmp = bx.icmp(IntPredicate::IntUGE, imm, low); + bx.assume(cmp); + } + + let type_max = scalar.size(self.cx).unsigned_int_max(); + if end < type_max { + let high = bx.const_uint_big(backend_ty, end); + let cmp = bx.icmp(IntPredicate::IntULE, imm, high); + bx.assume(cmp); + } + } else { + let low = bx.const_uint_big(backend_ty, start); + let cmp_low = bx.icmp(IntPredicate::IntUGE, imm, low); + + let high = bx.const_uint_big(backend_ty, end); + let cmp_high = bx.icmp(IntPredicate::IntULE, imm, high); + + let or = bx.or(cmp_low, cmp_high); + bx.assume(or); + } + } + pub fn codegen_rvalue_unsized( &mut self, bx: &mut Bx, @@ -604,13 +666,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - mir::Rvalue::NullaryOp(null_op, ty) => { + mir::Rvalue::NullaryOp(ref null_op, ty) => { let ty = self.monomorphize(ty); assert!(bx.cx().type_is_sized(ty)); let layout = bx.cx().layout_of(ty); let val = match null_op { mir::NullOp::SizeOf => layout.size.bytes(), mir::NullOp::AlignOf => layout.align.abi.bytes(), + mir::NullOp::OffsetOf(fields) => { + layout.offset_of_subfield(bx.cx(), fields.iter().map(|f| f.index())).bytes() + } }; let val = bx.cx().const_usize(val); let tcx = self.cx.tcx(); @@ -754,8 +819,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .builtin_deref(true) .unwrap_or_else(|| bug!("deref of non-pointer {:?}", input_ty)) .ty; - let llty = bx.cx().backend_type(bx.cx().layout_of(pointee_type)); - bx.inbounds_gep(llty, lhs, &[rhs]) + let pointee_layout = bx.cx().layout_of(pointee_type); + if pointee_layout.is_zst() { + // `Offset` works in terms of the size of pointee, + // so offsetting a pointer to ZST is a noop. + lhs + } else { + let llty = bx.cx().backend_type(pointee_layout); + bx.inbounds_gep(llty, lhs, &[rhs]) + } } mir::BinOp::Shl => common::build_unchecked_lshift(bx, lhs, rhs), mir::BinOp::Shr => common::build_unchecked_rshift(bx, input_ty, lhs, rhs), diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 611dd3d1cd18..a936b62dd4eb 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -1,3 +1,4 @@ +use crate::errors; use rustc_ast::ast; use rustc_attr::InstructionSetAttr; use rustc_data_structures::fx::FxHashMap; @@ -443,14 +444,10 @@ pub fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_s if let DefKind::AssocFn = tcx.def_kind(id) { let parent_id = tcx.local_parent(id); if let DefKind::Trait | DefKind::Impl { of_trait: true } = tcx.def_kind(parent_id) { - tcx.sess - .struct_span_err( - attr_span, - "`#[target_feature(..)]` cannot be applied to safe trait method", - ) - .span_label(attr_span, "cannot be applied to safe trait method") - .span_label(tcx.def_span(id), "not an `unsafe` function") - .emit(); + tcx.sess.emit_err(errors::TargetFeatureSafeTrait { + span: attr_span, + def: tcx.def_span(id), + }); } } } diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml index 98ac36c1ced7..74030a43c505 100644 --- a/compiler/rustc_const_eval/Cargo.toml +++ b/compiler/rustc_const_eval/Cargo.toml @@ -14,6 +14,7 @@ rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } +rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 4bd6fe19931e..99f180f475d6 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -296,12 +296,12 @@ pub fn eval_to_allocation_raw_provider<'tcx>( } let cid = key.value; - let def = cid.instance.def.with_opt_param(); - let is_static = tcx.is_static(def.did); + let def = cid.instance.def.def_id(); + let is_static = tcx.is_static(def); let mut ecx = InterpCx::new( tcx, - tcx.def_span(def.did), + tcx.def_span(def), key.param_env, // Statics (and promoteds inside statics) may access other statics, because unlike consts // they do not have to behave "as if" they were evaluated at runtime. diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index a5dfd1072f0a..814b67b46ec7 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -375,9 +375,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> { match instance { ty::InstanceDef::Item(def) => { - if ecx.tcx.is_ctfe_mir_available(def.did) { - Ok(ecx.tcx.mir_for_ctfe_opt_const_arg(def)) - } else if ecx.tcx.def_kind(def.did) == DefKind::AssocConst { + if ecx.tcx.is_ctfe_mir_available(def) { + Ok(ecx.tcx.mir_for_ctfe(def)) + } else if ecx.tcx.def_kind(def) == DefKind::AssocConst { let guar = ecx.tcx.sess.delay_span_bug( rustc_span::DUMMY_SP, "This is likely a const item that is missing from its impl", @@ -386,7 +386,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } else { // `find_mir_or_eval_fn` checks that this is a const fn before even calling us, // so this should be unreachable. - let path = ecx.tcx.def_path_str(def.did); + let path = ecx.tcx.def_path_str(def); bug!("trying to call extern function `{path}` at compile-time"); } } @@ -410,9 +410,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, // Execution might have wandered off into other crates, so we cannot do a stability- // sensitive check here. But we can at least rule out functions that are not const // at all. - if !ecx.tcx.is_const_fn_raw(def.did) { + if !ecx.tcx.is_const_fn_raw(def) { // allow calling functions inside a trait marked with #[const_trait]. - if !ecx.tcx.is_const_default_method(def.did) { + if !ecx.tcx.is_const_default_method(def) { // We certainly do *not* want to actually call the fn // though, so be sure we return here. throw_unsup_format!("calling non-const function `{}`", instance) diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index 557e721249d7..015a9beab832 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -211,18 +211,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let variant_index_relative = u32::try_from(variant_index_relative) .expect("we checked that this fits into a u32"); // Then computing the absolute variant idx should not overflow any more. - let variant_index = variants_start - .checked_add(variant_index_relative) - .expect("overflow computing absolute variant idx"); - let variants_len = op + let variant_index = VariantIdx::from_u32( + variants_start + .checked_add(variant_index_relative) + .expect("overflow computing absolute variant idx"), + ); + let variants = op .layout .ty .ty_adt_def() .expect("tagged layout for non adt") - .variants() - .len(); - assert!(usize::try_from(variant_index).unwrap() < variants_len); - VariantIdx::from_u32(variant_index) + .variants(); + assert!(variant_index < variants.next_index()); + variant_index } else { untagged_variant } diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 3e58a58aef7d..361ce123c78e 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -5,7 +5,7 @@ use std::mem; use either::{Either, Left, Right}; use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData}; -use rustc_index::vec::IndexVec; +use rustc_index::IndexVec; use rustc_middle::mir; use rustc_middle::mir::interpret::{ErrorHandled, InterpError}; use rustc_middle::ty::layout::{ @@ -132,11 +132,10 @@ pub struct Frame<'mir, 'tcx, Prov: Provenance = AllocId, Extra = ()> { } /// What we store about a frame in an interpreter backtrace. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct FrameInfo<'tcx> { pub instance: ty::Instance<'tcx>, pub span: Span, - pub lint_root: Option, } #[derive(Clone, Copy, Eq, PartialEq, Debug)] // Miri debug-prints these @@ -462,10 +461,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { instance: ty::InstanceDef<'tcx>, promoted: Option, ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> { - let def = instance.with_opt_param(); trace!("load mir(instance={:?}, promoted={:?})", instance, promoted); let body = if let Some(promoted) = promoted { - &self.tcx.promoted_mir_opt_const_arg(def)[promoted] + let def = instance.def_id(); + &self.tcx.promoted_mir(def)[promoted] } else { M::load_mir(self, instance)? }; @@ -503,13 +502,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// The `substs` are assumed to already be in our interpreter "universe" (param_env). pub(super) fn resolve( &self, - def: ty::WithOptConstParam, + def: DefId, substs: SubstsRef<'tcx>, ) -> InterpResult<'tcx, ty::Instance<'tcx>> { trace!("resolve: {:?}, {:#?}", def, substs); trace!("param_env: {:#?}", self.param_env); trace!("substs: {:#?}", substs); - match ty::Instance::resolve_opt_const_arg(*self.tcx, self.param_env, def, substs) { + match ty::Instance::resolve(*self.tcx, self.param_env, def, substs) { Ok(Some(instance)) => Ok(instance), Ok(None) => throw_inval!(TooGeneric), @@ -947,10 +946,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // This deliberately does *not* honor `requires_caller_location` since it is used for much // more than just panics. for frame in stack.iter().rev() { - let lint_root = frame.lint_root(); let span = frame.current_span(); - - frames.push(FrameInfo { span, instance: frame.instance, lint_root }); + frames.push(FrameInfo { span, instance: frame.instance }); } trace!("generate stacktrace: {:#?}", frames); frames diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 26fb041b4551..a77c699c22f7 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -75,7 +75,7 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>( } sym::type_id => { ensure_monomorphic_enough(tcx, tp_ty)?; - ConstValue::from_u64(tcx.type_id_hash(tp_ty)) + ConstValue::from_u64(tcx.type_id_hash(tp_ty).as_u64()) } sym::variant_count => match tp_ty.kind() { // Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough. @@ -286,14 +286,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { sym::write_bytes => { self.write_bytes_intrinsic(&args[0], &args[1], &args[2])?; } - sym::offset => { - let ptr = self.read_pointer(&args[0])?; - let offset_count = self.read_target_isize(&args[1])?; - let pointee_ty = substs.type_at(0); - - let offset_ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?; - self.write_pointer(offset_ptr, dest)?; - } sym::arith_offset => { let ptr = self.read_pointer(&args[0])?; let offset_count = self.read_target_isize(&args[1])?; diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index 0291cca7378a..b448e3a24c68 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -104,7 +104,7 @@ pub trait Machine<'mir, 'tcx>: Sized { type FrameExtra; /// Extra data stored in every allocation. - type AllocExtra: Debug + Clone + 'static; + type AllocExtra: Debug + Clone + 'tcx; /// Type for the bytes of the allocation. type Bytes: AllocBytes + 'static; diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index a3764a7d1426..d5b6a581a79f 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -215,7 +215,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.allocate_raw_ptr(alloc, kind) } - /// This can fail only of `alloc` contains provenance. + /// This can fail only if `alloc` contains provenance. pub fn allocate_raw_ptr( &mut self, alloc: Allocation, @@ -807,9 +807,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { DumpAllocs { ecx: self, allocs } } - /// Print leaked memory. Allocations reachable from `static_roots` or a `Global` allocation - /// are not considered leaked. Leaks whose kind `may_leak()` returns true are not reported. - pub fn leak_report(&self, static_roots: &[AllocId]) -> usize { + /// Find leaked allocations. Allocations reachable from `static_roots` or a `Global` allocation + /// are not considered leaked, as well as leaks whose kind's `may_leak()` returns true. + pub fn find_leaked_allocations( + &self, + static_roots: &[AllocId], + ) -> Vec<(AllocId, MemoryKind, Allocation)> + { // Collect the set of allocations that are *reachable* from `Global` allocations. let reachable = { let mut reachable = FxHashSet::default(); @@ -833,14 +837,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; // All allocations that are *not* `reachable` and *not* `may_leak` are considered leaking. - let leaks: Vec<_> = self.memory.alloc_map.filter_map_collect(|&id, &(kind, _)| { - if kind.may_leak() || reachable.contains(&id) { None } else { Some(id) } - }); - let n = leaks.len(); - if n > 0 { - eprintln!("The following memory was leaked: {:?}", self.dump_allocs(leaks)); - } - n + self.memory.alloc_map.filter_map_collect(|id, (kind, alloc)| { + if kind.may_leak() || reachable.contains(id) { + None + } else { + Some((*id, *kind, alloc.clone())) + } + }) } } diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 4decfe863e63..7186148daf0b 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -299,6 +299,30 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok((val, false, ty)) } + fn binary_ptr_op( + &self, + bin_op: mir::BinOp, + left: &ImmTy<'tcx, M::Provenance>, + right: &ImmTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { + use rustc_middle::mir::BinOp::*; + + match bin_op { + // Pointer ops that are always supported. + Offset => { + let ptr = left.to_scalar().to_pointer(self)?; + let offset_count = right.to_scalar().to_target_isize(self)?; + let pointee_ty = left.layout.ty.builtin_deref(true).unwrap().ty; + + let offset_ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?; + Ok((Scalar::from_maybe_pointer(offset_ptr, self), false, left.layout.ty)) + } + + // Fall back to machine hook so Miri can support more pointer ops. + _ => M::binary_ptr_op(self, bin_op, left, right), + } + } + /// Returns the result of the specified operation, whether it overflowed, and /// the result type. pub fn overflowing_binary_op( @@ -368,7 +392,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { right.layout.ty ); - M::binary_ptr_op(self, bin_op, left, right) + self.binary_ptr_op(bin_op, left, right) } _ => span_bug!( self.cur_span(), diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index 03b09cf830b7..2a31a59ad6c7 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -5,7 +5,7 @@ use either::{Either, Left, Right}; use rustc_ast::Mutability; -use rustc_index::vec::IndexSlice; +use rustc_index::IndexSlice; use rustc_middle::mir; use rustc_middle::ty; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 9a366364e769..319b80d66e18 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -113,8 +113,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Intrinsic(box intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?, - // Statements we do not track. - PlaceMention(..) | AscribeUserType(..) => {} + // Evaluate the place expression, without reading from it. + PlaceMention(box place) => { + let _ = self.eval_place(*place)?; + } + + // This exists purely to guide borrowck lifetime inference, and does not have + // an operational effect. + AscribeUserType(..) => {} // Currently, Miri discards Coverage statements. Coverage statements are only injected // via an optional compile time MIR pass and have no side effects. Since Coverage @@ -280,20 +286,23 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_immediate(*val, &dest)?; } - NullaryOp(null_op, ty) => { + NullaryOp(ref null_op, ty) => { let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty)?; let layout = self.layout_of(ty)?; - if layout.is_unsized() { + if let mir::NullOp::SizeOf | mir::NullOp::AlignOf = null_op && layout.is_unsized() { // FIXME: This should be a span_bug (#80742) self.tcx.sess.delay_span_bug( self.frame().current_span(), - &format!("Nullary MIR operator called for unsized type {}", ty), + &format!("{null_op:?} MIR operator called for unsized type {ty}"), ); throw_inval!(SizeOfUnsizedType(ty)); } let val = match null_op { mir::NullOp::SizeOf => layout.size.bytes(), mir::NullOp::AlignOf => layout.align.abi.bytes(), + mir::NullOp::OffsetOf(fields) => { + layout.offset_of_subfield(self, fields.iter().map(|f| f.index())).bytes() + } }; self.write_scalar(Scalar::from_target_usize(val, self), &dest)?; } diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index a07702f7d9bb..df3879200101 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -83,8 +83,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { (fn_val, self.fn_abi_of_fn_ptr(fn_sig_binder, extra_args)?, false) } ty::FnDef(def_id, substs) => { - let instance = - self.resolve(ty::WithOptConstParam::unknown(def_id), substs)?; + let instance = self.resolve(def_id, substs)?; ( FnVal::Instance(instance), self.fn_abi_of_instance(instance, extra_args)?, diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index bf2b4ee69abf..22bdd4d2c3fb 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -14,7 +14,7 @@ where T: TypeVisitable>, { debug!("ensure_monomorphic_enough: ty={:?}", ty); - if !ty.needs_subst() { + if !ty.has_param() { return Ok(()); } @@ -27,7 +27,7 @@ where type BreakTy = FoundParam; fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { - if !ty.needs_subst() { + if !ty.has_param() { return ControlFlow::Continue(()); } @@ -36,7 +36,7 @@ where ty::Closure(def_id, substs) | ty::Generator(def_id, substs, ..) | ty::FnDef(def_id, substs) => { - let instance = ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)); + let instance = ty::InstanceDef::Item(def_id); let unused_params = self.tcx.unused_generic_params(instance); for (index, subst) in substs.into_iter().enumerate() { let index = index @@ -46,7 +46,7 @@ where // are used and require substitution. // Just in case there are closures or generators within this subst, // recurse. - if unused_params.is_used(index) && subst.needs_subst() { + if unused_params.is_used(index) && subst.has_param() { return subst.visit_with(self); } } diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 93b5273e1b14..e06b634cdc33 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -784,7 +784,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> Abi::Scalar(scalar_layout) => { if !scalar_layout.is_uninit_valid() { // There is something to check here. - let scalar = self.read_scalar(op, "initiailized scalar value")?; + let scalar = self.read_scalar(op, "initialized scalar value")?; self.visit_scalar(scalar, scalar_layout)?; } } @@ -794,7 +794,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> // the other must be init. if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() { let (a, b) = - self.read_immediate(op, "initiailized scalar value")?.to_scalar_pair(); + self.read_immediate(op, "initialized scalar value")?.to_scalar_pair(); self.visit_scalar(a, a_layout)?; self.visit_scalar(b, b_layout)?; } diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 5ab389d04c7e..1b66eca97a57 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -34,7 +34,7 @@ pub mod transform; pub mod util; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_macros::fluent_messages; +use rustc_fluent_macro::fluent_messages; use rustc_middle::ty; use rustc_middle::ty::query::Providers; diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 9dad94790539..696c45177009 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -558,7 +558,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { Rvalue::Cast(_, _, _) => {} - Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {} + Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_), _) => {} Rvalue::ShallowInitBox(_, _) => {} Rvalue::UnaryOp(_, operand) => { @@ -874,7 +874,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { debug!("Resolving ({:?}) -> {:?}", callee, instance); if let Ok(Some(func)) = instance { if let InstanceDef::Item(def) = func.def { - callee = def.did; + callee = def; } } } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index c0f5b3725b36..4fb668545712 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -14,6 +14,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::{suggest_constraining_type_param, Adt, Closure, FnDef, FnPtr, Param, Ty}; use rustc_middle::ty::{Binder, TraitRef}; +use rustc_middle::util::{call_kind, CallDesugaringKind, CallKind}; use rustc_session::parse::feature_err; use rustc_span::symbol::sym; use rustc_span::{BytePos, Pos, Span, Symbol}; @@ -21,7 +22,6 @@ use rustc_trait_selection::traits::SelectionContext; use super::ConstCx; use crate::errors; -use crate::util::{call_kind, CallDesugaringKind, CallKind}; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Status { @@ -296,7 +296,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { diag_trait(&mut err, self_ty, tcx.require_lang_item(LangItem::Deref, Some(span))); err } - _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentV1Methods) => ccx + _ if tcx.opt_parent(callee) == tcx.get_diagnostic_item(sym::ArgumentMethods) => ccx .tcx .sess .create_err(errors::NonConstFmtMacroCall { span, kind: ccx.const_kind() }), @@ -610,10 +610,11 @@ pub struct RawPtrComparison; impl<'tcx> NonConstOp<'tcx> for RawPtrComparison { fn build_error( &self, - _: &ConstCx<'_, 'tcx>, + ccx: &ConstCx<'_, 'tcx>, span: Span, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - span_bug!(span, "raw ptr comparison should already be caught in the trait system"); + // FIXME(const_trait_impl): revert to span_bug? + ccx.tcx.sess.create_err(errors::RawPtrComparisonErr { span }) } } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 6758cba2eed3..bf688f2b34e9 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -364,9 +364,8 @@ where assert!(promoted.is_none() || Q::ALLOW_PROMOTED); // Don't peek inside trait associated constants. - if promoted.is_none() && cx.tcx.trait_of_item(def.did).is_none() { - assert_eq!(def.const_param_did, None, "expected associated const: {def:?}"); - let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def.did); + if promoted.is_none() && cx.tcx.trait_of_item(def).is_none() { + let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def); if !Q::in_qualifs(&qualifs) { return false; diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 7919aed097a4..0e2d9ee8fb2f 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -21,7 +21,7 @@ use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{self, List, TyCtxt, TypeVisitableExt}; use rustc_span::Span; -use rustc_index::vec::{Idx, IndexSlice, IndexVec}; +use rustc_index::{Idx, IndexSlice, IndexVec}; use std::cell::Cell; use std::{cmp, iter, mem}; @@ -514,6 +514,7 @@ impl<'tcx> Validator<'_, 'tcx> { Rvalue::NullaryOp(op, _) => match op { NullOp::SizeOf => {} NullOp::AlignOf => {} + NullOp::OffsetOf(_) => {} }, Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable), @@ -828,7 +829,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) -> Body<'tcx> { - let def = self.source.source.with_opt_param(); + let def = self.source.source.def_id(); let mut rvalue = { let promoted = &mut self.promoted; let promoted_id = Promoted::new(next_promoted_id); @@ -836,7 +837,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let mut promoted_operand = |ty, span| { promoted.span = span; promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span); - let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def.did)); + let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def)); let uneval = mir::UnevaluatedConst { def, substs, promoted: Some(promoted_id) }; Operand::Constant(Box::new(Constant { diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index d4bed97380ba..03ab2e568df8 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -2,15 +2,16 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::bit_set::BitSet; -use rustc_index::vec::IndexVec; +use rustc_index::IndexVec; use rustc_infer::traits::Reveal; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{ traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location, - MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, ProjectionElem, - RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, Terminator, - TerminatorKind, UnOp, UnwindAction, VarDebugInfo, VarDebugInfoContents, START_BLOCK, + MirPass, MirPhase, NonDivergingIntrinsic, NullOp, Operand, Place, PlaceElem, PlaceRef, + ProjectionElem, RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, + Terminator, TerminatorKind, UnOp, UnwindAction, VarDebugInfo, VarDebugInfoContents, + START_BLOCK, }; use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt}; use rustc_mir_dataflow::impls::MaybeStorageLive; @@ -262,7 +263,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // We sometimes have to use `defining_opaque_types` for subtyping // to succeed here and figuring out how exactly that should work // is annoying. It is harmless enough to just not validate anything - // in that case. We still check this after analysis as all opque + // in that case. We still check this after analysis as all opaque // types have been revealed at this point. if (src, dest).has_opaque_types() { return true; @@ -711,10 +712,54 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } } + Rvalue::NullaryOp(NullOp::OffsetOf(fields), container) => { + let fail_out_of_bounds = |this: &Self, location, field, ty| { + this.fail(location, format!("Out of bounds field {field:?} for {ty:?}")); + }; + + let mut current_ty = *container; + + for field in fields.iter() { + match current_ty.kind() { + ty::Tuple(fields) => { + let Some(&f_ty) = fields.get(field.as_usize()) else { + fail_out_of_bounds(self, location, field, current_ty); + return; + }; + + current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty); + } + ty::Adt(adt_def, substs) => { + if adt_def.is_enum() { + self.fail( + location, + format!("Cannot get field offset from enum {current_ty:?}"), + ); + return; + } + + let Some(field) = adt_def.non_enum_variant().fields.get(field) else { + fail_out_of_bounds(self, location, field, current_ty); + return; + }; + + let f_ty = field.ty(self.tcx, substs); + current_ty = self.tcx.normalize_erasing_regions(self.param_env, f_ty); + } + _ => { + self.fail( + location, + format!("Cannot get field offset from non-adt type {current_ty:?}"), + ); + return; + } + } + } + } Rvalue::Repeat(_, _) | Rvalue::ThreadLocalRef(_) | Rvalue::AddressOf(_, _) - | Rvalue::NullaryOp(_, _) + | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) | Rvalue::Discriminant(_) => {} } self.super_rvalue(rvalue, location); @@ -757,14 +802,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { } } } - StatementKind::PlaceMention(..) => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { - self.fail( - location, - "`PlaceMention` should have been removed after drop lowering phase", - ); - } - } StatementKind::AscribeUserType(..) => { if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { self.fail( @@ -874,6 +911,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { StatementKind::StorageDead(_) | StatementKind::Coverage(_) | StatementKind::ConstEvalCounter + | StatementKind::PlaceMention(..) | StatementKind::Nop => {} } diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs index c0aabd77ceea..7641f560714d 100644 --- a/compiler/rustc_const_eval/src/util/mod.rs +++ b/compiler/rustc_const_eval/src/util/mod.rs @@ -1,14 +1,9 @@ mod alignment; -mod call_kind; mod check_validity_requirement; -pub mod collect_writes; mod compare_types; -mod find_self_call; mod type_name; pub use self::alignment::is_disaligned; -pub use self::call_kind::{call_kind, CallDesugaringKind, CallKind}; pub use self::check_validity_requirement::check_validity_requirement; pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype}; -pub use self::find_self_call::find_self_call; pub use self::type_name::type_name; diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 2102f09c56a0..5e05fe463ed2 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -21,13 +21,11 @@ rustc-hash = "1.1.0" rustc_index = { path = "../rustc_index", package = "rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } -serde_json = "1.0.59" smallvec = { version = "1.8.1", features = [ "const_generics", "union", "may_dangle", ] } -stable_deref_trait = "1.0.0" stacker = "0.1.15" tempfile = "3.2" thin-vec = "0.2.12" diff --git a/compiler/rustc_data_structures/src/aligned.rs b/compiler/rustc_data_structures/src/aligned.rs new file mode 100644 index 000000000000..0e5ecfd9bff6 --- /dev/null +++ b/compiler/rustc_data_structures/src/aligned.rs @@ -0,0 +1,33 @@ +use std::ptr::Alignment; + +/// Returns the ABI-required minimum alignment of a type in bytes. +/// +/// This is equivalent to [`mem::align_of`], but also works for some unsized +/// types (e.g. slices or rustc's `List`s). +/// +/// [`mem::align_of`]: std::mem::align_of +pub const fn align_of() -> Alignment { + T::ALIGN +} + +/// A type with a statically known alignment. +/// +/// # Safety +/// +/// `Self::ALIGN` must be equal to the alignment of `Self`. For sized types it +/// is [`mem::align_of()`], for unsized types it depends on the type, for +/// example `[T]` has alignment of `T`. +/// +/// [`mem::align_of()`]: std::mem::align_of +pub unsafe trait Aligned { + /// Alignment of `Self`. + const ALIGN: Alignment; +} + +unsafe impl Aligned for T { + const ALIGN: Alignment = Alignment::of::(); +} + +unsafe impl Aligned for [T] { + const ALIGN: Alignment = Alignment::of::(); +} diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs index b6e866f15efe..6fa76981408c 100644 --- a/compiler/rustc_data_structures/src/fingerprint.rs +++ b/compiler/rustc_data_structures/src/fingerprint.rs @@ -1,4 +1,4 @@ -use crate::stable_hasher; +use crate::stable_hasher::{Hash64, StableHasher, StableHasherResult}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use std::hash::{Hash, Hasher}; @@ -9,32 +9,49 @@ mod tests; #[repr(C)] pub struct Fingerprint(u64, u64); +pub trait FingerprintComponent { + fn as_u64(&self) -> u64; +} + +impl FingerprintComponent for Hash64 { + #[inline] + fn as_u64(&self) -> u64 { + Hash64::as_u64(*self) + } +} + +impl FingerprintComponent for u64 { + #[inline] + fn as_u64(&self) -> u64 { + *self + } +} + impl Fingerprint { pub const ZERO: Fingerprint = Fingerprint(0, 0); #[inline] - pub fn new(_0: u64, _1: u64) -> Fingerprint { - Fingerprint(_0, _1) + pub fn new(_0: A, _1: B) -> Fingerprint + where + A: FingerprintComponent, + B: FingerprintComponent, + { + Fingerprint(_0.as_u64(), _1.as_u64()) } #[inline] - pub fn from_smaller_hash(hash: u64) -> Fingerprint { - Fingerprint(hash, hash) - } - - #[inline] - pub fn to_smaller_hash(&self) -> u64 { + pub fn to_smaller_hash(&self) -> Hash64 { // Even though both halves of the fingerprint are expected to be good // quality hash values, let's still combine the two values because the // Fingerprints in DefPathHash have the StableCrateId portion which is // the same for all DefPathHashes from the same crate. Combining the // two halves makes sure we get a good quality hash in such cases too. - self.0.wrapping_mul(3).wrapping_add(self.1) + Hash64::new(self.0.wrapping_mul(3).wrapping_add(self.1)) } #[inline] - pub fn as_value(&self) -> (u64, u64) { - (self.0, self.1) + pub fn split(&self) -> (Hash64, Hash64) { + (Hash64::new(self.0), Hash64::new(self.1)) } #[inline] @@ -131,9 +148,9 @@ impl FingerprintHasher for crate::unhash::Unhasher { } } -impl stable_hasher::StableHasherResult for Fingerprint { +impl StableHasherResult for Fingerprint { #[inline] - fn finish(hasher: stable_hasher::StableHasher) -> Self { + fn finish(hasher: StableHasher) -> Self { let (_0, _1) = hasher.finalize(); Fingerprint(_0, _1) } diff --git a/compiler/rustc_data_structures/src/fingerprint/tests.rs b/compiler/rustc_data_structures/src/fingerprint/tests.rs index 9b0783e33ab4..09ec2622a651 100644 --- a/compiler/rustc_data_structures/src/fingerprint/tests.rs +++ b/compiler/rustc_data_structures/src/fingerprint/tests.rs @@ -1,11 +1,12 @@ use super::*; +use crate::stable_hasher::Hash64; // Check that `combine_commutative` is order independent. #[test] fn combine_commutative_is_order_independent() { - let a = Fingerprint::new(0xf6622fb349898b06, 0x70be9377b2f9c610); - let b = Fingerprint::new(0xa9562bf5a2a5303c, 0x67d9b6c82034f13d); - let c = Fingerprint::new(0x0d013a27811dbbc3, 0x9a3f7b3d9142ec43); + let a = Fingerprint::new(Hash64::new(0xf6622fb349898b06), Hash64::new(0x70be9377b2f9c610)); + let b = Fingerprint::new(Hash64::new(0xa9562bf5a2a5303c), Hash64::new(0x67d9b6c82034f13d)); + let c = Fingerprint::new(Hash64::new(0x0d013a27811dbbc3), Hash64::new(0x9a3f7b3d9142ec43)); let permutations = [(a, b, c), (a, c, b), (b, a, c), (b, c, a), (c, a, b), (c, b, a)]; let f = a.combine_commutative(b).combine_commutative(c); for p in &permutations { diff --git a/compiler/rustc_data_structures/src/functor.rs b/compiler/rustc_data_structures/src/functor.rs index 28fcf80b31be..e3fcaccb1bd5 100644 --- a/compiler/rustc_data_structures/src/functor.rs +++ b/compiler/rustc_data_structures/src/functor.rs @@ -1,4 +1,4 @@ -use rustc_index::vec::{Idx, IndexVec}; +use rustc_index::{Idx, IndexVec}; use std::{mem, rc::Rc, sync::Arc}; pub trait IdFunctor: Sized { diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs index 0df9dc112ee6..e76bdac28641 100644 --- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs +++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs @@ -10,7 +10,8 @@ //! use super::ControlFlowGraph; -use rustc_index::vec::{Idx, IndexSlice, IndexVec}; +use rustc_index::{Idx, IndexSlice, IndexVec}; + use std::cmp::Ordering; #[cfg(test)] diff --git a/compiler/rustc_data_structures/src/graph/iterate/mod.rs b/compiler/rustc_data_structures/src/graph/iterate/mod.rs index 01a83b40a75a..9eb4b5278c07 100644 --- a/compiler/rustc_data_structures/src/graph/iterate/mod.rs +++ b/compiler/rustc_data_structures/src/graph/iterate/mod.rs @@ -1,6 +1,6 @@ use super::{DirectedGraph, WithNumNodes, WithStartNode, WithSuccessors}; use rustc_index::bit_set::BitSet; -use rustc_index::vec::{IndexSlice, IndexVec}; +use rustc_index::{IndexSlice, IndexVec}; use std::ops::ControlFlow; #[cfg(test)] diff --git a/compiler/rustc_data_structures/src/graph/mod.rs b/compiler/rustc_data_structures/src/graph/mod.rs index 3560df6e5e20..e06ab2fe36b9 100644 --- a/compiler/rustc_data_structures/src/graph/mod.rs +++ b/compiler/rustc_data_structures/src/graph/mod.rs @@ -1,4 +1,4 @@ -use rustc_index::vec::Idx; +use rustc_index::Idx; pub mod dominators; pub mod implementation; diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs index 28c357e54dd6..cf9312ea8fb6 100644 --- a/compiler/rustc_data_structures/src/graph/scc/mod.rs +++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs @@ -8,7 +8,7 @@ use crate::fx::FxHashSet; use crate::graph::vec_graph::VecGraph; use crate::graph::{DirectedGraph, GraphSuccessors, WithNumEdges, WithNumNodes, WithSuccessors}; -use rustc_index::vec::{Idx, IndexSlice, IndexVec}; +use rustc_index::{Idx, IndexSlice, IndexVec}; use std::ops::Range; #[cfg(test)] diff --git a/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs b/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs index 94232bb7626e..00f6266ce1df 100644 --- a/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs +++ b/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs @@ -1,5 +1,5 @@ use crate::graph::{DirectedGraph, GraphSuccessors, WithNumEdges, WithNumNodes, WithSuccessors}; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_index::{Idx, IndexVec}; #[cfg(test)] mod tests; diff --git a/compiler/rustc_data_structures/src/hashes.rs b/compiler/rustc_data_structures/src/hashes.rs new file mode 100644 index 000000000000..ad068cdbc984 --- /dev/null +++ b/compiler/rustc_data_structures/src/hashes.rs @@ -0,0 +1,132 @@ +//! rustc encodes a lot of hashes. If hashes are stored as `u64` or `u128`, a `derive(Encodable)` +//! will apply varint encoding to the hashes, which is less efficient than directly encoding the 8 +//! or 16 bytes of the hash. +//! +//! The types in this module represent 64-bit or 128-bit hashes produced by a `StableHasher`. +//! `Hash64` and `Hash128` expose some utilty functions to encourage users to not extract the inner +//! hash value as an integer type and accidentally apply varint encoding to it. +//! +//! In contrast with `Fingerprint`, users of these types cannot and should not attempt to construct +//! and decompose these types into constitutent pieces. The point of these types is only to +//! connect the fact that they can only be produced by a `StableHasher` to their +//! `Encode`/`Decode` impls. + +use crate::stable_hasher::{StableHasher, StableHasherResult}; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; +use std::fmt; +use std::ops::BitXorAssign; + +#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)] +pub struct Hash64 { + inner: u64, +} + +impl Hash64 { + pub const ZERO: Hash64 = Hash64 { inner: 0 }; + + #[inline] + pub(crate) fn new(n: u64) -> Self { + Self { inner: n } + } + + #[inline] + pub fn as_u64(self) -> u64 { + self.inner + } +} + +impl BitXorAssign for Hash64 { + #[inline] + fn bitxor_assign(&mut self, rhs: u64) { + self.inner ^= rhs; + } +} + +impl Encodable for Hash64 { + #[inline] + fn encode(&self, s: &mut S) { + s.emit_raw_bytes(&self.inner.to_le_bytes()); + } +} + +impl Decodable for Hash64 { + #[inline] + fn decode(d: &mut D) -> Self { + Self { inner: u64::from_le_bytes(d.read_raw_bytes(8).try_into().unwrap()) } + } +} + +impl StableHasherResult for Hash64 { + #[inline] + fn finish(hasher: StableHasher) -> Self { + Self { inner: hasher.finalize().0 } + } +} + +impl fmt::Debug for Hash64 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.inner.fmt(f) + } +} + +impl fmt::LowerHex for Hash64 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::LowerHex::fmt(&self.inner, f) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)] +pub struct Hash128 { + inner: u128, +} + +impl Hash128 { + #[inline] + pub fn truncate(self) -> Hash64 { + Hash64 { inner: self.inner as u64 } + } + + #[inline] + pub fn wrapping_add(self, other: Self) -> Self { + Self { inner: self.inner.wrapping_add(other.inner) } + } + + #[inline] + pub fn as_u128(self) -> u128 { + self.inner + } +} + +impl Encodable for Hash128 { + #[inline] + fn encode(&self, s: &mut S) { + s.emit_raw_bytes(&self.inner.to_le_bytes()); + } +} + +impl Decodable for Hash128 { + #[inline] + fn decode(d: &mut D) -> Self { + Self { inner: u128::from_le_bytes(d.read_raw_bytes(16).try_into().unwrap()) } + } +} + +impl StableHasherResult for Hash128 { + #[inline] + fn finish(hasher: StableHasher) -> Self { + let (_0, _1) = hasher.finalize(); + Self { inner: u128::from(_0) | (u128::from(_1) << 64) } + } +} + +impl fmt::Debug for Hash128 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.inner.fmt(f) + } +} + +impl fmt::LowerHex for Hash128 { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::LowerHex::fmt(&self.inner, f) + } +} diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index e373bd18402a..004017ec5f31 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -29,10 +29,14 @@ #![feature(get_mut_unchecked)] #![feature(lint_reasons)] #![feature(unwrap_infallible)] +#![feature(strict_provenance)] +#![feature(ptr_alignment_type)] +#![feature(macro_metavar_expr)] #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] +#![deny(unsafe_op_in_unsafe_fn)] #[macro_use] extern crate tracing; @@ -82,7 +86,9 @@ pub mod transitive_relation; pub mod vec_linked_list; pub mod work_queue; pub use atomic_ref::AtomicRef; +pub mod aligned; pub mod frozen; +mod hashes; pub mod owned_slice; pub mod sso; pub mod steal; diff --git a/compiler/rustc_data_structures/src/memmap.rs b/compiler/rustc_data_structures/src/memmap.rs index ef37a606f313..ca908671ae53 100644 --- a/compiler/rustc_data_structures/src/memmap.rs +++ b/compiler/rustc_data_structures/src/memmap.rs @@ -13,7 +13,8 @@ pub struct Mmap(Vec); impl Mmap { #[inline] pub unsafe fn map(file: File) -> io::Result { - memmap2::Mmap::map(&file).map(Mmap) + // Safety: this is in fact not safe. + unsafe { memmap2::Mmap::map(&file).map(Mmap) } } } diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index 1ed584eafad3..572bd4ac21c3 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -87,6 +87,7 @@ use crate::fx::FxHashMap; use std::borrow::Borrow; use std::collections::hash_map::Entry; use std::error::Error; +use std::fmt::Display; use std::fs; use std::intrinsics::unlikely; use std::path::Path; @@ -97,7 +98,6 @@ use std::time::{Duration, Instant}; pub use measureme::EventId; use measureme::{EventIdBuilder, Profiler, SerializableString, StringId}; use parking_lot::RwLock; -use serde_json::json; use smallvec::SmallVec; bitflags::bitflags! { @@ -557,7 +557,7 @@ impl SelfProfiler { let crate_name = crate_name.unwrap_or("unknown-crate"); // HACK(eddyb) we need to pad the PID, strange as it may seem, as its // length can behave as a source of entropy for heap addresses, when - // ASLR is disabled and the heap is otherwise determinic. + // ASLR is disabled and the heap is otherwise deterministic. let pid: u32 = process::id(); let filename = format!("{crate_name}-{pid:07}.rustc_profile"); let path = output_directory.join(&filename); @@ -763,6 +763,31 @@ impl Drop for VerboseTimingGuard<'_> { } } +struct JsonTimePassesEntry<'a> { + pass: &'a str, + time: f64, + start_rss: Option, + end_rss: Option, +} + +impl Display for JsonTimePassesEntry<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { pass: what, time, start_rss, end_rss } = self; + write!(f, r#"{{"pass":"{what}","time":{time},"rss_start":"#).unwrap(); + match start_rss { + Some(rss) => write!(f, "{rss}")?, + None => write!(f, "null")?, + } + write!(f, r#","rss_end":"#)?; + match end_rss { + Some(rss) => write!(f, "{rss}")?, + None => write!(f, "null")?, + } + write!(f, "}}")?; + Ok(()) + } +} + pub fn print_time_passes_entry( what: &str, dur: Duration, @@ -772,13 +797,10 @@ pub fn print_time_passes_entry( ) { match format { TimePassesFormat::Json => { - let json = json!({ - "pass": what, - "time": dur.as_secs_f64(), - "rss_start": start_rss, - "rss_end": end_rss, - }); - eprintln!("time: {json}"); + let entry = + JsonTimePassesEntry { pass: what, time: dur.as_secs_f64(), start_rss, end_rss }; + + eprintln!(r#"time: {entry}"#); return; } TimePassesFormat::Text => (), @@ -894,3 +916,6 @@ cfg_if! { } } } + +#[cfg(test)] +mod tests; diff --git a/compiler/rustc_data_structures/src/profiling/tests.rs b/compiler/rustc_data_structures/src/profiling/tests.rs new file mode 100644 index 000000000000..2b09de085da0 --- /dev/null +++ b/compiler/rustc_data_structures/src/profiling/tests.rs @@ -0,0 +1,19 @@ +use super::JsonTimePassesEntry; + +#[test] +fn with_rss() { + let entry = + JsonTimePassesEntry { pass: "typeck", time: 56.1, start_rss: Some(10), end_rss: Some(20) }; + + assert_eq!(entry.to_string(), r#"{"pass":"typeck","time":56.1,"rss_start":10,"rss_end":20}"#) +} + +#[test] +fn no_rss() { + let entry = JsonTimePassesEntry { pass: "typeck", time: 56.1, start_rss: None, end_rss: None }; + + assert_eq!( + entry.to_string(), + r#"{"pass":"typeck","time":56.1,"rss_start":null,"rss_end":null}"# + ) +} diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs index bd7a86f67800..7ed70ba1e0fc 100644 --- a/compiler/rustc_data_structures/src/sharded.rs +++ b/compiler/rustc_data_structures/src/sharded.rs @@ -1,14 +1,10 @@ use crate::fx::{FxHashMap, FxHasher}; -use crate::sync::{Lock, LockGuard}; +use crate::sync::{CacheAligned, Lock, LockGuard}; use std::borrow::Borrow; use std::collections::hash_map::RawEntryMut; use std::hash::{Hash, Hasher}; use std::mem; -#[derive(Default)] -#[cfg_attr(parallel_compiler, repr(align(64)))] -struct CacheAligned(T); - #[cfg(parallel_compiler)] // 32 shards is sufficient to reduce contention on an 8-core Ryzen 7 1700, // but this should be tested on higher core count CPUs. How the `Sharded` type gets used diff --git a/compiler/rustc_data_structures/src/sip128.rs b/compiler/rustc_data_structures/src/sip128.rs index d849fe0373f2..4a0ed87f77c8 100644 --- a/compiler/rustc_data_structures/src/sip128.rs +++ b/compiler/rustc_data_structures/src/sip128.rs @@ -96,28 +96,30 @@ macro_rules! compress { unsafe fn copy_nonoverlapping_small(src: *const u8, dst: *mut u8, count: usize) { debug_assert!(count <= 8); - if count == 8 { - ptr::copy_nonoverlapping(src, dst, 8); - return; - } + unsafe { + if count == 8 { + ptr::copy_nonoverlapping(src, dst, 8); + return; + } - let mut i = 0; - if i + 3 < count { - ptr::copy_nonoverlapping(src.add(i), dst.add(i), 4); - i += 4; - } + let mut i = 0; + if i + 3 < count { + ptr::copy_nonoverlapping(src.add(i), dst.add(i), 4); + i += 4; + } - if i + 1 < count { - ptr::copy_nonoverlapping(src.add(i), dst.add(i), 2); - i += 2 - } + if i + 1 < count { + ptr::copy_nonoverlapping(src.add(i), dst.add(i), 2); + i += 2 + } - if i < count { - *dst.add(i) = *src.add(i); - i += 1; - } + if i < count { + *dst.add(i) = *src.add(i); + i += 1; + } - debug_assert_eq!(i, count); + debug_assert_eq!(i, count); + } } // # Implementation @@ -232,38 +234,40 @@ impl SipHasher128 { // overflow) if it wasn't already. #[inline(never)] unsafe fn short_write_process_buffer(&mut self, bytes: [u8; LEN]) { - let nbuf = self.nbuf; - debug_assert!(LEN <= 8); - debug_assert!(nbuf < BUFFER_SIZE); - debug_assert!(nbuf + LEN >= BUFFER_SIZE); - debug_assert!(nbuf + LEN < BUFFER_WITH_SPILL_SIZE); + unsafe { + let nbuf = self.nbuf; + debug_assert!(LEN <= 8); + debug_assert!(nbuf < BUFFER_SIZE); + debug_assert!(nbuf + LEN >= BUFFER_SIZE); + debug_assert!(nbuf + LEN < BUFFER_WITH_SPILL_SIZE); - // Copy first part of input into end of buffer, possibly into spill - // element. The memcpy call is optimized away because the size is known. - let dst = (self.buf.as_mut_ptr() as *mut u8).add(nbuf); - ptr::copy_nonoverlapping(bytes.as_ptr(), dst, LEN); + // Copy first part of input into end of buffer, possibly into spill + // element. The memcpy call is optimized away because the size is known. + let dst = (self.buf.as_mut_ptr() as *mut u8).add(nbuf); + ptr::copy_nonoverlapping(bytes.as_ptr(), dst, LEN); - // Process buffer. - for i in 0..BUFFER_CAPACITY { - let elem = self.buf.get_unchecked(i).assume_init().to_le(); - self.state.v3 ^= elem; - Sip13Rounds::c_rounds(&mut self.state); - self.state.v0 ^= elem; + // Process buffer. + for i in 0..BUFFER_CAPACITY { + let elem = self.buf.get_unchecked(i).assume_init().to_le(); + self.state.v3 ^= elem; + Sip13Rounds::c_rounds(&mut self.state); + self.state.v0 ^= elem; + } + + // Copy remaining input into start of buffer by copying LEN - 1 + // elements from spill (at most LEN - 1 bytes could have overflowed + // into the spill). The memcpy call is optimized away because the size + // is known. And the whole copy is optimized away for LEN == 1. + let dst = self.buf.as_mut_ptr() as *mut u8; + let src = self.buf.get_unchecked(BUFFER_SPILL_INDEX) as *const _ as *const u8; + ptr::copy_nonoverlapping(src, dst, LEN - 1); + + // This function should only be called when the write fills the buffer. + // Therefore, when LEN == 1, the new `self.nbuf` must be zero. + // LEN is statically known, so the branch is optimized away. + self.nbuf = if LEN == 1 { 0 } else { nbuf + LEN - BUFFER_SIZE }; + self.processed += BUFFER_SIZE; } - - // Copy remaining input into start of buffer by copying LEN - 1 - // elements from spill (at most LEN - 1 bytes could have overflowed - // into the spill). The memcpy call is optimized away because the size - // is known. And the whole copy is optimized away for LEN == 1. - let dst = self.buf.as_mut_ptr() as *mut u8; - let src = self.buf.get_unchecked(BUFFER_SPILL_INDEX) as *const _ as *const u8; - ptr::copy_nonoverlapping(src, dst, LEN - 1); - - // This function should only be called when the write fills the buffer. - // Therefore, when LEN == 1, the new `self.nbuf` must be zero. - // LEN is statically known, so the branch is optimized away. - self.nbuf = if LEN == 1 { 0 } else { nbuf + LEN - BUFFER_SIZE }; - self.processed += BUFFER_SIZE; } // A write function for byte slices. @@ -301,57 +305,59 @@ impl SipHasher128 { // containing the byte offset `self.nbuf`. #[inline(never)] unsafe fn slice_write_process_buffer(&mut self, msg: &[u8]) { - let length = msg.len(); - let nbuf = self.nbuf; - debug_assert!(nbuf < BUFFER_SIZE); - debug_assert!(nbuf + length >= BUFFER_SIZE); + unsafe { + let length = msg.len(); + let nbuf = self.nbuf; + debug_assert!(nbuf < BUFFER_SIZE); + debug_assert!(nbuf + length >= BUFFER_SIZE); - // Always copy first part of input into current element of buffer. - // This function should only be called when the write fills the buffer, - // so we know that there is enough input to fill the current element. - let valid_in_elem = nbuf % ELEM_SIZE; - let needed_in_elem = ELEM_SIZE - valid_in_elem; + // Always copy first part of input into current element of buffer. + // This function should only be called when the write fills the buffer, + // so we know that there is enough input to fill the current element. + let valid_in_elem = nbuf % ELEM_SIZE; + let needed_in_elem = ELEM_SIZE - valid_in_elem; - let src = msg.as_ptr(); - let dst = (self.buf.as_mut_ptr() as *mut u8).add(nbuf); - copy_nonoverlapping_small(src, dst, needed_in_elem); + let src = msg.as_ptr(); + let dst = (self.buf.as_mut_ptr() as *mut u8).add(nbuf); + copy_nonoverlapping_small(src, dst, needed_in_elem); - // Process buffer. + // Process buffer. - // Using `nbuf / ELEM_SIZE + 1` rather than `(nbuf + needed_in_elem) / - // ELEM_SIZE` to show the compiler that this loop's upper bound is > 0. - // We know that is true, because last step ensured we have a full - // element in the buffer. - let last = nbuf / ELEM_SIZE + 1; + // Using `nbuf / ELEM_SIZE + 1` rather than `(nbuf + needed_in_elem) / + // ELEM_SIZE` to show the compiler that this loop's upper bound is > 0. + // We know that is true, because last step ensured we have a full + // element in the buffer. + let last = nbuf / ELEM_SIZE + 1; - for i in 0..last { - let elem = self.buf.get_unchecked(i).assume_init().to_le(); - self.state.v3 ^= elem; - Sip13Rounds::c_rounds(&mut self.state); - self.state.v0 ^= elem; + for i in 0..last { + let elem = self.buf.get_unchecked(i).assume_init().to_le(); + self.state.v3 ^= elem; + Sip13Rounds::c_rounds(&mut self.state); + self.state.v0 ^= elem; + } + + // Process the remaining element-sized chunks of input. + let mut processed = needed_in_elem; + let input_left = length - processed; + let elems_left = input_left / ELEM_SIZE; + let extra_bytes_left = input_left % ELEM_SIZE; + + for _ in 0..elems_left { + let elem = (msg.as_ptr().add(processed) as *const u64).read_unaligned().to_le(); + self.state.v3 ^= elem; + Sip13Rounds::c_rounds(&mut self.state); + self.state.v0 ^= elem; + processed += ELEM_SIZE; + } + + // Copy remaining input into start of buffer. + let src = msg.as_ptr().add(processed); + let dst = self.buf.as_mut_ptr() as *mut u8; + copy_nonoverlapping_small(src, dst, extra_bytes_left); + + self.nbuf = extra_bytes_left; + self.processed += nbuf + processed; } - - // Process the remaining element-sized chunks of input. - let mut processed = needed_in_elem; - let input_left = length - processed; - let elems_left = input_left / ELEM_SIZE; - let extra_bytes_left = input_left % ELEM_SIZE; - - for _ in 0..elems_left { - let elem = (msg.as_ptr().add(processed) as *const u64).read_unaligned().to_le(); - self.state.v3 ^= elem; - Sip13Rounds::c_rounds(&mut self.state); - self.state.v0 ^= elem; - processed += ELEM_SIZE; - } - - // Copy remaining input into start of buffer. - let src = msg.as_ptr().add(processed); - let dst = self.buf.as_mut_ptr() as *mut u8; - copy_nonoverlapping_small(src, dst, extra_bytes_left); - - self.nbuf = extra_bytes_left; - self.processed += nbuf + processed; } #[inline] diff --git a/compiler/rustc_data_structures/src/sorted_map/index_map.rs b/compiler/rustc_data_structures/src/sorted_map/index_map.rs index 7d23ff519487..c172ee1c9706 100644 --- a/compiler/rustc_data_structures/src/sorted_map/index_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map/index_map.rs @@ -3,7 +3,7 @@ use std::hash::{Hash, Hasher}; use crate::stable_hasher::{HashStable, StableHasher}; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_index::{Idx, IndexVec}; /// An indexed multi-map that preserves insertion order while permitting both *O*(log *n*) lookup of /// an item by key and *O*(1) lookup by index. diff --git a/compiler/rustc_data_structures/src/sso/map.rs b/compiler/rustc_data_structures/src/sso/map.rs index 89b8c8526496..99581ed23759 100644 --- a/compiler/rustc_data_structures/src/sso/map.rs +++ b/compiler/rustc_data_structures/src/sso/map.rs @@ -256,12 +256,9 @@ impl SsoHashMap { pub fn remove(&mut self, key: &K) -> Option { match self { SsoHashMap::Array(array) => { - if let Some(index) = array.iter().position(|(k, _v)| k == key) { - Some(array.swap_remove(index).1) - } else { - None - } + array.iter().position(|(k, _v)| k == key).map(|index| array.swap_remove(index).1) } + SsoHashMap::Map(map) => map.remove(key), } } diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index 3ed1de1bc3ca..6d57d81c56a4 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -1,7 +1,8 @@ use crate::sip128::SipHasher128; -use rustc_index::bit_set; -use rustc_index::vec; +use rustc_index::bit_set::{self, BitSet}; +use rustc_index::{Idx, IndexVec}; use smallvec::SmallVec; +use std::fmt; use std::hash::{BuildHasher, Hash, Hasher}; use std::marker::PhantomData; use std::mem; @@ -9,6 +10,8 @@ use std::mem; #[cfg(test)] mod tests; +pub use crate::hashes::{Hash128, Hash64}; + /// When hashing something that ends up affecting properties like symbol names, /// we want these symbol names to be calculated independently of other factors /// like what architecture you're compiling *from*. @@ -20,8 +23,8 @@ pub struct StableHasher { state: SipHasher128, } -impl ::std::fmt::Debug for StableHasher { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl fmt::Debug for StableHasher { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self.state) } } @@ -42,21 +45,6 @@ impl StableHasher { } } -impl StableHasherResult for u128 { - #[inline] - fn finish(hasher: StableHasher) -> Self { - let (_0, _1) = hasher.finalize(); - u128::from(_0) | (u128::from(_1) << 64) - } -} - -impl StableHasherResult for u64 { - #[inline] - fn finish(hasher: StableHasher) -> Self { - hasher.finalize().0 - } -} - impl StableHasher { #[inline] pub fn finalize(self) -> (u64, u64) { @@ -107,7 +95,8 @@ impl Hasher for StableHasher { #[inline] fn write_u128(&mut self, i: u128) { - self.state.write(&i.to_le_bytes()); + self.write_u64(i as u64); + self.write_u64((i >> 64) as u64); } #[inline] @@ -286,6 +275,9 @@ impl_stable_traits_for_trivial_type!(i128); impl_stable_traits_for_trivial_type!(char); impl_stable_traits_for_trivial_type!(()); +impl_stable_traits_for_trivial_type!(Hash64); +impl_stable_traits_for_trivial_type!(Hash128); + impl HashStable for ! { fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) { unreachable!() @@ -565,7 +557,7 @@ where } } -impl HashStable for vec::IndexVec +impl HashStable for IndexVec where T: HashStable, { @@ -577,13 +569,13 @@ where } } -impl HashStable for bit_set::BitSet { +impl HashStable for BitSet { fn hash_stable(&self, _ctx: &mut CTX, hasher: &mut StableHasher) { ::std::hash::Hash::hash(self, hasher); } } -impl HashStable for bit_set::BitMatrix { +impl HashStable for bit_set::BitMatrix { fn hash_stable(&self, _ctx: &mut CTX, hasher: &mut StableHasher) { ::std::hash::Hash::hash(self, hasher); } @@ -668,7 +660,7 @@ fn stable_hash_reduce( .map(|value| { let mut hasher = StableHasher::new(); hash_function(&mut hasher, hcx, value); - hasher.finish::() + hasher.finish::() }) .reduce(|accum, value| accum.wrapping_add(value)); hash.hash_stable(hcx, hasher); diff --git a/compiler/rustc_data_structures/src/stable_hasher/tests.rs b/compiler/rustc_data_structures/src/stable_hasher/tests.rs index a98b1bc36261..c8921f6a7784 100644 --- a/compiler/rustc_data_structures/src/stable_hasher/tests.rs +++ b/compiler/rustc_data_structures/src/stable_hasher/tests.rs @@ -72,7 +72,7 @@ fn test_hash_isize() { assert_eq!(h.finalize(), expected); } -fn hash>(t: &T) -> u128 { +fn hash>(t: &T) -> Hash128 { let mut h = StableHasher::new(); let ctx = &mut (); t.hash_stable(ctx, &mut h); diff --git a/compiler/rustc_data_structures/src/svh.rs b/compiler/rustc_data_structures/src/svh.rs index 61654b9e8f5f..a3d2724fcdbb 100644 --- a/compiler/rustc_data_structures/src/svh.rs +++ b/compiler/rustc_data_structures/src/svh.rs @@ -5,40 +5,30 @@ //! mismatches where we have two versions of the same crate that were //! compiled from distinct sources. -use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; +use crate::fingerprint::Fingerprint; use std::fmt; -use std::hash::{Hash, Hasher}; use crate::stable_hasher; -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, Hash)] pub struct Svh { - hash: u64, + hash: Fingerprint, } impl Svh { /// Creates a new `Svh` given the hash. If you actually want to /// compute the SVH from some HIR, you want the `calculate_svh` /// function found in `rustc_incremental`. - pub fn new(hash: u64) -> Svh { + pub fn new(hash: Fingerprint) -> Svh { Svh { hash } } pub fn as_u64(&self) -> u64 { - self.hash + self.hash.to_smaller_hash().as_u64() } pub fn to_string(&self) -> String { - format!("{:016x}", self.hash) - } -} - -impl Hash for Svh { - fn hash(&self, state: &mut H) - where - H: Hasher, - { - self.hash.to_le().hash(state); + format!("{:016x}", self.hash.to_smaller_hash()) } } @@ -48,18 +38,6 @@ impl fmt::Display for Svh { } } -impl Encodable for Svh { - fn encode(&self, s: &mut S) { - s.emit_u64(self.as_u64().to_le()); - } -} - -impl Decodable for Svh { - fn decode(d: &mut D) -> Svh { - Svh::new(u64::from_le(d.read_u64())) - } -} - impl stable_hasher::HashStable for Svh { #[inline] fn hash_stable(&self, ctx: &mut T, hasher: &mut stable_hasher::StableHasher) { diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index ef1da85198fd..e73ca56efa03 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -45,6 +45,9 @@ use std::hash::{BuildHasher, Hash}; use std::ops::{Deref, DerefMut}; use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe}; +mod worker_local; +pub use worker_local::{Registry, WorkerLocal}; + pub use std::sync::atomic::Ordering; pub use std::sync::atomic::Ordering::SeqCst; @@ -205,33 +208,6 @@ cfg_if! { use std::cell::Cell; - #[derive(Debug)] - pub struct WorkerLocal(OneThread); - - impl WorkerLocal { - /// Creates a new worker local where the `initial` closure computes the - /// value this worker local should take for each thread in the thread pool. - #[inline] - pub fn new T>(mut f: F) -> WorkerLocal { - WorkerLocal(OneThread::new(f(0))) - } - - /// Returns the worker-local value for each thread - #[inline] - pub fn into_inner(self) -> Vec { - vec![OneThread::into_inner(self.0)] - } - } - - impl Deref for WorkerLocal { - type Target = T; - - #[inline(always)] - fn deref(&self) -> &T { - &self.0 - } - } - pub type MTLockRef<'a, T> = &'a mut MTLock; #[derive(Debug, Default)] @@ -351,8 +327,6 @@ cfg_if! { }; } - pub use rayon_core::WorkerLocal; - pub use rayon::iter::ParallelIterator; use rayon::iter::IntoParallelIterator; @@ -383,6 +357,10 @@ pub fn assert_send() {} pub fn assert_send_val(_t: &T) {} pub fn assert_send_sync_val(_t: &T) {} +#[derive(Default)] +#[cfg_attr(parallel_compiler, repr(align(64)))] +pub struct CacheAligned(pub T); + pub trait HashMapExt { /// Same as HashMap::insert, but it may panic if there's already an /// entry for `key` with a value not equal to `value` diff --git a/compiler/rustc_data_structures/src/sync/vec.rs b/compiler/rustc_data_structures/src/sync/vec.rs index 1783b4b35725..e36dded9e5e5 100644 --- a/compiler/rustc_data_structures/src/sync/vec.rs +++ b/compiler/rustc_data_structures/src/sync/vec.rs @@ -1,6 +1,6 @@ use std::marker::PhantomData; -use rustc_index::vec::Idx; +use rustc_index::Idx; #[derive(Default)] pub struct AppendOnlyIndexVec { diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs new file mode 100644 index 000000000000..bfb04ba8a73f --- /dev/null +++ b/compiler/rustc_data_structures/src/sync/worker_local.rs @@ -0,0 +1,180 @@ +use crate::sync::Lock; +use std::cell::Cell; +use std::cell::OnceCell; +use std::ops::Deref; +use std::ptr; +use std::sync::Arc; + +#[cfg(parallel_compiler)] +use {crate::cold_path, crate::sync::CacheAligned}; + +/// A pointer to the `RegistryData` which uniquely identifies a registry. +/// This identifier can be reused if the registry gets freed. +#[derive(Clone, Copy, PartialEq)] +struct RegistryId(*const RegistryData); + +impl RegistryId { + #[inline(always)] + /// Verifies that the current thread is associated with the registry and returns its unique + /// index within the registry. This panics if the current thread is not associated with this + /// registry. + /// + /// Note that there's a race possible where the identifer in `THREAD_DATA` could be reused + /// so this can succeed from a different registry. + #[cfg(parallel_compiler)] + fn verify(self) -> usize { + let (id, index) = THREAD_DATA.with(|data| (data.registry_id.get(), data.index.get())); + + if id == self { + index + } else { + cold_path(|| panic!("Unable to verify registry association")) + } + } +} + +struct RegistryData { + thread_limit: usize, + threads: Lock, +} + +/// Represents a list of threads which can access worker locals. +#[derive(Clone)] +pub struct Registry(Arc); + +thread_local! { + /// The registry associated with the thread. + /// This allows the `WorkerLocal` type to clone the registry in its constructor. + static REGISTRY: OnceCell = OnceCell::new(); +} + +struct ThreadData { + registry_id: Cell, + index: Cell, +} + +thread_local! { + /// A thread local which contains the identifer of `REGISTRY` but allows for faster access. + /// It also holds the index of the current thread. + static THREAD_DATA: ThreadData = const { ThreadData { + registry_id: Cell::new(RegistryId(ptr::null())), + index: Cell::new(0), + }}; +} + +impl Registry { + /// Creates a registry which can hold up to `thread_limit` threads. + pub fn new(thread_limit: usize) -> Self { + Registry(Arc::new(RegistryData { thread_limit, threads: Lock::new(0) })) + } + + /// Gets the registry associated with the current thread. Panics if there's no such registry. + pub fn current() -> Self { + REGISTRY.with(|registry| registry.get().cloned().expect("No assocated registry")) + } + + /// Registers the current thread with the registry so worker locals can be used on it. + /// Panics if the thread limit is hit or if the thread already has an associated registry. + pub fn register(&self) { + let mut threads = self.0.threads.lock(); + if *threads < self.0.thread_limit { + REGISTRY.with(|registry| { + if registry.get().is_some() { + drop(threads); + panic!("Thread already has a registry"); + } + registry.set(self.clone()).ok(); + THREAD_DATA.with(|data| { + data.registry_id.set(self.id()); + data.index.set(*threads); + }); + *threads += 1; + }); + } else { + drop(threads); + panic!("Thread limit reached"); + } + } + + /// Gets the identifer of this registry. + fn id(&self) -> RegistryId { + RegistryId(&*self.0) + } +} + +/// Holds worker local values for each possible thread in a registry. You can only access the +/// worker local value through the `Deref` impl on the registry associated with the thread it was +/// created on. It will panic otherwise. +pub struct WorkerLocal { + #[cfg(not(parallel_compiler))] + local: T, + #[cfg(parallel_compiler)] + locals: Box<[CacheAligned]>, + #[cfg(parallel_compiler)] + registry: Registry, +} + +// This is safe because the `deref` call will return a reference to a `T` unique to each thread +// or it will panic for threads without an associated local. So there isn't a need for `T` to do +// it's own synchronization. The `verify` method on `RegistryId` has an issue where the the id +// can be reused, but `WorkerLocal` has a reference to `Registry` which will prevent any reuse. +#[cfg(parallel_compiler)] +unsafe impl Sync for WorkerLocal {} + +impl WorkerLocal { + /// Creates a new worker local where the `initial` closure computes the + /// value this worker local should take for each thread in the registry. + #[inline] + pub fn new T>(mut initial: F) -> WorkerLocal { + #[cfg(parallel_compiler)] + { + let registry = Registry::current(); + WorkerLocal { + locals: (0..registry.0.thread_limit).map(|i| CacheAligned(initial(i))).collect(), + registry, + } + } + #[cfg(not(parallel_compiler))] + { + WorkerLocal { local: initial(0) } + } + } + + /// Returns the worker-local values for each thread + #[inline] + pub fn into_inner(self) -> impl Iterator { + #[cfg(parallel_compiler)] + { + self.locals.into_vec().into_iter().map(|local| local.0) + } + #[cfg(not(parallel_compiler))] + { + std::iter::once(self.local) + } + } +} + +impl WorkerLocal> { + /// Joins the elements of all the worker locals into one Vec + pub fn join(self) -> Vec { + self.into_inner().into_iter().flat_map(|v| v).collect() + } +} + +impl Deref for WorkerLocal { + type Target = T; + + #[inline(always)] + #[cfg(not(parallel_compiler))] + fn deref(&self) -> &T { + &self.local + } + + #[inline(always)] + #[cfg(parallel_compiler)] + fn deref(&self) -> &T { + // This is safe because `verify` will only return values less than + // `self.registry.thread_limit` which is the size of the `self.locals` array. + unsafe { &self.locals.get_unchecked(self.registry.id().verify()).0 } + } +} diff --git a/compiler/rustc_data_structures/src/tagged_ptr.rs b/compiler/rustc_data_structures/src/tagged_ptr.rs index 651bc556c985..2914eece6796 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr.rs @@ -3,166 +3,281 @@ //! In order to utilize the pointer packing, you must have two types: a pointer, //! and a tag. //! -//! The pointer must implement the `Pointer` trait, with the primary requirement -//! being conversion to and from a usize. Note that the pointer must be -//! dereferenceable, so raw pointers generally cannot implement the `Pointer` -//! trait. This implies that the pointer must also be nonzero. +//! The pointer must implement the [`Pointer`] trait, with the primary +//! requirement being convertible to and from a raw pointer. Note that the +//! pointer must be dereferenceable, so raw pointers generally cannot implement +//! the [`Pointer`] trait. This implies that the pointer must also be non-null. //! -//! Many common pointer types already implement the `Pointer` trait. +//! Many common pointer types already implement the [`Pointer`] trait. //! -//! The tag must implement the `Tag` trait. We assert that the tag and `Pointer` -//! are compatible at compile time. +//! The tag must implement the [`Tag`] trait. +//! +//! We assert that the tag and the [`Pointer`] types are compatible at compile +//! time. -use std::mem::ManuallyDrop; use std::ops::Deref; +use std::ptr::NonNull; use std::rc::Rc; use std::sync::Arc; +use crate::aligned::Aligned; + mod copy; mod drop; +mod impl_tag; pub use copy::CopyTaggedPtr; pub use drop::TaggedPtr; -/// This describes the pointer type encapsulated by TaggedPtr. +/// This describes the pointer type encapsulated by [`TaggedPtr`] and +/// [`CopyTaggedPtr`]. /// /// # Safety /// -/// The usize returned from `into_usize` must be a valid, dereferenceable, -/// pointer to `::Target`. Note that pointers to `Pointee` must -/// be thin, even though `Pointee` may not be sized. +/// The pointer returned from [`into_ptr`] must be a [valid], pointer to +/// [`::Target`]. /// -/// Note that the returned pointer from `into_usize` should be castable to `&mut -/// ::Target` if `Pointer: DerefMut`. +/// Note that if `Self` implements [`DerefMut`] the pointer returned from +/// [`into_ptr`] must be valid for writes (and thus calling [`NonNull::as_mut`] +/// on it must be safe). /// -/// The BITS constant must be correct. At least `BITS` bits, least-significant, -/// must be zero on all returned pointers from `into_usize`. +/// The [`BITS`] constant must be correct. [`BITS`] least-significant bits, +/// must be zero on all pointers returned from [`into_ptr`]. /// -/// For example, if the alignment of `Pointee` is 2, then `BITS` should be 1. +/// For example, if the alignment of [`Self::Target`] is 2, then `BITS` should be 1. +/// +/// [`BITS`]: Pointer::BITS +/// [`into_ptr`]: Pointer::into_ptr +/// [valid]: std::ptr#safety +/// [`::Target`]: Deref::Target +/// [`Self::Target`]: Deref::Target +/// [`DerefMut`]: std::ops::DerefMut pub unsafe trait Pointer: Deref { + /// Number of unused (always zero) **least-significant bits** in this + /// pointer, usually related to the pointees alignment. + /// + /// For example if [`BITS`] = `2`, then given `ptr = Self::into_ptr(..)`, + /// `ptr.addr() & 0b11 == 0` must be true. + /// /// Most likely the value you want to use here is the following, unless - /// your Pointee type is unsized (e.g., `ty::List` in rustc) in which - /// case you'll need to manually figure out what the right type to pass to - /// align_of is. + /// your [`Self::Target`] type is unsized (e.g., `ty::List` in rustc) + /// or your pointer is over/under aligned, in which case you'll need to + /// manually figure out what the right type to pass to [`bits_for`] is, or + /// what the value to set here. /// - /// ```ignore UNSOLVED (what to do about the Self) + /// ```rust /// # use std::ops::Deref; - /// std::mem::align_of::<::Target>().trailing_zeros() as usize; + /// # use rustc_data_structures::tagged_ptr::bits_for; + /// # struct T; + /// # impl Deref for T { type Target = u8; fn deref(&self) -> &u8 { &0 } } + /// # impl T { + /// const BITS: u32 = bits_for::<::Target>(); + /// # } /// ``` - const BITS: usize; - fn into_usize(self) -> usize; - - /// # Safety /// - /// The passed `ptr` must be returned from `into_usize`. - /// - /// This acts as `ptr::read` semantically, it should not be called more than - /// once on non-`Copy` `Pointer`s. - unsafe fn from_usize(ptr: usize) -> Self; + /// [`BITS`]: Pointer::BITS + /// [`Self::Target`]: Deref::Target + const BITS: u32; - /// This provides a reference to the `Pointer` itself, rather than the - /// `Deref::Target`. It is used for cases where we want to call methods that - /// may be implement differently for the Pointer than the Pointee (e.g., - /// `Rc::clone` vs cloning the inner value). + /// Turns this pointer into a raw, non-null pointer. + /// + /// The inverse of this function is [`from_ptr`]. + /// + /// This function guarantees that the least-significant [`Self::BITS`] bits + /// are zero. + /// + /// [`from_ptr`]: Pointer::from_ptr + /// [`Self::BITS`]: Pointer::BITS + fn into_ptr(self) -> NonNull; + + /// Re-creates the original pointer, from a raw pointer returned by [`into_ptr`]. /// /// # Safety /// - /// The passed `ptr` must be returned from `into_usize`. - unsafe fn with_ref R>(ptr: usize, f: F) -> R; + /// The passed `ptr` must be returned from [`into_ptr`]. + /// + /// This acts as [`ptr::read::()`] semantically, it should not be called more than + /// once on non-[`Copy`] `Pointer`s. + /// + /// [`into_ptr`]: Pointer::into_ptr + /// [`ptr::read::()`]: std::ptr::read + unsafe fn from_ptr(ptr: NonNull) -> Self; } -/// This describes tags that the `TaggedPtr` struct can hold. +/// This describes tags that the [`TaggedPtr`] struct can hold. /// /// # Safety /// -/// The BITS constant must be correct. +/// The [`BITS`] constant must be correct. /// -/// No more than `BITS` least significant bits may be set in the returned usize. +/// No more than [`BITS`] least-significant bits may be set in the returned usize. +/// +/// [`BITS`]: Tag::BITS pub unsafe trait Tag: Copy { - const BITS: usize; + /// Number of least-significant bits in the return value of [`into_usize`] + /// which may be non-zero. In other words this is the bit width of the + /// value. + /// + /// [`into_usize`]: Tag::into_usize + const BITS: u32; + /// Turns this tag into an integer. + /// + /// The inverse of this function is [`from_usize`]. + /// + /// This function guarantees that only the least-significant [`Self::BITS`] + /// bits can be non-zero. + /// + /// [`from_usize`]: Tag::from_usize + /// [`Self::BITS`]: Tag::BITS fn into_usize(self) -> usize; + /// Re-creates the tag from the integer returned by [`into_usize`]. + /// /// # Safety /// - /// The passed `tag` must be returned from `into_usize`. + /// The passed `tag` must be returned from [`into_usize`]. + /// + /// [`into_usize`]: Tag::into_usize unsafe fn from_usize(tag: usize) -> Self; } -unsafe impl Pointer for Box { - const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; - #[inline] - fn into_usize(self) -> usize { - Box::into_raw(self) as usize +/// Returns the number of bits available for use for tags in a pointer to `T` +/// (this is based on `T`'s alignment). +pub const fn bits_for() -> u32 { + crate::aligned::align_of::().as_nonzero().trailing_zeros() +} + +/// Returns the correct [`Tag::BITS`] constant for a set of tag values. +pub const fn bits_for_tags(mut tags: &[usize]) -> u32 { + let mut bits = 0; + + while let &[tag, ref rest @ ..] = tags { + tags = rest; + + // bits required to represent `tag`, + // position of the most significant 1 + let b = usize::BITS - tag.leading_zeros(); + if b > bits { + bits = b; + } } + + bits +} + +unsafe impl Pointer for Box { + const BITS: u32 = bits_for::(); + #[inline] - unsafe fn from_usize(ptr: usize) -> Self { - Box::from_raw(ptr as *mut T) + fn into_ptr(self) -> NonNull { + // Safety: pointers from `Box::into_raw` are valid & non-null + unsafe { NonNull::new_unchecked(Box::into_raw(self)) } } - unsafe fn with_ref R>(ptr: usize, f: F) -> R { - let raw = ManuallyDrop::new(Self::from_usize(ptr)); - f(&raw) + + #[inline] + unsafe fn from_ptr(ptr: NonNull) -> Self { + // Safety: `ptr` comes from `into_ptr` which calls `Box::into_raw` + unsafe { Box::from_raw(ptr.as_ptr()) } } } -unsafe impl Pointer for Rc { - const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; +unsafe impl Pointer for Rc { + const BITS: u32 = bits_for::(); + #[inline] - fn into_usize(self) -> usize { - Rc::into_raw(self) as usize + fn into_ptr(self) -> NonNull { + // Safety: pointers from `Rc::into_raw` are valid & non-null + unsafe { NonNull::new_unchecked(Rc::into_raw(self).cast_mut()) } } + #[inline] - unsafe fn from_usize(ptr: usize) -> Self { - Rc::from_raw(ptr as *const T) - } - unsafe fn with_ref R>(ptr: usize, f: F) -> R { - let raw = ManuallyDrop::new(Self::from_usize(ptr)); - f(&raw) + unsafe fn from_ptr(ptr: NonNull) -> Self { + // Safety: `ptr` comes from `into_ptr` which calls `Rc::into_raw` + unsafe { Rc::from_raw(ptr.as_ptr()) } } } -unsafe impl Pointer for Arc { - const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; +unsafe impl Pointer for Arc { + const BITS: u32 = bits_for::(); + #[inline] - fn into_usize(self) -> usize { - Arc::into_raw(self) as usize + fn into_ptr(self) -> NonNull { + // Safety: pointers from `Arc::into_raw` are valid & non-null + unsafe { NonNull::new_unchecked(Arc::into_raw(self).cast_mut()) } } + #[inline] - unsafe fn from_usize(ptr: usize) -> Self { - Arc::from_raw(ptr as *const T) - } - unsafe fn with_ref R>(ptr: usize, f: F) -> R { - let raw = ManuallyDrop::new(Self::from_usize(ptr)); - f(&raw) + unsafe fn from_ptr(ptr: NonNull) -> Self { + // Safety: `ptr` comes from `into_ptr` which calls `Arc::into_raw` + unsafe { Arc::from_raw(ptr.as_ptr()) } } } -unsafe impl<'a, T: 'a> Pointer for &'a T { - const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; +unsafe impl<'a, T: 'a + ?Sized + Aligned> Pointer for &'a T { + const BITS: u32 = bits_for::(); + #[inline] - fn into_usize(self) -> usize { - self as *const T as usize + fn into_ptr(self) -> NonNull { + NonNull::from(self) } + #[inline] - unsafe fn from_usize(ptr: usize) -> Self { - &*(ptr as *const T) - } - unsafe fn with_ref R>(ptr: usize, f: F) -> R { - f(&*(&ptr as *const usize as *const Self)) + unsafe fn from_ptr(ptr: NonNull) -> Self { + // Safety: + // `ptr` comes from `into_ptr` which gets the pointer from a reference + unsafe { ptr.as_ref() } } } -unsafe impl<'a, T: 'a> Pointer for &'a mut T { - const BITS: usize = std::mem::align_of::().trailing_zeros() as usize; +unsafe impl<'a, T: 'a + ?Sized + Aligned> Pointer for &'a mut T { + const BITS: u32 = bits_for::(); + #[inline] - fn into_usize(self) -> usize { - self as *mut T as usize + fn into_ptr(self) -> NonNull { + NonNull::from(self) } + #[inline] - unsafe fn from_usize(ptr: usize) -> Self { - &mut *(ptr as *mut T) - } - unsafe fn with_ref R>(ptr: usize, f: F) -> R { - f(&*(&ptr as *const usize as *const Self)) + unsafe fn from_ptr(mut ptr: NonNull) -> Self { + // Safety: + // `ptr` comes from `into_ptr` which gets the pointer from a reference + unsafe { ptr.as_mut() } + } +} + +/// A tag type used in [`CopyTaggedPtr`] and [`TaggedPtr`] tests. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[cfg(test)] +enum Tag2 { + B00 = 0b00, + B01 = 0b01, + B10 = 0b10, + B11 = 0b11, +} + +#[cfg(test)] +unsafe impl Tag for Tag2 { + const BITS: u32 = 2; + + fn into_usize(self) -> usize { + self as _ + } + + unsafe fn from_usize(tag: usize) -> Self { + match tag { + 0b00 => Tag2::B00, + 0b01 => Tag2::B01, + 0b10 => Tag2::B10, + 0b11 => Tag2::B11, + _ => unreachable!(), + } + } +} + +#[cfg(test)] +impl crate::stable_hasher::HashStable for Tag2 { + fn hash_stable(&self, hcx: &mut HCX, hasher: &mut crate::stable_hasher::StableHasher) { + (*self as u8).hash_stable(hcx, hasher); } } diff --git a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs index e1d3e0bd35a6..e893a2c78134 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs @@ -1,78 +1,94 @@ use super::{Pointer, Tag}; use crate::stable_hasher::{HashStable, StableHasher}; use std::fmt; +use std::hash::{Hash, Hasher}; use std::marker::PhantomData; +use std::mem::ManuallyDrop; use std::num::NonZeroUsize; +use std::ops::{Deref, DerefMut}; +use std::ptr::NonNull; -/// A `Copy` TaggedPtr. +/// A [`Copy`] tagged pointer. /// -/// You should use this instead of the `TaggedPtr` type in all cases where -/// `P: Copy`. +/// This is essentially `{ pointer: P, tag: T }` packed in a single pointer. +/// +/// You should use this instead of the [`TaggedPtr`] type in all cases where +/// `P` implements [`Copy`]. /// /// If `COMPARE_PACKED` is true, then the pointers will be compared and hashed without -/// unpacking. Otherwise we don't implement PartialEq/Eq/Hash; if you want that, -/// wrap the TaggedPtr. +/// unpacking. Otherwise we don't implement [`PartialEq`], [`Eq`] and [`Hash`]; +/// if you want that, wrap the [`CopyTaggedPtr`]. +/// +/// [`TaggedPtr`]: crate::tagged_ptr::TaggedPtr pub struct CopyTaggedPtr where P: Pointer, T: Tag, { - packed: NonZeroUsize, - data: PhantomData<(P, T)>, + /// This is semantically a pair of `pointer: P` and `tag: T` fields, + /// however we pack them in a single pointer, to save space. + /// + /// We pack the tag into the **most**-significant bits of the pointer to + /// ease retrieval of the value. A left shift is a multiplication and + /// those are embeddable in instruction encoding, for example: + /// + /// ```asm + /// // () + /// example::shift_read3: + /// mov eax, dword ptr [8*rdi] + /// ret + /// + /// example::mask_read3: + /// and rdi, -8 + /// mov eax, dword ptr [rdi] + /// ret + /// ``` + /// + /// This is ASM outputted by rustc for reads of values behind tagged + /// pointers for different approaches of tagging: + /// - `shift_read3` uses `<< 3` (the tag is in the most-significant bits) + /// - `mask_read3` uses `& !0b111` (the tag is in the least-significant bits) + /// + /// The shift approach thus produces less instructions and is likely faster + /// (see ). + /// + /// Encoding diagram: + /// ```text + /// [ packed.addr ] + /// [ tag ] [ pointer.addr >> T::BITS ] <-- usize::BITS - T::BITS bits + /// ^ + /// | + /// T::BITS bits + /// ``` + /// + /// The tag can be retrieved by `packed.addr() >> T::BITS` and the pointer + /// can be retrieved by `packed.map_addr(|addr| addr << T::BITS)`. + packed: NonNull, + tag_ghost: PhantomData, } -impl Copy for CopyTaggedPtr -where - P: Pointer, - T: Tag, - P: Copy, -{ -} - -impl Clone for CopyTaggedPtr -where - P: Pointer, - T: Tag, - P: Copy, -{ - fn clone(&self) -> Self { - *self - } -} - -// We pack the tag into the *upper* bits of the pointer to ease retrieval of the -// value; a left shift is a multiplication and those are embeddable in -// instruction encoding. -impl CopyTaggedPtr +// Note that even though `CopyTaggedPtr` is only really expected to work with +// `P: Copy`, can't add `P: Copy` bound, because `CopyTaggedPtr` is used in the +// `TaggedPtr`'s implementation. +impl CopyTaggedPtr where P: Pointer, T: Tag, { - const TAG_BIT_SHIFT: usize = usize::BITS as usize - T::BITS; - const ASSERTION: () = { - assert!(T::BITS <= P::BITS); - // Used for the transmute_copy's below - assert!(std::mem::size_of::<&P::Target>() == std::mem::size_of::()); - }; - + /// Tags `pointer` with `tag`. + /// + /// Note that this leaks `pointer`: it won't be dropped when + /// `CopyTaggedPtr` is dropped. If you have a pointer with a significant + /// drop, use [`TaggedPtr`] instead. + /// + /// [`TaggedPtr`]: crate::tagged_ptr::TaggedPtr + #[inline] pub fn new(pointer: P, tag: T) -> Self { - // Trigger assert! - let () = Self::ASSERTION; - let packed_tag = tag.into_usize() << Self::TAG_BIT_SHIFT; - - Self { - // SAFETY: We know that the pointer is non-null, as it must be - // dereferenceable per `Pointer` safety contract. - packed: unsafe { - NonZeroUsize::new_unchecked((P::into_usize(pointer) >> T::BITS) | packed_tag) - }, - data: PhantomData, - } + Self { packed: Self::pack(P::into_ptr(pointer), tag), tag_ghost: PhantomData } } - pub(super) fn pointer_raw(&self) -> usize { - self.packed.get() << T::BITS - } + /// Retrieves the pointer. + #[inline] pub fn pointer(self) -> P where P: Copy, @@ -81,66 +97,143 @@ where // // Note that this isn't going to double-drop or anything because we have // P: Copy - unsafe { P::from_usize(self.pointer_raw()) } - } - pub fn pointer_ref(&self) -> &P::Target { - // SAFETY: pointer_raw returns the original pointer - unsafe { std::mem::transmute_copy(&self.pointer_raw()) } - } - pub fn pointer_mut(&mut self) -> &mut P::Target - where - P: std::ops::DerefMut, - { - // SAFETY: pointer_raw returns the original pointer - unsafe { std::mem::transmute_copy(&self.pointer_raw()) } + unsafe { P::from_ptr(self.pointer_raw()) } } + + /// Retrieves the tag. #[inline] pub fn tag(&self) -> T { - unsafe { T::from_usize(self.packed.get() >> Self::TAG_BIT_SHIFT) } + // Unpack the tag, according to the `self.packed` encoding scheme + let tag = self.packed.addr().get() >> Self::TAG_BIT_SHIFT; + + // Safety: + // The shift retrieves the original value from `T::into_usize`, + // satisfying `T::from_usize`'s preconditions. + unsafe { T::from_usize(tag) } } + + /// Sets the tag to a new value. #[inline] pub fn set_tag(&mut self, tag: T) { - let mut packed = self.packed.get(); - let new_tag = T::into_usize(tag) << Self::TAG_BIT_SHIFT; - let tag_mask = (1 << T::BITS) - 1; - packed &= !(tag_mask << Self::TAG_BIT_SHIFT); - packed |= new_tag; - self.packed = unsafe { NonZeroUsize::new_unchecked(packed) }; + self.packed = Self::pack(self.pointer_raw(), tag); + } + + const TAG_BIT_SHIFT: u32 = usize::BITS - T::BITS; + const ASSERTION: () = { assert!(T::BITS <= P::BITS) }; + + /// Pack pointer `ptr` that comes from [`P::into_ptr`] with a `tag`, + /// according to `self.packed` encoding scheme. + /// + /// [`P::into_ptr`]: Pointer::into_ptr + #[inline] + fn pack(ptr: NonNull, tag: T) -> NonNull { + // Trigger assert! + let () = Self::ASSERTION; + + let packed_tag = tag.into_usize() << Self::TAG_BIT_SHIFT; + + ptr.map_addr(|addr| { + // Safety: + // - The pointer is `NonNull` => it's address is `NonZeroUsize` + // - `P::BITS` least significant bits are always zero (`Pointer` contract) + // - `T::BITS <= P::BITS` (from `Self::ASSERTION`) + // + // Thus `addr >> T::BITS` is guaranteed to be non-zero. + // + // `{non_zero} | packed_tag` can't make the value zero. + + let packed = (addr.get() >> T::BITS) | packed_tag; + unsafe { NonZeroUsize::new_unchecked(packed) } + }) + } + + /// Retrieves the original raw pointer from `self.packed`. + #[inline] + pub(super) fn pointer_raw(&self) -> NonNull { + self.packed.map_addr(|addr| unsafe { NonZeroUsize::new_unchecked(addr.get() << T::BITS) }) + } + + /// This provides a reference to the `P` pointer itself, rather than the + /// `Deref::Target`. It is used for cases where we want to call methods + /// that may be implement differently for the Pointer than the Pointee + /// (e.g., `Rc::clone` vs cloning the inner value). + pub(super) fn with_pointer_ref(&self, f: impl FnOnce(&P) -> R) -> R { + // Safety: + // - `self.raw.pointer_raw()` is originally returned from `P::into_ptr` + // and as such is valid for `P::from_ptr`. + // - This also allows us to not care whatever `f` panics or not. + // - Even though we create a copy of the pointer, we store it inside + // `ManuallyDrop` and only access it by-ref, so we don't double-drop. + // + // Semantically this is just `f(&self.pointer)` (where `self.pointer` + // is non-packed original pointer). + // + // Note that even though `CopyTaggedPtr` is only really expected to + // work with `P: Copy`, we have to assume `P: ?Copy`, because + // `CopyTaggedPtr` is used in the `TaggedPtr`'s implementation. + let ptr = unsafe { ManuallyDrop::new(P::from_ptr(self.pointer_raw())) }; + f(&ptr) } } -impl std::ops::Deref for CopyTaggedPtr +impl Copy for CopyTaggedPtr +where + P: Pointer + Copy, + T: Tag, +{ +} + +impl Clone for CopyTaggedPtr +where + P: Pointer + Copy, + T: Tag, +{ + #[inline] + fn clone(&self) -> Self { + *self + } +} + +impl Deref for CopyTaggedPtr where P: Pointer, T: Tag, { type Target = P::Target; + + #[inline] fn deref(&self) -> &Self::Target { - self.pointer_ref() + // Safety: + // `pointer_raw` returns the original pointer from `P::into_ptr` which, + // by the `Pointer`'s contract, must be valid. + unsafe { self.pointer_raw().as_ref() } } } -impl std::ops::DerefMut for CopyTaggedPtr +impl DerefMut for CopyTaggedPtr where - P: Pointer + std::ops::DerefMut, + P: Pointer + DerefMut, T: Tag, { + #[inline] fn deref_mut(&mut self) -> &mut Self::Target { - self.pointer_mut() + // Safety: + // `pointer_raw` returns the original pointer from `P::into_ptr` which, + // by the `Pointer`'s contract, must be valid for writes if + // `P: DerefMut`. + unsafe { self.pointer_raw().as_mut() } } } -impl fmt::Debug for CopyTaggedPtr +impl fmt::Debug for CopyTaggedPtr where - P: Pointer, - P::Target: fmt::Debug, + P: Pointer + fmt::Debug, T: Tag + fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("CopyTaggedPtr") - .field("pointer", &self.pointer_ref()) - .field("tag", &self.tag()) - .finish() + self.with_pointer_ref(|ptr| { + f.debug_struct("CopyTaggedPtr").field("pointer", ptr).field("tag", &self.tag()).finish() + }) } } @@ -149,6 +242,7 @@ where P: Pointer, T: Tag, { + #[inline] fn eq(&self, other: &Self) -> bool { self.packed == other.packed } @@ -161,25 +255,74 @@ where { } -impl std::hash::Hash for CopyTaggedPtr +impl Hash for CopyTaggedPtr where P: Pointer, T: Tag, { - fn hash(&self, state: &mut H) { + #[inline] + fn hash(&self, state: &mut H) { self.packed.hash(state); } } -impl HashStable for CopyTaggedPtr +impl HashStable for CopyTaggedPtr where P: Pointer + HashStable, T: Tag + HashStable, { fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { - unsafe { - Pointer::with_ref(self.pointer_raw(), |p: &P| p.hash_stable(hcx, hasher)); - } + self.with_pointer_ref(|ptr| ptr.hash_stable(hcx, hasher)); self.tag().hash_stable(hcx, hasher); } } + +// Safety: +// `CopyTaggedPtr` is semantically just `{ ptr: P, tag: T }`, as such +// it's ok to implement `Sync` as long as `P: Sync, T: Sync` +unsafe impl Sync for CopyTaggedPtr +where + P: Sync + Pointer, + T: Sync + Tag, +{ +} + +// Safety: +// `CopyTaggedPtr` is semantically just `{ ptr: P, tag: T }`, as such +// it's ok to implement `Send` as long as `P: Send, T: Send` +unsafe impl Send for CopyTaggedPtr +where + P: Send + Pointer, + T: Send + Tag, +{ +} + +/// Test that `new` does not compile if there is not enough alignment for the +/// tag in the pointer. +/// +/// ```compile_fail,E0080 +/// use rustc_data_structures::tagged_ptr::{CopyTaggedPtr, Tag}; +/// +/// #[derive(Copy, Clone, Debug, PartialEq, Eq)] +/// enum Tag2 { B00 = 0b00, B01 = 0b01, B10 = 0b10, B11 = 0b11 }; +/// +/// unsafe impl Tag for Tag2 { +/// const BITS: u32 = 2; +/// +/// fn into_usize(self) -> usize { todo!() } +/// unsafe fn from_usize(tag: usize) -> Self { todo!() } +/// } +/// +/// let value = 12u16; +/// let reference = &value; +/// let tag = Tag2::B01; +/// +/// let _ptr = CopyTaggedPtr::<_, _, true>::new(reference, tag); +/// ``` +// For some reason miri does not get the compile error +// probably it `check`s instead of `build`ing? +#[cfg(not(miri))] +const _: () = (); + +#[cfg(test)] +mod tests; diff --git a/compiler/rustc_data_structures/src/tagged_ptr/copy/tests.rs b/compiler/rustc_data_structures/src/tagged_ptr/copy/tests.rs new file mode 100644 index 000000000000..bfcc2e603de4 --- /dev/null +++ b/compiler/rustc_data_structures/src/tagged_ptr/copy/tests.rs @@ -0,0 +1,50 @@ +use std::ptr; + +use crate::stable_hasher::{HashStable, StableHasher}; +use crate::tagged_ptr::{CopyTaggedPtr, Pointer, Tag, Tag2}; + +#[test] +fn smoke() { + let value = 12u32; + let reference = &value; + let tag = Tag2::B01; + + let ptr = tag_ptr(reference, tag); + + assert_eq!(ptr.tag(), tag); + assert_eq!(*ptr, 12); + assert!(ptr::eq(ptr.pointer(), reference)); + + let copy = ptr; + + let mut ptr = ptr; + ptr.set_tag(Tag2::B00); + assert_eq!(ptr.tag(), Tag2::B00); + + assert_eq!(copy.tag(), tag); + assert_eq!(*copy, 12); + assert!(ptr::eq(copy.pointer(), reference)); +} + +#[test] +fn stable_hash_hashes_as_tuple() { + let hash_packed = { + let mut hasher = StableHasher::new(); + tag_ptr(&12, Tag2::B11).hash_stable(&mut (), &mut hasher); + + hasher.finalize() + }; + + let hash_tupled = { + let mut hasher = StableHasher::new(); + (&12, Tag2::B11).hash_stable(&mut (), &mut hasher); + hasher.finalize() + }; + + assert_eq!(hash_packed, hash_tupled); +} + +/// Helper to create tagged pointers without specifying `COMPARE_PACKED` if it does not matter. +fn tag_ptr(ptr: P, tag: T) -> CopyTaggedPtr { + CopyTaggedPtr::new(ptr, tag) +} diff --git a/compiler/rustc_data_structures/src/tagged_ptr/drop.rs b/compiler/rustc_data_structures/src/tagged_ptr/drop.rs index b0315c93d934..4e42b5b4afe8 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr/drop.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr/drop.rs @@ -1,14 +1,21 @@ -use super::{Pointer, Tag}; -use crate::stable_hasher::{HashStable, StableHasher}; use std::fmt; +use std::hash::{Hash, Hasher}; +use std::ops::{Deref, DerefMut}; use super::CopyTaggedPtr; +use super::{Pointer, Tag}; +use crate::stable_hasher::{HashStable, StableHasher}; -/// A TaggedPtr implementing `Drop`. +/// A tagged pointer that supports pointers that implement [`Drop`]. +/// +/// This is essentially `{ pointer: P, tag: T }` packed in a single pointer. +/// +/// You should use [`CopyTaggedPtr`] instead of the this type in all cases +/// where `P` implements [`Copy`]. /// /// If `COMPARE_PACKED` is true, then the pointers will be compared and hashed without -/// unpacking. Otherwise we don't implement PartialEq/Eq/Hash; if you want that, -/// wrap the TaggedPtr. +/// unpacking. Otherwise we don't implement [`PartialEq`], [`Eq`] and [`Hash`]; +/// if you want that, wrap the [`TaggedPtr`]. pub struct TaggedPtr where P: Pointer, @@ -17,58 +24,67 @@ where raw: CopyTaggedPtr, } -impl Clone for TaggedPtr +impl TaggedPtr +where + P: Pointer, + T: Tag, +{ + /// Tags `pointer` with `tag`. + #[inline] + pub fn new(pointer: P, tag: T) -> Self { + TaggedPtr { raw: CopyTaggedPtr::new(pointer, tag) } + } + + /// Retrieves the tag. + #[inline] + pub fn tag(&self) -> T { + self.raw.tag() + } + + /// Sets the tag to a new value. + #[inline] + pub fn set_tag(&mut self, tag: T) { + self.raw.set_tag(tag) + } +} + +impl Clone for TaggedPtr where P: Pointer + Clone, T: Tag, { fn clone(&self) -> Self { - unsafe { Self::new(P::with_ref(self.raw.pointer_raw(), |p| p.clone()), self.raw.tag()) } + let ptr = self.raw.with_pointer_ref(P::clone); + + Self::new(ptr, self.tag()) } } -// We pack the tag into the *upper* bits of the pointer to ease retrieval of the -// value; a right shift is a multiplication and those are embeddable in -// instruction encoding. -impl TaggedPtr -where - P: Pointer, - T: Tag, -{ - pub fn new(pointer: P, tag: T) -> Self { - TaggedPtr { raw: CopyTaggedPtr::new(pointer, tag) } - } - - pub fn pointer_ref(&self) -> &P::Target { - self.raw.pointer_ref() - } - pub fn tag(&self) -> T { - self.raw.tag() - } -} - -impl std::ops::Deref for TaggedPtr +impl Deref for TaggedPtr where P: Pointer, T: Tag, { type Target = P::Target; + + #[inline] fn deref(&self) -> &Self::Target { - self.raw.pointer_ref() + self.raw.deref() } } -impl std::ops::DerefMut for TaggedPtr +impl DerefMut for TaggedPtr where - P: Pointer + std::ops::DerefMut, + P: Pointer + DerefMut, T: Tag, { + #[inline] fn deref_mut(&mut self) -> &mut Self::Target { - self.raw.pointer_mut() + self.raw.deref_mut() } } -impl Drop for TaggedPtr +impl Drop for TaggedPtr where P: Pointer, T: Tag, @@ -76,22 +92,20 @@ where fn drop(&mut self) { // No need to drop the tag, as it's Copy unsafe { - drop(P::from_usize(self.raw.pointer_raw())); + drop(P::from_ptr(self.raw.pointer_raw())); } } } -impl fmt::Debug for TaggedPtr +impl fmt::Debug for TaggedPtr where - P: Pointer, - P::Target: fmt::Debug, + P: Pointer + fmt::Debug, T: Tag + fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("TaggedPtr") - .field("pointer", &self.pointer_ref()) - .field("tag", &self.tag()) - .finish() + self.raw.with_pointer_ref(|ptr| { + f.debug_struct("TaggedPtr").field("pointer", ptr).field("tag", &self.tag()).finish() + }) } } @@ -100,6 +114,7 @@ where P: Pointer, T: Tag, { + #[inline] fn eq(&self, other: &Self) -> bool { self.raw.eq(&other.raw) } @@ -112,17 +127,18 @@ where { } -impl std::hash::Hash for TaggedPtr +impl Hash for TaggedPtr where P: Pointer, T: Tag, { - fn hash(&self, state: &mut H) { + #[inline] + fn hash(&self, state: &mut H) { self.raw.hash(state); } } -impl HashStable for TaggedPtr +impl HashStable for TaggedPtr where P: Pointer + HashStable, T: Tag + HashStable, @@ -131,3 +147,33 @@ where self.raw.hash_stable(hcx, hasher); } } + +/// Test that `new` does not compile if there is not enough alignment for the +/// tag in the pointer. +/// +/// ```compile_fail,E0080 +/// use rustc_data_structures::tagged_ptr::{TaggedPtr, Tag}; +/// +/// #[derive(Copy, Clone, Debug, PartialEq, Eq)] +/// enum Tag2 { B00 = 0b00, B01 = 0b01, B10 = 0b10, B11 = 0b11 }; +/// +/// unsafe impl Tag for Tag2 { +/// const BITS: u32 = 2; +/// +/// fn into_usize(self) -> usize { todo!() } +/// unsafe fn from_usize(tag: usize) -> Self { todo!() } +/// } +/// +/// let value = 12u16; +/// let reference = &value; +/// let tag = Tag2::B01; +/// +/// let _ptr = TaggedPtr::<_, _, true>::new(reference, tag); +/// ``` +// For some reason miri does not get the compile error +// probably it `check`s instead of `build`ing? +#[cfg(not(miri))] +const _: () = (); + +#[cfg(test)] +mod tests; diff --git a/compiler/rustc_data_structures/src/tagged_ptr/drop/tests.rs b/compiler/rustc_data_structures/src/tagged_ptr/drop/tests.rs new file mode 100644 index 000000000000..2c17d678d3aa --- /dev/null +++ b/compiler/rustc_data_structures/src/tagged_ptr/drop/tests.rs @@ -0,0 +1,71 @@ +use std::{ptr, sync::Arc}; + +use crate::tagged_ptr::{Pointer, Tag, Tag2, TaggedPtr}; + +#[test] +fn smoke() { + let value = 12u32; + let reference = &value; + let tag = Tag2::B01; + + let ptr = tag_ptr(reference, tag); + + assert_eq!(ptr.tag(), tag); + assert_eq!(*ptr, 12); + + let clone = ptr.clone(); + assert_eq!(clone.tag(), tag); + assert_eq!(*clone, 12); + + let mut ptr = ptr; + ptr.set_tag(Tag2::B00); + assert_eq!(ptr.tag(), Tag2::B00); + + assert_eq!(clone.tag(), tag); + assert_eq!(*clone, 12); + assert!(ptr::eq(&*ptr, &*clone)) +} + +#[test] +fn boxed() { + let value = 12u32; + let boxed = Box::new(value); + let tag = Tag2::B01; + + let ptr = tag_ptr(boxed, tag); + + assert_eq!(ptr.tag(), tag); + assert_eq!(*ptr, 12); + + let clone = ptr.clone(); + assert_eq!(clone.tag(), tag); + assert_eq!(*clone, 12); + + let mut ptr = ptr; + ptr.set_tag(Tag2::B00); + assert_eq!(ptr.tag(), Tag2::B00); + + assert_eq!(clone.tag(), tag); + assert_eq!(*clone, 12); + assert!(!ptr::eq(&*ptr, &*clone)) +} + +#[test] +fn arclones() { + let value = 12u32; + let arc = Arc::new(value); + let tag = Tag2::B01; + + let ptr = tag_ptr(arc, tag); + + assert_eq!(ptr.tag(), tag); + assert_eq!(*ptr, 12); + + let clone = ptr.clone(); + assert!(ptr::eq(&*ptr, &*clone)) +} + +/// Helper to create tagged pointers without specifying `COMPARE_PACKED` if it does not matter. +fn tag_ptr(ptr: P, tag: T) -> TaggedPtr { + TaggedPtr::new(ptr, tag) +} diff --git a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs new file mode 100644 index 000000000000..cb7f7d318dc4 --- /dev/null +++ b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag.rs @@ -0,0 +1,144 @@ +/// Implements [`Tag`] for a given type. +/// +/// You can use `impl_tag` on structs and enums. +/// You need to specify the type and all its possible values, +/// which can only be paths with optional fields. +/// +/// [`Tag`]: crate::tagged_ptr::Tag +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// #![feature(macro_metavar_expr)] +/// use rustc_data_structures::{impl_tag, tagged_ptr::Tag}; +/// +/// #[derive(Copy, Clone, PartialEq, Debug)] +/// enum SomeTag { +/// A, +/// B, +/// X { v: bool }, +/// Y(bool, bool), +/// } +/// +/// impl_tag! { +/// // The type for which the `Tag` will be implemented +/// impl Tag for SomeTag; +/// // You need to specify all possible tag values: +/// SomeTag::A, // 0 +/// SomeTag::B, // 1 +/// // For variants with fields, you need to specify the fields: +/// SomeTag::X { v: true }, // 2 +/// SomeTag::X { v: false }, // 3 +/// // For tuple variants use named syntax: +/// SomeTag::Y { 0: true, 1: true }, // 4 +/// SomeTag::Y { 0: false, 1: true }, // 5 +/// SomeTag::Y { 0: true, 1: false }, // 6 +/// SomeTag::Y { 0: false, 1: false }, // 7 +/// } +/// +/// // Tag values are assigned in order: +/// assert_eq!(SomeTag::A.into_usize(), 0); +/// assert_eq!(SomeTag::X { v: false }.into_usize(), 3); +/// assert_eq!(SomeTag::Y(false, true).into_usize(), 5); +/// +/// assert_eq!(unsafe { SomeTag::from_usize(1) }, SomeTag::B); +/// assert_eq!(unsafe { SomeTag::from_usize(2) }, SomeTag::X { v: true }); +/// assert_eq!(unsafe { SomeTag::from_usize(7) }, SomeTag::Y(false, false)); +/// ``` +/// +/// Structs are supported: +/// +/// ``` +/// #![feature(macro_metavar_expr)] +/// # use rustc_data_structures::impl_tag; +/// #[derive(Copy, Clone)] +/// struct Flags { a: bool, b: bool } +/// +/// impl_tag! { +/// impl Tag for Flags; +/// Flags { a: true, b: true }, +/// Flags { a: false, b: true }, +/// Flags { a: true, b: false }, +/// Flags { a: false, b: false }, +/// } +/// ``` +/// +/// Not specifying all values results in a compile error: +/// +/// ```compile_fail,E0004 +/// #![feature(macro_metavar_expr)] +/// # use rustc_data_structures::impl_tag; +/// #[derive(Copy, Clone)] +/// enum E { +/// A, +/// B, +/// } +/// +/// impl_tag! { +/// impl Tag for E; +/// E::A, +/// } +/// ``` +#[macro_export] +macro_rules! impl_tag { + ( + impl Tag for $Self:ty; + $( + $($path:ident)::* $( { $( $fields:tt )* })?, + )* + ) => { + // Safety: + // `bits_for_tags` is called on the same `${index()}`-es as + // `into_usize` returns, thus `BITS` constant is correct. + unsafe impl $crate::tagged_ptr::Tag for $Self { + const BITS: u32 = $crate::tagged_ptr::bits_for_tags(&[ + $( + ${index()}, + $( ${ignore(path)} )* + )* + ]); + + #[inline] + fn into_usize(self) -> usize { + // This forbids use of repeating patterns (`Enum::V`&`Enum::V`, etc) + // (or at least it should, see ) + #[forbid(unreachable_patterns)] + match self { + // `match` is doing heavy lifting here, by requiring exhaustiveness + $( + $($path)::* $( { $( $fields )* } )? => ${index()}, + )* + } + } + + #[inline] + unsafe fn from_usize(tag: usize) -> Self { + match tag { + $( + ${index()} => $($path)::* $( { $( $fields )* } )?, + )* + + // Safety: + // `into_usize` only returns `${index()}` of the same + // repetition as we are filtering above, thus if this is + // reached, the safety contract of this function was + // already breached. + _ => unsafe { + debug_assert!( + false, + "invalid tag: {tag}\ + (this is a bug in the caller of `from_usize`)" + ); + std::hint::unreachable_unchecked() + }, + } + } + + } + }; +} + +#[cfg(test)] +mod tests; diff --git a/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs new file mode 100644 index 000000000000..62c926153e1e --- /dev/null +++ b/compiler/rustc_data_structures/src/tagged_ptr/impl_tag/tests.rs @@ -0,0 +1,34 @@ +#[test] +fn bits_constant() { + use crate::tagged_ptr::Tag; + + #[derive(Copy, Clone)] + struct Unit; + impl_tag! { impl Tag for Unit; Unit, } + assert_eq!(Unit::BITS, 0); + + #[derive(Copy, Clone)] + enum Enum3 { + A, + B, + C, + } + impl_tag! { impl Tag for Enum3; Enum3::A, Enum3::B, Enum3::C, } + assert_eq!(Enum3::BITS, 2); + + #[derive(Copy, Clone)] + struct Eight(bool, bool, bool); + impl_tag! { + impl Tag for Eight; + Eight { 0: true, 1: true, 2: true }, + Eight { 0: true, 1: true, 2: false }, + Eight { 0: true, 1: false, 2: true }, + Eight { 0: true, 1: false, 2: false }, + Eight { 0: false, 1: true, 2: true }, + Eight { 0: false, 1: true, 2: false }, + Eight { 0: false, 1: false, 2: true }, + Eight { 0: false, 1: false, 2: false }, + } + + assert_eq!(Eight::BITS, 3); +} diff --git a/compiler/rustc_data_structures/src/vec_linked_list.rs b/compiler/rustc_data_structures/src/vec_linked_list.rs index ce60d40b24b4..fda72c9a3b20 100644 --- a/compiler/rustc_data_structures/src/vec_linked_list.rs +++ b/compiler/rustc_data_structures/src/vec_linked_list.rs @@ -1,4 +1,4 @@ -use rustc_index::vec::{Idx, IndexVec}; +use rustc_index::{Idx, IndexVec}; pub fn iter( first: Option, diff --git a/compiler/rustc_data_structures/src/work_queue.rs b/compiler/rustc_data_structures/src/work_queue.rs index 10317f1afff6..9db6b6f20bed 100644 --- a/compiler/rustc_data_structures/src/work_queue.rs +++ b/compiler/rustc_data_structures/src/work_queue.rs @@ -1,5 +1,5 @@ use rustc_index::bit_set::BitSet; -use rustc_index::vec::Idx; +use rustc_index::Idx; use std::collections::VecDeque; /// A work queue is a handy data structure for tracking work left to diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 73a1f79a020f..cc4c5a0cacdd 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -18,6 +18,7 @@ rustc_const_eval = { path = "../rustc_const_eval" } rustc_error_messages = { path = "../rustc_error_messages" } rustc_expand = { path = "../rustc_expand" } rustc_hir_typeck = { path = "../rustc_hir_typeck" } +rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_incremental = { path = "../rustc_incremental" } rustc_infer = { path = "../rustc_infer" } rustc_mir_build = { path = "../rustc_mir_build" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index b9f0e756e65f..5fac485de641 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -28,10 +28,10 @@ use rustc_errors::{ DiagnosticMessage, ErrorGuaranteed, PResult, SubdiagnosticMessage, TerminalUrl, }; use rustc_feature::find_gated_cfg; +use rustc_fluent_macro::fluent_messages; use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; use rustc_interface::{interface, Queries}; use rustc_lint::LintStore; -use rustc_macros::fluent_messages; use rustc_metadata::locator; use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS}; use rustc_session::config::{ErrorOutputType, Input, OutputType, PrintRequest, TrimmedDefPaths}; @@ -58,8 +58,16 @@ use std::str; use std::sync::LazyLock; use std::time::Instant; +// This import blocks the use of panicking `print` and `println` in all the code +// below. Please use `safe_print` and `safe_println` to avoid ICE when +// encountering an I/O error during print. +#[allow(unused_imports)] +use std::{compile_error as print, compile_error as println}; + pub mod args; pub mod pretty; +#[macro_use] +mod print; mod session_diagnostics; use crate::session_diagnostics::{ @@ -511,7 +519,7 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) { if io::stdout().is_terminal() { show_content_with_pager(&text); } else { - print!("{text}"); + safe_print!("{text}"); } } Err(InvalidErrorCode) => { @@ -547,7 +555,7 @@ fn show_content_with_pager(content: &str) { // If pager fails for whatever reason, we should still print the content // to standard output if fallback_to_println { - print!("{content}"); + safe_print!("{content}"); } } @@ -601,7 +609,7 @@ pub fn list_metadata(sess: &Session, metadata_loader: &dyn MetadataLoader) -> Co let path = &(*ifile); let mut v = Vec::new(); locator::list_file_metadata(&sess.target, path, metadata_loader, &mut v).unwrap(); - println!("{}", String::from_utf8(v).unwrap()); + safe_println!("{}", String::from_utf8(v).unwrap()); } Input::Str { .. } => { early_error(ErrorOutputType::default(), "cannot list metadata for stdin"); @@ -642,12 +650,12 @@ fn print_crate_info( TargetList => { let mut targets = rustc_target::spec::TARGETS.to_vec(); targets.sort_unstable(); - println!("{}", targets.join("\n")); + safe_println!("{}", targets.join("\n")); } - Sysroot => println!("{}", sess.sysroot.display()), - TargetLibdir => println!("{}", sess.target_tlib_path.dir.display()), + Sysroot => safe_println!("{}", sess.sysroot.display()), + TargetLibdir => safe_println!("{}", sess.target_tlib_path.dir.display()), TargetSpec => { - println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap()); + safe_println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap()); } AllTargetSpecs => { let mut targets = BTreeMap::new(); @@ -656,7 +664,7 @@ fn print_crate_info( let target = Target::expect_builtin(&triple); targets.insert(name, target.to_json()); } - println!("{}", serde_json::to_string_pretty(&targets).unwrap()); + safe_println!("{}", serde_json::to_string_pretty(&targets).unwrap()); } FileNames | CrateName => { let Some(attrs) = attrs.as_ref() else { @@ -666,14 +674,14 @@ fn print_crate_info( let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess); let id = rustc_session::output::find_crate_name(sess, attrs); if *req == PrintRequest::CrateName { - println!("{id}"); + safe_println!("{id}"); continue; } let crate_types = collect_crate_types(sess, attrs); for &style in &crate_types { let fname = rustc_session::output::filename_for_input(sess, style, id, &t_outputs); - println!("{}", fname.file_name().unwrap().to_string_lossy()); + safe_println!("{}", fname.file_name().unwrap().to_string_lossy()); } } Cfg => { @@ -707,13 +715,13 @@ fn print_crate_info( cfgs.sort(); for cfg in cfgs { - println!("{cfg}"); + safe_println!("{cfg}"); } } CallingConventions => { let mut calling_conventions = rustc_target::spec::abi::all_names(); calling_conventions.sort_unstable(); - println!("{}", calling_conventions.join("\n")); + safe_println!("{}", calling_conventions.join("\n")); } RelocationModels | CodeModels @@ -733,7 +741,7 @@ fn print_crate_info( let stable = sess.target.options.supported_split_debuginfo.contains(split); let unstable_ok = sess.unstable_options(); if stable || unstable_ok { - println!("{split}"); + safe_println!("{split}"); } } } @@ -770,14 +778,14 @@ pub fn version_at_macro_invocation( ) { let verbose = matches.opt_present("verbose"); - println!("{binary} {version}"); + safe_println!("{binary} {version}"); if verbose { - println!("binary: {binary}"); - println!("commit-hash: {commit_hash}"); - println!("commit-date: {commit_date}"); - println!("host: {}", config::host_triple()); - println!("release: {release}"); + safe_println!("binary: {binary}"); + safe_println!("commit-hash: {commit_hash}"); + safe_println!("commit-date: {commit_date}"); + safe_println!("host: {}", config::host_triple()); + safe_println!("release: {release}"); let debug_flags = matches.opt_strs("Z"); let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); @@ -807,7 +815,7 @@ fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) { } else { "" }; - println!( + safe_println!( "{options}{at_path}\nAdditional help: -C help Print codegen options -W help \ @@ -820,7 +828,7 @@ fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) { } fn print_wall_help() { - println!( + safe_println!( " The flag `-Wall` does not exist in `rustc`. Most useful lints are enabled by default. Use `rustc -W help` to see all available lints. It's more common to put @@ -832,7 +840,7 @@ the command line flag directly. /// Write to stdout lint command options, together with a list of all available lints pub fn describe_lints(sess: &Session, lint_store: &LintStore, loaded_plugins: bool) { - println!( + safe_println!( " Available lint options: -W Warn about @@ -877,21 +885,21 @@ Available lint options: s }; - println!("Lint checks provided by rustc:\n"); + safe_println!("Lint checks provided by rustc:\n"); let print_lints = |lints: Vec<&Lint>| { - println!(" {} {:7.7} {}", padded("name"), "default", "meaning"); - println!(" {} {:7.7} {}", padded("----"), "-------", "-------"); + safe_println!(" {} {:7.7} {}", padded("name"), "default", "meaning"); + safe_println!(" {} {:7.7} {}", padded("----"), "-------", "-------"); for lint in lints { let name = lint.name_lower().replace('_', "-"); - println!( + safe_println!( " {} {:7.7} {}", padded(&name), lint.default_level(sess.edition()).as_str(), lint.desc ); } - println!("\n"); + safe_println!("\n"); }; print_lints(builtin); @@ -912,14 +920,14 @@ Available lint options: s }; - println!("Lint groups provided by rustc:\n"); + safe_println!("Lint groups provided by rustc:\n"); let print_lint_groups = |lints: Vec<(&'static str, Vec)>, all_warnings| { - println!(" {} sub-lints", padded("name")); - println!(" {} ---------", padded("----")); + safe_println!(" {} sub-lints", padded("name")); + safe_println!(" {} ---------", padded("----")); if all_warnings { - println!(" {} all lints that are set to issue warnings", padded("warnings")); + safe_println!(" {} all lints that are set to issue warnings", padded("warnings")); } for (name, to) in lints { @@ -929,26 +937,26 @@ Available lint options: .map(|x| x.to_string().replace('_', "-")) .collect::>() .join(", "); - println!(" {} {}", padded(&name), desc); + safe_println!(" {} {}", padded(&name), desc); } - println!("\n"); + safe_println!("\n"); }; print_lint_groups(builtin_groups, true); match (loaded_plugins, plugin.len(), plugin_groups.len()) { (false, 0, _) | (false, _, 0) => { - println!("Lint tools like Clippy can provide additional lints and lint groups."); + safe_println!("Lint tools like Clippy can provide additional lints and lint groups."); } (false, ..) => panic!("didn't load lint plugins but got them anyway!"), - (true, 0, 0) => println!("This crate does not load any lint plugins or lint groups."), + (true, 0, 0) => safe_println!("This crate does not load any lint plugins or lint groups."), (true, l, g) => { if l > 0 { - println!("Lint checks provided by plugins loaded by this crate:\n"); + safe_println!("Lint checks provided by plugins loaded by this crate:\n"); print_lints(plugin); } if g > 0 { - println!("Lint groups provided by plugins loaded by this crate:\n"); + safe_println!("Lint groups provided by plugins loaded by this crate:\n"); print_lint_groups(plugin_groups, false); } } @@ -996,12 +1004,12 @@ pub fn describe_flag_categories(matches: &Matches) -> bool { } fn describe_debug_flags() { - println!("\nAvailable options:\n"); + safe_println!("\nAvailable options:\n"); print_flag_list("-Z", config::Z_OPTIONS); } fn describe_codegen_flags() { - println!("\nAvailable codegen options:\n"); + safe_println!("\nAvailable codegen options:\n"); print_flag_list("-C", config::CG_OPTIONS); } @@ -1012,7 +1020,7 @@ fn print_flag_list( let max_len = flag_list.iter().map(|&(name, _, _, _)| name.chars().count()).max().unwrap_or(0); for &(name, _, _, desc) in flag_list { - println!( + safe_println!( " {} {:>width$}=val -- {}", cmdline_opt, name.replace('_', "-"), diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index 446c6832cb7b..ee64b18d3f60 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -488,12 +488,7 @@ fn print_with_analysis(tcx: TyCtxt<'_>, ppm: PpMode) -> Result<(), ErrorGuarante abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess); debug!("pretty printing THIR tree"); for did in tcx.hir().body_owners() { - let _ = writeln!( - out, - "{:?}:\n{}\n", - did, - tcx.thir_tree(ty::WithOptConstParam::unknown(did)) - ); + let _ = writeln!(out, "{:?}:\n{}\n", did, tcx.thir_tree(did)); } out } @@ -503,12 +498,7 @@ fn print_with_analysis(tcx: TyCtxt<'_>, ppm: PpMode) -> Result<(), ErrorGuarante abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess); debug!("pretty printing THIR flat"); for did in tcx.hir().body_owners() { - let _ = writeln!( - out, - "{:?}:\n{}\n", - did, - tcx.thir_flat(ty::WithOptConstParam::unknown(did)) - ); + let _ = writeln!(out, "{:?}:\n{}\n", did, tcx.thir_flat(did)); } out } diff --git a/compiler/rustc_driver_impl/src/print.rs b/compiler/rustc_driver_impl/src/print.rs new file mode 100644 index 000000000000..70de55320f7a --- /dev/null +++ b/compiler/rustc_driver_impl/src/print.rs @@ -0,0 +1,20 @@ +use std::fmt; +use std::io::{self, Write as _}; + +macro_rules! safe_print { + ($($arg:tt)*) => {{ + $crate::print::print(std::format_args!($($arg)*)); + }}; +} + +macro_rules! safe_println { + ($($arg:tt)*) => { + safe_print!("{}\n", std::format_args!($($arg)*)) + }; +} + +pub(crate) fn print(args: fmt::Arguments<'_>) { + if let Err(_) = io::stdout().write_fmt(args) { + rustc_errors::FatalError.raise(); + } +} diff --git a/compiler/rustc_error_codes/src/error_codes/E0026.md b/compiler/rustc_error_codes/src/error_codes/E0026.md index 72c575aabb64..f485112cca29 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0026.md +++ b/compiler/rustc_error_codes/src/error_codes/E0026.md @@ -1,4 +1,4 @@ -A struct pattern attempted to extract a non-existent field from a struct. +A struct pattern attempted to extract a nonexistent field from a struct. Erroneous code example: diff --git a/compiler/rustc_error_codes/src/error_codes/E0208.md b/compiler/rustc_error_codes/src/error_codes/E0208.md index 1ae01106f201..c6db9b5d61be 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0208.md +++ b/compiler/rustc_error_codes/src/error_codes/E0208.md @@ -32,7 +32,7 @@ error: [-, o] This error is deliberately triggered with the `#[rustc_variance]` attribute (`#![feature(rustc_attrs)]` must be enabled) and helps to show you the variance of the type's generic parameters. You can read more about variance and -subtyping in [this section of the Rustnomicon]. For a more in depth look at +subtyping in [this section of the Rustonomicon]. For a more in depth look at variance (including a more complete list of common variances) see [this section of the Reference]. For information on how variance is implemented in the compiler, see [this section of `rustc-dev-guide`]. @@ -41,6 +41,6 @@ This error can be easily fixed by removing the `#[rustc_variance]` attribute, the compiler's suggestion to comment it out can be applied automatically with `rustfix`. -[this section of the Rustnomicon]: https://doc.rust-lang.org/nomicon/subtyping.html +[this section of the Rustonomicon]: https://doc.rust-lang.org/nomicon/subtyping.html [this section of the Reference]: https://doc.rust-lang.org/reference/subtyping.html#variance [this section of `rustc-dev-guide`]: https://rustc-dev-guide.rust-lang.org/variance.html diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md index 08159d3f469a..c1104a88a767 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0311.md +++ b/compiler/rustc_error_codes/src/error_codes/E0311.md @@ -29,7 +29,7 @@ If `no_restriction()` were to use `&T` instead of `&()` as an argument, the compiler would have added an implied bound, causing this to compile. This error can be resolved by explicitly naming the elided lifetime for `x` and -then explicily requiring that the generic parameter `T` outlives that lifetime: +then explicitly requiring that the generic parameter `T` outlives that lifetime: ``` fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () { diff --git a/compiler/rustc_error_codes/src/error_codes/E0457.md b/compiler/rustc_error_codes/src/error_codes/E0457.md index 53d384d36c42..2c33d1e6a241 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0457.md +++ b/compiler/rustc_error_codes/src/error_codes/E0457.md @@ -1,6 +1,6 @@ Plugin `..` only found in rlib format, but must be available in dylib format. -Erroronous code example: +Erroneous code example: `rlib-plugin.rs` ```ignore (needs-linkage-with-other-tests) diff --git a/compiler/rustc_error_codes/src/error_codes/E0576.md b/compiler/rustc_error_codes/src/error_codes/E0576.md index 8eead4e7e3b5..300a57a1985f 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0576.md +++ b/compiler/rustc_error_codes/src/error_codes/E0576.md @@ -10,7 +10,7 @@ trait Hello { } ``` -In this example, we tried to use the non-existent associated type `You` of the +In this example, we tried to use the nonexistent associated type `You` of the `Hello` trait. To fix this error, use an existing associated type: ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0609.md b/compiler/rustc_error_codes/src/error_codes/E0609.md index a9db34f474e2..0f5ac94e6d58 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0609.md +++ b/compiler/rustc_error_codes/src/error_codes/E0609.md @@ -1,4 +1,4 @@ -Attempted to access a non-existent field in a struct. +Attempted to access a nonexistent field in a struct. Erroneous code example: diff --git a/compiler/rustc_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml index 27783d60be46..481c94266f27 100644 --- a/compiler/rustc_error_messages/Cargo.toml +++ b/compiler/rustc_error_messages/Cargo.toml @@ -11,6 +11,7 @@ fluent-syntax = "0.11" intl-memoizer = "0.5.1" rustc_baked_icu_data = { path = "../rustc_baked_icu_data" } rustc_data_structures = { path = "../rustc_data_structures" } +rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index 6f319b96f2fa..88d94c93bf52 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -12,7 +12,8 @@ use fluent_bundle::FluentResource; use fluent_syntax::parser::ParserError; use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker}; use rustc_data_structures::sync::Lrc; -use rustc_macros::{fluent_messages, Decodable, Encodable}; +use rustc_fluent_macro::fluent_messages; +use rustc_macros::{Decodable, Encodable}; use rustc_span::Span; use std::borrow::Cow; use std::error::Error; diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index e1ead08ea66b..46ace8eb2dd8 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -10,6 +10,7 @@ tracing = "0.1" rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_error_messages = { path = "../rustc_error_messages" } +rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index fe44799efdb6..2498ae2b7bce 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1336,6 +1336,7 @@ impl EmitterWriter { // see? for (text, style) in msg.iter() { let text = self.translate_message(text, args).map_err(Report::new).unwrap(); + let text = &normalize_whitespace(&text); let lines = text.split('\n').collect::>(); if lines.len() > 1 { for (i, line) in lines.iter().enumerate() { @@ -1980,7 +1981,7 @@ impl EmitterWriter { } if let DisplaySuggestion::Add = show_code_change && is_item_attribute { // The suggestion adds an entire line of code, ending on a newline, so we'll also - // print the *following* line, to provide context of what we're advicing people to + // print the *following* line, to provide context of what we're advising people to // do. Otherwise you would only see contextless code that can be confused for // already existing code, despite the colors and UI elements. // We special case `#[derive(_)]\n` and other attribute suggestions, because those diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index d20b168904d6..b65a636d7701 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -31,15 +31,15 @@ use Level::*; use emitter::{is_case_difference, Emitter, EmitterWriter}; use registry::Registry; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; -use rustc_data_structures::stable_hasher::StableHasher; +use rustc_data_structures::stable_hasher::{Hash128, StableHasher}; use rustc_data_structures::sync::{self, Lock, Lrc}; use rustc_data_structures::AtomicRef; pub use rustc_error_messages::{ fallback_fluent_bundle, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle, LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagnosticMessage, }; +use rustc_fluent_macro::fluent_messages; pub use rustc_lint_defs::{pluralize, Applicability}; -use rustc_macros::fluent_messages; use rustc_span::source_map::SourceMap; pub use rustc_span::ErrorGuaranteed; use rustc_span::{Loc, Span}; @@ -427,7 +427,7 @@ struct HandlerInner { /// This set contains a hash of every diagnostic that has been emitted by /// this handler. These hashes is used to avoid emitting the same error /// twice. - emitted_diagnostics: FxHashSet, + emitted_diagnostics: FxHashSet, /// Stashed diagnostics emitted in one stage of the compiler that may be /// stolen by other stages (e.g. to improve them and add more information). diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml index c971714e05bb..2dae0e3f53c3 100644 --- a/compiler/rustc_expand/Cargo.toml +++ b/compiler/rustc_expand/Cargo.toml @@ -16,6 +16,7 @@ rustc_attr = { path = "../rustc_attr" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } +rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_lexer = { path = "../rustc_lexer" } rustc_lint_defs = { path = "../rustc_lint_defs" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 5d999d0db5db..70d2718b7063 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -136,3 +136,7 @@ expand_proc_macro_panicked = expand_proc_macro_derive_tokens = proc-macro derive produced unparsable tokens + +expand_duplicate_matcher_binding = duplicate matcher binding + .label = duplicate binding + .label2 = previous binding diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index e5102a952e74..e3a0ae3570eb 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -397,3 +397,13 @@ pub struct ProcMacroDeriveTokens { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(expand_duplicate_matcher_binding)] +pub struct DuplicateMatcherBinding { + #[primary_span] + #[label] + pub span: Span, + #[label(expand_label2)] + pub prev: Span, +} diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs index ced7531c3fe7..83a5043b0aa6 100644 --- a/compiler/rustc_expand/src/lib.rs +++ b/compiler/rustc_expand/src/lib.rs @@ -21,7 +21,7 @@ extern crate tracing; extern crate proc_macro as pm; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_macros::fluent_messages; +use rustc_fluent_macro::fluent_messages; mod placeholders; mod proc_macro_server; diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 5be134f4e664..75b6396f0be3 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -104,6 +104,7 @@ //! Kleene operators under which a meta-variable is repeating is the concatenation of the stacks //! stored when entering a macro definition starting from the state in which the meta-variable is //! bound. +use crate::errors; use crate::mbe::{KleeneToken, TokenTree}; use rustc_ast::token::{Delimiter, Token, TokenKind}; @@ -281,10 +282,7 @@ fn check_binders( // Duplicate binders at the top-level macro definition are errors. The lint is only // for nested macro definitions. sess.span_diagnostic - .struct_span_err(span, "duplicate matcher binding") - .span_label(span, "duplicate binding") - .span_label(prev_info.span, "previous binding") - .emit(); + .emit_err(errors::DuplicateMatcherBinding { span, prev: prev_info.span }); *valid = false; } else { binders.insert(name, BinderInfo { span, ops: ops.into() }); diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 5679cdcbbd06..3aeb2edb54ca 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -341,7 +341,7 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>( Success(named_matches) => { debug!("Parsed arm successfully"); // The matcher was `Success(..)`ful. - // Merge the gated spans from parsing the matcher with the pre-existing ones. + // Merge the gated spans from parsing the matcher with the preexisting ones. sess.gated_spans.merge(gated_spans_snapshot); return Ok((i, named_matches)); @@ -873,7 +873,7 @@ impl<'tt> FirstSets<'tt> { } } -// Most `mbe::TokenTree`s are pre-existing in the matcher, but some are defined +// Most `mbe::TokenTree`s are preexisting in the matcher, but some are defined // implicitly, such as opening/closing delimiters and sequence repetition ops. // This type encapsulates both kinds. It implements `Clone` while avoiding the // need for `mbe::TokenTree` to implement `Clone`. diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 341ae18541b3..1e7d07bc22d5 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -18,7 +18,7 @@ use rustc_span::def_id::CrateNum; use rustc_span::symbol::{self, sym, Symbol}; use rustc_span::{BytePos, FileName, Pos, SourceFile, Span}; use smallvec::{smallvec, SmallVec}; -use std::ops::Bound; +use std::ops::{Bound, Range}; trait FromInternal { fn from_internal(x: T) -> Self; @@ -634,6 +634,15 @@ impl server::Span for Rustc<'_, '_> { span.source_callsite() } + fn byte_range(&mut self, span: Self::Span) -> Range { + let source_map = self.sess().source_map(); + + let relative_start_pos = source_map.lookup_byte_offset(span.lo()).pos; + let relative_end_pos = source_map.lookup_byte_offset(span.hi()).pos; + + Range { start: relative_start_pos.0 as usize, end: relative_end_pos.0 as usize } + } + fn start(&mut self, span: Self::Span) -> LineColumn { let loc = self.sess().source_map().lookup_char_pos(span.lo()); LineColumn { line: loc.line, column: loc.col.to_usize() } diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs index 480d95b77e90..8a5e09475ff1 100644 --- a/compiler/rustc_expand/src/tests.rs +++ b/compiler/rustc_expand/src/tests.rs @@ -513,7 +513,7 @@ error: foo } #[test] -fn non_overlaping() { +fn non_overlapping() { test_harness( r#" fn foo() { @@ -552,7 +552,7 @@ error: foo } #[test] -fn overlaping_start_and_end() { +fn overlapping_start_and_end() { test_harness( r#" fn foo() { diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 3d644de16652..3b9fc5e9a513 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -239,7 +239,7 @@ declare_features! ( /// Allows using `Self` and associated types in struct expressions and patterns. (accepted, more_struct_aliases, "1.16.0", Some(37544), None), /// Allows using the MOVBE target feature. - (accepted, movbe_target_feature, "CURRENT_RUSTC_VERSION", Some(44839), None), + (accepted, movbe_target_feature, "1.70.0", Some(44839), None), /// Allows patterns with concurrent by-move and by-ref bindings. /// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref. (accepted, move_ref_pattern, "1.49.0", Some(68354), None), diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 48f5bd1cb504..052d312d9a0d 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -417,7 +417,7 @@ declare_features! ( /// Allows `if let` guard in match arms. (active, if_let_guard, "1.47.0", Some(51114), None), /// Allows `impl Trait` to be used inside associated types (RFC 2515). - (active, impl_trait_in_assoc_type, "CURRENT_RUSTC_VERSION", Some(63063), None), + (active, impl_trait_in_assoc_type, "1.70.0", Some(63063), None), /// Allows `impl Trait` as output type in `Fn` traits in return position of functions. (active, impl_trait_in_fn_trait_return, "1.64.0", Some(99697), None), /// Allows referencing `Self` and projections in impl-trait. @@ -498,7 +498,7 @@ declare_features! ( /// Allows return-position `impl Trait` in traits. (incomplete, return_position_impl_trait_in_trait, "1.65.0", Some(91611), None), /// Allows bounding the return type of AFIT/RPITIT. - (incomplete, return_type_notation, "CURRENT_RUSTC_VERSION", Some(109417), None), + (incomplete, return_type_notation, "1.70.0", Some(109417), None), /// Allows `extern "rust-cold"`. (active, rust_cold_cc, "1.63.0", Some(97544), None), /// Allows the use of SIMD types in functions declared in `extern` blocks. @@ -521,7 +521,7 @@ declare_features! ( /// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`. (active, trait_upcasting, "1.56.0", Some(65991), None), /// Allows for transmuting between arrays with sizes that contain generic consts. - (active, transmute_generic_consts, "CURRENT_RUSTC_VERSION", Some(109929), None), + (active, transmute_generic_consts, "1.70.0", Some(109929), None), /// Allows #[repr(transparent)] on unions (RFC 2645). (active, transparent_unions, "1.37.0", Some(60405), None), /// Allows inconsistent bounds in where clauses. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index c77292fdd164..103e0f344070 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -344,7 +344,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), ungated!(link_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), ungated!(no_link, Normal, template!(Word), WarnFollowing), - ungated!(repr, Normal, template!(List: "C"), DuplicatesOk, @only_local: true), + ungated!(repr, Normal, template!(List: "C"), DuplicatesOk), ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), ungated!(no_mangle, Normal, template!(Word), WarnFollowing, @only_local: true), diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 48d9fbfa6d26..8bca24b2bf01 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -53,7 +53,7 @@ declare_features! ( (removed, await_macro, "1.38.0", Some(50547), None, Some("subsumed by `.await` syntax")), /// Allows using the `box $expr` syntax. - (removed, box_syntax, "CURRENT_RUSTC_VERSION", Some(49733), None, Some("replaced with `#[rustc_box]`")), + (removed, box_syntax, "1.70.0", Some(49733), None, Some("replaced with `#[rustc_box]`")), /// Allows capturing disjoint fields in a closure/generator (RFC 2229). (removed, capture_disjoint_fields, "1.49.0", Some(53488), None, Some("stabilized in Rust 2021")), /// Allows comparing raw pointers during const eval. @@ -139,7 +139,7 @@ declare_features! ( /// Allows using `#[on_unimplemented(..)]` on traits. /// (Moved to `rustc_attrs`.) (removed, on_unimplemented, "1.40.0", None, None, None), - /// A way to temporarily opt out of opt in copy. This will *never* be accepted. + /// A way to temporarily opt out of opt-in copy. This will *never* be accepted. (removed, opt_out_copy, "1.0.0", None, None, None), /// Allows features specific to OIBIT (now called auto traits). /// Renamed to `auto_traits`. diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml new file mode 100644 index 000000000000..f5a6585b5c68 --- /dev/null +++ b/compiler/rustc_fluent_macro/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "rustc_fluent_macro" +version = "0.1.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +annotate-snippets = "0.9" +fluent-bundle = "0.15.2" +fluent-syntax = "0.11" +syn = { version = "2", features = ["full"] } +proc-macro2 = "1" +quote = "1" +unic-langid = { version = "0.9.0", features = ["macros"] } diff --git a/compiler/rustc_macros/src/diagnostics/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs similarity index 99% rename from compiler/rustc_macros/src/diagnostics/fluent.rs rename to compiler/rustc_fluent_macro/src/fluent.rs index 607d51f5608d..9dffc9a76454 100644 --- a/compiler/rustc_macros/src/diagnostics/fluent.rs +++ b/compiler/rustc_fluent_macro/src/fluent.rs @@ -68,7 +68,7 @@ fn failed(crate_name: &Ident) -> proc_macro::TokenStream { .into() } -/// See [rustc_macros::fluent_messages]. +/// See [rustc_fluent_macro::fluent_messages]. pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let crate_name = std::env::var("CARGO_PKG_NAME") // If `CARGO_PKG_NAME` is missing, then we're probably running in a test, so use diff --git a/compiler/rustc_fluent_macro/src/lib.rs b/compiler/rustc_fluent_macro/src/lib.rs new file mode 100644 index 000000000000..a01643cd67d2 --- /dev/null +++ b/compiler/rustc_fluent_macro/src/lib.rs @@ -0,0 +1,64 @@ +#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(proc_macro_diagnostic)] +#![feature(proc_macro_span)] +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::default_hash_types)] + +use proc_macro::TokenStream; + +mod fluent; + +/// Implements the `fluent_messages` macro, which performs compile-time validation of the +/// compiler's Fluent resources (i.e. that the resources parse and don't multiply define the same +/// messages) and generates constants that make using those messages in diagnostics more ergonomic. +/// +/// For example, given the following invocation of the macro.. +/// +/// ```ignore (rust) +/// fluent_messages! { "./typeck.ftl" } +/// ``` +/// ..where `typeck.ftl` has the following contents.. +/// +/// ```fluent +/// typeck_field_multiply_specified_in_initializer = +/// field `{$ident}` specified more than once +/// .label = used more than once +/// .label_previous_use = first use of `{$ident}` +/// ``` +/// ...then the macro parse the Fluent resource, emitting a diagnostic if it fails to do so, and +/// will generate the following code: +/// +/// ```ignore (rust) +/// pub static DEFAULT_LOCALE_RESOURCE: &'static [&'static str] = include_str!("./typeck.ftl"); +/// +/// mod fluent_generated { +/// mod typeck { +/// pub const field_multiply_specified_in_initializer: DiagnosticMessage = +/// DiagnosticMessage::fluent("typeck_field_multiply_specified_in_initializer"); +/// pub const field_multiply_specified_in_initializer_label_previous_use: DiagnosticMessage = +/// DiagnosticMessage::fluent_attr( +/// "typeck_field_multiply_specified_in_initializer", +/// "previous_use_label" +/// ); +/// } +/// } +/// ``` +/// When emitting a diagnostic, the generated constants can be used as follows: +/// +/// ```ignore (rust) +/// let mut err = sess.struct_span_err( +/// span, +/// fluent::typeck::field_multiply_specified_in_initializer +/// ); +/// err.span_default_label(span); +/// err.span_label( +/// previous_use_span, +/// fluent::typeck::field_multiply_specified_in_initializer_label_previous_use +/// ); +/// err.emit(); +/// ``` +#[proc_macro] +pub fn fluent_messages(input: TokenStream) -> TokenStream { + fluent::fluent_messages(input) +} diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs index c89e7eb75f8f..e213623e06d9 100644 --- a/compiler/rustc_hir/src/arena.rs +++ b/compiler/rustc_hir/src/arena.rs @@ -1,56 +1,17 @@ /// This higher-order macro declares a list of types which can be allocated by `Arena`. -/// -/// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]`, -/// where `T` is the type listed. These impls will appear in the implement_ty_decoder! macro. +/// Note that all `Copy` types can be allocated by default and need not be specified here. #[macro_export] macro_rules! arena_types { ($macro:path) => ( $macro!([ // HIR types [] hir_krate: rustc_hir::Crate<'tcx>, - [] arm: rustc_hir::Arm<'tcx>, - [] asm_operand: (rustc_hir::InlineAsmOperand<'tcx>, rustc_span::Span), [] asm_template: rustc_ast::InlineAsmTemplatePiece, [] attribute: rustc_ast::Attribute, - [] closure: rustc_hir::Closure<'tcx>, - [] block: rustc_hir::Block<'tcx>, - [] bare_fn_ty: rustc_hir::BareFnTy<'tcx>, - [] body: rustc_hir::Body<'tcx>, - [] generics: rustc_hir::Generics<'tcx>, - [] generic_arg: rustc_hir::GenericArg<'tcx>, - [] generic_args: rustc_hir::GenericArgs<'tcx>, - [] generic_bound: rustc_hir::GenericBound<'tcx>, - [] generic_param: rustc_hir::GenericParam<'tcx>, - [] expr: rustc_hir::Expr<'tcx>, - [] impl_: rustc_hir::Impl<'tcx>, - [] let_expr: rustc_hir::Let<'tcx>, - [] expr_field: rustc_hir::ExprField<'tcx>, - [] pat_field: rustc_hir::PatField<'tcx>, - [] fn_decl: rustc_hir::FnDecl<'tcx>, - [] foreign_item: rustc_hir::ForeignItem<'tcx>, - [] foreign_item_ref: rustc_hir::ForeignItemRef, - [] impl_item: rustc_hir::ImplItem<'tcx>, - [] impl_item_ref: rustc_hir::ImplItemRef, - [] item: rustc_hir::Item<'tcx>, - [] inline_asm: rustc_hir::InlineAsm<'tcx>, - [] local: rustc_hir::Local<'tcx>, - [] mod_: rustc_hir::Mod<'tcx>, [] owner_info: rustc_hir::OwnerInfo<'tcx>, - [] param: rustc_hir::Param<'tcx>, - [] pat: rustc_hir::Pat<'tcx>, - [] path: rustc_hir::Path<'tcx>, [] use_path: rustc_hir::UsePath<'tcx>, - [] path_segment: rustc_hir::PathSegment<'tcx>, - [] poly_trait_ref: rustc_hir::PolyTraitRef<'tcx>, - [] qpath: rustc_hir::QPath<'tcx>, - [] stmt: rustc_hir::Stmt<'tcx>, - [] field_def: rustc_hir::FieldDef<'tcx>, - [] trait_item: rustc_hir::TraitItem<'tcx>, - [] trait_item_ref: rustc_hir::TraitItemRef, - [] ty: rustc_hir::Ty<'tcx>, - [] type_binding: rustc_hir::TypeBinding<'tcx>, - [] variant: rustc_hir::Variant<'tcx>, - [] where_predicate: rustc_hir::WherePredicate<'tcx>, + [] lit: rustc_hir::Lit, + [] macro_def: rustc_ast::MacroDef, ]); ) } diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 8c58129c800f..30bf8c2ad104 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -234,10 +234,7 @@ impl DefKind { #[inline] pub fn is_fn_like(self) -> bool { - match self { - DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Generator => true, - _ => false, - } + matches!(self, DefKind::Fn | DefKind::AssocFn | DefKind::Closure | DefKind::Generator) } /// Whether `query get_codegen_attrs` should be used with this definition. diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 8ceb176491b6..66b153d8931b 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -9,8 +9,8 @@ use crate::def_id::{CrateNum, DefIndex, LocalDefId, StableCrateId, CRATE_DEF_IND use crate::def_path_hash_map::DefPathHashMap; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::stable_hasher::StableHasher; -use rustc_index::vec::IndexVec; +use rustc_data_structures::stable_hasher::{Hash64, StableHasher}; +use rustc_index::IndexVec; use rustc_span::symbol::{kw, sym, Symbol}; use std::fmt::{self, Write}; @@ -130,7 +130,7 @@ impl DefKey { disambiguator.hash(&mut hasher); - let local_hash: u64 = hasher.finish(); + let local_hash = hasher.finish(); // Construct the new DefPathHash, making sure that the `crate_id` // portion of the hash is properly copied from the parent. This way the @@ -325,7 +325,7 @@ impl Definitions { }, }; - let parent_hash = DefPathHash::new(stable_crate_id, 0); + let parent_hash = DefPathHash::new(stable_crate_id, Hash64::ZERO); let def_path_hash = key.compute_stable_hash(parent_hash); // Create the root definition. diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 35a72f868fbc..e220a0293393 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -14,7 +14,7 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sorted_map::SortedMap; use rustc_error_messages::MultiSpan; -use rustc_index::vec::IndexVec; +use rustc_index::IndexVec; use rustc_macros::HashStable_Generic; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::Spanned; @@ -26,7 +26,7 @@ use rustc_target::spec::abi::Abi; use smallvec::SmallVec; use std::fmt; -#[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)] +#[derive(Debug, Copy, Clone, HashStable_Generic)] pub struct Lifetime { pub hir_id: HirId, @@ -41,8 +41,7 @@ pub struct Lifetime { pub res: LifetimeName, } -#[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)] -#[derive(HashStable_Generic)] +#[derive(Debug, Copy, Clone, HashStable_Generic)] pub enum ParamName { /// Some user-given name like `T` or `'x`. Plain(Ident), @@ -85,8 +84,7 @@ impl ParamName { } } -#[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)] -#[derive(HashStable_Generic)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)] pub enum LifetimeName { /// User-given names or fresh (synthetic) names. Param(LocalDefId), @@ -182,7 +180,7 @@ impl Lifetime { /// A `Path` is essentially Rust's notion of a name; for instance, /// `std::cmp::PartialEq`. It's represented as a sequence of identifiers, /// along with a bunch of supporting information. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Path<'hir, R = Res> { pub span: Span, /// The resolution for the path. @@ -202,7 +200,7 @@ impl Path<'_> { /// A segment of a path: an identifier, an optional lifetime, and a set of /// types. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct PathSegment<'hir> { /// The identifier portion of this path segment. pub ident: Ident, @@ -243,13 +241,13 @@ impl<'hir> PathSegment<'hir> { } } -#[derive(Encodable, Debug, HashStable_Generic)] +#[derive(Clone, Copy, Debug, HashStable_Generic)] pub struct ConstArg { pub value: AnonConst, pub span: Span, } -#[derive(Encodable, Debug, HashStable_Generic)] +#[derive(Clone, Copy, Debug, HashStable_Generic)] pub struct InferArg { pub hir_id: HirId, pub span: Span, @@ -261,7 +259,7 @@ impl InferArg { } } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum GenericArg<'hir> { Lifetime(&'hir Lifetime), Type(&'hir Ty<'hir>), @@ -318,7 +316,7 @@ impl GenericArg<'_> { } } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct GenericArgs<'hir> { /// The generic arguments for this path segment. pub args: &'hir [GenericArg<'hir>], @@ -422,8 +420,7 @@ impl<'hir> GenericArgs<'hir> { } } -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)] -#[derive(HashStable_Generic)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable_Generic)] pub enum GenericArgsParentheses { No, /// Bounds for `feature(return_type_notation)`, like `T: Trait`, @@ -435,8 +432,7 @@ pub enum GenericArgsParentheses { /// A modifier on a bound, currently this is only used for `?Sized`, where the /// modifier is `Maybe`. Negative bounds should also be handled here. -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)] -#[derive(HashStable_Generic)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub enum TraitBoundModifier { None, Maybe, @@ -447,7 +443,7 @@ pub enum TraitBoundModifier { /// `typeck::collect::compute_bounds` matches these against /// the "special" built-in traits (see `middle::lang_items`) and /// detects `Copy`, `Send` and `Sync`. -#[derive(Clone, Debug, HashStable_Generic)] +#[derive(Clone, Copy, Debug, HashStable_Generic)] pub enum GenericBound<'hir> { Trait(PolyTraitRef<'hir>, TraitBoundModifier), // FIXME(davidtwco): Introduce `PolyTraitRef::LangItem` @@ -474,7 +470,7 @@ impl GenericBound<'_> { pub type GenericBounds<'hir> = &'hir [GenericBound<'hir>]; -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)] +#[derive(Copy, Clone, Debug, HashStable_Generic)] pub enum LifetimeParamKind { // Indicates that the lifetime definition was explicitly declared (e.g., in // `fn foo<'a>(x: &'a u8) -> &'a u8 { x }`). @@ -488,7 +484,7 @@ pub enum LifetimeParamKind { Error, } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum GenericParamKind<'hir> { /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`). Lifetime { @@ -505,7 +501,7 @@ pub enum GenericParamKind<'hir> { }, } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct GenericParam<'hir> { pub hir_id: HirId, pub def_id: LocalDefId, @@ -539,7 +535,7 @@ impl<'hir> GenericParam<'hir> { /// early-bound (but can be a late-bound lifetime in functions, for example), /// or from a `for<...>` binder, in which case it's late-bound (and notably, /// does not show up in the parent item's generics). -#[derive(Debug, HashStable_Generic, PartialEq, Eq, Copy, Clone)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum GenericParamSource { // Early or late-bound parameters defined on an item Generics, @@ -557,7 +553,7 @@ pub struct GenericParamCount { /// Represents lifetimes and type parameters attached to a declaration /// of a function, enum, trait, etc. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Generics<'hir> { pub params: &'hir [GenericParam<'hir>], pub predicates: &'hir [WherePredicate<'hir>], @@ -729,7 +725,7 @@ impl<'hir> Generics<'hir> { } /// A single predicate in a where-clause. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum WherePredicate<'hir> { /// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`). BoundPredicate(WhereBoundPredicate<'hir>), @@ -773,7 +769,7 @@ pub enum PredicateOrigin { } /// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`). -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct WhereBoundPredicate<'hir> { pub hir_id: HirId, pub span: Span, @@ -795,7 +791,7 @@ impl<'hir> WhereBoundPredicate<'hir> { } /// A lifetime predicate (e.g., `'a: 'b + 'c`). -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct WhereRegionPredicate<'hir> { pub span: Span, pub in_where_clause: bool, @@ -811,7 +807,7 @@ impl<'hir> WhereRegionPredicate<'hir> { } /// An equality predicate (e.g., `T = int`); currently unsupported. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct WhereEqPredicate<'hir> { pub span: Span, pub lhs_ty: &'hir Ty<'hir>, @@ -821,7 +817,7 @@ pub struct WhereEqPredicate<'hir> { /// HIR node coupled with its parent's id in the same HIR owner. /// /// The parent is trash when the node is a HIR owner. -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] pub struct ParentedNode<'tcx> { pub parent: ItemLocalId, pub node: Node<'tcx>, @@ -863,7 +859,7 @@ pub struct OwnerNodes<'tcx> { impl<'tcx> OwnerNodes<'tcx> { pub fn node(&self) -> OwnerNode<'tcx> { - use rustc_index::vec::Idx; + use rustc_index::Idx; let node = self.nodes[ItemLocalId::new(0)].as_ref().unwrap().node; let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode. node @@ -959,7 +955,7 @@ pub struct Crate<'hir> { pub opt_hir_hash: Option, } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Closure<'hir> { pub def_id: LocalDefId, pub binder: ClosureBinder, @@ -978,7 +974,7 @@ pub struct Closure<'hir> { /// A block of statements `{ .. }`, which may have a label (in this case the /// `targeted_by_break` field will be `true`) and may be `unsafe` by means of /// the `rules` being anything but `DefaultBlock`. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Block<'hir> { /// Statements in a block. pub stmts: &'hir [Stmt<'hir>], @@ -1006,7 +1002,7 @@ impl<'hir> Block<'hir> { } } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Pat<'hir> { #[stable_hasher(ignore)] pub hir_id: HirId, @@ -1085,7 +1081,7 @@ impl<'hir> Pat<'hir> { /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` /// are treated the same as` x: x, y: ref y, z: ref mut z`, /// except `is_shorthand` is true. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct PatField<'hir> { #[stable_hasher(ignore)] pub hir_id: HirId, @@ -1097,7 +1093,7 @@ pub struct PatField<'hir> { pub span: Span, } -#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)] +#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)] pub enum RangeEnd { Included, Excluded, @@ -1141,7 +1137,7 @@ impl fmt::Debug for DotDotPos { } } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum PatKind<'hir> { /// Represents a wildcard pattern (i.e., `_`). Wild, @@ -1197,7 +1193,7 @@ pub enum PatKind<'hir> { Slice(&'hir [Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [Pat<'hir>]), } -#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)] +#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)] pub enum BinOpKind { /// The `+` operator (addition). Add, @@ -1325,7 +1321,7 @@ impl Into for BinOpKind { pub type BinOp = Spanned; -#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)] +#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)] pub enum UnOp { /// The `*` operator (dereferencing). Deref, @@ -1351,7 +1347,7 @@ impl UnOp { } /// A statement. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Stmt<'hir> { pub hir_id: HirId, pub kind: StmtKind<'hir>, @@ -1359,7 +1355,7 @@ pub struct Stmt<'hir> { } /// The contents of a statement. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum StmtKind<'hir> { /// A local (`let`) binding. Local(&'hir Local<'hir>), @@ -1375,7 +1371,7 @@ pub enum StmtKind<'hir> { } /// Represents a `let` statement (i.e., `let : = ;`). -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Local<'hir> { pub pat: &'hir Pat<'hir>, /// Type annotation, if any (otherwise the type will be inferred). @@ -1393,7 +1389,7 @@ pub struct Local<'hir> { /// Represents a single arm of a `match` expression, e.g. /// ` (if ) => `. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Arm<'hir> { #[stable_hasher(ignore)] pub hir_id: HirId, @@ -1411,7 +1407,7 @@ pub struct Arm<'hir> { /// /// In an if-let, imagine it as `if (let = ) { ... }`; in a let-else, it is part of the /// desugaring to if-let. Only let-else supports the type annotation at present. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Let<'hir> { pub hir_id: HirId, pub span: Span, @@ -1420,7 +1416,7 @@ pub struct Let<'hir> { pub init: &'hir Expr<'hir>, } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum Guard<'hir> { If(&'hir Expr<'hir>), IfLet(&'hir Let<'hir>), @@ -1440,7 +1436,7 @@ impl<'hir> Guard<'hir> { } } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct ExprField<'hir> { #[stable_hasher(ignore)] pub hir_id: HirId, @@ -1450,19 +1446,19 @@ pub struct ExprField<'hir> { pub is_shorthand: bool, } -#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)] +#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)] pub enum BlockCheckMode { DefaultBlock, UnsafeBlock(UnsafeSource), } -#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)] +#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)] pub enum UnsafeSource { CompilerGenerated, UserProvided, } -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct BodyId { pub hir_id: HirId, } @@ -1488,7 +1484,7 @@ pub struct BodyId { /// /// All bodies have an **owner**, which can be accessed via the HIR /// map using `body_owner_def_id()`. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Body<'hir> { pub params: &'hir [Param<'hir>], pub value: &'hir Expr<'hir>, @@ -1506,7 +1502,7 @@ impl<'hir> Body<'hir> { } /// The type of source expression that caused this generator to be created. -#[derive(Clone, PartialEq, PartialOrd, Eq, Hash, Debug, Copy)] +#[derive(Clone, PartialEq, Eq, Debug, Copy, Hash)] #[derive(HashStable_Generic, Encodable, Decodable)] pub enum GeneratorKind { /// An explicit `async` block or the body of an async function. @@ -1539,7 +1535,7 @@ impl GeneratorKind { /// /// This helps error messages but is also used to drive coercions in /// type-checking (see #60424). -#[derive(Clone, PartialEq, PartialOrd, Eq, Hash, Debug, Copy)] +#[derive(Clone, PartialEq, Eq, Hash, Debug, Copy)] #[derive(HashStable_Generic, Encodable, Decodable)] pub enum AsyncGeneratorKind { /// An explicit `async` block written by the user. @@ -1649,7 +1645,7 @@ impl fmt::Display for ConstContext { /// A literal. pub type Lit = Spanned; -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)] +#[derive(Copy, Clone, Debug, HashStable_Generic)] pub enum ArrayLen { Infer(HirId, Span), Body(AnonConst), @@ -1671,7 +1667,7 @@ impl ArrayLen { /// /// You can check if this anon const is a default in a const param /// `const N: usize = { ... }` with `tcx.hir().opt_const_param_default_param_def_id(..)` -#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)] +#[derive(Copy, Clone, Debug, HashStable_Generic)] pub struct AnonConst { pub hir_id: HirId, pub def_id: LocalDefId, @@ -1679,7 +1675,7 @@ pub struct AnonConst { } /// An expression. -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Expr<'hir> { pub hir_id: HirId, pub kind: ExprKind<'hir>, @@ -1715,6 +1711,7 @@ impl Expr<'_> { ExprKind::Continue(..) => ExprPrecedence::Continue, ExprKind::Ret(..) => ExprPrecedence::Ret, ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm, + ExprKind::OffsetOf(..) => ExprPrecedence::OffsetOf, ExprKind::Struct(..) => ExprPrecedence::Struct, ExprKind::Repeat(..) => ExprPrecedence::Repeat, ExprKind::Yield(..) => ExprPrecedence::Yield, @@ -1774,6 +1771,7 @@ impl Expr<'_> { | ExprKind::Loop(..) | ExprKind::Assign(..) | ExprKind::InlineAsm(..) + | ExprKind::OffsetOf(..) | ExprKind::AssignOp(..) | ExprKind::Lit(_) | ExprKind::ConstBlock(..) @@ -1818,7 +1816,7 @@ impl Expr<'_> { pub fn can_have_side_effects(&self) -> bool { match self.peel_drop_temps().kind { - ExprKind::Path(_) | ExprKind::Lit(_) => false, + ExprKind::Path(_) | ExprKind::Lit(_) | ExprKind::OffsetOf(..) => false, ExprKind::Type(base, _) | ExprKind::Unary(_, base) | ExprKind::Field(base, _) @@ -1920,7 +1918,7 @@ pub fn is_range_literal(expr: &Expr<'_>) -> bool { } } -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum ExprKind<'hir> { /// Allow anonymous constants from an inline `const` block ConstBlock(AnonConst), @@ -1957,10 +1955,10 @@ pub enum ExprKind<'hir> { /// A unary operation (e.g., `!x`, `*x`). Unary(UnOp, &'hir Expr<'hir>), /// A literal (e.g., `1`, `"foo"`). - Lit(Lit), + Lit(&'hir Lit), /// A cast (e.g., `foo as f64`). Cast(&'hir Expr<'hir>, &'hir Ty<'hir>), - /// A type reference (e.g., `Foo`). + /// A type ascription (e.g., `x: Foo`). See RFC 3307. Type(&'hir Expr<'hir>, &'hir Ty<'hir>), /// Wraps the expression in a terminating scope. /// This makes it semantically equivalent to `{ let _t = expr; _t }`. @@ -2022,6 +2020,9 @@ pub enum ExprKind<'hir> { /// Inline assembly (from `asm!`), with its outputs and inputs. InlineAsm(&'hir InlineAsm<'hir>), + /// Field offset (`offset_of!`) + OffsetOf(&'hir Ty<'hir>, &'hir [Ident]), + /// A struct or struct-like variant literal expression. /// /// E.g., `Foo {x: 1, y: 2}`, or `Foo {x: 1, .. base}`, @@ -2046,7 +2047,7 @@ pub enum ExprKind<'hir> { /// To resolve the path to a `DefId`, call [`qpath_res`]. /// /// [`qpath_res`]: ../../rustc_middle/ty/struct.TypeckResults.html#method.qpath_res -#[derive(Debug, HashStable_Generic)] +#[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum QPath<'hir> { /// Path to a definition, optionally "fully-qualified" with a `Self` /// type, if the path points to an associated item in a trait. @@ -2100,7 +2101,7 @@ impl<'hir> QPath<'hir> { } /// Hints at the original code for a let statement. -#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)] +#[derive(Copy, Clone, Debug, HashStable_Generic)] pub enum LocalSource { /// A `match _ { .. }`. Normal, @@ -2153,7 +2154,7 @@ impl MatchSource { } /// The loop type that yielded an `ExprKind::Loop`. -#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)] +#[derive(Copy, Clone, PartialEq, Debug, HashStable_Generic)] pub enum LoopSource { /// A `loop { .. }` loop. Loop, @@ -2173,7 +2174,7 @@ impl LoopSource { } } -#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)] +#[derive(Copy, Clone, Debug, HashStable_Generic)] pub enum LoopIdError { OutsideLoopScope, UnlabeledCfInWhileCondition, @@ -2192,7 +2193,7 @@ impl fmt::Display for LoopIdError { } } -#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)] +#[derive(Copy, Clone, Debug, HashStable_Generic)] pub struct Destination { /// This is `Some(_)` iff there is an explicit user-specified 'label pub label: Option