diff options
1572 files changed, 18952 insertions, 10273 deletions
diff --git a/.github/ISSUE_TEMPLATE/bootstrap.md b/.github/ISSUE_TEMPLATE/bootstrap.md index 8d72eae8593..344ea30e1fc 100644 --- a/.github/ISSUE_TEMPLATE/bootstrap.md +++ b/.github/ISSUE_TEMPLATE/bootstrap.md @@ -32,7 +32,7 @@ Describe what you expected to happen. Describe what actually happened. --> -### Bootstrap configuration (config.toml) +### Bootstrap configuration (bootstrap.toml) ```toml <config> ``` diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 96c0955e871..25397006ee2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -239,16 +239,31 @@ jobs: if: github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1' - name: postprocess metrics into the summary + # This step is not critical, and if some I/O problem happens, we don't want + # to cancel the build. + continue-on-error: true run: | if [ -f build/metrics.json ]; then - ./build/citool/debug/citool postprocess-metrics build/metrics.json ${GITHUB_STEP_SUMMARY} + METRICS=build/metrics.json elif [ -f obj/build/metrics.json ]; then - ./build/citool/debug/citool postprocess-metrics obj/build/metrics.json ${GITHUB_STEP_SUMMARY} + METRICS=obj/build/metrics.json else echo "No metrics.json found" + exit 0 fi + # Get closest bors merge commit + PARENT_COMMIT=`git rev-list --author='bors <bors@rust-lang.org>' -n1 --first-parent HEAD^1` + + ./build/citool/debug/citool postprocess-metrics \ + --job-name ${CI_JOB_NAME} \ + --parent ${PARENT_COMMIT} \ + ${METRICS} >> ${GITHUB_STEP_SUMMARY} + - name: upload job metrics to DataDog + # This step is not critical, and if some I/O problem happens, we don't want + # to cancel the build. + continue-on-error: true if: needs.calculate_matrix.outputs.run_type != 'pr' env: DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY }} diff --git a/.github/workflows/ghcr.yml b/.github/workflows/ghcr.yml index 052c9ae72b8..c2c0c11f008 100644 --- a/.github/workflows/ghcr.yml +++ b/.github/workflows/ghcr.yml @@ -5,6 +5,9 @@ # Docker Hub has a rate limit, while ghcr.io doesn't. # Those images are pushed to ghcr.io by this job. # +# While Docker Hub rate limit *shouldn't* be an issue on GitHub Actions, +# it certainly is for AWS codebuild. +# # Note that authenticating to DockerHub or other registries isn't possible # for PR jobs, because forks can't access secrets. # That's why we use ghcr.io: it has no rate limit and it doesn't require authentication. @@ -54,6 +57,10 @@ jobs: "ubuntu:22.04" # Mirrored because used by all linux CI jobs, including mingw-check-tidy "moby/buildkit:buildx-stable-1" + # Mirrored because used when CI is running inside a Docker container + "alpine:3.4" + # Mirrored because used by dist-x86_64-linux + "centos:7" ) # Mirror each image from DockerHub to ghcr.io diff --git a/.github/workflows/post-merge.yml b/.github/workflows/post-merge.yml index 31e075f45d6..94553608a2f 100644 --- a/.github/workflows/post-merge.yml +++ b/.github/workflows/post-merge.yml @@ -35,8 +35,12 @@ jobs: cd src/ci/citool - echo "Post-merge analysis result" > output.log + printf "<details>\n<summary>What is this?</summary>\n" >> output.log + printf "This is an experimental post-merge analysis report that shows differences in test outcomes between the merged PR and its parent PR.\n" >> output.log + printf "</details>\n\n" >> output.log + cargo run --release post-merge-report ${PARENT_COMMIT} ${{ github.sha }} >> output.log + cat output.log gh pr comment ${HEAD_PR} -F output.log diff --git a/.gitignore b/.gitignore index b8cb31e8190..a549b6e6e56 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ # This file should only ignore things that are generated during a `x.py` build, # generated by common IDEs, and optional files controlled by the user that -# affect the build (such as config.toml). +# affect the build (such as bootstrap.toml). # In particular, things like `mir_dump` should not be listed here; they are only # created during manual debugging and many people like to clean up instead of # having git ignore such leftovers. You can use `.git/info/exclude` to @@ -34,6 +34,7 @@ Session.vim !/tests/run-make/thumb-none-qemu/example/.cargo ## Configuration +/bootstrap.toml /config.toml /Makefile config.mk diff --git a/.ignore b/.ignore index 40d1513978f..b0c640fee3d 100644 --- a/.ignore +++ b/.ignore @@ -1,2 +1,3 @@ -# Make vscode *not* count `config.toml` as ignored, so it is included in search +# Make vscode *not* count `bootstrap.toml` and `config.toml` as ignored, so it is included in search +!/bootstrap.toml !/config.toml diff --git a/Cargo.lock b/Cargo.lock index 6d252ca8c82..a62bd618d40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -547,7 +547,7 @@ dependencies = [ "termize", "tokio", "toml 0.7.8", - "ui_test 0.26.5", + "ui_test 0.29.2", "walkdir", ] @@ -1548,16 +1548,14 @@ dependencies = [ [[package]] name = "html5ever" -version = "0.27.0" +version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" +checksum = "9b958f80f0fde8601dc6c08685adc743eecaa046181cebd5a57551468dfc2ddc" dependencies = [ "log", "mac", "markup5ever", - "proc-macro2", - "quote", - "syn 2.0.96", + "match_token", ] [[package]] @@ -1927,7 +1925,7 @@ version = "0.1.0" dependencies = [ "fs-err", "getopts", - "jsonpath_lib", + "jsonpath-rust", "regex", "serde_json", "shlex", @@ -1947,14 +1945,16 @@ dependencies = [ ] [[package]] -name = "jsonpath_lib" -version = "0.3.0" +name = "jsonpath-rust" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaa63191d68230cccb81c5aa23abd53ed64d83337cacbb25a7b8c7979523774f" +checksum = "9b0231bb404a6cd6c8f0ab41b907049063a089fc02aa7636cc5cd9a4d87364c9" dependencies = [ - "log", - "serde", + "pest", + "pest_derive", + "regex", "serde_json", + "thiserror 2.0.11", ] [[package]] @@ -2134,9 +2134,9 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" [[package]] name = "markup5ever" -version = "0.12.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" +checksum = "03a7b81dfb91586d0677086d40a6d755070e0799b71bb897485bac408dfd5c69" dependencies = [ "log", "phf", @@ -2147,6 +2147,17 @@ dependencies = [ ] [[package]] +name = "match_token" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] name = "matchers" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2180,6 +2191,20 @@ dependencies = [ ] [[package]] +name = "measureme" +version = "12.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "570a507d8948a66a97f42cbbaf8a6bb9516a51017d4ee949502ad7a10a864395" +dependencies = [ + "log", + "memmap2", + "parking_lot", + "perf-event-open-sys", + "rustc-hash 1.1.0", + "smallvec", +] + +[[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2262,7 +2287,7 @@ dependencies = [ "libc", "libffi", "libloading", - "measureme", + "measureme 11.0.1", "rand 0.9.0", "regex", "rustc_version", @@ -2623,51 +2648,77 @@ dependencies = [ ] [[package]] -name = "phf" -version = "0.11.3" +name = "pest" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" dependencies = [ - "phf_shared 0.11.3", + "memchr", + "thiserror 2.0.11", + "ucd-trie", ] [[package]] -name = "phf_codegen" -version = "0.11.3" +name = "pest_derive" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +checksum = "816518421cfc6887a0d62bf441b6ffb4536fcc926395a69e1a85852d4363f57e" dependencies = [ - "phf_generator 0.11.3", - "phf_shared 0.11.3", + "pest", + "pest_generator", ] [[package]] -name = "phf_generator" -version = "0.10.0" +name = "pest_generator" +version = "2.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +checksum = "7d1396fd3a870fc7838768d171b4616d5c91f6cc25e377b673d714567d99377b" dependencies = [ - "phf_shared 0.10.0", - "rand 0.8.5", + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.96", ] [[package]] -name = "phf_generator" +name = "pest_meta" +version = "2.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e58089ea25d717bfd31fb534e4f3afcc2cc569c70de3e239778991ea3b7dea" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + +[[package]] +name = "phf" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ - "phf_shared 0.11.3", - "rand 0.8.5", + "phf_shared", ] [[package]] -name = "phf_shared" -version = "0.10.0" +name = "phf_codegen" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ - "siphasher 0.3.11", + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared", + "rand 0.8.5", ] [[package]] @@ -2676,7 +2727,7 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ - "siphasher 1.0.1", + "siphasher", ] [[package]] @@ -3202,7 +3253,6 @@ dependencies = [ "rustc_data_structures", "rustc_macros", "rustc_serialize", - "rustc_span", ] [[package]] @@ -3221,7 +3271,6 @@ dependencies = [ "rustc_index", "rustc_macros", "rustc_middle", - "rustc_parse", "rustc_session", "rustc_span", "rustc_target", @@ -3256,7 +3305,6 @@ version = "0.0.0" dependencies = [ "itertools", "rustc_ast", - "rustc_data_structures", "rustc_lexer", "rustc_span", "thin-vec", @@ -3284,15 +3332,12 @@ dependencies = [ "rustc_ast", "rustc_ast_pretty", "rustc_attr_data_structures", - "rustc_data_structures", "rustc_errors", "rustc_feature", "rustc_fluent_macro", "rustc_hir", "rustc_lexer", "rustc_macros", - "rustc_middle", - "rustc_serialize", "rustc_session", "rustc_span", "thin-vec", @@ -3371,7 +3416,7 @@ dependencies = [ "gimli 0.30.0", "itertools", "libc", - "measureme", + "measureme 12.0.1", "object 0.36.7", "rustc-demangle", "rustc_abi", @@ -3419,7 +3464,6 @@ dependencies = [ "rustc_abi", "rustc_arena", "rustc_ast", - "rustc_ast_pretty", "rustc_attr_parsing", "rustc_data_structures", "rustc_errors", @@ -3427,7 +3471,6 @@ dependencies = [ "rustc_fs_util", "rustc_hashes", "rustc_hir", - "rustc_hir_pretty", "rustc_incremental", "rustc_index", "rustc_macros", @@ -3440,7 +3483,6 @@ dependencies = [ "rustc_symbol_mangling", "rustc_target", "rustc_trait_selection", - "rustc_type_ir", "serde_json", "smallvec", "tempfile", @@ -3473,7 +3515,6 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_trait_selection", - "rustc_type_ir", "tracing", ] @@ -3490,7 +3531,7 @@ dependencies = [ "indexmap", "jobserver", "libc", - "measureme", + "measureme 12.0.1", "memmap2", "parking_lot", "portable-atomic", @@ -3736,7 +3777,6 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_trait_selection", - "rustc_type_ir", "smallvec", "tracing", ] @@ -3775,7 +3815,6 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_trait_selection", - "rustc_type_ir", "smallvec", "tracing", ] @@ -3879,7 +3918,6 @@ dependencies = [ "rustc_query_impl", "rustc_query_system", "rustc_resolve", - "rustc_serialize", "rustc_session", "rustc_span", "rustc_symbol_mangling", @@ -3922,7 +3960,6 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_trait_selection", - "rustc_type_ir", "smallvec", "tracing", "unicode-security", @@ -3955,7 +3992,6 @@ dependencies = [ name = "rustc_log" version = "0.0.0" dependencies = [ - "rustc_span", "tracing", "tracing-core", "tracing-subscriber", @@ -3998,7 +4034,6 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "rustc_type_ir", "tempfile", "tracing", ] @@ -4045,13 +4080,11 @@ dependencies = [ name = "rustc_mir_build" version = "0.0.0" dependencies = [ - "either", "itertools", "rustc_abi", "rustc_apfloat", "rustc_arena", "rustc_ast", - "rustc_attr_parsing", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", @@ -4114,7 +4147,6 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_trait_selection", - "rustc_type_ir", "smallvec", "tracing", ] @@ -4257,10 +4289,8 @@ dependencies = [ name = "rustc_query_impl" version = "0.0.0" dependencies = [ - "measureme", - "rustc_attr_data_structures", + "measureme 12.0.1", "rustc_data_structures", - "rustc_errors", "rustc_hashes", "rustc_hir", "rustc_index", @@ -4269,7 +4299,6 @@ dependencies = [ "rustc_serialize", "rustc_session", "rustc_span", - "thin-vec", "tracing", ] @@ -4294,7 +4323,6 @@ dependencies = [ "rustc_session", "rustc_span", "smallvec", - "thin-vec", "tracing", ] @@ -4332,7 +4360,6 @@ version = "0.0.0" dependencies = [ "bitflags", "rustc_abi", - "rustc_ast", "rustc_data_structures", "rustc_hir", "rustc_middle", @@ -4387,7 +4414,6 @@ name = "rustc_smir" version = "0.0.0" dependencies = [ "rustc_abi", - "rustc_ast", "rustc_data_structures", "rustc_hir", "rustc_hir_pretty", @@ -4429,7 +4455,6 @@ dependencies = [ "punycode", "rustc-demangle", "rustc_abi", - "rustc_ast", "rustc_data_structures", "rustc_errors", "rustc_hashes", @@ -4524,7 +4549,6 @@ version = "0.0.0" dependencies = [ "itertools", "rustc_abi", - "rustc_attr_parsing", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", @@ -4538,7 +4562,6 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_trait_selection", - "rustc_type_ir", "tracing", ] @@ -4804,7 +4827,6 @@ version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" dependencies = [ - "indexmap", "itoa", "memchr", "ryu", @@ -4871,12 +4893,6 @@ checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" [[package]] name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - -[[package]] -name = "siphasher" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" @@ -4989,26 +5005,25 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "string_cache" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +checksum = "938d512196766101d333398efde81bc1f37b00cb42c2f8350e5df639f040bbbe" dependencies = [ "new_debug_unreachable", - "once_cell", "parking_lot", - "phf_shared 0.10.0", + "phf_shared", "precomputed-hash", "serde", ] [[package]] name = "string_cache_codegen" -version = "0.5.2" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", + "phf_generator", + "phf_shared", "proc-macro2", "quote", ] @@ -5518,10 +5533,16 @@ dependencies = [ ] [[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] name = "ui_test" -version = "0.26.5" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ee4c40e5a5f9fa6864ff976473e5d6a6e9884b6ce68b40690d9f87e1994c83" +checksum = "7484683d60d50ca1d1b6433c3dbf6c5ad71d20387acdcfb16fe79573f3fba576" dependencies = [ "annotate-snippets 0.11.5", "anyhow", @@ -5545,9 +5566,9 @@ dependencies = [ [[package]] name = "ui_test" -version = "0.28.0" +version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7484683d60d50ca1d1b6433c3dbf6c5ad71d20387acdcfb16fe79573f3fba576" +checksum = "1211b1111c752c73b33073d2958072be08825fd97c9ab4d83444da361a06634b" dependencies = [ "annotate-snippets 0.11.5", "anyhow", diff --git a/INSTALL.md b/INSTALL.md index a46d3d70093..30e08201d6d 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -6,9 +6,9 @@ If you just want to install Rust, check out the [README.md](README.md) instead.* 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 +It also uses a file named `bootstrap.toml` to determine various configuration settings for the build. You can see a full list of options in -`config.example.toml`. +`bootstrap.example.toml`. The `x.py` command can be run directly on most Unix systems in the following format: @@ -115,7 +115,7 @@ See [the rustc-dev-guide for more info][sysllvm]. This project provides a configure script and makefile (the latter of which just invokes `x.py`). `./configure` is the recommended way to programmatically -generate a `config.toml`. `make` is not recommended (we suggest using `x.py` +generate a `bootstrap.toml`. `make` is not recommended (we suggest using `x.py` directly), but it is supported and we try not to break it unnecessarily. ```sh @@ -123,7 +123,7 @@ directly), but it is supported and we try not to break it unnecessarily. make && sudo make install ``` -`configure` generates a `config.toml` which can also be used with normal `x.py` +`configure` generates a `bootstrap.toml` which can also be used with normal `x.py` invocations. ## Building on Windows @@ -255,7 +255,7 @@ Windows build triples are: - `x86_64-pc-windows-msvc` The build triple can be specified by either specifying `--build=<triple>` when -invoking `x.py` commands, or by creating a `config.toml` file (as described in +invoking `x.py` commands, or by creating a `bootstrap.toml` file (as described in [Building on a Unix-like system](#building-on-a-unix-like-system)), and passing `--set build.build=<triple>` to `./configure`. diff --git a/README.md b/README.md index d84d96a0e91..611260470f1 100644 --- a/README.md +++ b/README.md @@ -67,11 +67,11 @@ See [LICENSE-APACHE](LICENSE-APACHE), [LICENSE-MIT](LICENSE-MIT), and trademarks and logos (the "Rust Trademarks"). If you want to use these names or brands, please read the -[media guide][media-guide]. +[Rust language trademark policy][trademark-policy]. Third-party logos may be subject to third-party copyrights and trademarks. See [Licenses][policies-licenses] for details. -[rust-foundation]: https://foundation.rust-lang.org/ -[media-guide]: https://foundation.rust-lang.org/policies/logo-policy-and-media-guide/ +[rust-foundation]: https://rustfoundation.org/ +[trademark-policy]: https://rustfoundation.org/policy/rust-trademark-policy/ [policies-licenses]: https://www.rust-lang.org/policies/licenses diff --git a/RELEASES.md b/RELEASES.md index 038d7ca639f..755e73a34c6 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,14 @@ +Version 1.85.1 (2025-03-18) +========================== + +<a id="1.85.1"></a> + +- [Fix the doctest-merging feature of the 2024 Edition.](https://github.com/rust-lang/rust/pull/137899/) +- [Relax some `target_feature` checks when generating docs.](https://github.com/rust-lang/rust/pull/137632/) +- [Fix errors in `std::fs::rename` on Windows 10, version 1607.](https://github.com/rust-lang/rust/pull/137528/) +- [Downgrade bootstrap `cc` to fix custom targets.](https://github.com/rust-lang/rust/pull/137460/) +- [Skip submodule updates when building Rust from a source tarball.](https://github.com/rust-lang/rust/pull/137338/) + Version 1.85.0 (2025-02-20) ========================== @@ -2282,7 +2293,7 @@ Compatibility Notes - [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 + If `tools = [...]` is set in bootstrap.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. @@ -5268,7 +5279,7 @@ related tools. - [Building `rustc` from source now uses `ninja` by default over `make`.][74922] You can continue building with `make` by setting `ninja=false` in - your `config.toml`. + your `bootstrap.toml`. - [cg_llvm: `fewer_names` in `uncached_llvm_type`][76030] - [Made `ensure_sufficient_stack()` non-generic][76680] diff --git a/REUSE.toml b/REUSE.toml index 9e873e94eff..816c6d730c8 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -22,7 +22,7 @@ path = [ "Cargo.lock", "Cargo.toml", "CODE_OF_CONDUCT.md", - "config.example.toml", + "bootstrap.example.toml", "configure", "CONTRIBUTING.md", "COPYRIGHT", diff --git a/config.example.toml b/bootstrap.example.toml index c3d2ad094ce..294d9780716 100644 --- a/config.example.toml +++ b/bootstrap.example.toml @@ -5,7 +5,7 @@ # # All options are commented out by default in this file, and they're commented # out with their default values. The build system by default looks for -# `config.toml` in the current directory of a build for build configuration, but +# `bootstrap.toml` in the current directory of a build for build configuration, but # a custom configuration file can also be specified with `--config` to the build # system. @@ -16,7 +16,7 @@ # Use different pre-set defaults than the global defaults. # # See `src/bootstrap/defaults` for more information. -# Note that this has no default value (x.py uses the defaults in `config.example.toml`). +# Note that this has no default value (x.py uses the defaults in `bootstrap.example.toml`). #profile = <none> # Keeps track of major changes made to this configuration. @@ -346,7 +346,7 @@ # Enable a build of the extended Rust tool set which is not only the compiler # but also tools such as Cargo. This will also produce "combined installers" # which are used to install Rust and Cargo together. -# The `tools` (check `config.example.toml` to see its default value) option specifies +# The `tools` (check `bootstrap.example.toml` to see its default value) option specifies # which tools should be built if `extended = true`. # # This is disabled by default. @@ -446,6 +446,10 @@ # a specific version. #ccache = false +# List of paths to exclude from the build and test processes. +# For example, exclude = ["tests/ui", "src/tools/tidy"]. +#exclude = [] + # ============================================================================= # General install configuration options # ============================================================================= diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index d2f663999ba..3f28dc7a1ef 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -52,7 +52,7 @@ use rustc_data_structures::stable_hasher::StableOrd; use rustc_hashes::Hash64; use rustc_index::{Idx, IndexSlice, IndexVec}; #[cfg(feature = "nightly")] -use rustc_macros::{Decodable_Generic, Encodable_Generic, HashStable_Generic}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_Generic}; mod callconv; mod layout; @@ -74,7 +74,10 @@ pub use layout::{LayoutCalculator, LayoutCalculatorError}; pub trait HashStableContext {} #[derive(Clone, Copy, PartialEq, Eq, Default)] -#[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_Generic) +)] pub struct ReprFlags(u8); bitflags! { @@ -106,7 +109,10 @@ impl std::fmt::Debug for ReprFlags { } #[derive(Copy, Clone, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_Generic) +)] pub enum IntegerType { /// Pointer-sized integer type, i.e. `isize` and `usize`. The field shows signedness, e.g. /// `Pointer(true)` means `isize`. @@ -127,7 +133,10 @@ impl IntegerType { /// Represents the repr options provided by the user. #[derive(Copy, Clone, Debug, Eq, PartialEq, Default)] -#[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_Generic) +)] pub struct ReprOptions { pub int: Option<IntegerType>, pub align: Option<Align>, @@ -487,7 +496,10 @@ impl FromStr for Endian { /// Size of a type in bytes. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_Generic) +)] pub struct Size { raw: u64, } @@ -713,7 +725,10 @@ impl Step for Size { /// Alignment of a type in bytes (always a power of two). #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_Generic) +)] pub struct Align { pow2: u8, } @@ -872,7 +887,10 @@ impl AbiAndPrefAlign { /// Integers, also used for enum discriminants. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[cfg_attr(feature = "nightly", derive(Encodable_Generic, Decodable_Generic, HashStable_Generic))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_Generic) +)] pub enum Integer { I8, I16, diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 1b831c454e6..5b7545b3396 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1657,7 +1657,7 @@ pub enum ExprKind { Try(P<Expr>), /// A `yield`, with an optional value to be yielded. - Yield(Option<P<Expr>>), + Yield(YieldKind), /// A `do yeet` (aka `throw`/`fail`/`bail`/`raise`/whatever), /// with an optional value to be returned. @@ -1903,6 +1903,44 @@ pub enum MatchKind { Postfix, } +/// The kind of yield expression +#[derive(Clone, Encodable, Decodable, Debug)] +pub enum YieldKind { + /// yield expr { ... } + Prefix(Option<P<Expr>>), + /// expr.yield { ... } + Postfix(P<Expr>), +} + +impl YieldKind { + /// Returns the expression inside the yield expression, if any. + /// + /// For postfix yields, this is guaranteed to be `Some`. + pub const fn expr(&self) -> Option<&P<Expr>> { + match self { + YieldKind::Prefix(expr) => expr.as_ref(), + YieldKind::Postfix(expr) => Some(expr), + } + } + + /// Returns a mutable reference to the expression being yielded, if any. + pub const fn expr_mut(&mut self) -> Option<&mut P<Expr>> { + match self { + YieldKind::Prefix(expr) => expr.as_mut(), + YieldKind::Postfix(expr) => Some(expr), + } + } + + /// Returns true if both yields are prefix or both are postfix. + pub const fn same_kind(&self, other: &Self) -> bool { + match (self, other) { + (YieldKind::Prefix(_), YieldKind::Prefix(_)) => true, + (YieldKind::Postfix(_), YieldKind::Postfix(_)) => true, + _ => false, + } + } +} + /// A literal in a meta item. #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] pub struct MetaItemLit { diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 4a1636e6aec..4edd0864300 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -238,6 +238,10 @@ pub trait MutVisitor: Sized { walk_ident(self, i); } + fn visit_modifiers(&mut self, m: &mut TraitBoundModifiers) { + walk_modifiers(self, m); + } + fn visit_path(&mut self, p: &mut Path) { walk_path(self, p); } @@ -1156,12 +1160,29 @@ fn walk_trait_ref<T: MutVisitor>(vis: &mut T, TraitRef { path, ref_id }: &mut Tr } fn walk_poly_trait_ref<T: MutVisitor>(vis: &mut T, p: &mut PolyTraitRef) { - let PolyTraitRef { bound_generic_params, modifiers: _, trait_ref, span } = p; + let PolyTraitRef { bound_generic_params, modifiers, trait_ref, span } = p; + vis.visit_modifiers(modifiers); bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param)); vis.visit_trait_ref(trait_ref); vis.visit_span(span); } +fn walk_modifiers<V: MutVisitor>(vis: &mut V, m: &mut TraitBoundModifiers) { + let TraitBoundModifiers { constness, asyncness, polarity } = m; + match constness { + BoundConstness::Never => {} + BoundConstness::Always(span) | BoundConstness::Maybe(span) => vis.visit_span(span), + } + match asyncness { + BoundAsyncness::Normal => {} + BoundAsyncness::Async(span) => vis.visit_span(span), + } + match polarity { + BoundPolarity::Positive => {} + BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => vis.visit_span(span), + } +} + pub fn walk_field_def<T: MutVisitor>(visitor: &mut T, fd: &mut FieldDef) { let FieldDef { span, ident, vis, id, ty, attrs, is_placeholder: _, safety, default } = fd; visitor.visit_id(id); @@ -1813,8 +1834,11 @@ pub fn walk_expr<T: MutVisitor>(vis: &mut T, Expr { kind, id, span, attrs, token ExprKind::Paren(expr) => { vis.visit_expr(expr); } - ExprKind::Yield(expr) => { - visit_opt(expr, |expr| vis.visit_expr(expr)); + ExprKind::Yield(kind) => { + let expr = kind.expr_mut(); + if let Some(expr) = expr { + vis.visit_expr(expr); + } } ExprKind::Try(expr) => vis.visit_expr(expr), ExprKind::TryBlock(body) => vis.visit_block(body), diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index e43d78f6e72..989ebe14bf8 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -182,11 +182,14 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> { | Range(_, Some(e), _) | Ret(Some(e)) | Unary(_, e) - | Yield(Some(e)) | Yeet(Some(e)) | Become(e) => { expr = e; } + Yield(kind) => match kind.expr() { + Some(e) => expr = e, + None => break None, + }, Closure(closure) => { expr = &closure.body; } @@ -217,7 +220,6 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> { Break(_, None) | Range(_, None, _) | Ret(None) - | Yield(None) | Array(_) | Call(_, _) | MethodCall(_) @@ -237,7 +239,9 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<TrailingBrace<'_>> { | Yeet(None) | UnsafeBinderCast(..) | Err(_) - | Dummy => break None, + | Dummy => { + break None; + } } } } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index cfcb0e23cb5..ce8d6df75af 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -1269,8 +1269,8 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V try_visit!(visitor.visit_ty(container)); walk_list!(visitor, visit_ident, fields.iter()); } - ExprKind::Yield(optional_expression) => { - visit_opt!(visitor, visit_expr, optional_expression); + ExprKind::Yield(kind) => { + visit_opt!(visitor, visit_expr, kind.expr()); } ExprKind::Try(subexpression) => try_visit!(visitor.visit_expr(subexpression)), ExprKind::TryBlock(body) => try_visit!(visitor.visit_block(body)), diff --git a/compiler/rustc_ast_ir/Cargo.toml b/compiler/rustc_ast_ir/Cargo.toml index f54e9687d8c..76bdd9f7eb6 100644 --- a/compiler/rustc_ast_ir/Cargo.toml +++ b/compiler/rustc_ast_ir/Cargo.toml @@ -8,7 +8,6 @@ edition = "2024" rustc_data_structures = { path = "../rustc_data_structures", optional = true } rustc_macros = { path = "../rustc_macros", optional = true } rustc_serialize = { path = "../rustc_serialize", optional = true } -rustc_span = { path = "../rustc_span", optional = true } # tidy-alphabetical-end [features] @@ -17,5 +16,4 @@ nightly = [ "dep:rustc_serialize", "dep:rustc_data_structures", "dep:rustc_macros", - "dep:rustc_span", ] diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs index 6d05cd18cec..0898433a74c 100644 --- a/compiler/rustc_ast_ir/src/lib.rs +++ b/compiler/rustc_ast_ir/src/lib.rs @@ -12,14 +12,17 @@ // tidy-alphabetical-end #[cfg(feature = "nightly")] -use rustc_macros::{Decodable, Encodable, HashStable_NoContext}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; pub mod visit; /// The movability of a coroutine / closure literal: /// whether a coroutine contains self-references, causing it to be `!Unpin`. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] -#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub enum Movability { /// May contain self-references, `!Unpin`. Static, @@ -28,7 +31,10 @@ pub enum Movability { } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] -#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub enum Mutability { // N.B. Order is deliberate, so that Not < Mut Not, @@ -87,7 +93,10 @@ impl Mutability { } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] -#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub enum Pinnedness { Not, Pinned, diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 2ec4f4b0555..6ac258155fe 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -20,7 +20,6 @@ rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } -rustc_parse = { path = "../rustc_parse" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index 906fb213ee7..65e5b530bbe 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -185,8 +185,6 @@ ast_lowering_underscore_expr_lhs_assign = ast_lowering_unstable_inline_assembly = inline assembly is not stable yet on this architecture ast_lowering_unstable_inline_assembly_label_operand_with_outputs = using both label and output operands for inline assembly is unstable -ast_lowering_unstable_inline_assembly_label_operands = - label operands for inline assembly are unstable ast_lowering_unstable_may_unwind = the `may_unwind` option is unstable ast_lowering_use_angle_brackets = use angle brackets instead diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 65784af92c7..af279e07acc 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -470,22 +470,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - // Feature gate checking for asm goto. + // Feature gate checking for `asm_goto_with_outputs`. if let Some((_, op_sp)) = operands.iter().find(|(op, _)| matches!(op, hir::InlineAsmOperand::Label { .. })) { - if !self.tcx.features().asm_goto() { - feature_err( - sess, - sym::asm_goto, - *op_sp, - fluent::ast_lowering_unstable_inline_assembly_label_operands, - ) - .emit(); - } - - // In addition, check if an output operand is used. - // This is gated behind an additional feature. + // Check if an output operand is used. let output_operand_used = operands.iter().any(|(op, _)| { matches!( op, diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 5bb6704dde4..52291fdfb30 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -351,7 +351,7 @@ impl<'hir> LoweringContext<'_, 'hir> { rest, ) } - ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), + ExprKind::Yield(kind) => self.lower_expr_yield(e.span, kind.expr().map(|x| &**x)), ExprKind::Err(guar) => hir::ExprKind::Err(*guar), ExprKind::UnsafeBinderCast(kind, expr, ty) => hir::ExprKind::UnsafeBinderCast( @@ -2150,11 +2150,6 @@ impl<'hir> LoweringContext<'_, 'hir> { self.expr_uint(sp, ast::UintTy::U16, value as u128) } - pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> { - 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> { let lit = self .arena diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index faa47274f96..343895984ca 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -361,24 +361,26 @@ fn make_format_spec<'hir>( zero_pad, debug_hex, } = &placeholder.format_options; - let fill = ctx.expr_char(sp, fill.unwrap_or(' ')); - let align = ctx.expr_lang_item_type_relative( - sp, - hir::LangItem::FormatAlignment, - match alignment { - Some(FormatAlignment::Left) => sym::Left, - Some(FormatAlignment::Right) => sym::Right, - Some(FormatAlignment::Center) => sym::Center, - None => sym::Unknown, - }, - ); - // 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 - | (zero_pad as u32) << 3 - | ((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 4 - | ((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 5; + let fill = fill.unwrap_or(' '); + // These need to match the constants in library/core/src/fmt/rt.rs. + let align = match alignment { + Some(FormatAlignment::Left) => 0, + Some(FormatAlignment::Right) => 1, + Some(FormatAlignment::Center) => 2, + None => 3, + }; + // This needs to match the constants in library/core/src/fmt/rt.rs. + let flags: u32 = fill as u32 + | ((sign == Some(FormatSign::Plus)) as u32) << 21 + | ((sign == Some(FormatSign::Minus)) as u32) << 22 + | (alternate as u32) << 23 + | (zero_pad as u32) << 24 + | ((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 25 + | ((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 26 + | (width.is_some() as u32) << 27 + | (precision.is_some() as u32) << 28 + | align << 29 + | 1 << 31; // Highest bit always set. let flags = ctx.expr_u32(sp, flags); let precision = make_count(ctx, sp, precision, argmap); let width = make_count(ctx, sp, width, argmap); @@ -387,7 +389,7 @@ fn make_format_spec<'hir>( hir::LangItem::FormatPlaceholder, sym::new, )); - let args = ctx.arena.alloc_from_iter([position, fill, align, flags, precision, width]); + let args = ctx.arena.alloc_from_iter([position, flags, precision, width]); ctx.expr_call_mut(sp, format_placeholder_new, args) } diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index d1e23bf2522..26c0e7e5f82 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -164,7 +164,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_item(&mut self, i: &'hir Item<'hir>) { debug_assert_eq!(i.owner_id, self.owner); self.with_parent(i.hir_id(), |this| { - if let ItemKind::Struct(struct_def, _) = &i.kind { + if let ItemKind::Struct(_, struct_def, _) = &i.kind { // If this is a tuple or unit-like struct, register the constructor. if let Some(ctor_hir_id) = struct_def.ctor_hir_id() { this.insert(i.span, ctor_hir_id, Node::Ctor(struct_def)); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 9adc8bdd361..bd011d59aaa 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -111,6 +111,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { } fn lower_foreign_item(&mut self, item: &ForeignItem) { + debug_assert_ne!(item.ident.name, kw::Empty); self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))) } } @@ -154,14 +155,12 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> { - let mut ident = i.ident; let vis_span = self.lower_span(i.vis.span); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); - let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, vis_span, &i.kind); + let kind = self.lower_item_kind(i.span, i.id, hir_id, i.ident, attrs, vis_span, &i.kind); let item = hir::Item { owner_id: hir_id.expect_owner(), - ident: self.lower_ident(ident), kind, vis_span, span: self.lower_span(i.span), @@ -174,25 +173,34 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, id: NodeId, hir_id: hir::HirId, - ident: &mut Ident, + ident: Ident, attrs: &'hir [hir::Attribute], vis_span: Span, i: &ItemKind, ) -> hir::ItemKind<'hir> { match i { - ItemKind::ExternCrate(orig_name) => hir::ItemKind::ExternCrate(*orig_name), + ItemKind::ExternCrate(orig_name) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); + hir::ItemKind::ExternCrate(*orig_name, ident) + } ItemKind::Use(use_tree) => { + debug_assert_eq!(ident.name, kw::Empty); // Start with an empty prefix. let prefix = Path { segments: ThinVec::new(), span: use_tree.span, tokens: None }; - self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs) + self.lower_use_tree(use_tree, &prefix, id, vis_span, attrs) } ItemKind::Static(box ast::StaticItem { ty: t, safety: _, mutability: m, expr: e }) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); let (ty, body_id) = self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy); - hir::ItemKind::Static(ty, *m, body_id) + hir::ItemKind::Static(ident, ty, *m, body_id) } ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); let (generics, (ty, body_id)) = self.lower_generics( generics, id, @@ -201,7 +209,7 @@ impl<'hir> LoweringContext<'_, 'hir> { this.lower_const_item(ty, span, expr.as_deref(), ImplTraitPosition::ConstTy) }, ); - hir::ItemKind::Const(ty, generics, body_id) + hir::ItemKind::Const(ident, ty, generics, body_id) } ItemKind::Fn(box Fn { sig: FnSig { decl, header, span: fn_sig_span }, @@ -211,6 +219,7 @@ impl<'hir> LoweringContext<'_, 'hir> { define_opaque, .. }) => { + debug_assert_ne!(ident.name, kw::Empty); self.with_new_scopes(*fn_sig_span, |this| { // Note: we don't need to change the return type from `T` to // `impl Future<Output = T>` here because lower_body @@ -238,28 +247,44 @@ impl<'hir> LoweringContext<'_, 'hir> { span: this.lower_span(*fn_sig_span), }; this.lower_define_opaque(hir_id, &define_opaque); - hir::ItemKind::Fn { sig, generics, body: body_id, has_body: body.is_some() } + let ident = this.lower_ident(ident); + hir::ItemKind::Fn { + ident, + sig, + generics, + body: body_id, + has_body: body.is_some(), + } }) } - ItemKind::Mod(_, mod_kind) => match mod_kind { - ModKind::Loaded(items, _, spans, _) => { - hir::ItemKind::Mod(self.lower_mod(items, spans)) + ItemKind::Mod(_, mod_kind) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); + match mod_kind { + ModKind::Loaded(items, _, spans, _) => { + hir::ItemKind::Mod(ident, self.lower_mod(items, spans)) + } + ModKind::Unloaded => panic!("`mod` items should have been loaded by now"), } - ModKind::Unloaded => panic!("`mod` items should have been loaded by now"), - }, - ItemKind::ForeignMod(fm) => hir::ItemKind::ForeignMod { - abi: fm.abi.map_or(ExternAbi::FALLBACK, |abi| self.lower_abi(abi)), - items: self - .arena - .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))), - }, + } + ItemKind::ForeignMod(fm) => { + debug_assert_eq!(ident.name, kw::Empty); + hir::ItemKind::ForeignMod { + abi: fm.abi.map_or(ExternAbi::FALLBACK, |abi| self.lower_abi(abi)), + items: self + .arena + .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))), + } + } ItemKind::GlobalAsm(asm) => { + debug_assert_eq!(ident.name, kw::Empty); let asm = self.lower_inline_asm(span, asm); let fake_body = self.lower_body(|this| (&[], this.expr(span, hir::ExprKind::InlineAsm(asm)))); hir::ItemKind::GlobalAsm { asm, fake_body } } ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => { + debug_assert_ne!(ident.name, kw::Empty); // We lower // // type Foo = impl Trait @@ -268,6 +293,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // // type Foo = Foo1 // opaque type Foo1: Trait + let ident = self.lower_ident(ident); let mut generics = generics.clone(); add_ty_alias_where_clause(&mut generics, *where_clauses, true); let (generics, ty) = self.lower_generics( @@ -293,9 +319,11 @@ impl<'hir> LoweringContext<'_, 'hir> { ), }, ); - hir::ItemKind::TyAlias(ty, generics) + hir::ItemKind::TyAlias(ident, ty, generics) } ItemKind::Enum(enum_definition, generics) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); let (generics, variants) = self.lower_generics( generics, id, @@ -306,25 +334,29 @@ impl<'hir> LoweringContext<'_, 'hir> { ) }, ); - hir::ItemKind::Enum(hir::EnumDef { variants }, generics) + hir::ItemKind::Enum(ident, hir::EnumDef { variants }, generics) } ItemKind::Struct(struct_def, generics) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); let (generics, struct_def) = self.lower_generics( generics, id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, struct_def), ); - hir::ItemKind::Struct(struct_def, generics) + hir::ItemKind::Struct(ident, struct_def, generics) } ItemKind::Union(vdata, generics) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); let (generics, vdata) = self.lower_generics( generics, id, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), |this| this.lower_variant_data(hir_id, vdata), ); - hir::ItemKind::Union(vdata, generics) + hir::ItemKind::Union(ident, vdata, generics) } ItemKind::Impl(box Impl { safety, @@ -336,6 +368,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self_ty: ty, items: impl_items, }) => { + debug_assert_eq!(ident.name, kw::Empty); // Lower the "impl header" first. This ordering is important // for in-band lifetimes! Consider `'a` here: // @@ -401,6 +434,8 @@ impl<'hir> LoweringContext<'_, 'hir> { })) } ItemKind::Trait(box Trait { is_auto, safety, generics, bounds, items }) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); let (generics, (safety, items, bounds)) = self.lower_generics( generics, id, @@ -417,9 +452,11 @@ impl<'hir> LoweringContext<'_, 'hir> { (safety, items, bounds) }, ); - hir::ItemKind::Trait(*is_auto, safety, generics, bounds, items) + hir::ItemKind::Trait(*is_auto, safety, ident, generics, bounds, items) } ItemKind::TraitAlias(generics, bounds) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); let (generics, bounds) = self.lower_generics( generics, id, @@ -431,9 +468,11 @@ impl<'hir> LoweringContext<'_, 'hir> { ) }, ); - hir::ItemKind::TraitAlias(generics, bounds) + hir::ItemKind::TraitAlias(ident, generics, bounds) } ItemKind::MacroDef(MacroDef { body, macro_rules }) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); let body = P(self.lower_delim_args(body)); let def_id = self.local_def_id(id); let def_kind = self.tcx.def_kind(def_id); @@ -444,11 +483,14 @@ impl<'hir> LoweringContext<'_, 'hir> { ); }; let macro_def = self.arena.alloc(ast::MacroDef { body, macro_rules: *macro_rules }); - hir::ItemKind::Macro(macro_def, macro_kind) + hir::ItemKind::Macro(ident, macro_def, macro_kind) } ItemKind::Delegation(box delegation) => { + debug_assert_ne!(ident.name, kw::Empty); + let ident = self.lower_ident(ident); let delegation_results = self.lower_delegation(delegation, id); hir::ItemKind::Fn { + ident, sig: delegation_results.sig, generics: delegation_results.generics, body: delegation_results.body_id, @@ -479,7 +521,6 @@ impl<'hir> LoweringContext<'_, 'hir> { prefix: &Path, id: NodeId, vis_span: Span, - ident: &mut Ident, attrs: &'hir [hir::Attribute], ) -> hir::ItemKind<'hir> { let path = &tree.prefix; @@ -487,7 +528,7 @@ impl<'hir> LoweringContext<'_, 'hir> { match tree.kind { UseTreeKind::Simple(rename) => { - *ident = tree.ident(); + let mut ident = tree.ident(); // First, apply the prefix to the path. let mut path = Path { segments, span: path.span, tokens: None }; @@ -498,13 +539,14 @@ impl<'hir> LoweringContext<'_, 'hir> { { let _ = path.segments.pop(); if rename.is_none() { - *ident = path.segments.last().unwrap().ident; + ident = path.segments.last().unwrap().ident; } } let res = self.lower_import_res(id, path.span); let path = self.lower_use_path(res, &path, ParamMode::Explicit); - hir::ItemKind::Use(path, hir::UseKind::Single) + let ident = self.lower_ident(ident); + hir::ItemKind::Use(path, hir::UseKind::Single(ident)) } UseTreeKind::Glob => { let res = self.expect_full_res(id); @@ -551,20 +593,16 @@ impl<'hir> LoweringContext<'_, 'hir> { // own its own names, we have to adjust the owner before // lowering the rest of the import. self.with_hir_id_owner(id, |this| { - let mut ident = *ident; - // `prefix` is lowered multiple times, but in different HIR owners. // So each segment gets renewed `HirId` with the same // `ItemLocalId` and the new owner. (See `lower_node_id`) - let kind = - this.lower_use_tree(use_tree, &prefix, id, vis_span, &mut ident, attrs); + let kind = this.lower_use_tree(use_tree, &prefix, id, vis_span, attrs); if !attrs.is_empty() { this.attrs.insert(hir::ItemLocalId::ZERO, attrs); } let item = hir::Item { owner_id: hir::OwnerId { def_id: new_hir_id }, - ident: this.lower_ident(ident), kind, vis_span, span: this.lower_span(use_tree.span), @@ -604,7 +642,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ItemKind::Impl(impl_) => { self.is_in_trait_impl = impl_.of_trait.is_some(); } - hir::ItemKind::Trait(_, _, _, _, _) => {} + hir::ItemKind::Trait(..) => {} kind => { span_bug!(item.span, "assoc item has unexpected kind of parent: {}", kind.descr()) } @@ -760,6 +798,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> { + debug_assert_ne!(i.ident.name, kw::Empty); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); let trait_item_def_id = hir_id.expect_owner(); @@ -907,6 +946,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> { + debug_assert_ne!(i.ident.name, kw::Empty); // Since `default impl` is not yet implemented, this is always true in impls. let has_value = true; let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); @@ -1720,7 +1760,6 @@ impl<'hir> LoweringContext<'_, 'hir> { let bounds = self.lower_param_bounds(bounds, itctx); - let ident = self.lower_ident(ident); let param_span = ident.span; // Reconstruct the span of the entire predicate from the individual generic bounds. @@ -1739,6 +1778,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let def_id = self.local_def_id(id).to_def_id(); let hir_id = self.next_id(); let res = Res::Def(DefKind::TyParam, def_id); + let ident = self.lower_ident(ident); let ty_path = self.arena.alloc(hir::Path { span: param_span, res, @@ -1757,7 +1797,6 @@ impl<'hir> LoweringContext<'_, 'hir> { }) } GenericParamKind::Lifetime => { - let ident = self.lower_ident(ident); let lt_id = self.next_node_id(); let lifetime = self.new_named_lifetime(id, lt_id, ident); hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index c7d37e2704d..e08850da4a7 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1513,10 +1513,23 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { })) } - fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Ident] { + fn lower_fn_params_to_names(&mut self, decl: &FnDecl) -> &'hir [Option<Ident>] { self.arena.alloc_from_iter(decl.inputs.iter().map(|param| match param.pat.kind { - PatKind::Ident(_, ident, _) => self.lower_ident(ident), - _ => Ident::new(kw::Empty, self.lower_span(param.pat.span)), + PatKind::Ident(_, ident, _) => { + if ident.name != kw::Empty { + Some(self.lower_ident(ident)) + } else { + None + } + } + PatKind::Wild => Some(Ident::new(kw::Underscore, self.lower_span(param.pat.span))), + _ => { + self.dcx().span_delayed_bug( + param.pat.span, + "non-ident/wild param pat must trigger an error", + ); + None + } })) } @@ -1762,17 +1775,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_lifetime(&mut self, l: &Lifetime) -> &'hir hir::Lifetime { - let ident = self.lower_ident(l.ident); - self.new_named_lifetime(l.id, l.id, ident) + self.new_named_lifetime(l.id, l.id, l.ident) } #[instrument(level = "debug", skip(self))] - fn new_named_lifetime_with_res( + fn new_named_lifetime( &mut self, id: NodeId, + new_id: NodeId, ident: Ident, - res: LifetimeRes, ) -> &'hir hir::Lifetime { + let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error); let res = match res { LifetimeRes::Param { param, .. } => hir::LifetimeName::Param(param), LifetimeRes::Fresh { param, .. } => { @@ -1782,31 +1795,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { LifetimeRes::Infer => hir::LifetimeName::Infer, LifetimeRes::Static { .. } => hir::LifetimeName::Static, LifetimeRes::Error => hir::LifetimeName::Error, - res => panic!( - "Unexpected lifetime resolution {:?} for {:?} at {:?}", - res, ident, ident.span - ), + LifetimeRes::ElidedAnchor { .. } => { + panic!("Unexpected `ElidedAnchar` {:?} at {:?}", ident, ident.span); + } }; debug!(?res); self.arena.alloc(hir::Lifetime { - hir_id: self.lower_node_id(id), + hir_id: self.lower_node_id(new_id), ident: self.lower_ident(ident), res, }) } - #[instrument(level = "debug", skip(self))] - fn new_named_lifetime( - &mut self, - id: NodeId, - new_id: NodeId, - ident: Ident, - ) -> &'hir hir::Lifetime { - let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error); - self.new_named_lifetime_with_res(new_id, ident, res) - } - fn lower_generic_params_mut( &mut self, params: &[GenericParam], diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 232d60be4eb..75839e86b8d 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -336,6 +336,7 @@ impl<'a> AstValidator<'a> { sym::allow, sym::cfg, sym::cfg_attr, + sym::cfg_attr_trace, sym::deny, sym::expect, sym::forbid, diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml index 2634dd1fdf9..b704040be96 100644 --- a/compiler/rustc_ast_pretty/Cargo.toml +++ b/compiler/rustc_ast_pretty/Cargo.toml @@ -7,8 +7,11 @@ edition = "2024" # tidy-alphabetical-start itertools = "0.12" rustc_ast = { path = "../rustc_ast" } -rustc_data_structures = { path = "../rustc_data_structures" } rustc_lexer = { path = "../rustc_lexer" } rustc_span = { path = "../rustc_span" } +# tidy-alphabetical-end + +[dev-dependencies] +# tidy-alphabetical-start thin-vec = "0.2.12" # tidy-alphabetical-end diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index a8eaff7346b..cdb18179449 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -578,11 +578,12 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere let mut printed = false; for attr in attrs { if attr.style == kind { - self.print_attribute_inline(attr, is_inline); - if is_inline { - self.nbsp(); + if self.print_attribute_inline(attr, is_inline) { + if is_inline { + self.nbsp(); + } + printed = true; } - printed = true; } } if printed && trailing_hardbreak && !is_inline { @@ -591,7 +592,12 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere printed } - fn print_attribute_inline(&mut self, attr: &ast::Attribute, is_inline: bool) { + fn print_attribute_inline(&mut self, attr: &ast::Attribute, is_inline: bool) -> bool { + if attr.has_name(sym::cfg_attr_trace) { + // It's not a valid identifier, so avoid printing it + // to keep the printed code reasonably parse-able. + return false; + } if !is_inline { self.hardbreak_if_not_bol(); } @@ -610,6 +616,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere self.hardbreak() } } + true } fn print_attr_item(&mut self, item: &ast::AttrItem, span: Span) { @@ -2047,7 +2054,7 @@ impl<'a> State<'a> { } fn print_attribute(&mut self, attr: &ast::Attribute) { - self.print_attribute_inline(attr, false) + self.print_attribute_inline(attr, false); } fn print_meta_list_item(&mut self, item: &ast::MetaItemInner) { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index e3c41f117ab..7d9dc89bd75 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -8,7 +8,7 @@ use rustc_ast::util::literal::escape_byte_str_symbol; use rustc_ast::util::parser::{self, ExprPrecedence, Fixity}; use rustc_ast::{ self as ast, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount, - FormatDebugHex, FormatSign, FormatTrait, token, + FormatDebugHex, FormatSign, FormatTrait, YieldKind, token, }; use crate::pp::Breaks::Inconsistent; @@ -761,7 +761,7 @@ impl<'a> State<'a> { self.print_expr(e, FixupContext::default()); self.pclose(); } - ast::ExprKind::Yield(e) => { + ast::ExprKind::Yield(YieldKind::Prefix(e)) => { self.word("yield"); if let Some(expr) = e { @@ -773,6 +773,14 @@ impl<'a> State<'a> { ); } } + ast::ExprKind::Yield(YieldKind::Postfix(e)) => { + self.print_expr_cond_paren( + e, + e.precedence() < ExprPrecedence::Unambiguous, + fixup.leftmost_subexpression_with_dot(), + ); + self.word(".yield"); + } ast::ExprKind::Try(e) => { self.print_expr_cond_paren( e, diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index d2d1285b075..969bce7ae20 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -191,6 +191,7 @@ pub enum AttributeKind { }, MacroTransparency(Transparency), Repr(ThinVec<(ReprAttr, Span)>), + RustcMacroEdition2021, Stability { stability: Stability, /// Span of the `#[stable(...)]` or `#[unstable(...)]` attribute diff --git a/compiler/rustc_attr_data_structures/src/lib.rs b/compiler/rustc_attr_data_structures/src/lib.rs index bbd3308809c..c61b44b273d 100644 --- a/compiler/rustc_attr_data_structures/src/lib.rs +++ b/compiler/rustc_attr_data_structures/src/lib.rs @@ -182,21 +182,18 @@ macro_rules! find_attr { }}; ($attributes_list: expr, $pattern: pat $(if $guard: expr)? => $e: expr) => {{ - fn check_attribute_iterator<'a>(_: &'_ impl IntoIterator<Item = &'a rustc_hir::Attribute>) {} - check_attribute_iterator(&$attributes_list); - - let find_attribute = |iter| { + 'done: { for i in $attributes_list { + let i: &rustc_hir::Attribute = i; match i { rustc_hir::Attribute::Parsed($pattern) $(if $guard)? => { - return Some($e); + break 'done Some($e); } _ => {} } } None - }; - find_attribute($attributes_list) + } }}; } diff --git a/compiler/rustc_attr_parsing/Cargo.toml b/compiler/rustc_attr_parsing/Cargo.toml index 6b4ce957630..32029137268 100644 --- a/compiler/rustc_attr_parsing/Cargo.toml +++ b/compiler/rustc_attr_parsing/Cargo.toml @@ -9,15 +9,12 @@ rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_attr_data_structures = { path = "../rustc_attr_data_structures" } -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_hir = { path = "../rustc_hir" } rustc_lexer = { path = "../rustc_lexer" } rustc_macros = { path = "../rustc_macros" } -rustc_middle = { path = "../rustc_middle" } -rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } thin-vec = "0.2.12" diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 6ecd6b4d7db..bac111159db 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -28,6 +28,7 @@ pub(crate) mod cfg; pub(crate) mod confusables; pub(crate) mod deprecation; pub(crate) mod repr; +pub(crate) mod rustc; pub(crate) mod stability; pub(crate) mod transparency; pub(crate) mod util; diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc.rs b/compiler/rustc_attr_parsing/src/attributes/rustc.rs new file mode 100644 index 00000000000..bdd3bef2834 --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/rustc.rs @@ -0,0 +1,19 @@ +use rustc_attr_data_structures::AttributeKind; +use rustc_span::sym; + +use super::{AcceptContext, SingleAttributeParser}; +use crate::parser::ArgParser; + +pub(crate) struct RustcMacroEdition2021Parser; + +// FIXME(jdonszelmann): make these proper diagnostics +impl SingleAttributeParser for RustcMacroEdition2021Parser { + const PATH: &'static [rustc_span::Symbol] = &[sym::rustc_macro_edition_2021]; + + fn on_duplicate(_cx: &crate::context::AcceptContext<'_>, _first_span: rustc_span::Span) {} + + fn convert(_cx: &AcceptContext<'_>, args: &ArgParser<'_>) -> Option<AttributeKind> { + assert!(args.no_args()); + Some(AttributeKind::RustcMacroEdition2021) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 35541bb04bd..a68d4578b40 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -15,6 +15,7 @@ use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInterna use crate::attributes::confusables::ConfusablesParser; use crate::attributes::deprecation::DeprecationParser; use crate::attributes::repr::ReprParser; +use crate::attributes::rustc::RustcMacroEdition2021Parser; use crate::attributes::stability::{ BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser, }; @@ -76,6 +77,7 @@ attribute_groups!( // tidy-alphabetical-start Single<ConstStabilityIndirectParser>, Single<DeprecationParser>, + Single<RustcMacroEdition2021Parser>, Single<TransparencyParser>, // tidy-alphabetical-end ]; diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 2694a1eda78..978186f76a1 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2514,12 +2514,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { 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(tcx.hir_body_param_names(closure.body)).find(|(param_ty, name)| { + let Some(this_name) = params.iter().zip(tcx.hir_body_param_names(closure.body)).find_map( + |(param_ty, name)| { // FIXME: also support deref for stuff like `Rc` arguments - param_ty.peel_refs() == local_ty && name != &Ident::empty() - }) - else { + if param_ty.peel_refs() == local_ty { name } else { None } + }, + ) else { return; }; @@ -3787,7 +3787,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { method_args, *fn_span, call_source.from_hir_call(), - Some(self.infcx.tcx.fn_arg_names(method_did)[0]), + self.infcx.tcx.fn_arg_names(method_did)[0], ) { err.note(format!("borrow occurs due to deref coercion to `{deref_target_ty}`")); diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 208d510db2e..899e145c2c0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1029,7 +1029,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { method_args, *fn_span, call_source.from_hir_call(), - Some(self.infcx.tcx.fn_arg_names(method_did)[0]), + self.infcx.tcx.fn_arg_names(method_did)[0], ); return FnSelfUse { diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 3951b467961..fddddf404db 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -691,7 +691,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { true, td.is_local(), td.as_local().and_then(|tld| match self.infcx.tcx.hir_node_by_def_id(tld) { - Node::Item(hir::Item { kind: hir::ItemKind::Trait(_, _, _, _, items), .. }) => { + Node::Item(hir::Item { + kind: hir::ItemKind::Trait(_, _, _, _, _, items), .. + }) => { let mut f_in_trait_opt = None; for hir::TraitItemRef { id: fi, kind: k, .. } in *items { let hi = fi.hir_id(); @@ -980,7 +982,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let arg = match tcx.hir_get_if_local(callee_def_id) { Some( hir::Node::Item(hir::Item { - ident, kind: hir::ItemKind::Fn { sig, .. }, .. + kind: hir::ItemKind::Fn { ident, sig, .. }, .. }) | hir::Node::TraitItem(hir::TraitItem { ident, @@ -1021,7 +1023,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // return type. match tcx.hir_node_by_def_id(tcx.hir_get_parent_item(fn_call_id).def_id) { hir::Node::Item(hir::Item { - ident, kind: hir::ItemKind::Fn { sig, .. }, .. + kind: hir::ItemKind::Fn { ident, sig, .. }, .. }) | hir::Node::TraitItem(hir::TraitItem { ident, @@ -1632,8 +1634,8 @@ fn get_mut_span_in_struct_field<'tcx>( /// If possible, suggest replacing `ref` with `ref mut`. fn suggest_ref_mut(tcx: TyCtxt<'_>, span: Span) -> Option<Span> { let pattern_str = tcx.sess.source_map().span_to_snippet(span).ok()?; - if pattern_str.starts_with("ref") - && pattern_str["ref".len()..].starts_with(rustc_lexer::is_whitespace) + if let Some(rest) = pattern_str.strip_prefix("ref") + && rest.starts_with(rustc_lexer::is_whitespace) { let span = span.with_lo(span.lo() + BytePos(4)).shrink_to_lo(); Some(span) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 55b6367f35f..6b11f1a3681 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -14,9 +14,8 @@ use rustc_infer::infer::{NllRegionVariableOrigin, RelateParamBound}; use rustc_middle::bug; use rustc_middle::hir::place::PlaceBase; use rustc_middle::mir::{AnnotationSource, ConstraintCategory, ReturnConstraint}; -use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{ - self, GenericArgs, Region, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitor, + self, GenericArgs, Region, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitor, fold_regions, }; use rustc_span::{Ident, Span, kw}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 7ae7936a2a2..84b7b8c6a2d 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -35,8 +35,7 @@ use rustc_infer::infer::{ }; use rustc_middle::mir::*; use rustc_middle::query::Providers; -use rustc_middle::ty::fold::fold_regions; -use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode}; +use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt, TypingMode, fold_regions}; use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::impls::{ EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces, @@ -74,6 +73,7 @@ mod def_use; mod diagnostics; mod member_constraints; mod nll; +mod opaque_types; mod path_utils; mod place_ext; mod places_conflict; @@ -193,7 +193,7 @@ fn do_mir_borrowck<'tcx>( // Compute non-lexical lifetimes. let nll::NllOutput { regioncx, - opaque_type_values, + concrete_opaque_types, polonius_input, polonius_output, opt_closure_req, @@ -223,7 +223,7 @@ fn do_mir_borrowck<'tcx>( body, ®ioncx, &opt_closure_req, - &opaque_type_values, + &concrete_opaque_types, diags_buffer, ); @@ -358,7 +358,7 @@ fn do_mir_borrowck<'tcx>( let tainted_by_errors = mbcx.emit_errors(); let result = BorrowCheckResult { - concrete_opaque_types: opaque_type_values, + concrete_opaque_types: concrete_opaque_types.into_inner(), closure_requirements: opt_closure_req, used_mut_upvars: mbcx.used_mut_upvars, tainted_by_errors, @@ -2480,19 +2480,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { let body = self.body; for local in body.mut_vars_and_args_iter().filter(|local| !self.used_mut.contains(local)) { let local_decl = &body.local_decls[local]; - let lint_root = match &body.source_scopes[local_decl.source_info.scope].local_data { - ClearCrossCrate::Set(data) => data.lint_root, - _ => continue, + let ClearCrossCrate::Set(SourceScopeLocalData { lint_root, .. }) = + body.source_scopes[local_decl.source_info.scope].local_data + else { + continue; }; // Skip over locals that begin with an underscore or have no name - match self.local_names[local] { - Some(name) => { - if name.as_str().starts_with('_') { - continue; - } - } - None => continue, + if self.local_names[local].is_none_or(|name| name.as_str().starts_with('_')) { + continue; } let span = local_decl.source_info.span; diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 2031579dfd5..d0bd364425a 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -6,8 +6,6 @@ use std::str::FromStr; use std::{env, io}; use polonius_engine::{Algorithm, Output}; -use rustc_data_structures::fx::FxIndexMap; -use rustc_hir::def_id::LocalDefId; use rustc_index::IndexSlice; use rustc_middle::mir::pretty::{PrettyPrintMirOptions, dump_mir_with_options}; use rustc_middle::mir::{ @@ -15,7 +13,7 @@ use rustc_middle::mir::{ dump_enabled, dump_mir, }; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_mir_dataflow::ResultsCursor; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::MoveData; @@ -27,6 +25,7 @@ use tracing::{debug, instrument}; use crate::borrow_set::BorrowSet; use crate::consumers::ConsumerOptions; use crate::diagnostics::{BorrowckDiagnosticsBuffer, RegionErrors}; +use crate::opaque_types::ConcreteOpaqueTypes; use crate::polonius::PoloniusDiagnosticsContext; use crate::polonius::legacy::{ PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput, @@ -40,7 +39,7 @@ use crate::{BorrowckInferCtxt, polonius, renumber}; /// closure requirements to propagate, and any generated errors. pub(crate) struct NllOutput<'tcx> { pub regioncx: RegionInferenceContext<'tcx>, - pub opaque_type_values: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>, + pub concrete_opaque_types: ConcreteOpaqueTypes<'tcx>, pub polonius_input: Option<Box<PoloniusFacts>>, pub polonius_output: Option<Box<PoloniusOutput>>, pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>, @@ -99,6 +98,8 @@ pub(crate) fn compute_regions<'a, 'tcx>( let location_map = Rc::new(DenseLocationMap::new(body)); + let mut concrete_opaque_types = ConcreteOpaqueTypes::default(); + // Run the MIR type-checker. let MirTypeckResults { constraints, @@ -116,6 +117,7 @@ pub(crate) fn compute_regions<'a, 'tcx>( flow_inits, move_data, Rc::clone(&location_map), + &mut concrete_opaque_types, ); // Create the region inference context, taking ownership of the @@ -180,11 +182,11 @@ pub(crate) fn compute_regions<'a, 'tcx>( infcx.set_tainted_by_errors(guar); } - let remapped_opaque_tys = regioncx.infer_opaque_types(infcx, opaque_type_values); + regioncx.infer_opaque_types(infcx, opaque_type_values, &mut concrete_opaque_types); NllOutput { regioncx, - opaque_type_values: remapped_opaque_tys, + concrete_opaque_types, polonius_input: polonius_facts.map(Box::new), polonius_output, opt_closure_req: closure_region_requirements, @@ -300,7 +302,7 @@ pub(super) fn dump_annotation<'tcx, 'infcx>( body: &Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>, - opaque_type_values: &FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>, + concrete_opaque_types: &ConcreteOpaqueTypes<'tcx>, diagnostics_buffer: &mut BorrowckDiagnosticsBuffer<'infcx, 'tcx>, ) { let tcx = infcx.tcx; @@ -343,8 +345,8 @@ pub(super) fn dump_annotation<'tcx, 'infcx>( err }; - if !opaque_type_values.is_empty() { - err.note(format!("Inferred opaque type values:\n{opaque_type_values:#?}")); + if !concrete_opaque_types.is_empty() { + err.note(format!("Inferred opaque type values:\n{concrete_opaque_types:#?}")); } diagnostics_buffer.buffer_non_error(err); diff --git a/compiler/rustc_borrowck/src/opaque_types.rs b/compiler/rustc_borrowck/src/opaque_types.rs new file mode 100644 index 00000000000..5c78814abdd --- /dev/null +++ b/compiler/rustc_borrowck/src/opaque_types.rs @@ -0,0 +1,55 @@ +use rustc_data_structures::fx::FxIndexMap; +use rustc_hir::def_id::LocalDefId; +use rustc_middle::ty::{OpaqueHiddenType, Ty, TyCtxt}; + +#[derive(Debug, Default)] +pub(super) struct ConcreteOpaqueTypes<'tcx> { + concrete_opaque_types: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>, +} + +impl<'tcx> ConcreteOpaqueTypes<'tcx> { + pub(super) fn is_empty(&self) -> bool { + self.concrete_opaque_types.is_empty() + } + + pub(super) fn into_inner(self) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> { + self.concrete_opaque_types + } + + /// Insert an opaque type into the list of opaque types defined by this function + /// after mapping the hidden type to the generic parameters of the opaque type + /// definition. + pub(super) fn insert( + &mut self, + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, + hidden_ty: OpaqueHiddenType<'tcx>, + ) { + // Sometimes two opaque types are the same only after we remap the generic parameters + // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to + // `(X, Y)` and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we + // only know that once we convert the generic parameters to those of the opaque type. + if let Some(prev) = self.concrete_opaque_types.get_mut(&def_id) { + if prev.ty != hidden_ty.ty { + let (Ok(guar) | Err(guar)) = + prev.build_mismatch_error(&hidden_ty, tcx).map(|d| d.emit()); + prev.ty = Ty::new_error(tcx, guar); + } + // Pick a better span if there is one. + // FIXME(oli-obk): collect multiple spans for better diagnostics down the road. + prev.span = prev.span.substitute_dummy(hidden_ty.span); + } else { + self.concrete_opaque_types.insert(def_id, hidden_ty); + } + } + + pub(super) fn extend_from_nested_body( + &mut self, + tcx: TyCtxt<'tcx>, + nested_body: &FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>>, + ) { + for (&def_id, &hidden_ty) in nested_body { + self.insert(tcx, def_id, hidden_ty); + } + } +} diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index bb209a95711..a80d74d9e37 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -18,8 +18,7 @@ use rustc_middle::mir::{ ReturnConstraint, TerminatorKind, }; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; -use rustc_middle::ty::fold::fold_regions; -use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex}; +use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, fold_regions}; use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::hygiene::DesugaringKind; use rustc_span::{DUMMY_SP, Span}; diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 54f9e82dbb8..ca8b9fb4e9d 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -5,11 +5,9 @@ use rustc_hir::def_id::LocalDefId; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _}; use rustc_macros::extension; -use rustc_middle::ty::fold::fold_regions; -use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ self, GenericArgKind, GenericArgs, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, - TypingMode, + TypeVisitableExt, TypingMode, fold_regions, }; use rustc_span::Span; use rustc_trait_selection::regions::OutlivesEnvironmentBuildExt; @@ -17,6 +15,7 @@ use rustc_trait_selection::traits::ObligationCtxt; use tracing::{debug, instrument}; use super::RegionInferenceContext; +use crate::opaque_types::ConcreteOpaqueTypes; use crate::session_diagnostics::{LifetimeMismatchOpaqueParam, NonGenericOpaqueTypeParam}; use crate::universal_regions::RegionClassification; @@ -69,8 +68,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { &self, infcx: &InferCtxt<'tcx>, opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>, - ) -> FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> { - let mut result: FxIndexMap<LocalDefId, OpaqueHiddenType<'tcx>> = FxIndexMap::default(); + concrete_opaque_types: &mut ConcreteOpaqueTypes<'tcx>, + ) { let mut decls_modulo_regions: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueTypeKey<'tcx>, Span)> = FxIndexMap::default(); @@ -145,33 +144,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { continue; } } - // Sometimes two opaque types are the same only after we remap the generic parameters - // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to - // `(X, Y)` and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we - // only know that once we convert the generic parameters to those of the opaque type. - if let Some(prev) = result.get_mut(&opaque_type_key.def_id) { - if prev.ty != ty { - let guar = ty.error_reported().err().unwrap_or_else(|| { - let (Ok(e) | Err(e)) = prev - .build_mismatch_error( - &OpaqueHiddenType { ty, span: concrete_type.span }, - infcx.tcx, - ) - .map(|d| d.emit()); - e - }); - prev.ty = Ty::new_error(infcx.tcx, guar); - } - // Pick a better span if there is one. - // FIXME(oli-obk): collect multiple spans for better diagnostics down the road. - prev.span = prev.span.substitute_dummy(concrete_type.span); - } else { - result.insert( - opaque_type_key.def_id, - OpaqueHiddenType { ty, span: concrete_type.span }, - ); - } + concrete_opaque_types.insert( + infcx.tcx, + opaque_type_key.def_id, + OpaqueHiddenType { ty, span: concrete_type.span }, + ); // Check that all opaque types have the same region parameters if they have the same // non-region parameters. This is necessary because within the new solver we perform // various query operations modulo regions, and thus could unsoundly select some impls @@ -195,7 +173,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { }); } } - result } /// Map the regions in the type to named regions. This is similar to what diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index e355d2b415b..ff92b4168a8 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -2,8 +2,7 @@ use rustc_index::IndexSlice; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::mir::visit::{MutVisitor, TyContext}; use rustc_middle::mir::{Body, ConstOperand, Location, Promoted}; -use rustc_middle::ty::fold::fold_regions; -use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeFoldable, fold_regions}; use rustc_span::Symbol; use tracing::{debug, instrument}; diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 8dff40ba6ac..6fbe1db6330 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -7,8 +7,9 @@ use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; use rustc_infer::traits::query::type_op::DeeplyNormalize; use rustc_middle::bug; use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory}; -use rustc_middle::ty::fold::fold_regions; -use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; +use rustc_middle::ty::{ + self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions, +}; use rustc_span::Span; use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; use tracing::{debug, instrument}; diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index f17ad23f4bf..b7a21cf48c8 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -4,8 +4,7 @@ use rustc_middle::mir::visit::{TyContext, Visitor}; use rustc_middle::mir::{Body, Local, Location, SourceInfo}; use rustc_middle::span_bug; use rustc_middle::ty::relate::Relate; -use rustc_middle::ty::visit::TypeVisitable; -use rustc_middle::ty::{GenericArgsRef, Region, RegionVid, Ty, TyCtxt}; +use rustc_middle::ty::{GenericArgsRef, Region, RegionVid, Ty, TyCtxt, TypeVisitable}; use rustc_mir_dataflow::ResultsCursor; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::MoveData; diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index d2eb7a52f78..f6144a25938 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -24,12 +24,10 @@ use rustc_middle::mir::*; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::cast::CastTy; -use rustc_middle::ty::fold::fold_regions; -use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt, - Dynamic, GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserArgs, - UserTypeAnnotationIndex, + Dynamic, GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, + TypeVisitableExt, UserArgs, UserTypeAnnotationIndex, fold_regions, }; use rustc_middle::{bug, span_bug}; use rustc_mir_dataflow::ResultsCursor; @@ -47,6 +45,7 @@ use crate::borrow_set::BorrowSet; use crate::constraints::{OutlivesConstraint, OutlivesConstraintSet}; use crate::diagnostics::UniverseInfo; use crate::member_constraints::MemberConstraintSet; +use crate::opaque_types::ConcreteOpaqueTypes; use crate::polonius::legacy::{PoloniusFacts, PoloniusLocationTable}; use crate::polonius::{PoloniusContext, PoloniusLivenessContext}; use crate::region_infer::TypeTest; @@ -113,6 +112,7 @@ pub(crate) fn type_check<'a, 'tcx>( flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, move_data: &MoveData<'tcx>, location_map: Rc<DenseLocationMap>, + concrete_opaque_types: &mut ConcreteOpaqueTypes<'tcx>, ) -> MirTypeckResults<'tcx> { let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body); let mut constraints = MirTypeckRegionConstraints { @@ -167,6 +167,7 @@ pub(crate) fn type_check<'a, 'tcx>( polonius_facts, borrow_set, constraints: &mut constraints, + concrete_opaque_types, polonius_liveness, }; @@ -232,6 +233,7 @@ struct TypeChecker<'a, 'tcx> { polonius_facts: &'a mut Option<PoloniusFacts>, borrow_set: &'a BorrowSet<'tcx>, constraints: &'a mut MirTypeckRegionConstraints<'tcx>, + concrete_opaque_types: &'a mut ConcreteOpaqueTypes<'tcx>, /// When using `-Zpolonius=next`, the liveness helper data used to create polonius constraints. polonius_liveness: Option<PoloniusLivenessContext>, } @@ -1773,6 +1775,22 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { { span_mirbug!(self, constant, "bad static type {:?} ({:?})", constant, terr); } + } else if let Const::Ty(_, ct) = constant.const_ + && let ty::ConstKind::Param(p) = ct.kind() + { + let body_def_id = self.universal_regions.defining_ty.def_id(); + let const_param = tcx.generics_of(body_def_id).const_param(p, tcx); + self.ascribe_user_type( + constant.const_.ty(), + ty::UserType::new(ty::UserTypeKind::TypeOf( + const_param.def_id, + UserArgs { + args: self.universal_regions.defining_ty.args(), + user_self_ty: None, + }, + )), + locations.span(self.body), + ); } if let ty::FnDef(def_id, args) = *constant.const_.ty().kind() { @@ -2485,7 +2503,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { args: GenericArgsRef<'tcx>, locations: Locations, ) -> ty::InstantiatedPredicates<'tcx> { - if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements { + let closure_borrowck_results = tcx.mir_borrowck(def_id); + self.concrete_opaque_types + .extend_from_nested_body(tcx, &closure_borrowck_results.concrete_opaque_types); + + if let Some(closure_requirements) = &closure_borrowck_results.closure_requirements { constraint_conversion::ConstraintConversion::new( self.infcx, self.universal_regions, diff --git a/compiler/rustc_borrowck/src/type_check/opaque_types.rs b/compiler/rustc_borrowck/src/type_check/opaque_types.rs index 94b3d0c2bbf..8bab979a724 100644 --- a/compiler/rustc_borrowck/src/type_check/opaque_types.rs +++ b/compiler/rustc_borrowck/src/type_check/opaque_types.rs @@ -2,10 +2,9 @@ use std::iter; use rustc_data_structures::fx::FxIndexMap; use rustc_middle::span_bug; -use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{ self, GenericArgKind, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, TypeVisitor, + TypeVisitable, TypeVisitableExt, TypeVisitor, fold_regions, }; use tracing::{debug, trace}; diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 59e2eee41d3..02a41469c97 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -10,9 +10,8 @@ use rustc_middle::mir::ConstraintCategory; use rustc_middle::span_bug; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::query::NoSolution; -use rustc_middle::ty::fold::FnMutDelegate; use rustc_middle::ty::relate::combine::{super_combine_consts, super_combine_tys}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, FnMutDelegate, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::{Span, Symbol, sym}; use tracing::{debug, instrument}; diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index cfac9b36832..8f6b405fcef 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -27,11 +27,10 @@ use rustc_hir::lang_items::LangItem; use rustc_index::IndexVec; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_macros::extension; -use rustc_middle::ty::fold::{TypeFoldable, fold_regions}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ self, GenericArgs, GenericArgsRef, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, - TyCtxt, TypeVisitableExt, + TyCtxt, TypeFoldable, TypeVisitableExt, fold_regions, }; use rustc_middle::{bug, span_bug}; use rustc_span::{ErrorGuaranteed, kw, sym}; @@ -184,6 +183,20 @@ impl<'tcx> DefiningTy<'tcx> { | DefiningTy::GlobalAsm(def_id) => def_id, } } + + /// Returns the args of the `DefiningTy`. These are equivalent to the identity + /// substs of the body, but replaced with region vids. + pub(crate) fn args(&self) -> ty::GenericArgsRef<'tcx> { + match *self { + DefiningTy::Closure(_, args) + | DefiningTy::Coroutine(_, args) + | DefiningTy::CoroutineClosure(_, args) + | DefiningTy::FnDef(_, args) + | DefiningTy::Const(_, args) + | DefiningTy::InlineConst(_, args) => args, + DefiningTy::GlobalAsm(_) => ty::List::empty(), + } + } } #[derive(Debug)] diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index dcd3c1ce8d9..6591ed151cf 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -26,6 +26,16 @@ mod llvm_enzyme { use crate::errors; + pub(crate) fn outer_normal_attr( + kind: &P<rustc_ast::NormalAttr>, + id: rustc_ast::AttrId, + span: Span, + ) -> rustc_ast::Attribute { + let style = rustc_ast::AttrStyle::Outer; + let kind = rustc_ast::AttrKind::Normal(kind.clone()); + rustc_ast::Attribute { kind, id, style, span } + } + // If we have a default `()` return type or explicitley `()` return type, // then we often can skip doing some work. fn has_ret(ty: &FnRetTy) -> bool { @@ -224,20 +234,8 @@ mod llvm_enzyme { .filter(|a| **a == DiffActivity::Active || **a == DiffActivity::ActiveOnly) .count() as u32; let (d_sig, new_args, idents, errored) = gen_enzyme_decl(ecx, &sig, &x, span); - let new_decl_span = d_sig.span; let d_body = gen_enzyme_body( - ecx, - &x, - n_active, - &sig, - &d_sig, - primal, - &new_args, - span, - sig_span, - new_decl_span, - idents, - errored, + ecx, &x, n_active, &sig, &d_sig, primal, &new_args, span, sig_span, idents, errored, ); let d_ident = first_ident(&meta_item_vec[0]); @@ -270,36 +268,39 @@ mod llvm_enzyme { }; let inline_never_attr = P(ast::NormalAttr { item: inline_item, tokens: None }); let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id(); - let attr: ast::Attribute = ast::Attribute { - kind: ast::AttrKind::Normal(rustc_ad_attr.clone()), - id: new_id, - style: ast::AttrStyle::Outer, - span, - }; + let attr = outer_normal_attr(&rustc_ad_attr, new_id, span); let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id(); - let inline_never: ast::Attribute = ast::Attribute { - kind: ast::AttrKind::Normal(inline_never_attr), - id: new_id, - style: ast::AttrStyle::Outer, - span, - }; + let inline_never = outer_normal_attr(&inline_never_attr, new_id, span); + + // We're avoid duplicating the attributes `#[rustc_autodiff]` and `#[inline(never)]`. + fn same_attribute(attr: &ast::AttrKind, item: &ast::AttrKind) -> bool { + match (attr, item) { + (ast::AttrKind::Normal(a), ast::AttrKind::Normal(b)) => { + let a = &a.item.path; + let b = &b.item.path; + a.segments.len() == b.segments.len() + && a.segments.iter().zip(b.segments.iter()).all(|(a, b)| a.ident == b.ident) + } + _ => false, + } + } // Don't add it multiple times: let orig_annotatable: Annotatable = match item { Annotatable::Item(ref mut iitem) => { - if !iitem.attrs.iter().any(|a| a.id == attr.id) { + if !iitem.attrs.iter().any(|a| same_attribute(&a.kind, &attr.kind)) { iitem.attrs.push(attr); } - if !iitem.attrs.iter().any(|a| a.id == inline_never.id) { + if !iitem.attrs.iter().any(|a| same_attribute(&a.kind, &inline_never.kind)) { iitem.attrs.push(inline_never.clone()); } Annotatable::Item(iitem.clone()) } Annotatable::AssocItem(ref mut assoc_item, i @ Impl) => { - if !assoc_item.attrs.iter().any(|a| a.id == attr.id) { + if !assoc_item.attrs.iter().any(|a| same_attribute(&a.kind, &attr.kind)) { assoc_item.attrs.push(attr); } - if !assoc_item.attrs.iter().any(|a| a.id == inline_never.id) { + if !assoc_item.attrs.iter().any(|a| same_attribute(&a.kind, &inline_never.kind)) { assoc_item.attrs.push(inline_never.clone()); } Annotatable::AssocItem(assoc_item.clone(), i) @@ -314,13 +315,7 @@ mod llvm_enzyme { delim: rustc_ast::token::Delimiter::Parenthesis, tokens: ts, }); - let d_attr: ast::Attribute = ast::Attribute { - kind: ast::AttrKind::Normal(rustc_ad_attr.clone()), - id: new_id, - style: ast::AttrStyle::Outer, - span, - }; - + let d_attr = outer_normal_attr(&rustc_ad_attr, new_id, span); let d_annotatable = if is_impl { let assoc_item: AssocItemKind = ast::AssocItemKind::Fn(asdf); let d_fn = P(ast::AssocItem { @@ -361,30 +356,27 @@ mod llvm_enzyme { ty } - /// We only want this function to type-check, since we will replace the body - /// later on llvm level. Using `loop {}` does not cover all return types anymore, - /// so instead we build something that should pass. We also add a inline_asm - /// line, as one more barrier for rustc to prevent inlining of this function. - /// FIXME(ZuseZ4): We still have cases of incorrect inlining across modules, see - /// <https://github.com/EnzymeAD/rust/issues/173>, so this isn't sufficient. - /// It also triggers an Enzyme crash if we due to a bug ever try to differentiate - /// this function (which should never happen, since it is only a placeholder). - /// Finally, we also add back_box usages of all input arguments, to prevent rustc - /// from optimizing any arguments away. - fn gen_enzyme_body( + // Will generate a body of the type: + // ``` + // { + // unsafe { + // asm!("NOP"); + // } + // ::core::hint::black_box(primal(args)); + // ::core::hint::black_box((args, ret)); + // <This part remains to be done by following function> + // } + // ``` + fn init_body_helper( ecx: &ExtCtxt<'_>, - x: &AutoDiffAttrs, - n_active: u32, - sig: &ast::FnSig, - d_sig: &ast::FnSig, + span: Span, primal: Ident, new_names: &[String], - span: Span, sig_span: Span, new_decl_span: Span, - idents: Vec<Ident>, + idents: &[Ident], errored: bool, - ) -> P<ast::Block> { + ) -> (P<ast::Block>, P<ast::Expr>, P<ast::Expr>, P<ast::Expr>) { let blackbox_path = ecx.std_path(&[sym::hint, sym::black_box]); let noop = ast::InlineAsm { asm_macro: ast::AsmMacro::Asm, @@ -433,6 +425,51 @@ mod llvm_enzyme { } body.stmts.push(ecx.stmt_semi(black_box_remaining_args)); + (body, primal_call, black_box_primal_call, blackbox_call_expr) + } + + /// We only want this function to type-check, since we will replace the body + /// later on llvm level. Using `loop {}` does not cover all return types anymore, + /// so instead we manually build something that should pass the type checker. + /// We also add a inline_asm line, as one more barrier for rustc to prevent inlining + /// or const propagation. inline_asm will also triggers an Enzyme crash if due to another + /// bug would ever try to accidentially differentiate this placeholder function body. + /// Finally, we also add back_box usages of all input arguments, to prevent rustc + /// from optimizing any arguments away. + fn gen_enzyme_body( + ecx: &ExtCtxt<'_>, + x: &AutoDiffAttrs, + n_active: u32, + sig: &ast::FnSig, + d_sig: &ast::FnSig, + primal: Ident, + new_names: &[String], + span: Span, + sig_span: Span, + idents: Vec<Ident>, + errored: bool, + ) -> P<ast::Block> { + let new_decl_span = d_sig.span; + + // Just adding some default inline-asm and black_box usages to prevent early inlining + // and optimizations which alter the function signature. + // + // The bb_primal_call is the black_box call of the primal function. We keep it around, + // since it has the convenient property of returning the type of the primal function, + // Remember, we only care to match types here. + // No matter which return we pick, we always wrap it into a std::hint::black_box call, + // to prevent rustc from propagating it into the caller. + let (mut body, primal_call, bb_primal_call, bb_call_expr) = init_body_helper( + ecx, + span, + primal, + new_names, + sig_span, + new_decl_span, + &idents, + errored, + ); + if !has_ret(&d_sig.decl.output) { // there is no return type that we have to match, () works fine. return body; @@ -444,7 +481,7 @@ mod llvm_enzyme { if primal_ret && n_active == 0 && x.mode.is_rev() { // We only have the primal ret. - body.stmts.push(ecx.stmt_expr(black_box_primal_call)); + body.stmts.push(ecx.stmt_expr(bb_primal_call)); return body; } @@ -536,11 +573,11 @@ mod llvm_enzyme { return body; } [arg] => { - ret = ecx.expr_call(new_decl_span, blackbox_call_expr, thin_vec![arg.clone()]); + ret = ecx.expr_call(new_decl_span, bb_call_expr, thin_vec![arg.clone()]); } args => { let ret_tuple: P<ast::Expr> = ecx.expr_tuple(span, args.into()); - ret = ecx.expr_call(new_decl_span, blackbox_call_expr, thin_vec![ret_tuple]); + ret = ecx.expr_call(new_decl_span, bb_call_expr, thin_vec![ret_tuple]); } } assert!(has_ret(&d_sig.decl.output)); @@ -553,7 +590,7 @@ mod llvm_enzyme { ecx: &ExtCtxt<'_>, span: Span, primal: Ident, - idents: Vec<Ident>, + idents: &[Ident], ) -> P<ast::Expr> { let has_self = idents.len() > 0 && idents[0].name == kw::SelfLower; if has_self { diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index dab3053d8b0..606e85577f7 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -23,6 +23,8 @@ extern crate proc_macro; +use std::sync::Arc; + use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind}; use rustc_expand::proc_macro::BangProcMacro; use rustc_span::sym; @@ -67,13 +69,13 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { let mut register = |name, kind| resolver.register_builtin_macro(name, kind); macro register_bang($($name:ident: $f:expr,)*) { - $(register(sym::$name, SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)));)* + $(register(sym::$name, SyntaxExtensionKind::LegacyBang(Arc::new($f as MacroExpanderFn)));)* } macro register_attr($($name:ident: $f:expr,)*) { - $(register(sym::$name, SyntaxExtensionKind::LegacyAttr(Box::new($f)));)* + $(register(sym::$name, SyntaxExtensionKind::LegacyAttr(Arc::new($f)));)* } macro register_derive($($name:ident: $f:expr,)*) { - $(register(sym::$name, SyntaxExtensionKind::LegacyDerive(Box::new(BuiltinDerive($f))));)* + $(register(sym::$name, SyntaxExtensionKind::LegacyDerive(Arc::new(BuiltinDerive($f))));)* } register_bang! { @@ -139,9 +141,9 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { } let client = proc_macro::bridge::client::Client::expand1(proc_macro::quote); - register(sym::quote, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client }))); - let requires = SyntaxExtensionKind::Attr(Box::new(contracts::ExpandRequires)); + register(sym::quote, SyntaxExtensionKind::Bang(Arc::new(BangProcMacro { client }))); + let requires = SyntaxExtensionKind::Attr(Arc::new(contracts::ExpandRequires)); register(sym::contracts_requires, requires); - let ensures = SyntaxExtensionKind::Attr(Box::new(contracts::ExpandEnsures)); + let ensures = SyntaxExtensionKind::Attr(Arc::new(contracts::ExpandEnsures)); register(sym::contracts_ensures, ensures); } diff --git a/compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch index 3c81b04c0ea..d7e3b11127c 100644 --- a/compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch +++ b/compiler/rustc_codegen_cranelift/patches/0027-stdlib-128bit-atomic-operations.patch @@ -1,4 +1,4 @@ -From ad7ffe71baba46865f2e65266ab025920dfdc20b Mon Sep 17 00:00:00 2001 +From 5d7c709608b01301d4628d2159265936d4440b67 Mon Sep 17 00:00:00 2001 From: bjorn3 <bjorn3@users.noreply.github.com> Date: Thu, 18 Feb 2021 18:45:28 +0100 Subject: [PATCH] Disable 128bit atomic operations @@ -7,11 +7,10 @@ Cranelift doesn't support them yet --- library/core/src/panic/unwind_safe.rs | 6 ----- library/core/src/sync/atomic.rs | 38 --------------------------- - library/core/tests/atomic.rs | 4 --- - 4 files changed, 4 insertions(+), 50 deletions(-) + 2 files changed, 44 deletions(-) diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs -index 092b7cf..158cf71 100644 +index a60f0799c0e..af056fbf41f 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs @@ -216,9 +216,6 @@ impl RefUnwindSafe for crate::sync::atomic::AtomicI32 {} @@ -21,7 +20,7 @@ index 092b7cf..158cf71 100644 -#[cfg(target_has_atomic_load_store = "128")] -#[unstable(feature = "integer_atomics", issue = "99069")] -impl RefUnwindSafe for crate::sync::atomic::AtomicI128 {} - + #[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] @@ -235,9 +232,6 @@ impl RefUnwindSafe for crate::sync::atomic::AtomicU32 {} @@ -31,14 +30,14 @@ index 092b7cf..158cf71 100644 -#[cfg(target_has_atomic_load_store = "128")] -#[unstable(feature = "integer_atomics", issue = "99069")] -impl RefUnwindSafe for crate::sync::atomic::AtomicU128 {} - + #[cfg(target_has_atomic_load_store = "8")] #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs -index d9de37e..8293fce 100644 +index bf2b6d59f88..d5ccce03bbf 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs -@@ -2996,44 +2996,6 @@ atomic_int! { +@@ -3585,44 +3585,6 @@ pub const fn as_ptr(&self) -> *mut $int_type { 8, u64 AtomicU64 } @@ -54,7 +53,7 @@ index d9de37e..8293fce 100644 - unstable(feature = "integer_atomics", issue = "99069"), - rustc_const_unstable(feature = "integer_atomics", issue = "99069"), - rustc_const_unstable(feature = "integer_atomics", issue = "99069"), -- cfg_attr(not(test), rustc_diagnostic_item = "AtomicI128"), +- rustc_diagnostic_item = "AtomicI128", - "i128", - "#![feature(integer_atomics)]\n\n", - atomic_min, atomic_max, @@ -73,7 +72,7 @@ index d9de37e..8293fce 100644 - unstable(feature = "integer_atomics", issue = "99069"), - rustc_const_unstable(feature = "integer_atomics", issue = "99069"), - rustc_const_unstable(feature = "integer_atomics", issue = "99069"), -- cfg_attr(not(test), rustc_diagnostic_item = "AtomicU128"), +- rustc_diagnostic_item = "AtomicU128", - "u128", - "#![feature(integer_atomics)]\n\n", - atomic_umin, atomic_umax, @@ -83,7 +82,6 @@ index d9de37e..8293fce 100644 #[cfg(target_has_atomic_load_store = "ptr")] macro_rules! atomic_int_ptr_sized { - ( $($target_pointer_width:literal $align:literal)* ) => { $( --- -2.26.2.7.g19db9cfb68 +-- +2.48.1 diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs index 5e33b9d606f..9cff8a84db3 100644 --- a/compiler/rustc_codegen_cranelift/src/allocator.rs +++ b/compiler/rustc_codegen_cranelift/src/allocator.rs @@ -7,6 +7,7 @@ use rustc_ast::expand::allocator::{ }; use rustc_codegen_ssa::base::allocator_kind_for_codegen; use rustc_session::config::OomStrategy; +use rustc_symbol_mangling::mangle_internal_symbol; use crate::prelude::*; @@ -14,6 +15,7 @@ use crate::prelude::*; pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool { let Some(kind) = allocator_kind_for_codegen(tcx) else { return false }; codegen_inner( + tcx, module, kind, tcx.alloc_error_handler_kind(()).unwrap(), @@ -23,6 +25,7 @@ pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool { } fn codegen_inner( + tcx: TyCtxt<'_>, module: &mut dyn Module, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind, @@ -62,8 +65,8 @@ fn codegen_inner( crate::common::create_wrapper_function( module, sig, - &global_fn_name(method.name), - &default_fn_name(method.name), + &mangle_internal_symbol(tcx, &global_fn_name(method.name)), + &mangle_internal_symbol(tcx, &default_fn_name(method.name)), ); } } @@ -76,19 +79,32 @@ fn codegen_inner( crate::common::create_wrapper_function( module, sig, - "__rust_alloc_error_handler", - &alloc_error_handler_name(alloc_error_handler_kind), + &mangle_internal_symbol(tcx, "__rust_alloc_error_handler"), + &mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)), ); - let data_id = module.declare_data(OomStrategy::SYMBOL, Linkage::Export, false, false).unwrap(); + let data_id = module + .declare_data( + &mangle_internal_symbol(tcx, OomStrategy::SYMBOL), + Linkage::Export, + false, + false, + ) + .unwrap(); let mut data = DataDescription::new(); data.set_align(1); let val = oom_strategy.should_panic(); data.define(Box::new([val])); module.define_data(data_id, &data).unwrap(); - let data_id = - module.declare_data(NO_ALLOC_SHIM_IS_UNSTABLE, Linkage::Export, false, false).unwrap(); + let data_id = module + .declare_data( + &mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE), + Linkage::Export, + false, + false, + ) + .unwrap(); let mut data = DataDescription::new(); data.set_align(1); data.define(Box::new([0])); diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index a52b18573b1..fb7864ae612 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -103,12 +103,14 @@ impl OngoingCodegen { ("o", &module_regular.object.as_ref().unwrap()), ("asm.o", &module_global_asm.object.as_ref().unwrap()), ], + &[], ) } else { rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( sess, &module_regular.name, &[("o", &module_regular.object.as_ref().unwrap())], + &[], ) }; if let Some((work_product_id, work_product)) = work_product { @@ -381,6 +383,7 @@ fn emit_cgu( bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), }), existing_work_product: None, }) @@ -437,6 +440,7 @@ fn emit_module( bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), }) } @@ -460,22 +464,23 @@ fn reuse_workproduct_for_cgu( err )); } + let obj_out_global_asm = crate::global_asm::add_file_stem_postfix(obj_out_regular.clone(), ".asm"); - let has_global_asm = if let Some(asm_o) = work_product.saved_files.get("asm.o") { + let source_file_global_asm = if let Some(asm_o) = work_product.saved_files.get("asm.o") { let source_file_global_asm = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, asm_o); if let Err(err) = rustc_fs_util::link_or_copy(&source_file_global_asm, &obj_out_global_asm) { return Err(format!( "unable to copy {} to {}: {}", - source_file_regular.display(), - obj_out_regular.display(), + source_file_global_asm.display(), + obj_out_global_asm.display(), err )); } - true + Some(source_file_global_asm) } else { - false + None }; Ok(ModuleCodegenResult { @@ -487,8 +492,9 @@ fn reuse_workproduct_for_cgu( bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: vec![source_file_regular], }, - module_global_asm: has_global_asm.then(|| CompiledModule { + module_global_asm: source_file_global_asm.map(|source_file| CompiledModule { name: cgu.name().to_string(), kind: ModuleKind::Regular, object: Some(obj_out_global_asm), @@ -496,6 +502,7 @@ fn reuse_workproduct_for_cgu( bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: vec![source_file], }), existing_work_product: Some((cgu.work_product_id(), work_product)), }) @@ -637,6 +644,7 @@ fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> Compiled bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), } } diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 06939beb374..ab3386a9b4c 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -26,6 +26,7 @@ extern crate rustc_index; extern crate rustc_metadata; extern crate rustc_session; extern crate rustc_span; +extern crate rustc_symbol_mangling; extern crate rustc_target; #[macro_use] extern crate tracing; diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs index 416f3231a13..f4ebd42ee2d 100644 --- a/compiler/rustc_codegen_gcc/src/allocator.rs +++ b/compiler/rustc_codegen_gcc/src/allocator.rs @@ -8,6 +8,7 @@ use rustc_ast::expand::allocator::{ use rustc_middle::bug; use rustc_middle::ty::TyCtxt; use rustc_session::config::OomStrategy; +use rustc_symbol_mangling::mangle_internal_symbol; use crate::GccContext; #[cfg(feature = "master")] @@ -53,8 +54,8 @@ pub(crate) unsafe fn codegen( panic!("invalid allocator output") } }; - let from_name = global_fn_name(method.name); - let to_name = default_fn_name(method.name); + let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name)); + let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name)); create_wrapper_function(tcx, context, &from_name, &to_name, &types, output); } @@ -64,13 +65,13 @@ pub(crate) unsafe fn codegen( create_wrapper_function( tcx, context, - "__rust_alloc_error_handler", - alloc_error_handler_name(alloc_error_handler_kind), + &mangle_internal_symbol(tcx, "__rust_alloc_error_handler"), + &mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)), &[usize, usize], None, ); - let name = OomStrategy::SYMBOL.to_string(); + let name = mangle_internal_symbol(tcx, OomStrategy::SYMBOL); let global = context.new_global(None, GlobalKind::Exported, i8, name); #[cfg(feature = "master")] global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc( @@ -80,7 +81,7 @@ pub(crate) unsafe fn codegen( let value = context.new_rvalue_from_int(i8, value as i32); global.global_set_initializer_rvalue(value); - let name = NO_ALLOC_SHIM_IS_UNSTABLE.to_string(); + let name = mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE); let global = context.new_global(None, GlobalKind::Exported, i8, name); #[cfg(feature = "master")] global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc( diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index d478b2af46c..bfa23174a19 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -52,6 +52,7 @@ extern crate rustc_metadata; extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; +extern crate rustc_symbol_mangling; extern crate rustc_target; // This prevents duplicating functions and statics that are already part of the host rustc process. diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index d3ce7c5a113..ec1fd4b641a 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -14,7 +14,7 @@ bitflags = "2.4.1" gimli = "0.30" itertools = "0.12" libc = "0.2" -measureme = "11" +measureme = "12.0.1" object = { version = "0.36.3", default-features = false, features = ["std", "read"] } rustc-demangle = "0.1.21" rustc_abi = { path = "../rustc_abi" } diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index e614115f64b..4a78e694979 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -7,6 +7,7 @@ use rustc_codegen_ssa::traits::BaseTypeCodegenMethods as _; use rustc_middle::bug; use rustc_middle::ty::TyCtxt; use rustc_session::config::{DebugInfo, OomStrategy}; +use rustc_symbol_mangling::mangle_internal_symbol; use crate::builder::SBuilder; use crate::declare::declare_simple_fn; @@ -53,8 +54,8 @@ pub(crate) unsafe fn codegen( } }; - let from_name = global_fn_name(method.name); - let to_name = default_fn_name(method.name); + let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name)); + let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name)); create_wrapper_function(tcx, &cx, &from_name, &to_name, &args, output, false); } @@ -64,8 +65,8 @@ pub(crate) unsafe fn codegen( create_wrapper_function( tcx, &cx, - "__rust_alloc_error_handler", - alloc_error_handler_name(alloc_error_handler_kind), + &mangle_internal_symbol(tcx, "__rust_alloc_error_handler"), + &mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)), &[usize, usize], // size, align None, true, @@ -73,15 +74,15 @@ pub(crate) unsafe fn codegen( unsafe { // __rust_alloc_error_handler_should_panic - let name = OomStrategy::SYMBOL; - let ll_g = cx.declare_global(name, i8); + let name = mangle_internal_symbol(tcx, OomStrategy::SYMBOL); + let ll_g = cx.declare_global(&name, i8); llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility())); let val = tcx.sess.opts.unstable_opts.oom.should_panic(); let llval = llvm::LLVMConstInt(i8, val as u64, False); llvm::set_initializer(ll_g, llval); - let name = NO_ALLOC_SHIM_IS_UNSTABLE; - let ll_g = cx.declare_global(name, i8); + let name = mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE); + let ll_g = cx.declare_global(&name, i8); llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility())); let llval = llvm::LLVMConstInt(i8, 0, False); llvm::set_initializer(ll_g, llval); diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs index 71705ecb4d0..7cd4ee539d8 100644 --- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs +++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs @@ -28,6 +28,113 @@ fn get_params(fnc: &Value) -> Vec<&Value> { } } +fn match_args_from_caller_to_enzyme<'ll>( + cx: &SimpleCx<'ll>, + args: &mut Vec<&'ll llvm::Value>, + inputs: &[DiffActivity], + outer_args: &[&'ll llvm::Value], +) { + debug!("matching autodiff arguments"); + // We now handle the issue that Rust level arguments not always match the llvm-ir level + // arguments. A slice, `&[f32]`, for example, is represented as a pointer and a length on + // llvm-ir level. The number of activities matches the number of Rust level arguments, so we + // need to match those. + // FIXME(ZuseZ4): This logic is a bit more complicated than it should be, can we simplify it + // using iterators and peek()? + let mut outer_pos: usize = 0; + let mut activity_pos = 0; + + let enzyme_const = cx.create_metadata("enzyme_const".to_string()).unwrap(); + let enzyme_out = cx.create_metadata("enzyme_out".to_string()).unwrap(); + let enzyme_dup = cx.create_metadata("enzyme_dup".to_string()).unwrap(); + let enzyme_dupnoneed = cx.create_metadata("enzyme_dupnoneed".to_string()).unwrap(); + + while activity_pos < inputs.len() { + let diff_activity = inputs[activity_pos as usize]; + // Duplicated arguments received a shadow argument, into which enzyme will write the + // gradient. + let (activity, duplicated): (&Metadata, bool) = match diff_activity { + DiffActivity::None => panic!("not a valid input activity"), + DiffActivity::Const => (enzyme_const, false), + DiffActivity::Active => (enzyme_out, false), + DiffActivity::ActiveOnly => (enzyme_out, false), + DiffActivity::Dual => (enzyme_dup, true), + DiffActivity::DualOnly => (enzyme_dupnoneed, true), + DiffActivity::Duplicated => (enzyme_dup, true), + DiffActivity::DuplicatedOnly => (enzyme_dupnoneed, true), + DiffActivity::FakeActivitySize => (enzyme_const, false), + }; + let outer_arg = outer_args[outer_pos]; + args.push(cx.get_metadata_value(activity)); + args.push(outer_arg); + if duplicated { + // We know that duplicated args by construction have a following argument, + // so this can not be out of bounds. + let next_outer_arg = outer_args[outer_pos + 1]; + let next_outer_ty = cx.val_ty(next_outer_arg); + // FIXME(ZuseZ4): We should add support for Vec here too, but it's less urgent since + // vectors behind references (&Vec<T>) are already supported. Users can not pass a + // Vec by value for reverse mode, so this would only help forward mode autodiff. + let slice = { + if activity_pos + 1 >= inputs.len() { + // If there is no arg following our ptr, it also can't be a slice, + // since that would lead to a ptr, int pair. + false + } else { + let next_activity = inputs[activity_pos + 1]; + // We analyze the MIR types and add this dummy activity if we visit a slice. + next_activity == DiffActivity::FakeActivitySize + } + }; + if slice { + // A duplicated slice will have the following two outer_fn arguments: + // (..., ptr1, int1, ptr2, int2, ...). We add the following llvm-ir to our __enzyme call: + // (..., metadata! enzyme_dup, ptr, ptr, int1, ...). + // FIXME(ZuseZ4): We will upstream a safety check later which asserts that + // int2 >= int1, which means the shadow vector is large enough to store the gradient. + assert!(unsafe { + llvm::LLVMRustGetTypeKind(next_outer_ty) == llvm::TypeKind::Integer + }); + let next_outer_arg2 = outer_args[outer_pos + 2]; + let next_outer_ty2 = cx.val_ty(next_outer_arg2); + assert!(unsafe { + llvm::LLVMRustGetTypeKind(next_outer_ty2) == llvm::TypeKind::Pointer + }); + let next_outer_arg3 = outer_args[outer_pos + 3]; + let next_outer_ty3 = cx.val_ty(next_outer_arg3); + assert!(unsafe { + llvm::LLVMRustGetTypeKind(next_outer_ty3) == llvm::TypeKind::Integer + }); + args.push(next_outer_arg2); + args.push(cx.get_metadata_value(enzyme_const)); + args.push(next_outer_arg); + outer_pos += 4; + activity_pos += 2; + } else { + // A duplicated pointer will have the following two outer_fn arguments: + // (..., ptr, ptr, ...). We add the following llvm-ir to our __enzyme call: + // (..., metadata! enzyme_dup, ptr, ptr, ...). + if matches!(diff_activity, DiffActivity::Duplicated | DiffActivity::DuplicatedOnly) + { + assert!( + unsafe { llvm::LLVMRustGetTypeKind(next_outer_ty) } + == llvm::TypeKind::Pointer + ); + } + // In the case of Dual we don't have assumptions, e.g. f32 would be valid. + args.push(next_outer_arg); + outer_pos += 2; + activity_pos += 1; + } + } else { + // We do not differentiate with resprect to this argument. + // We already added the metadata and argument above, so just increase the counters. + outer_pos += 1; + activity_pos += 1; + } + } +} + /// When differentiating `fn_to_diff`, take a `outer_fn` and generate another /// function with expected naming and calling conventions[^1] which will be /// discovered by the enzyme LLVM pass and its body populated with the differentiated @@ -43,9 +150,6 @@ fn generate_enzyme_call<'ll>( outer_fn: &'ll Value, attrs: AutoDiffAttrs, ) { - let inputs = attrs.input_activity; - let output = attrs.ret_activity; - // We have to pick the name depending on whether we want forward or reverse mode autodiff. let mut ad_name: String = match attrs.mode { DiffMode::Forward => "__enzyme_fwddiff", @@ -132,111 +236,13 @@ fn generate_enzyme_call<'ll>( let mut args = Vec::with_capacity(num_args as usize + 1); args.push(fn_to_diff); - let enzyme_const = cx.create_metadata("enzyme_const".to_string()).unwrap(); - let enzyme_out = cx.create_metadata("enzyme_out".to_string()).unwrap(); - let enzyme_dup = cx.create_metadata("enzyme_dup".to_string()).unwrap(); - let enzyme_dupnoneed = cx.create_metadata("enzyme_dupnoneed".to_string()).unwrap(); let enzyme_primal_ret = cx.create_metadata("enzyme_primal_return".to_string()).unwrap(); - - match output { - DiffActivity::Dual => { - args.push(cx.get_metadata_value(enzyme_primal_ret)); - } - DiffActivity::Active => { - args.push(cx.get_metadata_value(enzyme_primal_ret)); - } - _ => {} + if matches!(attrs.ret_activity, DiffActivity::Dual | DiffActivity::Active) { + args.push(cx.get_metadata_value(enzyme_primal_ret)); } - debug!("matching autodiff arguments"); - // We now handle the issue that Rust level arguments not always match the llvm-ir level - // arguments. A slice, `&[f32]`, for example, is represented as a pointer and a length on - // llvm-ir level. The number of activities matches the number of Rust level arguments, so we - // need to match those. - // FIXME(ZuseZ4): This logic is a bit more complicated than it should be, can we simplify it - // using iterators and peek()? - let mut outer_pos: usize = 0; - let mut activity_pos = 0; let outer_args: Vec<&llvm::Value> = get_params(outer_fn); - while activity_pos < inputs.len() { - let diff_activity = inputs[activity_pos as usize]; - // Duplicated arguments received a shadow argument, into which enzyme will write the - // gradient. - let (activity, duplicated): (&Metadata, bool) = match diff_activity { - DiffActivity::None => panic!("not a valid input activity"), - DiffActivity::Const => (enzyme_const, false), - DiffActivity::Active => (enzyme_out, false), - DiffActivity::ActiveOnly => (enzyme_out, false), - DiffActivity::Dual => (enzyme_dup, true), - DiffActivity::DualOnly => (enzyme_dupnoneed, true), - DiffActivity::Duplicated => (enzyme_dup, true), - DiffActivity::DuplicatedOnly => (enzyme_dupnoneed, true), - DiffActivity::FakeActivitySize => (enzyme_const, false), - }; - let outer_arg = outer_args[outer_pos]; - args.push(cx.get_metadata_value(activity)); - args.push(outer_arg); - if duplicated { - // We know that duplicated args by construction have a following argument, - // so this can not be out of bounds. - let next_outer_arg = outer_args[outer_pos + 1]; - let next_outer_ty = cx.val_ty(next_outer_arg); - // FIXME(ZuseZ4): We should add support for Vec here too, but it's less urgent since - // vectors behind references (&Vec<T>) are already supported. Users can not pass a - // Vec by value for reverse mode, so this would only help forward mode autodiff. - let slice = { - if activity_pos + 1 >= inputs.len() { - // If there is no arg following our ptr, it also can't be a slice, - // since that would lead to a ptr, int pair. - false - } else { - let next_activity = inputs[activity_pos + 1]; - // We analyze the MIR types and add this dummy activity if we visit a slice. - next_activity == DiffActivity::FakeActivitySize - } - }; - if slice { - // A duplicated slice will have the following two outer_fn arguments: - // (..., ptr1, int1, ptr2, int2, ...). We add the following llvm-ir to our __enzyme call: - // (..., metadata! enzyme_dup, ptr, ptr, int1, ...). - // FIXME(ZuseZ4): We will upstream a safety check later which asserts that - // int2 >= int1, which means the shadow vector is large enough to store the gradient. - assert!(llvm::LLVMRustGetTypeKind(next_outer_ty) == llvm::TypeKind::Integer); - let next_outer_arg2 = outer_args[outer_pos + 2]; - let next_outer_ty2 = cx.val_ty(next_outer_arg2); - assert!(llvm::LLVMRustGetTypeKind(next_outer_ty2) == llvm::TypeKind::Pointer); - let next_outer_arg3 = outer_args[outer_pos + 3]; - let next_outer_ty3 = cx.val_ty(next_outer_arg3); - assert!(llvm::LLVMRustGetTypeKind(next_outer_ty3) == llvm::TypeKind::Integer); - args.push(next_outer_arg2); - args.push(cx.get_metadata_value(enzyme_const)); - args.push(next_outer_arg); - outer_pos += 4; - activity_pos += 2; - } else { - // A duplicated pointer will have the following two outer_fn arguments: - // (..., ptr, ptr, ...). We add the following llvm-ir to our __enzyme call: - // (..., metadata! enzyme_dup, ptr, ptr, ...). - if matches!( - diff_activity, - DiffActivity::Duplicated | DiffActivity::DuplicatedOnly - ) { - assert!( - llvm::LLVMRustGetTypeKind(next_outer_ty) == llvm::TypeKind::Pointer - ); - } - // In the case of Dual we don't have assumptions, e.g. f32 would be valid. - args.push(next_outer_arg); - outer_pos += 2; - activity_pos += 1; - } - } else { - // We do not differentiate with resprect to this argument. - // We already added the metadata and argument above, so just increase the counters. - outer_pos += 1; - activity_pos += 1; - } - } + match_args_from_caller_to_enzyme(&cx, &mut args, &attrs.input_activity, &outer_args); let call = builder.call(enzyme_ty, ad_fn, &args, None); diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index a4e5749b3ac..62fa2884e0f 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -5,6 +5,7 @@ use rustc_abi::{ }; use rustc_codegen_ssa::common; use rustc_codegen_ssa::traits::*; +use rustc_hir::LangItem; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; @@ -12,9 +13,9 @@ use rustc_middle::mir::interpret::{ Allocation, ConstAllocation, ErrorHandled, InitChunk, Pointer, Scalar as InterpScalar, read_target_uint, }; -use rustc_middle::mir::mono::MonoItem; -use rustc_middle::ty::Instance; +use rustc_middle::mir::mono::{Linkage, MonoItem}; use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; +use rustc_middle::ty::{self, Instance}; use rustc_middle::{bug, span_bug}; use tracing::{debug, instrument, trace}; @@ -171,8 +172,27 @@ fn check_and_apply_linkage<'ll, 'tcx>( if let Some(linkage) = attrs.import_linkage { debug!("get_static: sym={} linkage={:?}", sym, linkage); - // Declare a symbol `foo` with the desired linkage. - let g1 = cx.declare_global(sym, cx.type_i8()); + // Declare a symbol `foo`. If `foo` is an extern_weak symbol, we declare + // an extern_weak function, otherwise a global with the desired linkage. + let g1 = if matches!(attrs.import_linkage, Some(Linkage::ExternalWeak)) { + // An `extern_weak` function is represented as an `Option<unsafe extern ...>`, + // we extract the function signature and declare it as an extern_weak function + // instead of an extern_weak i8. + let instance = Instance::mono(cx.tcx, def_id); + if let ty::Adt(struct_def, args) = instance.ty(cx.tcx, cx.typing_env()).kind() + && cx.tcx.is_lang_item(struct_def.did(), LangItem::Option) + && let ty::FnPtr(sig, header) = args.type_at(0).kind() + { + let fn_sig = sig.with(*header); + + let fn_abi = cx.fn_abi_of_fn_ptr(fn_sig, ty::List::empty()); + cx.declare_fn(sym, &fn_abi, None) + } else { + cx.declare_global(sym, cx.type_i8()) + } + } else { + cx.declare_global(sym, cx.type_i8()) + }; llvm::set_linkage(g1, base::linkage_to_llvm(linkage)); // Declare an internal global `extern_with_linkage_foo` which diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 9f8ec0ea526..926445c780b 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -27,6 +27,7 @@ use rustc_session::config::{ }; use rustc_span::source_map::Spanned; use rustc_span::{DUMMY_SP, Span}; +use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::spec::{HasTargetSpec, RelocModel, SmallDataThresholdSupport, Target, TlsModel}; use smallvec::SmallVec; @@ -1199,7 +1200,7 @@ impl<'ll> CodegenCx<'ll, '_> { Some(def_id) => self.get_static(def_id), _ => { let ty = self.type_struct(&[self.type_ptr(), self.type_ptr()], false); - self.declare_global("rust_eh_catch_typeinfo", ty) + self.declare_global(&mangle_internal_symbol(self.tcx, "rust_eh_catch_typeinfo"), ty) } }; self.eh_catch_typeinfo.set(Some(eh_catch_typeinfo)); diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index b617f4d37f5..f6000e72840 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -146,6 +146,7 @@ pub(crate) struct CoverageSpan { #[derive(Clone, Debug, Default)] pub(crate) struct Regions { pub(crate) code_regions: Vec<CodeRegion>, + pub(crate) expansion_regions: Vec<ExpansionRegion>, pub(crate) branch_regions: Vec<BranchRegion>, pub(crate) mcdc_branch_regions: Vec<MCDCBranchRegion>, pub(crate) mcdc_decision_regions: Vec<MCDCDecisionRegion>, @@ -154,10 +155,16 @@ pub(crate) struct Regions { impl Regions { /// Returns true if none of this structure's tables contain any regions. pub(crate) fn has_no_regions(&self) -> bool { - let Self { code_regions, branch_regions, mcdc_branch_regions, mcdc_decision_regions } = - self; + let Self { + code_regions, + expansion_regions, + branch_regions, + mcdc_branch_regions, + mcdc_decision_regions, + } = self; code_regions.is_empty() + && expansion_regions.is_empty() && branch_regions.is_empty() && mcdc_branch_regions.is_empty() && mcdc_decision_regions.is_empty() @@ -172,6 +179,14 @@ pub(crate) struct CodeRegion { pub(crate) counter: Counter, } +/// Must match the layout of `LLVMRustCoverageExpansionRegion`. +#[derive(Clone, Debug)] +#[repr(C)] +pub(crate) struct ExpansionRegion { + pub(crate) cov_span: CoverageSpan, + pub(crate) expanded_file_id: u32, +} + /// Must match the layout of `LLVMRustCoverageBranchRegion`. #[derive(Clone, Debug)] #[repr(C)] diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs index 2cd7fa3225a..907d6d41a1f 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/llvm_cov.rs @@ -63,8 +63,18 @@ pub(crate) fn write_function_mappings_to_buffer( expressions: &[ffi::CounterExpression], regions: &ffi::Regions, ) -> Vec<u8> { - let ffi::Regions { code_regions, branch_regions, mcdc_branch_regions, mcdc_decision_regions } = - regions; + let ffi::Regions { + code_regions, + expansion_regions, + branch_regions, + mcdc_branch_regions, + mcdc_decision_regions, + } = regions; + + // SAFETY: + // - All types are FFI-compatible and have matching representations in Rust/C++. + // - For pointer/length pairs, the pointer and length come from the same vector or slice. + // - C++ code does not retain any pointers after the call returns. llvm::build_byte_buffer(|buffer| unsafe { llvm::LLVMRustCoverageWriteFunctionMappingsToBuffer( virtual_file_mapping.as_ptr(), @@ -73,6 +83,8 @@ pub(crate) fn write_function_mappings_to_buffer( expressions.len(), code_regions.as_ptr(), code_regions.len(), + expansion_regions.as_ptr(), + expansion_regions.len(), branch_regions.as_ptr(), branch_regions.len(), mcdc_branch_regions.as_ptr(), diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs index 80e54bf045e..048e1988c32 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs @@ -105,9 +105,14 @@ fn fill_region_tables<'tcx>( ids_info: &'tcx CoverageIdsInfo, covfun: &mut CovfunRecord<'tcx>, ) { - // Currently a function's mappings must all be in the same file as its body span. + // Currently a function's mappings must all be in the same file, so use the + // first mapping's span to determine the file. let source_map = tcx.sess.source_map(); - let source_file = source_map.lookup_source_file(fn_cov_info.body_span.lo()); + let Some(first_span) = (try { fn_cov_info.mappings.first()?.span }) else { + debug_assert!(false, "function has no mappings: {:?}", covfun.mangled_function_name); + return; + }; + let source_file = source_map.lookup_source_file(first_span.lo()); // Look up the global file ID for that file. let global_file_id = global_file_table.global_file_id_for_file(&source_file); @@ -115,13 +120,22 @@ fn fill_region_tables<'tcx>( // Associate that global file ID with a local file ID for this function. let local_file_id = covfun.virtual_file_mapping.local_id_for_global(global_file_id); - let ffi::Regions { code_regions, branch_regions, mcdc_branch_regions, mcdc_decision_regions } = - &mut covfun.regions; - - let make_cov_span = |span: Span| { - spans::make_coverage_span(local_file_id, source_map, fn_cov_info, &source_file, span) - }; + // In rare cases, _all_ of a function's spans are discarded, and coverage + // codegen needs to handle that gracefully to avoid #133606. + // It's hard for tests to trigger this organically, so instead we set + // `-Zcoverage-options=discard-all-spans-in-codegen` to force it to occur. let discard_all = tcx.sess.coverage_discard_all_spans_in_codegen(); + let make_coords = |span: Span| { + if discard_all { None } else { spans::make_coords(source_map, &source_file, span) } + }; + + let ffi::Regions { + code_regions, + expansion_regions: _, // FIXME(Zalathar): Fill out support for expansion regions + branch_regions, + mcdc_branch_regions, + mcdc_decision_regions, + } = &mut covfun.regions; // For each counter/region pair in this function+file, convert it to a // form suitable for FFI. @@ -136,17 +150,8 @@ fn fill_region_tables<'tcx>( ffi::Counter::from_term(term) }; - // Convert the `Span` into coordinates that we can pass to LLVM, or - // discard the span if conversion fails. In rare, cases _all_ of a - // function's spans are discarded, and the rest of coverage codegen - // needs to handle that gracefully to avoid a repeat of #133606. - // We don't have a good test case for triggering that organically, so - // instead we set `-Zcoverage-options=discard-all-spans-in-codegen` - // to force it to occur. - let Some(cov_span) = make_cov_span(span) else { continue }; - if discard_all { - continue; - } + let Some(coords) = make_coords(span) else { continue }; + let cov_span = coords.make_coverage_span(local_file_id); match *kind { MappingKind::Code { bcb } => { diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs index 6d1d91340c2..39a59560c9d 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs @@ -1,4 +1,3 @@ -use rustc_middle::mir::coverage::FunctionCoverageInfo; use rustc_span::source_map::SourceMap; use rustc_span::{BytePos, Pos, SourceFile, Span}; use tracing::debug; @@ -6,24 +5,41 @@ use tracing::debug; use crate::coverageinfo::ffi; use crate::coverageinfo::mapgen::LocalFileId; +/// Line and byte-column coordinates of a source code span within some file. +/// The file itself must be tracked separately. +#[derive(Clone, Copy, Debug)] +pub(crate) struct Coords { + /// 1-based starting line of the source code span. + pub(crate) start_line: u32, + /// 1-based starting column (in bytes) of the source code span. + pub(crate) start_col: u32, + /// 1-based ending line of the source code span. + pub(crate) end_line: u32, + /// 1-based ending column (in bytes) of the source code span. High bit must be unset. + pub(crate) end_col: u32, +} + +impl Coords { + /// Attaches a local file ID to these coordinates to produce an `ffi::CoverageSpan`. + pub(crate) fn make_coverage_span(&self, local_file_id: LocalFileId) -> ffi::CoverageSpan { + let &Self { start_line, start_col, end_line, end_col } = self; + let file_id = local_file_id.as_u32(); + ffi::CoverageSpan { file_id, start_line, start_col, end_line, end_col } + } +} + /// Converts the span into its start line and column, and end line and column. /// /// Line numbers and column numbers are 1-based. Unlike most column numbers emitted by /// the compiler, these column numbers are denoted in **bytes**, because that's what /// LLVM's `llvm-cov` tool expects to see in coverage maps. /// -/// Returns `None` if the conversion failed for some reason. This shouldn't happen, +/// Returns `None` if the conversion failed for some reason. This should be uncommon, /// but it's hard to rule out entirely (especially in the presence of complex macros /// or other expansions), and if it does happen then skipping a span or function is /// better than an ICE or `llvm-cov` failure that the user might have no way to avoid. -pub(crate) fn make_coverage_span( - file_id: LocalFileId, - source_map: &SourceMap, - fn_cov_info: &FunctionCoverageInfo, - file: &SourceFile, - span: Span, -) -> Option<ffi::CoverageSpan> { - let span = ensure_non_empty_span(source_map, fn_cov_info, span)?; +pub(crate) fn make_coords(source_map: &SourceMap, file: &SourceFile, span: Span) -> Option<Coords> { + let span = ensure_non_empty_span(source_map, span)?; let lo = span.lo(); let hi = span.hi(); @@ -46,8 +62,7 @@ pub(crate) fn make_coverage_span( start_line = source_map.doctest_offset_line(&file.name, start_line); end_line = source_map.doctest_offset_line(&file.name, end_line); - check_coverage_span(ffi::CoverageSpan { - file_id: file_id.as_u32(), + check_coords(Coords { start_line: start_line as u32, start_col: start_col as u32, end_line: end_line as u32, @@ -55,36 +70,22 @@ pub(crate) fn make_coverage_span( }) } -fn ensure_non_empty_span( - source_map: &SourceMap, - fn_cov_info: &FunctionCoverageInfo, - span: Span, -) -> Option<Span> { +fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option<Span> { if !span.is_empty() { return Some(span); } - let lo = span.lo(); - let hi = span.hi(); - - // The span is empty, so try to expand it to cover an adjacent '{' or '}', - // but only within the bounds of the body span. - let try_next = hi < fn_cov_info.body_span.hi(); - let try_prev = fn_cov_info.body_span.lo() < lo; - if !(try_next || try_prev) { - return None; - } - + // The span is empty, so try to enlarge it to cover an adjacent '{' or '}'. source_map .span_to_source(span, |src, start, end| try { // Adjusting span endpoints by `BytePos(1)` is normally a bug, // but in this case we have specifically checked that the character // we're skipping over is one of two specific ASCII characters, so // adjusting by exactly 1 byte is correct. - if try_next && src.as_bytes()[end] == b'{' { - Some(span.with_hi(hi + BytePos(1))) - } else if try_prev && src.as_bytes()[start - 1] == b'}' { - Some(span.with_lo(lo - BytePos(1))) + if src.as_bytes().get(end).copied() == Some(b'{') { + Some(span.with_hi(span.hi() + BytePos(1))) + } else if start > 0 && src.as_bytes()[start - 1] == b'}' { + Some(span.with_lo(span.lo() - BytePos(1))) } else { None } @@ -96,8 +97,8 @@ fn ensure_non_empty_span( /// it will immediately exit with a fatal error. To prevent that from happening, /// discard regions that are improperly ordered, or might be interpreted in a /// way that makes them improperly ordered. -fn check_coverage_span(cov_span: ffi::CoverageSpan) -> Option<ffi::CoverageSpan> { - let ffi::CoverageSpan { file_id: _, start_line, start_col, end_line, end_col } = cov_span; +fn check_coords(coords: Coords) -> Option<Coords> { + let Coords { start_line, start_col, end_line, end_col } = coords; // Line/column coordinates are supposed to be 1-based. If we ever emit // coordinates of 0, `llvm-cov` might misinterpret them. @@ -110,17 +111,17 @@ fn check_coverage_span(cov_span: ffi::CoverageSpan) -> Option<ffi::CoverageSpan> let is_ordered = (start_line, start_col) <= (end_line, end_col); if all_nonzero && end_col_has_high_bit_unset && is_ordered { - Some(cov_span) + Some(coords) } else { debug!( - ?cov_span, + ?coords, ?all_nonzero, ?end_col_has_high_bit_unset, ?is_ordered, "Skipping source region that would be misinterpreted or rejected by LLVM" ); // If this happens in a debug build, ICE to make it easier to notice. - debug_assert!(false, "Improper source region: {cov_span:?}"); + debug_assert!(false, "Improper source region: {coords:?}"); None } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 98d59f5a8ae..2eaaf127e41 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::fmt::{self, Write}; use std::hash::{Hash, Hasher}; use std::path::{Path, PathBuf}; +use std::sync::Arc; use std::{iter, ptr}; use libc::{c_char, c_longlong, c_uint}; @@ -38,8 +39,8 @@ use crate::debuginfo::metadata::type_map::build_type_with_children; use crate::debuginfo::utils::{WidePtrKind, wide_pointer_kind}; use crate::llvm; use crate::llvm::debuginfo::{ - DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType, DebugEmissionKind, - DebugNameTableKind, + DIBasicType, DIBuilder, DICompositeType, DIDescriptor, DIFile, DIFlags, DILexicalBlock, + DIScope, DIType, DebugEmissionKind, DebugNameTableKind, }; use crate::value::Value; @@ -68,7 +69,8 @@ pub(super) const UNKNOWN_COLUMN_NUMBER: c_uint = 0; const NO_SCOPE_METADATA: Option<&DIScope> = None; /// A function that returns an empty list of generic parameter debuginfo nodes. -const NO_GENERICS: for<'ll> fn(&CodegenCx<'ll, '_>) -> SmallVec<&'ll DIType> = |_| SmallVec::new(); +const NO_GENERICS: for<'ll> fn(&CodegenCx<'ll, '_>) -> SmallVec<Option<&'ll DIType>> = + |_| SmallVec::new(); // SmallVec is used quite a bit in this module, so create a shorthand. // The actual number of elements is not so important. @@ -243,7 +245,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( cx, owner, addr_field_name, - (addr_field.size, addr_field.align.abi), + addr_field, layout.fields.offset(WIDE_PTR_ADDR), DIFlags::FlagZero, data_ptr_type_di_node, @@ -253,7 +255,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( cx, owner, extra_field_name, - (extra_field.size, extra_field.align.abi), + extra_field, layout.fields.offset(WIDE_PTR_EXTRA), DIFlags::FlagZero, type_di_node(cx, extra_field.ty), @@ -311,12 +313,7 @@ fn build_subroutine_type_di_node<'ll, 'tcx>( debug_context(cx).type_map.unique_id_to_di_node.borrow_mut().remove(&unique_type_id); - let fn_di_node = unsafe { - llvm::LLVMRustDIBuilderCreateSubroutineType( - DIB(cx), - create_DIArray(DIB(cx), &signature_di_nodes[..]), - ) - }; + let fn_di_node = create_subroutine_type(cx, create_DIArray(DIB(cx), &signature_di_nodes[..])); // This is actually a function pointer, so wrap it in pointer DI. let name = compute_debuginfo_type_name(cx.tcx, fn_ty, false); @@ -340,6 +337,13 @@ fn build_subroutine_type_di_node<'ll, 'tcx>( DINodeCreationResult::new(di_node, false) } +pub(super) fn create_subroutine_type<'ll>( + cx: &CodegenCx<'ll, '_>, + signature: &'ll DICompositeType, +) -> &'ll DICompositeType { + unsafe { llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(cx), signature) } +} + /// Create debuginfo for `dyn SomeTrait` types. Currently these are empty structs /// we with the correct type name (e.g. "dyn SomeTrait<Foo, Item=u32> + Sync"). fn build_dyn_type_di_node<'ll, 'tcx>( @@ -487,26 +491,22 @@ pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> // FIXME(mw): Cache this via a regular UniqueTypeId instead of an extra field in the debug context. fn recursion_marker_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> &'ll DIType { *debug_context(cx).recursion_marker_type.get_or_init(move || { - unsafe { - // The choice of type here is pretty arbitrary - - // anything reading the debuginfo for a recursive - // type is going to see *something* weird - the only - // question is what exactly it will see. - // - // FIXME: the name `<recur_type>` does not fit the naming scheme - // of other types. - // - // FIXME: it might make sense to use an actual pointer type here - // so that debuggers can show the address. - let name = "<recur_type>"; - llvm::LLVMRustDIBuilderCreateBasicType( - DIB(cx), - name.as_c_char_ptr(), - name.len(), - cx.tcx.data_layout.pointer_size.bits(), - dwarf_const::DW_ATE_unsigned, - ) - } + // The choice of type here is pretty arbitrary - + // anything reading the debuginfo for a recursive + // type is going to see *something* weird - the only + // question is what exactly it will see. + // + // FIXME: the name `<recur_type>` does not fit the naming scheme + // of other types. + // + // FIXME: it might make sense to use an actual pointer type here + // so that debuggers can show the address. + create_basic_type( + cx, + "<recur_type>", + cx.tcx.data_layout.pointer_size, + dwarf_const::DW_ATE_unsigned, + ) }) } @@ -620,42 +620,38 @@ pub(crate) fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFi let source = cx.sess().opts.unstable_opts.embed_source.then_some(()).and(source_file.src.as_ref()); - unsafe { - llvm::LLVMRustDIBuilderCreateFile( - DIB(cx), - file_name.as_c_char_ptr(), - file_name.len(), - directory.as_c_char_ptr(), - directory.len(), - hash_kind, - hash_value.as_c_char_ptr(), - hash_value.len(), - source.map_or(ptr::null(), |x| x.as_c_char_ptr()), - source.map_or(0, |x| x.len()), - ) - } + create_file(DIB(cx), &file_name, &directory, &hash_value, hash_kind, source) } } fn unknown_file_metadata<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile { - debug_context(cx).created_files.borrow_mut().entry(None).or_insert_with(|| unsafe { - let file_name = "<unknown>"; - let directory = ""; - let hash_value = ""; + debug_context(cx).created_files.borrow_mut().entry(None).or_insert_with(|| { + create_file(DIB(cx), "<unknown>", "", "", llvm::ChecksumKind::None, None) + }) +} +fn create_file<'ll>( + builder: &DIBuilder<'ll>, + file_name: &str, + directory: &str, + hash_value: &str, + hash_kind: llvm::ChecksumKind, + source: Option<&Arc<String>>, +) -> &'ll DIFile { + unsafe { llvm::LLVMRustDIBuilderCreateFile( - DIB(cx), + builder, file_name.as_c_char_ptr(), file_name.len(), directory.as_c_char_ptr(), directory.len(), - llvm::ChecksumKind::None, + hash_kind, hash_value.as_c_char_ptr(), hash_value.len(), - ptr::null(), - 0, + source.map_or(ptr::null(), |x| x.as_c_char_ptr()), + source.map_or(0, |x| x.len()), ) - }) + } } trait MsvcBasicName { @@ -742,7 +738,7 @@ fn build_cpp_f16_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> DINodeCreation cx, float_di_node, "bits", - cx.size_and_align_of(bits_ty), + cx.layout_of(bits_ty), Size::ZERO, DIFlags::FlagZero, type_di_node(cx, bits_ty), @@ -788,15 +784,7 @@ fn build_basic_type_di_node<'ll, 'tcx>( _ => bug!("debuginfo::build_basic_type_di_node - `t` is invalid type"), }; - let ty_di_node = unsafe { - llvm::LLVMRustDIBuilderCreateBasicType( - DIB(cx), - name.as_c_char_ptr(), - name.len(), - cx.size_of(t).bits(), - encoding, - ) - }; + let ty_di_node = create_basic_type(cx, name, cx.size_of(t), encoding); if !cpp_like_debuginfo { return DINodeCreationResult::new(ty_di_node, false); @@ -824,6 +812,23 @@ fn build_basic_type_di_node<'ll, 'tcx>( DINodeCreationResult::new(typedef_di_node, false) } +fn create_basic_type<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + name: &str, + size: Size, + encoding: u32, +) -> &'ll DIBasicType { + unsafe { + llvm::LLVMRustDIBuilderCreateBasicType( + DIB(cx), + name.as_c_char_ptr(), + name.len(), + size.bits(), + encoding, + ) + } +} + fn build_foreign_type_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, @@ -929,17 +934,13 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>( }; unsafe { - let compile_unit_file = llvm::LLVMRustDIBuilderCreateFile( + let compile_unit_file = create_file( debug_context.builder.as_ref(), - name_in_debuginfo.as_c_char_ptr(), - name_in_debuginfo.len(), - work_dir.as_c_char_ptr(), - work_dir.len(), + &name_in_debuginfo, + &work_dir, + "", llvm::ChecksumKind::None, - ptr::null(), - 0, - ptr::null(), - 0, + None, ); let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit( @@ -971,7 +972,7 @@ fn build_field_di_node<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, owner: &'ll DIScope, name: &str, - size_and_align: (Size, Align), + layout: TyAndLayout<'tcx>, offset: Size, flags: DIFlags, type_di_node: &'ll DIType, @@ -983,6 +984,30 @@ fn build_field_di_node<'ll, 'tcx>( } else { (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) }; + create_member_type( + cx, + owner, + name, + file_metadata, + line_number, + layout, + offset, + flags, + type_di_node, + ) +} + +fn create_member_type<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + owner: &'ll DIScope, + name: &str, + file_metadata: &'ll DIType, + line_number: u32, + layout: TyAndLayout<'tcx>, + offset: Size, + flags: DIFlags, + type_di_node: &'ll DIType, +) -> &'ll DIType { unsafe { llvm::LLVMRustDIBuilderCreateMemberType( DIB(cx), @@ -991,8 +1016,8 @@ fn build_field_di_node<'ll, 'tcx>( name.len(), file_metadata, line_number, - size_and_align.0.bits(), - size_and_align.1.bits() as u32, + layout.size.bits(), + layout.align.abi.bits() as u32, offset.bits(), flags, type_di_node, @@ -1076,7 +1101,7 @@ fn build_struct_type_di_node<'ll, 'tcx>( cx, owner, &field_name[..], - (field_layout.size, field_layout.align.abi), + field_layout, struct_type_and_layout.fields.offset(i), visibility_di_flags(cx, f.did, adt_def.did()), type_di_node(cx, field_layout.ty), @@ -1126,7 +1151,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>( cx, closure_or_coroutine_di_node, capture_name.as_str(), - cx.size_and_align_of(up_var_ty), + cx.layout_of(up_var_ty), layout.fields.offset(index), DIFlags::FlagZero, type_di_node(cx, up_var_ty), @@ -1171,7 +1196,7 @@ fn build_tuple_type_di_node<'ll, 'tcx>( cx, tuple_di_node, &tuple_field_name(index), - cx.size_and_align_of(component_type), + cx.layout_of(component_type), tuple_type_and_layout.fields.offset(index), DIFlags::FlagZero, type_di_node(cx, component_type), @@ -1269,7 +1294,7 @@ fn build_union_type_di_node<'ll, 'tcx>( cx, owner, f.name.as_str(), - size_and_align_of(field_layout), + field_layout, Size::ZERO, DIFlags::FlagZero, type_di_node(cx, field_layout.ty), @@ -1287,32 +1312,33 @@ fn build_union_type_di_node<'ll, 'tcx>( fn build_generic_type_param_di_nodes<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, -) -> SmallVec<&'ll DIType> { +) -> SmallVec<Option<&'ll DIType>> { if let ty::Adt(def, args) = *ty.kind() { - if args.types().next().is_some() { - let generics = cx.tcx.generics_of(def.did()); - let names = get_parameter_names(cx, generics); - let template_params: SmallVec<_> = iter::zip(args, names) - .filter_map(|(kind, name)| { - kind.as_type().map(|ty| { - let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty); - let actual_type_di_node = type_di_node(cx, actual_type); - let name = name.as_str(); - unsafe { - llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( - DIB(cx), - None, - name.as_c_char_ptr(), - name.len(), - actual_type_di_node, - ) - } - }) + let generics = cx.tcx.generics_of(def.did()); + return get_template_parameters(cx, generics, args); + } + + return smallvec![]; +} + +pub(super) fn get_template_parameters<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + generics: &ty::Generics, + args: ty::GenericArgsRef<'tcx>, +) -> SmallVec<Option<&'ll DIType>> { + if args.types().next().is_some() { + let names = get_parameter_names(cx, generics); + let template_params: SmallVec<_> = iter::zip(args, names) + .filter_map(|(kind, name)| { + kind.as_type().map(|ty| { + let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty); + let actual_type_di_node = type_di_node(cx, actual_type); + Some(cx.create_template_type_parameter(name.as_str(), actual_type_di_node)) }) - .collect(); + }) + .collect(); - return template_params; - } + return template_params; } return smallvec![]; @@ -1416,7 +1442,9 @@ fn build_vtable_type_di_node<'ll, 'tcx>( let void_pointer_ty = Ty::new_imm_ptr(tcx, tcx.types.unit); let void_pointer_type_di_node = type_di_node(cx, void_pointer_ty); let usize_di_node = type_di_node(cx, tcx.types.usize); - let (pointer_size, pointer_align) = cx.size_and_align_of(void_pointer_ty); + let pointer_layout = cx.layout_of(void_pointer_ty); + let pointer_size = pointer_layout.size; + let pointer_align = pointer_layout.align.abi; // If `usize` is not pointer-sized and -aligned then the size and alignment computations // for the vtable as a whole would be wrong. Let's make sure this holds even on weird // platforms. @@ -1472,7 +1500,7 @@ fn build_vtable_type_di_node<'ll, 'tcx>( cx, vtable_type_di_node, &field_name, - (pointer_size, pointer_align), + pointer_layout, field_offset, DIFlags::FlagZero, field_type_di_node, 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 a72e205c9b2..07075be55fa 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 @@ -17,8 +17,8 @@ use crate::debuginfo::metadata::enums::DiscrResult; use crate::debuginfo::metadata::type_map::{self, Stub, UniqueTypeId}; use crate::debuginfo::metadata::{ DINodeCreationResult, NO_GENERICS, NO_SCOPE_METADATA, SmallVec, UNKNOWN_LINE_NUMBER, - build_field_di_node, file_metadata, file_metadata_from_def_id, size_and_align_of, type_di_node, - unknown_file_metadata, visibility_di_flags, + build_field_di_node, create_member_type, file_metadata, file_metadata_from_def_id, + size_and_align_of, type_di_node, unknown_file_metadata, visibility_di_flags, }; use crate::debuginfo::utils::DIB; use crate::llvm::debuginfo::{DIFile, DIFlags, DIType}; @@ -370,9 +370,9 @@ fn build_single_variant_union_fields<'ll, 'tcx>( cx, enum_type_di_node, &variant_union_field_name(variant_index), - // NOTE: We use the size and align of the entire type, not from variant_layout + // NOTE: We use the layout of the entire type, not from variant_layout // since the later is sometimes smaller (if it has fewer fields). - size_and_align_of(enum_type_and_layout), + enum_type_and_layout, Size::ZERO, visibility_flags, variant_struct_type_wrapper_di_node, @@ -560,7 +560,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>( cx, wrapper_struct_type_di_node, "value", - size_and_align_of(enum_or_coroutine_type_and_layout), + enum_or_coroutine_type_and_layout, Size::ZERO, DIFlags::FlagZero, variant_struct_type_di_node, @@ -820,7 +820,6 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( .unwrap_or_else(|| (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)); let field_name = variant_union_field_name(variant_member_info.variant_index); - let (size, align) = size_and_align_of(enum_type_and_layout); let variant_struct_type_wrapper = build_variant_struct_wrapper_type_di_node( cx, @@ -840,27 +839,23 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( }, ); - // We use LLVMRustDIBuilderCreateMemberType() member type directly because + // We use create_member_type() member type directly because // the build_field_di_node() function does not support specifying a source location, // which is something that we don't do anywhere else. - unsafe { - llvm::LLVMRustDIBuilderCreateMemberType( - DIB(cx), - enum_type_di_node, - field_name.as_c_char_ptr(), - field_name.len(), - file_di_node, - line_number, - // NOTE: We use the size and align of the entire type, not from variant_layout - // since the later is sometimes smaller (if it has fewer fields). - size.bits(), - align.bits() as u32, - // Union fields are always at offset zero - Size::ZERO.bits(), - di_flags, - variant_struct_type_wrapper, - ) - } + create_member_type( + cx, + enum_type_di_node, + &field_name, + file_di_node, + line_number, + // NOTE: We use the layout of the entire type, not from variant_layout + // since the later is sometimes smaller (if it has fewer fields). + enum_type_and_layout, + // Union fields are always at offset zero + Size::ZERO, + di_flags, + variant_struct_type_wrapper, + ) })); assert_eq!( @@ -874,7 +869,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( if is_128_bits { let type_di_node = type_di_node(cx, cx.tcx.types.u64); - let size_and_align = cx.size_and_align_of(cx.tcx.types.u64); + let u64_layout = cx.layout_of(cx.tcx.types.u64); let (lo_offset, hi_offset) = match cx.tcx.data_layout.endian { Endian::Little => (0, 8), @@ -889,7 +884,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( cx, enum_type_di_node, TAG_FIELD_NAME_128_LO, - size_and_align, + u64_layout, lo_offset, di_flags, type_di_node, @@ -900,7 +895,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( cx, enum_type_di_node, TAG_FIELD_NAME_128_HI, - size_and_align, + u64_layout, hi_offset, DIFlags::FlagZero, type_di_node, @@ -911,7 +906,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>( cx, enum_type_di_node, TAG_FIELD_NAME, - cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field).ty), + enum_type_and_layout.field(cx, tag_field), enum_type_and_layout.fields.offset(tag_field), di_flags, tag_base_type_di_node, 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 9f6a5cc89e0..6792c307fdc 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -249,7 +249,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>( cx, struct_type_di_node, &field_name, - (field_layout.size, field_layout.align.abi), + field_layout, variant_layout.fields.offset(field_index), di_flags, type_di_node(cx, field_layout.ty), @@ -332,7 +332,7 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( cx, variant_struct_type_di_node, &field_name, - cx.size_and_align_of(field_type), + cx.layout_of(field_type), variant_layout.fields.offset(field_index), DIFlags::FlagZero, type_di_node(cx, field_type), @@ -352,7 +352,7 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( cx, variant_struct_type_di_node, upvar_name.as_str(), - cx.size_and_align_of(upvar_ty), + cx.layout_of(upvar_ty), coroutine_type_and_layout.fields.offset(index), DIFlags::FlagZero, type_di_node(cx, upvar_ty), @@ -363,6 +363,7 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( state_specific_fields.into_iter().chain(common_fields).collect() }, + // FIXME: this is a no-op. `build_generic_type_param_di_nodes` only works for Adts. |cx| build_generic_type_param_di_nodes(cx, coroutine_type_and_layout.ty), ) .di_node diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index 187d97c54c8..bfd131cfd3d 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -13,9 +13,9 @@ use smallvec::smallvec; use crate::common::{AsCCharPtr, CodegenCx}; use crate::debuginfo::metadata::type_map::{self, Stub, StubInfo, UniqueTypeId}; use crate::debuginfo::metadata::{ - DINodeCreationResult, NO_GENERICS, SmallVec, UNKNOWN_LINE_NUMBER, file_metadata, - file_metadata_from_def_id, size_and_align_of, type_di_node, unknown_file_metadata, - visibility_di_flags, + DINodeCreationResult, NO_GENERICS, SmallVec, UNKNOWN_LINE_NUMBER, create_member_type, + file_metadata, file_metadata_from_def_id, size_and_align_of, type_di_node, + unknown_file_metadata, visibility_di_flags, }; use crate::debuginfo::utils::{DIB, create_DIArray, get_namespace_for_item}; use crate::llvm::debuginfo::{DIFile, DIFlags, DIType}; @@ -363,23 +363,22 @@ fn build_discr_member_di_node<'ll, 'tcx>( &Variants::Multiple { tag_field, .. } => { let tag_base_type = tag_base_type(cx.tcx, enum_or_coroutine_type_and_layout); - let (size, align) = cx.size_and_align_of(tag_base_type); - - unsafe { - Some(llvm::LLVMRustDIBuilderCreateMemberType( - DIB(cx), - containing_scope, - tag_name.as_c_char_ptr(), - tag_name.len(), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, - size.bits(), - align.bits() as u32, - enum_or_coroutine_type_and_layout.fields.offset(tag_field).bits(), - DIFlags::FlagArtificial, - type_di_node(cx, tag_base_type), - )) - } + let ty = type_di_node(cx, tag_base_type); + let file = unknown_file_metadata(cx); + + let layout = cx.layout_of(tag_base_type); + + Some(create_member_type( + cx, + containing_scope, + &tag_name, + file, + UNKNOWN_LINE_NUMBER, + layout, + enum_or_coroutine_type_and_layout.fields.offset(tag_field), + DIFlags::FlagArtificial, + ty, + )) } } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index af1d503ad6a..ae2ab32ef53 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -257,7 +257,7 @@ pub(super) fn build_type_with_children<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, stub_info: StubInfo<'ll, 'tcx>, members: impl FnOnce(&CodegenCx<'ll, 'tcx>, &'ll DIType) -> SmallVec<&'ll DIType>, - generics: impl FnOnce(&CodegenCx<'ll, 'tcx>) -> SmallVec<&'ll DIType>, + generics: impl FnOnce(&CodegenCx<'ll, 'tcx>) -> SmallVec<Option<&'ll DIType>>, ) -> DINodeCreationResult<'ll> { assert_eq!(debug_context(cx).type_map.di_node_for_unique_id(stub_info.unique_type_id), None); @@ -265,8 +265,7 @@ pub(super) fn build_type_with_children<'ll, 'tcx>( let members: SmallVec<_> = members(cx, stub_info.metadata).into_iter().map(|node| Some(node)).collect(); - let generics: SmallVec<Option<&'ll DIType>> = - generics(cx).into_iter().map(|node| Some(node)).collect(); + let generics = generics(cx); if !(members.is_empty() && generics.is_empty()) { unsafe { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 10819a53b1d..ae7d080db66 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -2,10 +2,11 @@ use std::cell::{OnceCell, RefCell}; use std::ops::Range; +use std::ptr; use std::sync::Arc; -use std::{iter, ptr}; use libc::c_uint; +use metadata::create_subroutine_type; use rustc_abi::Size; use rustc_codegen_ssa::debuginfo::type_names; use rustc_codegen_ssa::mir::debuginfo::VariableKind::*; @@ -34,8 +35,8 @@ use crate::builder::Builder; use crate::common::{AsCCharPtr, CodegenCx}; use crate::llvm; use crate::llvm::debuginfo::{ - DIArray, DIBuilderBox, DIFile, DIFlags, DILexicalBlock, DILocation, DISPFlags, DIScope, DIType, - DIVariable, + DIArray, DIBuilderBox, DIFile, DIFlags, DILexicalBlock, DILocation, DISPFlags, DIScope, + DITemplateTypeParameter, DIType, DIVariable, }; use crate::value::Value; @@ -251,7 +252,7 @@ struct DebugLoc { col: u32, } -impl CodegenCx<'_, '_> { +impl<'ll> CodegenCx<'ll, '_> { /// Looks up debug source information about a `BytePos`. // FIXME(eddyb) rename this to better indicate it's a duplicate of // `lookup_char_pos` rather than `dbg_loc`, perhaps by making @@ -279,6 +280,22 @@ impl CodegenCx<'_, '_> { DebugLoc { file, line, col } } } + + fn create_template_type_parameter( + &self, + name: &str, + actual_type_metadata: &'ll DIType, + ) -> &'ll DITemplateTypeParameter { + unsafe { + llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( + DIB(self), + None, + name.as_c_char_ptr(), + name.len(), + actual_type_metadata, + ) + } + } } impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { @@ -325,10 +342,8 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { let loc = self.lookup_debug_loc(span.lo()); let file_metadata = file_metadata(self, &loc.file); - let function_type_metadata = unsafe { - let fn_signature = get_function_signature(self, fn_abi); - llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), fn_signature) - }; + let function_type_metadata = + create_subroutine_type(self, get_function_signature(self, fn_abi)); let mut name = String::with_capacity(64); type_names::push_item_name(tcx, def_id, false, &mut name); @@ -471,46 +486,10 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { generics: &ty::Generics, args: GenericArgsRef<'tcx>, ) -> &'ll DIArray { - if args.types().next().is_none() { - return create_DIArray(DIB(cx), &[]); - } - - // Again, only create type information if full debuginfo is enabled - let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full { - let names = get_parameter_names(cx, generics); - iter::zip(args, names) - .filter_map(|(kind, name)| { - kind.as_type().map(|ty| { - let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty); - let actual_type_metadata = type_di_node(cx, actual_type); - let name = name.as_str(); - unsafe { - Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( - DIB(cx), - None, - name.as_c_char_ptr(), - name.len(), - actual_type_metadata, - )) - } - }) - }) - .collect() - } else { - vec![] - }; - + let template_params = metadata::get_template_parameters(cx, generics, args); create_DIArray(DIB(cx), &template_params) } - fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> { - let mut names = generics.parent.map_or_else(Vec::new, |def_id| { - get_parameter_names(cx, cx.tcx.generics_of(def_id)) - }); - names.extend(generics.own_params.iter().map(|param| param.name)); - names - } - /// Returns a scope, plus `true` if that's a type scope for "class" methods, /// otherwise `false` for plain namespace scopes. fn get_containing_scope<'ll, 'tcx>( diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 660fc7ec4c4..67135fcc308 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -14,6 +14,7 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, GenericArgsRef, Ty}; use rustc_middle::{bug, span_bug}; use rustc_span::{Span, Symbol, sym}; +use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::callconv::{FnAbi, PassMode}; use rustc_target::spec::{HasTargetSpec, PanicStrategy}; use tracing::debug; @@ -812,7 +813,10 @@ fn codegen_msvc_try<'ll>( let type_name = bx.const_bytes(b"rust_panic\0"); let type_info = bx.const_struct(&[type_info_vtable, bx.const_null(bx.type_ptr()), type_name], false); - let tydesc = bx.declare_global("__rust_panic_type_info", bx.val_ty(type_info)); + let tydesc = bx.declare_global( + &mangle_internal_symbol(bx.tcx, "__rust_panic_type_info"), + bx.val_ty(type_info), + ); llvm::set_linkage(tydesc, llvm::Linkage::LinkOnceODRLinkage); if bx.cx.tcx.sess.target.supports_comdat() { diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 39087a4d6f4..83efb3ea660 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2019,6 +2019,8 @@ unsafe extern "C" { NumExpressions: size_t, CodeRegions: *const crate::coverageinfo::ffi::CodeRegion, NumCodeRegions: size_t, + ExpansionRegions: *const crate::coverageinfo::ffi::ExpansionRegion, + NumExpansionRegions: size_t, BranchRegions: *const crate::coverageinfo::ffi::BranchRegion, NumBranchRegions: size_t, MCDCBranchRegions: *const crate::coverageinfo::ffi::MCDCBranchRegion, diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 1346efcb87c..0a2f1d5bb67 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -19,7 +19,6 @@ regex = "1.4" rustc_abi = { path = "../rustc_abi" } rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } -rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } @@ -27,7 +26,6 @@ rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_fs_util = { path = "../rustc_fs_util" } rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } -rustc_hir_pretty = { path = "../rustc_hir_pretty" } rustc_incremental = { path = "../rustc_incremental" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } @@ -40,7 +38,6 @@ rustc_span = { path = "../rustc_span" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } -rustc_type_ir = { path = "../rustc_type_ir" } serde_json = "1.0.59" smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tempfile = "3.2" diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 60af462b6b6..34c84c64070 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -389,11 +389,10 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { mut skip: Box<dyn FnMut(&str) -> bool + 'static>, ) -> io::Result<()> { let mut archive_path = archive_path.to_path_buf(); - if self.sess.target.llvm_target.contains("-apple-macosx") { - if let Some(new_archive_path) = try_extract_macho_fat_archive(self.sess, &archive_path)? - { - archive_path = new_archive_path - } + if self.sess.target.llvm_target.contains("-apple-macosx") + && let Some(new_archive_path) = try_extract_macho_fat_archive(self.sess, &archive_path)? + { + archive_path = new_archive_path } if self.src_archives.iter().any(|archive| archive.0 == archive_path) { diff --git a/compiler/rustc_codegen_ssa/src/back/command.rs b/compiler/rustc_codegen_ssa/src/back/command.rs index 383d0579e52..05351bd6ca3 100644 --- a/compiler/rustc_codegen_ssa/src/back/command.rs +++ b/compiler/rustc_codegen_ssa/src/back/command.rs @@ -137,12 +137,42 @@ impl Command { /// Returns a `true` if we're pretty sure that this'll blow OS spawn limits, /// or `false` if we should attempt to spawn and see what the OS says. pub(crate) fn very_likely_to_exceed_some_spawn_limit(&self) -> bool { - // We mostly only care about Windows in this method, on Unix the limits - // can be gargantuan anyway so we're pretty unlikely to hit them - if cfg!(unix) { + #[cfg(not(any(windows, unix)))] + { return false; } + // On Unix the limits can be gargantuan anyway so we're pretty + // unlikely to hit them, but might still exceed it. + // We consult ARG_MAX here to get an estimate. + #[cfg(unix)] + { + let ptr_size = mem::size_of::<usize>(); + // arg + \0 + pointer + let args_size = self.args.iter().fold(0usize, |acc, a| { + let arg = a.as_encoded_bytes().len(); + let nul = 1; + acc.saturating_add(arg).saturating_add(nul).saturating_add(ptr_size) + }); + // key + `=` + value + \0 + pointer + let envs_size = self.env.iter().fold(0usize, |acc, (k, v)| { + let k = k.as_encoded_bytes().len(); + let eq = 1; + let v = v.as_encoded_bytes().len(); + let nul = 1; + acc.saturating_add(k) + .saturating_add(eq) + .saturating_add(v) + .saturating_add(nul) + .saturating_add(ptr_size) + }); + let arg_max = match unsafe { libc::sysconf(libc::_SC_ARG_MAX) } { + -1 => return false, // Go to OS anyway. + max => max as usize, + }; + return args_size.saturating_add(envs_size) > arg_max; + } + // Ok so on Windows to spawn a process is 32,768 characters in its // command line [1]. Unfortunately we don't actually have access to that // as it's calculated just before spawning. Instead we perform a @@ -165,9 +195,14 @@ impl Command { // // [1]: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa // [2]: https://devblogs.microsoft.com/oldnewthing/?p=41553 - - let estimated_command_line_len = self.args.iter().map(|a| a.len()).sum::<usize>(); - estimated_command_line_len > 1024 * 6 + #[cfg(windows)] + { + let estimated_command_line_len = self + .args + .iter() + .fold(0usize, |acc, a| acc.saturating_add(a.as_encoded_bytes().len())); + return estimated_command_line_len > 1024 * 6; + } } } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index ea961f222db..74597f6263d 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -151,17 +151,17 @@ pub fn link_binary( sess.dcx().emit_artifact_notification(&out_filename, "link"); } - if sess.prof.enabled() { - if let Some(artifact_name) = out_filename.file_name() { - // Record size for self-profiling - let file_size = std::fs::metadata(&out_filename).map(|m| m.len()).unwrap_or(0); - - sess.prof.artifact_size( - "linked_artifact", - artifact_name.to_string_lossy(), - file_size, - ); - } + if sess.prof.enabled() + && let Some(artifact_name) = out_filename.file_name() + { + // Record size for self-profiling + let file_size = std::fs::metadata(&out_filename).map(|m| m.len()).unwrap_or(0); + + sess.prof.artifact_size( + "linked_artifact", + artifact_name.to_string_lossy(), + file_size, + ); } if output.is_stdout() { @@ -186,16 +186,12 @@ pub fn link_binary( let maybe_remove_temps_from_module = |preserve_objects: bool, preserve_dwarf_objects: bool, module: &CompiledModule| { - if !preserve_objects { - if let Some(ref obj) = module.object { - ensure_removed(sess.dcx(), obj); - } + if !preserve_objects && let Some(ref obj) = module.object { + ensure_removed(sess.dcx(), obj); } - if !preserve_dwarf_objects { - if let Some(ref dwo_obj) = module.dwarf_object { - ensure_removed(sess.dcx(), dwo_obj); - } + if !preserve_dwarf_objects && let Some(ref dwo_obj) = module.dwarf_object { + ensure_removed(sess.dcx(), dwo_obj); } }; @@ -1538,8 +1534,13 @@ fn print_native_static_libs( } let stem = path.file_stem().unwrap().to_str().unwrap(); // Convert library file-stem into a cc -l argument. - let prefix = if stem.starts_with("lib") && !sess.target.is_like_windows { 3 } else { 0 }; - let lib = &stem[prefix..]; + let lib = if let Some(lib) = stem.strip_prefix("lib") + && !sess.target.is_like_windows + { + lib + } else { + stem + }; let path = parent.unwrap_or_else(|| Path::new("")); if sess.target.is_like_msvc { // When producing a dll, the MSVC linker may not actually emit a @@ -2111,11 +2112,11 @@ fn add_local_crate_metadata_objects( // When linking a dynamic library, we put the metadata into a section of the // executable. This metadata is in a separate object file from the main // object file, so we link that in here. - if crate_type == CrateType::Dylib || crate_type == CrateType::ProcMacro { - if let Some(obj) = codegen_results.metadata_module.as_ref().and_then(|m| m.object.as_ref()) - { - cmd.add_object(obj); - } + if matches!(crate_type, CrateType::Dylib | CrateType::ProcMacro) + && let Some(m) = &codegen_results.metadata_module + && let Some(obj) = &m.object + { + cmd.add_object(obj); } } @@ -2131,7 +2132,7 @@ fn add_library_search_dirs( } let fallback = Some(NativeLibSearchFallback { self_contained_components, apple_sdk_root }); - walk_native_lib_search_dirs(sess, fallback, |dir, is_framework| { + let _ = walk_native_lib_search_dirs(sess, fallback, |dir, is_framework| { if is_framework { cmd.framework_path(dir); } else { @@ -2535,10 +2536,11 @@ fn add_order_independent_options( cmd.output_filename(out_filename); - if crate_type == CrateType::Executable && sess.target.is_like_windows { - if let Some(ref s) = codegen_results.crate_info.windows_subsystem { - cmd.subsystem(s); - } + if crate_type == CrateType::Executable + && sess.target.is_like_windows + && let Some(s) = &codegen_results.crate_info.windows_subsystem + { + cmd.subsystem(s); } // Try to strip as much out of the generated object by removing unused diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index a8405a2aec9..e2a59c6efb8 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -111,24 +111,22 @@ pub(crate) fn get_linker<'a>( // PATH for the child. let mut new_path = sess.get_tools_search_paths(self_contained); let mut msvc_changed_path = false; - if sess.target.is_like_msvc { - if let Some(ref tool) = msvc_tool { - cmd.args(tool.args()); - for (k, v) in tool.env() { - if k == "PATH" { - new_path.extend(env::split_paths(v)); - msvc_changed_path = true; - } else { - cmd.env(k, v); - } + if sess.target.is_like_msvc + && let Some(ref tool) = msvc_tool + { + cmd.args(tool.args()); + for (k, v) in tool.env() { + if k == "PATH" { + new_path.extend(env::split_paths(v)); + msvc_changed_path = true; + } else { + cmd.env(k, v); } } } - if !msvc_changed_path { - if let Some(path) = env::var_os("PATH") { - new_path.extend(env::split_paths(&path)); - } + if !msvc_changed_path && let Some(path) = env::var_os("PATH") { + new_path.extend(env::split_paths(&path)); } cmd.env("PATH", env::join_paths(new_path).unwrap()); diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 459f4329d6e..5c9e72ae0f1 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -1,6 +1,6 @@ use std::collections::hash_map::Entry::*; -use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE}; +use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name}; use rustc_data_structures::unord::UnordMap; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId}; @@ -13,6 +13,7 @@ use rustc_middle::query::LocalCrate; use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Instance, SymbolName, Ty, TyCtxt}; use rustc_middle::util::Providers; use rustc_session::config::{CrateType, OomStrategy}; +use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::callconv::Conv; use rustc_target::spec::{SanitizerSet, TlsModel}; use tracing::debug; @@ -219,8 +220,11 @@ fn exported_symbols_provider_local( if allocator_kind_for_codegen(tcx).is_some() { for symbol_name in ALLOCATOR_METHODS .iter() - .map(|method| format!("__rust_{}", method.name)) - .chain(["__rust_alloc_error_handler".to_string(), OomStrategy::SYMBOL.to_string()]) + .map(|method| mangle_internal_symbol(tcx, global_fn_name(method.name).as_str())) + .chain([ + mangle_internal_symbol(tcx, "__rust_alloc_error_handler"), + mangle_internal_symbol(tcx, OomStrategy::SYMBOL), + ]) { let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name)); @@ -234,8 +238,10 @@ fn exported_symbols_provider_local( )); } - let exported_symbol = - ExportedSymbol::NoDefId(SymbolName::new(tcx, NO_ALLOC_SHIM_IS_UNSTABLE)); + let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new( + tcx, + &mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE), + )); symbols.push(( exported_symbol, SymbolExportInfo { diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 9cc737d194c..216a18e72ed 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -546,9 +546,12 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( if let Some(path) = &module.bytecode { files.push((OutputType::Bitcode.extension(), path.as_path())); } - if let Some((id, product)) = - copy_cgu_workproduct_to_incr_comp_cache_dir(sess, &module.name, files.as_slice()) - { + if let Some((id, product)) = copy_cgu_workproduct_to_incr_comp_cache_dir( + sess, + &module.name, + files.as_slice(), + &module.links_from_incr_cache, + ) { work_products.insert(id, product); } } @@ -566,16 +569,13 @@ fn produce_final_output_artifacts( // Produce final compile outputs. let copy_gracefully = |from: &Path, to: &OutFileName| match to { - OutFileName::Stdout => { - if let Err(e) = copy_to_stdout(from) { - sess.dcx().emit_err(errors::CopyPath::new(from, to.as_path(), e)); - } + OutFileName::Stdout if let Err(e) = copy_to_stdout(from) => { + sess.dcx().emit_err(errors::CopyPath::new(from, to.as_path(), e)); } - OutFileName::Real(path) => { - if let Err(e) = fs::copy(from, path) { - sess.dcx().emit_err(errors::CopyPath::new(from, path, e)); - } + OutFileName::Real(path) if let Err(e) = fs::copy(from, path) => { + sess.dcx().emit_err(errors::CopyPath::new(from, path, e)); } + _ => {} }; let copy_if_one_unit = |output_type: OutputType, keep_numbered: bool| { @@ -685,14 +685,12 @@ fn produce_final_output_artifacts( needs_crate_object || (user_wants_objects && sess.codegen_units().as_usize() > 1); for module in compiled_modules.modules.iter() { - if let Some(ref path) = module.object { - if !keep_numbered_objects { + if !keep_numbered_objects { + if let Some(ref path) = module.object { ensure_removed(sess.dcx(), path); } - } - if let Some(ref path) = module.dwarf_object { - if !keep_numbered_objects { + if let Some(ref path) = module.dwarf_object { ensure_removed(sess.dcx(), path); } } @@ -704,12 +702,11 @@ fn produce_final_output_artifacts( } } - if !user_wants_bitcode { - if let Some(ref allocator_module) = compiled_modules.allocator_module { - if let Some(ref path) = allocator_module.bytecode { - ensure_removed(sess.dcx(), path); - } - } + if !user_wants_bitcode + && let Some(ref allocator_module) = compiled_modules.allocator_module + && let Some(ref path) = allocator_module.bytecode + { + ensure_removed(sess.dcx(), path); } } @@ -940,7 +937,9 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>( ) -> WorkItemResult<B> { let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap(); - let load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| { + let mut links_from_incr_cache = Vec::new(); + + let mut 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 preexisting module `{}` from {:?} to {}", @@ -949,7 +948,10 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>( output_path.display() ); match link_or_copy(&source_file, &output_path) { - Ok(_) => Some(output_path), + Ok(_) => { + links_from_incr_cache.push(source_file); + Some(output_path) + } Err(error) => { cgcx.create_dcx().handle().emit_err(errors::CopyPathBuf { source_file, @@ -972,7 +974,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>( load_from_incr_comp_dir(dwarf_obj_out, saved_dwarf_object_file) }); - let load_from_incr_cache = |perform, output_type: OutputType| { + let mut load_from_incr_cache = |perform, output_type: OutputType| { if perform { let saved_file = module.source.saved_files.get(output_type.extension())?; let output_path = cgcx.output_filenames.temp_path(output_type, Some(&module.name)); @@ -992,6 +994,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>( } WorkItemResult::Finished(CompiledModule { + links_from_incr_cache, name: module.name, kind: ModuleKind::Regular, object, diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index e9c886d28ed..a739743be8c 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -28,6 +28,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_session::Session; use rustc_session::config::{self, CrateType, EntryFnType, OutputType}; use rustc_span::{DUMMY_SP, Symbol, sym}; +use rustc_symbol_mangling::mangle_internal_symbol; use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt}; use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt}; use tracing::{debug, info}; @@ -657,6 +658,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>( bytecode: None, assembly: None, llvm_ir: None, + links_from_incr_cache: Vec::new(), } }) }); @@ -989,7 +991,12 @@ impl CrateInfo { .for_each(|(_, linked_symbols)| { let mut symbols = missing_weak_lang_items .iter() - .map(|item| (format!("{prefix}{item}"), SymbolExportKind::Text)) + .map(|item| { + ( + format!("{prefix}{}", mangle_internal_symbol(tcx, item.as_str())), + SymbolExportKind::Text, + ) + }) .collect::<Vec<_>>(); symbols.sort_unstable_by(|a, b| a.0.cmp(&b.0)); linked_symbols.extend(symbols); @@ -1002,7 +1009,13 @@ impl CrateInfo { // errors. linked_symbols.extend(ALLOCATOR_METHODS.iter().map(|method| { ( - format!("{prefix}{}", global_fn_name(method.name).as_str()), + format!( + "{prefix}{}", + mangle_internal_symbol( + tcx, + global_fn_name(method.name).as_str() + ) + ), SymbolExportKind::Text, ) })); diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 998a4ff727e..d16d4ed2283 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -601,25 +601,19 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // strippable by the linker. // // Additionally weak lang items have predetermined symbol names. - if WEAK_LANG_ITEMS.iter().any(|&l| tcx.lang_items().get(l) == Some(did.to_def_id())) { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; - } if let Some((name, _)) = lang_items::extract(attrs) && let Some(lang_item) = LangItem::from_name(name) - && let Some(link_name) = lang_item.link_name() { - codegen_fn_attrs.export_name = Some(link_name); - codegen_fn_attrs.link_name = Some(link_name); + if WEAK_LANG_ITEMS.iter().any(|&l| l == lang_item) { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; + } + if let Some(link_name) = lang_item.link_name() { + codegen_fn_attrs.export_name = Some(link_name); + codegen_fn_attrs.link_name = Some(link_name); + } } check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span); - // Internal symbols to the standard library all have no_mangle semantics in - // that they have defined symbol names present in the function name. This - // also applies to weak symbols where they all have known symbol names. - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE; - } - // Any linkage to LLVM intrinsics for now forcibly marks them all as never // unwinds since LLVM sometimes can't handle codegen which `invoke`s // intrinsic functions. @@ -796,16 +790,10 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> { // check for exactly one autodiff attribute on placeholder functions. // There should only be one, since we generate a new placeholder per ad macro. - // FIXME(ZuseZ4): re-enable this check. Currently we add multiple, which doesn't cause harm but - // looks strange e.g. under cargo-expand. let attr = match &attrs[..] { [] => return None, [attr] => attr, - // These two attributes are the same and unfortunately duplicated due to a previous bug. - [attr, _attr2] => attr, _ => { - //FIXME(ZuseZ4): Once we fixed our parser, we should also prohibit the two-attribute - //branch above. span_bug!(attrs[1].span(), "cg_ssa: rustc_autodiff should only exist once per source"); } }; diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 84703a0a156..18279a4d05f 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -555,11 +555,9 @@ pub fn compute_debuginfo_vtable_name<'tcx>( pub fn push_item_name(tcx: TyCtxt<'_>, def_id: DefId, qualified: bool, output: &mut String) { let def_key = tcx.def_key(def_id); - if qualified { - if let Some(parent) = def_key.parent { - push_item_name(tcx, DefId { krate: def_id.krate, index: parent }, true, output); - output.push_str("::"); - } + if qualified && let Some(parent) = def_key.parent { + push_item_name(tcx, DefId { krate: def_id.krate, index: parent }, true, output); + output.push_str("::"); } push_unqualified_item_name(tcx, def_id, def_key.disambiguated_data, output); diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 394c80fcfbd..0b7cad0c2fd 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -12,10 +12,9 @@ use rustc_errors::{ Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; -use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutError; +use rustc_middle::ty::{FloatTy, Ty}; use rustc_span::{Span, Symbol}; -use rustc_type_ir::FloatTy; use crate::assert_module_sources::CguReuse; use crate::back::command::Command; diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 44b8cc459cf..93c34a2f576 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -122,6 +122,7 @@ impl<M> ModuleCodegen<M> { bytecode, assembly, llvm_ir, + links_from_incr_cache: Vec::new(), } } } @@ -135,6 +136,7 @@ pub struct CompiledModule { pub bytecode: Option<PathBuf>, pub assembly: Option<PathBuf>, // --emit=asm pub llvm_ir: Option<PathBuf>, // --emit=llvm-ir, llvm-bc is in bytecode + pub links_from_incr_cache: Vec<PathBuf>, } impl CompiledModule { diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 6d1930a402d..d184ce3d61d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -163,25 +163,25 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { mergeable_succ: bool, ) -> MergingSucc { let tcx = bx.tcx(); - if let Some(instance) = instance { - if is_call_from_compiler_builtins_to_upstream_monomorphization(tcx, instance) { - if destination.is_some() { - let caller_def = fx.instance.def_id(); - let e = CompilerBuiltinsCannotCall { - span: tcx.def_span(caller_def), - caller: with_no_trimmed_paths!(tcx.def_path_str(caller_def)), - callee: with_no_trimmed_paths!(tcx.def_path_str(instance.def_id())), - }; - tcx.dcx().emit_err(e); - } else { - info!( - "compiler_builtins call to diverging function {:?} replaced with abort", - instance.def_id() - ); - bx.abort(); - bx.unreachable(); - return MergingSucc::False; - } + if let Some(instance) = instance + && is_call_from_compiler_builtins_to_upstream_monomorphization(tcx, instance) + { + if destination.is_some() { + let caller_def = fx.instance.def_id(); + let e = CompilerBuiltinsCannotCall { + span: tcx.def_span(caller_def), + caller: with_no_trimmed_paths!(tcx.def_path_str(caller_def)), + callee: with_no_trimmed_paths!(tcx.def_path_str(instance.def_id())), + }; + tcx.dcx().emit_err(e); + } else { + info!( + "compiler_builtins call to diverging function {:?} replaced with abort", + instance.def_id() + ); + bx.abort(); + bx.unreachable(); + return MergingSucc::False; } } diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index eafc551501c..68a56044a07 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -43,7 +43,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Const::Ty(_, c) => match c.kind() { // A constant that came from a const generic but was then used as an argument to // old-style simd_shuffle (passing as argument instead of as a generic param). - rustc_type_ir::ConstKind::Value(cv) => return Ok(Ok(cv.valtree)), + ty::ConstKind::Value(cv) => return Ok(Ok(cv.valtree)), other => span_bug!(constant.span, "{other:#?}"), }, // We should never encounter `Const::Val` unless MIR opts (like const prop) evaluate diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 96be44ee09f..0fe6a174735 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -747,7 +747,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let tcx = self.cx.tcx(); OperandRef { val: OperandValue::Immediate(val), - layout: self.cx.layout_of(tcx.types.usize), + layout: self.cx.layout_of(null_op.ty(tcx)), } } @@ -837,15 +837,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn evaluate_array_len(&mut self, bx: &mut Bx, place: mir::Place<'tcx>) -> Bx::Value { // ZST are passed as operands and require special handling // because codegen_place() panics if Local is operand. - if let Some(index) = place.as_local() { - if let LocalRef::Operand(op) = self.locals[index] { - if let ty::Array(_, n) = op.layout.ty.kind() { - let n = n - .try_to_target_usize(bx.tcx()) - .expect("expected monomorphic const in codegen"); - return bx.cx().const_usize(n); - } - } + if let Some(index) = place.as_local() + && let LocalRef::Operand(op) = self.locals[index] + && let ty::Array(_, n) = op.layout.ty.kind() + { + let n = n.try_to_target_usize(bx.tcx()).expect("expected monomorphic const in codegen"); + return bx.cx().const_usize(n); } // use common size calculation for non zero-sized types let cg_value = self.codegen_place(bx, place.as_ref()); diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml index a0cc2c65e6e..02be8762d6f 100644 --- a/compiler/rustc_const_eval/Cargo.toml +++ b/compiler/rustc_const_eval/Cargo.toml @@ -23,6 +23,5 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } -rustc_type_ir = { path = "../rustc_type_ir" } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index ccf9b240d40..dd481e04abb 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -93,7 +93,7 @@ const_eval_expected_inbounds_pointer = } const_eval_extern_static = - cannot access extern static ({$did}) + cannot access extern static `{$did}` const_eval_extern_type_field = `extern type` field does not have a known offset const_eval_fn_ptr_call = @@ -381,7 +381,7 @@ const_eval_thread_local_access = thread-local statics cannot be accessed at compile-time const_eval_thread_local_static = - cannot access thread local static ({$did}) + cannot access thread local static `{$did}` const_eval_too_generic = encountered overly generic constant const_eval_too_many_caller_args = diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 4db862afd9f..496f6c86f71 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -22,7 +22,7 @@ use crate::errors::{LongRunning, LongRunningWarn}; use crate::fluent_generated as fluent; use crate::interpret::{ self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, - GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, RangeSet, Scalar, + GlobalAlloc, ImmTy, InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, RangeSet, Scalar, compile_time_machine, interp_ok, throw_exhaust, throw_inval, throw_ub, throw_ub_custom, throw_unsup, throw_unsup_format, }; @@ -688,6 +688,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { _tcx: TyCtxtAt<'tcx>, _machine: &mut Self, _alloc_extra: &mut Self::AllocExtra, + _ptr: Pointer<Option<Self::Provenance>>, (_alloc_id, immutable): (AllocId, bool), range: AllocRange, ) -> InterpResult<'tcx> { diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index b020eeccf71..e2675e2f4c9 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -898,6 +898,7 @@ impl ReportErrorExt for UnsupportedOpInfo { UnsupportedOpInfo::ExternStatic(_) => const_eval_extern_static, } } + fn add_args<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) { use UnsupportedOpInfo::*; @@ -917,9 +918,9 @@ impl ReportErrorExt for UnsupportedOpInfo { OverwritePartialPointer(ptr) | ReadPartialPointer(ptr) => { diag.arg("ptr", ptr); } - ThreadLocalStatic(did) | ExternStatic(did) => { - diag.arg("did", format!("{did:?}")); - } + ThreadLocalStatic(did) | ExternStatic(did) => rustc_middle::ty::tls::with(|tcx| { + diag.arg("did", tcx.def_path_str(did)); + }), } } } diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 7b706334ed8..643a5805019 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -9,7 +9,6 @@ use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::layout::{IntegerExt, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, FloatTy, Ty}; use rustc_middle::{bug, span_bug}; -use rustc_type_ir::TyKind::*; use tracing::trace; use super::util::ensure_monomorphic_enough; @@ -182,9 +181,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { src: &ImmTy<'tcx, M::Provenance>, cast_to: TyAndLayout<'tcx>, ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> { - use rustc_type_ir::TyKind::*; - - let Float(fty) = src.layout.ty.kind() else { + let ty::Float(fty) = src.layout.ty.kind() else { bug!("FloatToFloat/FloatToInt cast: source type {} is not a float type", src.layout.ty) }; let val = match fty { @@ -277,19 +274,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let signed = src_layout.backend_repr.is_signed(); // Also asserts that abi is `Scalar`. let v = match src_layout.ty.kind() { - Uint(_) | RawPtr(..) | FnPtr(..) => scalar.to_uint(src_layout.size)?, - Int(_) => scalar.to_int(src_layout.size)? as u128, // we will cast back to `i128` below if the sign matters - Bool => scalar.to_bool()?.into(), - Char => scalar.to_char()?.into(), + ty::Uint(_) | ty::RawPtr(..) | ty::FnPtr(..) => scalar.to_uint(src_layout.size)?, + ty::Int(_) => scalar.to_int(src_layout.size)? as u128, // we will cast back to `i128` below if the sign matters + ty::Bool => scalar.to_bool()?.into(), + ty::Char => scalar.to_char()?.into(), _ => span_bug!(self.cur_span(), "invalid int-like cast from {}", src_layout.ty), }; interp_ok(match *cast_ty.kind() { // int -> int - Int(_) | Uint(_) => { + ty::Int(_) | ty::Uint(_) => { let size = match *cast_ty.kind() { - Int(t) => Integer::from_int_ty(self, t).size(), - Uint(t) => Integer::from_uint_ty(self, t).size(), + ty::Int(t) => Integer::from_int_ty(self, t).size(), + ty::Uint(t) => Integer::from_uint_ty(self, t).size(), _ => bug!(), }; let v = size.truncate(v); @@ -297,7 +294,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } // signed int -> float - Float(fty) if signed => { + ty::Float(fty) if signed => { let v = v as i128; match fty { FloatTy::F16 => Scalar::from_f16(Half::from_i128(v).value), @@ -307,7 +304,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } } // unsigned int -> float - Float(fty) => match fty { + ty::Float(fty) => match fty { FloatTy::F16 => Scalar::from_f16(Half::from_u128(v).value), FloatTy::F32 => Scalar::from_f32(Single::from_u128(v).value), FloatTy::F64 => Scalar::from_f64(Double::from_u128(v).value), @@ -315,7 +312,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }, // u8 -> char - Char => Scalar::from_u32(u8::try_from(v).unwrap().into()), + ty::Char => Scalar::from_u32(u8::try_from(v).unwrap().into()), // Casts to bool are not permitted by rustc, no need to handle them here. _ => span_bug!(self.cur_span(), "invalid int to {} cast", cast_ty), @@ -332,11 +329,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { + FloatConvert<Double> + FloatConvert<Quad>, { - use rustc_type_ir::TyKind::*; - match *dest_ty.kind() { // float -> uint - Uint(t) => { + ty::Uint(t) => { let size = Integer::from_uint_ty(self, t).size(); // `to_u128` is a saturating cast, which is what we need // (https://doc.rust-lang.org/nightly/nightly-rustc/rustc_apfloat/trait.Float.html#method.to_i128_r). @@ -345,7 +340,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Scalar::from_uint(v, size) } // float -> int - Int(t) => { + ty::Int(t) => { let size = Integer::from_int_ty(self, t).size(); // `to_i128` is a saturating cast, which is what we need // (https://doc.rust-lang.org/nightly/nightly-rustc/rustc_apfloat/trait.Float.html#method.to_i128_r). @@ -353,7 +348,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Scalar::from_int(v, size) } // float -> float - Float(fty) => match fty { + ty::Float(fty) => match fty { FloatTy::F16 => { Scalar::from_f16(self.adjust_nan(f.convert(&mut false).value, &[f])) } diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index a21bf018d01..e5026eff21f 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -400,6 +400,8 @@ pub trait Machine<'tcx>: Sized { ) -> InterpResult<'tcx, Self::AllocExtra>; /// Hook for performing extra checks on a memory read access. + /// `ptr` will always be a pointer with the provenance in `prov` pointing to the beginning of + /// `range`. /// /// This will *not* be called during validation! /// @@ -413,6 +415,7 @@ pub trait Machine<'tcx>: Sized { _tcx: TyCtxtAt<'tcx>, _machine: &Self, _alloc_extra: &Self::AllocExtra, + _ptr: Pointer<Option<Self::Provenance>>, _prov: (AllocId, Self::ProvenanceExtra), _range: AllocRange, ) -> InterpResult<'tcx> { @@ -432,11 +435,14 @@ pub trait Machine<'tcx>: Sized { /// Hook for performing extra checks on a memory write access. /// This is not invoked for ZST accesses, as no write actually happens. + /// `ptr` will always be a pointer with the provenance in `prov` pointing to the beginning of + /// `range`. #[inline(always)] fn before_memory_write( _tcx: TyCtxtAt<'tcx>, _machine: &mut Self, _alloc_extra: &mut Self::AllocExtra, + _ptr: Pointer<Option<Self::Provenance>>, _prov: (AllocId, Self::ProvenanceExtra), _range: AllocRange, ) -> InterpResult<'tcx> { @@ -444,11 +450,14 @@ pub trait Machine<'tcx>: Sized { } /// Hook for performing extra operations on a memory deallocation. + /// `ptr` will always be a pointer with the provenance in `prov` pointing to the beginning of + /// the allocation. #[inline(always)] fn before_memory_deallocation( _tcx: TyCtxtAt<'tcx>, _machine: &mut Self, _alloc_extra: &mut Self::AllocExtra, + _ptr: Pointer<Option<Self::Provenance>>, _prov: (AllocId, Self::ProvenanceExtra), _size: Size, _align: Align, diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 75726269a86..8f286971e63 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -385,6 +385,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.tcx, &mut self.machine, &mut alloc.extra, + ptr, (alloc_id, prov), size, alloc.align, @@ -727,6 +728,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.tcx, &self.machine, &alloc.extra, + ptr, (alloc_id, prov), range, )?; @@ -816,7 +818,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if let Some((alloc_id, offset, prov, alloc, machine)) = ptr_and_alloc { let range = alloc_range(offset, size); if !validation_in_progress { - M::before_memory_write(tcx, machine, &mut alloc.extra, (alloc_id, prov), range)?; + M::before_memory_write( + tcx, + machine, + &mut alloc.extra, + ptr, + (alloc_id, prov), + range, + )?; } interp_ok(Some(AllocRefMut { alloc, range, tcx: *tcx, alloc_id })) } else { @@ -1373,6 +1382,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { tcx, &self.machine, &src_alloc.extra, + src, (src_alloc_id, src_prov), src_range, )?; @@ -1403,6 +1413,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { tcx, extra, &mut dest_alloc.extra, + dest, (dest_alloc_id, dest_prov), dest_range, )?; diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index b9a5fc3a1fe..fcaf2750507 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -12,7 +12,7 @@ elsa = "1.11.0" ena = "0.14.3" indexmap = "2.4.0" jobserver_crate = { version = "0.1.28", package = "jobserver" } -measureme = "11" +measureme = "12.0.1" rustc-hash = "2.0.0" rustc-rayon = { version = "0.5.1", features = ["indexmap"] } rustc-stable-hash = { version = "0.1.0", features = ["nightly"] } diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs index a01a420dfbd..c002d47815b 100644 --- a/compiler/rustc_data_structures/src/sorted_map.rs +++ b/compiler/rustc_data_structures/src/sorted_map.rs @@ -4,7 +4,7 @@ use std::fmt::Debug; use std::mem; use std::ops::{Bound, Index, IndexMut, RangeBounds}; -use rustc_macros::{Decodable_Generic, Encodable_Generic}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext}; use crate::stable_hasher::{HashStable, StableHasher, StableOrd}; @@ -20,7 +20,7 @@ pub use index_map::SortedIndexMultiMap; /// stores data in a more compact way. It also supports accessing contiguous /// ranges of elements as a slice, and slices of already sorted elements can be /// inserted efficiently. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable_Generic, Decodable_Generic)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable_NoContext, Decodable_NoContext)] pub struct SortedMap<K, V> { data: Vec<(K, V)>, } diff --git a/compiler/rustc_data_structures/src/svh.rs b/compiler/rustc_data_structures/src/svh.rs index 391a7c9f30d..f51fcb8ed22 100644 --- a/compiler/rustc_data_structures/src/svh.rs +++ b/compiler/rustc_data_structures/src/svh.rs @@ -7,12 +7,12 @@ use std::fmt; -use rustc_macros::{Decodable_Generic, Encodable_Generic}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext}; use crate::fingerprint::Fingerprint; use crate::stable_hasher; -#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable_Generic, Decodable_Generic, Hash)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable_NoContext, Decodable_NoContext, Hash)] pub struct Svh { hash: Fingerprint, } diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs index 34895d3efe6..baa66cd7c85 100644 --- a/compiler/rustc_data_structures/src/unord.rs +++ b/compiler/rustc_data_structures/src/unord.rs @@ -9,7 +9,7 @@ use std::iter::{Product, Sum}; use std::ops::Index; use rustc_hash::{FxHashMap, FxHashSet}; -use rustc_macros::{Decodable_Generic, Encodable_Generic}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext}; use crate::fingerprint::Fingerprint; use crate::stable_hasher::{HashStable, StableCompare, StableHasher, ToStableHashKey}; @@ -224,7 +224,7 @@ trait UnordCollection {} /// /// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533) /// for more information. -#[derive(Debug, Eq, PartialEq, Clone, Encodable_Generic, Decodable_Generic)] +#[derive(Debug, Eq, PartialEq, Clone, Encodable_NoContext, Decodable_NoContext)] pub struct UnordSet<V: Eq + Hash> { inner: FxHashSet<V>, } @@ -259,6 +259,12 @@ impl<V: Eq + Hash> UnordSet<V> { self.inner.is_empty() } + /// If the set has only one element, returns it, otherwise returns `None`. + #[inline] + pub fn get_only(&self) -> Option<&V> { + if self.inner.len() == 1 { self.inner.iter().next() } else { None } + } + #[inline] pub fn insert(&mut self, v: V) -> bool { self.inner.insert(v) @@ -415,7 +421,7 @@ impl<HCX, V: Hash + Eq + HashStable<HCX>> HashStable<HCX> for UnordSet<V> { /// /// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533) /// for more information. -#[derive(Debug, Eq, PartialEq, Clone, Encodable_Generic, Decodable_Generic)] +#[derive(Debug, Eq, PartialEq, Clone, Encodable_NoContext, Decodable_NoContext)] pub struct UnordMap<K: Eq + Hash, V> { inner: FxHashMap<K, V>, } @@ -639,7 +645,7 @@ impl<HCX, K: Hash + Eq + HashStable<HCX>, V: HashStable<HCX>> HashStable<HCX> fo /// /// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533) /// for more information. -#[derive(Default, Debug, Eq, PartialEq, Clone, Encodable_Generic, Decodable_Generic)] +#[derive(Default, Debug, Eq, PartialEq, Clone, Encodable_NoContext, Decodable_NoContext)] pub struct UnordBag<V> { inner: Vec<V>, } diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 8593d1faba2..de643355f5f 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -54,7 +54,7 @@ time = { version = "0.3.36", default-features = false, features = ["alloc", "for tracing = { version = "0.1.35" } # tidy-alphabetical-end -[target.'cfg(unix)'.dependencies] +[target.'cfg(all(unix, any(target_env = "gnu", target_os = "macos")))'.dependencies] # tidy-alphabetical-start libc = "0.2" # tidy-alphabetical-end diff --git a/compiler/rustc_driver_impl/messages.ftl b/compiler/rustc_driver_impl/messages.ftl index 05e11c4527f..2c6a0291ac2 100644 --- a/compiler/rustc_driver_impl/messages.ftl +++ b/compiler/rustc_driver_impl/messages.ftl @@ -1,3 +1,5 @@ +driver_impl_cant_emit_mir = could not emit MIR: {$error} + driver_impl_ice = the compiler unexpectedly panicked. this is a bug. driver_impl_ice_bug_report = we would appreciate a bug report: {$bug_report_url} driver_impl_ice_bug_report_internal_feature = using internal features is not supported and expected to cause internal compiler errors when used incorrectly diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index ed5662da16d..4ba076c64e1 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -44,6 +44,10 @@ use rustc_errors::emitter::stderr_destination; use rustc_errors::registry::Registry; use rustc_errors::{ColorConfig, DiagCtxt, ErrCode, FatalError, PResult, markdown}; use rustc_feature::find_gated_cfg; +// This avoids a false positive with `-Wunused_crate_dependencies`. +// `rust_index` isn't used in this crate's code, but it must be named in the +// `Cargo.toml` for the `rustc_randomized_layouts` feature. +use rustc_index as _; use rustc_interface::util::{self, get_codegen_backend}; use rustc_interface::{Linker, create_and_enter_global_ctxt, interface, passes}; use rustc_lint::unerased_lint_store; @@ -89,6 +93,10 @@ pub mod pretty; #[macro_use] mod print; mod session_diagnostics; + +// Keep the OS parts of this `cfg` in sync with the `cfg` on the `libc` +// dependency in `compiler/rustc_driver/Cargo.toml`, to keep +// `-Wunused-crated-dependencies` satisfied. #[cfg(all(not(miri), unix, any(target_env = "gnu", target_os = "macos")))] mod signal_handler; @@ -100,7 +108,7 @@ mod signal_handler { } use crate::session_diagnostics::{ - RLinkEmptyVersionNumber, RLinkEncodingVersionMismatch, RLinkRustcVersionMismatch, + CantEmitMIR, RLinkEmptyVersionNumber, RLinkEncodingVersionMismatch, RLinkRustcVersionMismatch, RLinkWrongFileType, RlinkCorruptFile, RlinkNotAFile, RlinkUnableToRead, UnstableFeatureUsage, }; @@ -235,12 +243,17 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) return; } + let input = make_input(&default_early_dcx, &matches.free); + let has_input = input.is_some(); let (odir, ofile) = make_output(&matches); + + drop(default_early_dcx); + let mut config = interface::Config { opts: sopts, crate_cfg: matches.opt_strs("cfg"), crate_check_cfg: matches.opt_strs("check-cfg"), - input: Input::File(PathBuf::new()), + input: input.unwrap_or(Input::File(PathBuf::new())), output_file: ofile, output_dir: odir, ice_file, @@ -257,16 +270,6 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) expanded_args: args, }; - let has_input = match make_input(&default_early_dcx, &matches.free) { - Some(input) => { - config.input = input; - true // has input: normal compilation - } - None => false, // no input: we will exit early - }; - - drop(default_early_dcx); - callbacks.config(&mut config); let registered_lints = config.register_lints.is_some(); @@ -371,6 +374,12 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) return early_exit(); } + if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) { + if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx) { + tcx.dcx().emit_fatal(CantEmitMIR { error }); + } + } + Some(Linker::codegen_and_build_linker(tcx, &*compiler.codegen_backend)) }); @@ -399,7 +408,7 @@ fn dump_feature_usage_metrics(tcxt: TyCtxt<'_>, metrics_dir: &Path) { } } -// Extract output directory and file from matches. +/// Extract output directory and file from matches. fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<OutFileName>) { let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o)); let ofile = matches.opt_str("o").map(|o| match o.as_str() { @@ -457,8 +466,7 @@ pub enum Compilation { fn handle_explain(early_dcx: &EarlyDiagCtxt, registry: Registry, code: &str, color: ColorConfig) { // Allow "E0123" or "0123" form. let upper_cased_code = code.to_ascii_uppercase(); - let start = if upper_cased_code.starts_with('E') { 1 } else { 0 }; - if let Ok(code) = upper_cased_code[start..].parse::<u32>() + if let Ok(code) = upper_cased_code.strip_prefix('E').unwrap_or(&upper_cased_code).parse::<u32>() && let Ok(description) = registry.try_find_description(ErrCode::from_u32(code)) { let mut is_in_code_block = false; @@ -649,10 +657,10 @@ fn print_crate_info( HostTuple => println_info!("{}", rustc_session::config::host_tuple()), Sysroot => println_info!("{}", sess.sysroot.display()), TargetLibdir => println_info!("{}", sess.target_tlib_path.dir.display()), - TargetSpec => { + TargetSpecJson => { println_info!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap()); } - AllTargetSpecs => { + AllTargetSpecsJson => { let mut targets = BTreeMap::new(); for name in rustc_target::spec::TARGETS { let triple = TargetTuple::from_tuple(name); diff --git a/compiler/rustc_driver_impl/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/session_diagnostics.rs index e06c56539d1..774221fd396 100644 --- a/compiler/rustc_driver_impl/src/session_diagnostics.rs +++ b/compiler/rustc_driver_impl/src/session_diagnostics.rs @@ -3,6 +3,12 @@ use std::error::Error; use rustc_macros::{Diagnostic, Subdiagnostic}; #[derive(Diagnostic)] +#[diag(driver_impl_cant_emit_mir)] +pub struct CantEmitMIR { + pub error: std::io::Error, +} + +#[derive(Diagnostic)] #[diag(driver_impl_rlink_unable_to_read)] pub(crate) struct RlinkUnableToRead { pub err: std::io::Error, diff --git a/compiler/rustc_error_codes/src/error_codes/E0092.md b/compiler/rustc_error_codes/src/error_codes/E0092.md index 84ec0656d1a..be459d040c2 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0092.md +++ b/compiler/rustc_error_codes/src/error_codes/E0092.md @@ -6,10 +6,9 @@ Erroneous code example: #![feature(intrinsics)] #![allow(internal_features)] -extern "rust-intrinsic" { - fn atomic_foo(); // error: unrecognized atomic operation - // function -} +#[rustc_intrinsic] +unsafe fn atomic_foo(); // error: unrecognized atomic operation + // function ``` Please check you didn't make a mistake in the function's name. All intrinsic @@ -20,7 +19,6 @@ functions are defined in `compiler/rustc_codegen_llvm/src/intrinsic.rs` and in #![feature(intrinsics)] #![allow(internal_features)] -extern "rust-intrinsic" { - fn atomic_fence_seqcst(); // ok! -} +#[rustc_intrinsic] +unsafe fn atomic_fence_seqcst(); // ok! ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0093.md b/compiler/rustc_error_codes/src/error_codes/E0093.md index 2bda4d74f72..9929a069927 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0093.md +++ b/compiler/rustc_error_codes/src/error_codes/E0093.md @@ -6,9 +6,8 @@ Erroneous code example: #![feature(intrinsics)] #![allow(internal_features)] -extern "rust-intrinsic" { - fn foo(); // error: unrecognized intrinsic function: `foo` -} +#[rustc_intrinsic] +unsafe fn foo(); // error: unrecognized intrinsic function: `foo` fn main() { unsafe { @@ -25,9 +24,8 @@ functions are defined in `compiler/rustc_codegen_llvm/src/intrinsic.rs` and in #![feature(intrinsics)] #![allow(internal_features)] -extern "rust-intrinsic" { - fn atomic_fence_seqcst(); // ok! -} +#[rustc_intrinsic] +unsafe fn atomic_fence_seqcst(); // ok! fn main() { unsafe { diff --git a/compiler/rustc_error_codes/src/error_codes/E0211.md b/compiler/rustc_error_codes/src/error_codes/E0211.md index 7aa42628549..c702f14d4d6 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0211.md +++ b/compiler/rustc_error_codes/src/error_codes/E0211.md @@ -7,9 +7,8 @@ used. Erroneous code examples: #![feature(intrinsics)] #![allow(internal_features)] -extern "rust-intrinsic" { - fn unreachable(); // error: intrinsic has wrong type -} +#[rustc_intrinsic] +unsafe fn unreachable(); // error: intrinsic has wrong type // or: @@ -43,9 +42,8 @@ For the first code example, please check the function definition. Example: #![feature(intrinsics)] #![allow(internal_features)] -extern "rust-intrinsic" { - fn unreachable() -> !; // ok! -} +#[rustc_intrinsic] +unsafe fn unreachable() -> !; // ok! ``` The second case example is a bit particular: the main function must always diff --git a/compiler/rustc_error_codes/src/error_codes/E0511.md b/compiler/rustc_error_codes/src/error_codes/E0511.md index 45ff49bdebb..0fb1cfda67d 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0511.md +++ b/compiler/rustc_error_codes/src/error_codes/E0511.md @@ -5,9 +5,8 @@ Erroneous code example: ```compile_fail,E0511 #![feature(intrinsics)] -extern "rust-intrinsic" { - fn simd_add<T>(a: T, b: T) -> T; -} +#[rustc_intrinsic] +unsafe fn simd_add<T>(a: T, b: T) -> T; fn main() { unsafe { simd_add(0, 1); } @@ -25,9 +24,8 @@ The generic type has to be a SIMD type. Example: #[derive(Copy, Clone)] struct i32x2([i32; 2]); -extern "rust-intrinsic" { - fn simd_add<T>(a: T, b: T) -> T; -} +#[rustc_intrinsic] +unsafe fn simd_add<T>(a: T, b: T) -> T; unsafe { simd_add(i32x2([0, 0]), i32x2([1, 2])); } // ok! ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0515.md b/compiler/rustc_error_codes/src/error_codes/E0515.md index 0f4fbf67223..87bbe4aea70 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0515.md +++ b/compiler/rustc_error_codes/src/error_codes/E0515.md @@ -17,10 +17,13 @@ fn get_dangling_iterator<'a>() -> Iter<'a, i32> { } ``` -Local variables, function parameters and temporaries are all dropped before the -end of the function body. So a reference to them cannot be returned. +Local variables, function parameters and temporaries are all dropped before +the end of the function body. A returned reference (or struct containing a +reference) to such a dropped value would immediately be invalid. Therefore +it is not allowed to return such a reference. -Consider returning an owned value instead: +Consider returning a value that takes ownership of local data instead of +referencing it: ``` use std::vec::IntoIter; diff --git a/compiler/rustc_error_codes/src/error_codes/E0773.md b/compiler/rustc_error_codes/src/error_codes/E0773.md index aa65a475a4f..5ebb43c6683 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0773.md +++ b/compiler/rustc_error_codes/src/error_codes/E0773.md @@ -1,40 +1,4 @@ -A builtin-macro was defined more than once. +#### this error code is no longer emitted by the compiler. -Erroneous code example: - -```compile_fail,E0773 -#![feature(decl_macro)] -#![feature(rustc_attrs)] -#![allow(internal_features)] - -#[rustc_builtin_macro] -pub macro test($item:item) { - /* compiler built-in */ -} - -mod inner { - #[rustc_builtin_macro] - pub macro test($item:item) { - /* compiler built-in */ - } -} -``` - -To fix the issue, remove the duplicate declaration: - -``` -#![feature(decl_macro)] -#![feature(rustc_attrs)] -#![allow(internal_features)] - -#[rustc_builtin_macro] -pub macro test($item:item) { - /* compiler built-in */ -} -``` - -In very rare edge cases, this may happen when loading `core` or `std` twice, -once with `check` metadata and once with `build` metadata. -For more information, see [#75176]. - -[#75176]: https://github.com/rust-lang/rust/pull/75176#issuecomment-683234468 +This was triggered when multiple macro definitions used the same +`#[rustc_builtin_macro(..)]`. This is no longer an error. diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 21255fcca96..fe01e289334 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -297,7 +297,9 @@ pub trait Emitter: Translate { // are some which do actually involve macros. ExpnKind::Desugaring(..) | ExpnKind::AstPass(..) => None, - ExpnKind::Macro(macro_kind, name) => Some((macro_kind, name)), + ExpnKind::Macro(macro_kind, name) => { + Some((macro_kind, name, expn_data.hide_backtrace)) + } } }) .collect(); @@ -309,13 +311,17 @@ pub trait Emitter: Translate { self.render_multispans_macro_backtrace(span, children, backtrace); if !backtrace { - if let Some((macro_kind, name)) = has_macro_spans.first() { + // Skip builtin macros, as their expansion isn't relevant to the end user. This includes + // actual intrinsics, like `asm!`. + if let Some((macro_kind, name, _)) = has_macro_spans.first() + && let Some((_, _, false)) = has_macro_spans.last() + { // Mark the actual macro this originates from - let and_then = if let Some((macro_kind, last_name)) = has_macro_spans.last() + let and_then = if let Some((macro_kind, last_name, _)) = has_macro_spans.last() && last_name != name { let descr = macro_kind.descr(); - format!(" which comes from the expansion of the {descr} `{last_name}`",) + format!(" which comes from the expansion of the {descr} `{last_name}`") } else { "".to_string() }; diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 895efe05e11..1dd152beb47 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -681,17 +681,18 @@ impl MacResult for DummyResult { } /// A syntax extension kind. +#[derive(Clone)] pub enum SyntaxExtensionKind { /// A token-based function-like macro. Bang( /// An expander with signature TokenStream -> TokenStream. - Box<dyn BangProcMacro + sync::DynSync + sync::DynSend>, + Arc<dyn BangProcMacro + sync::DynSync + sync::DynSend>, ), /// An AST-based function-like macro. LegacyBang( /// An expander with signature TokenStream -> AST. - Box<dyn TTMacroExpander + sync::DynSync + sync::DynSend>, + Arc<dyn TTMacroExpander + sync::DynSync + sync::DynSend>, ), /// A token-based attribute macro. @@ -699,7 +700,7 @@ pub enum SyntaxExtensionKind { /// An expander with signature (TokenStream, TokenStream) -> TokenStream. /// The first TokenStream is the attribute itself, the second is the annotated item. /// The produced TokenStream replaces the input TokenStream. - Box<dyn AttrProcMacro + sync::DynSync + sync::DynSend>, + Arc<dyn AttrProcMacro + sync::DynSync + sync::DynSend>, ), /// An AST-based attribute macro. @@ -707,7 +708,7 @@ pub enum SyntaxExtensionKind { /// An expander with signature (AST, AST) -> AST. /// The first AST fragment is the attribute itself, the second is the annotated item. /// The produced AST fragment replaces the input AST fragment. - Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>, + Arc<dyn MultiItemModifier + sync::DynSync + sync::DynSend>, ), /// A trivial attribute "macro" that does nothing, @@ -724,18 +725,18 @@ pub enum SyntaxExtensionKind { /// is handled identically to `LegacyDerive`. It should be migrated to /// a token-based representation like `Bang` and `Attr`, instead of /// using `MultiItemModifier`. - Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>, + Arc<dyn MultiItemModifier + sync::DynSync + sync::DynSend>, ), /// An AST-based derive macro. LegacyDerive( /// An expander with signature AST -> AST. /// The produced AST fragment is appended to the input AST fragment. - Box<dyn MultiItemModifier + sync::DynSync + sync::DynSend>, + Arc<dyn MultiItemModifier + sync::DynSync + sync::DynSend>, ), /// A glob delegation. - GlobDelegation(Box<dyn GlobDelegationExpander + sync::DynSync + sync::DynSend>), + GlobDelegation(Arc<dyn GlobDelegationExpander + sync::DynSync + sync::DynSend>), } /// A struct representing a macro definition in "lowered" form ready for expansion. @@ -889,16 +890,16 @@ impl SyntaxExtension { }) .unwrap_or_else(|| (None, helper_attrs)); - let stability = find_attr!(attrs, AttributeKind::Stability{stability, ..} => *stability); + let stability = find_attr!(attrs, AttributeKind::Stability { stability, .. } => *stability); // FIXME(jdonszelmann): make it impossible to miss the or_else in the typesystem - if let Some(sp) = find_attr!(attrs, AttributeKind::ConstStability{span, ..} => *span) { + if let Some(sp) = find_attr!(attrs, AttributeKind::ConstStability { span, .. } => *span) { sess.dcx().emit_err(errors::MacroConstStability { span: sp, head_span: sess.source_map().guess_head_span(span), }); } - if let Some(sp) = find_attr!(attrs, AttributeKind::BodyStability{span, ..} => *span) { + if let Some(sp) = find_attr!(attrs, AttributeKind::BodyStability{ span, .. } => *span) { sess.dcx().emit_err(errors::MacroBodyStability { span: sp, head_span: sess.source_map().guess_head_span(span), @@ -912,7 +913,10 @@ impl SyntaxExtension { // FIXME(jdonszelmann): avoid the into_iter/collect? .then(|| allow_internal_unstable.iter().map(|i| i.0).collect::<Vec<_>>().into()), stability, - deprecation: find_attr!(attrs, AttributeKind::Deprecation{deprecation, ..} => *deprecation), + deprecation: find_attr!( + attrs, + AttributeKind::Deprecation { deprecation, .. } => *deprecation + ), helper_attrs, edition, builtin_name, @@ -934,7 +938,7 @@ impl SyntaxExtension { cx.dcx().span_delayed_bug(span, "expanded a dummy bang macro"), )) } - SyntaxExtension::default(SyntaxExtensionKind::LegacyBang(Box::new(expander)), edition) + SyntaxExtension::default(SyntaxExtensionKind::LegacyBang(Arc::new(expander)), edition) } /// A dummy derive macro `#[derive(Foo)]`. @@ -947,7 +951,7 @@ impl SyntaxExtension { ) -> Vec<Annotatable> { Vec::new() } - SyntaxExtension::default(SyntaxExtensionKind::Derive(Box::new(expander)), edition) + SyntaxExtension::default(SyntaxExtensionKind::Derive(Arc::new(expander)), edition) } pub fn non_macro_attr(edition: Edition) -> SyntaxExtension { @@ -977,7 +981,7 @@ impl SyntaxExtension { } let expander = GlobDelegationExpanderImpl { trait_def_id, impl_def_id }; - SyntaxExtension::default(SyntaxExtensionKind::GlobDelegation(Box::new(expander)), edition) + SyntaxExtension::default(SyntaxExtensionKind::GlobDelegation(Arc::new(expander)), edition) } pub fn expn_data( @@ -1000,6 +1004,7 @@ impl SyntaxExtension { self.allow_internal_unsafe, self.local_inner_macros, self.collapse_debuginfo, + self.builtin_name.is_some(), ) } } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 5570c0c38e8..ada49eef7b2 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -1,12 +1,15 @@ //! Conditional compilation stripping. +use std::iter; + use rustc_ast::ptr::P; use rustc_ast::token::{Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::{ AttrTokenStream, AttrTokenTree, LazyAttrTokenStream, Spacing, TokenTree, }; use rustc_ast::{ - self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, MetaItemInner, NodeId, + self as ast, AttrKind, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem, MetaItemInner, + NodeId, NormalAttr, }; use rustc_attr_parsing as attr; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; @@ -275,10 +278,23 @@ impl<'a> StripUnconfigured<'a> { pub(crate) fn expand_cfg_attr(&self, cfg_attr: &Attribute, recursive: bool) -> Vec<Attribute> { validate_attr::check_attribute_safety(&self.sess.psess, AttributeSafety::Normal, &cfg_attr); + // A trace attribute left in AST in place of the original `cfg_attr` attribute. + // It can later be used by lints or other diagnostics. + let mut trace_attr = cfg_attr.clone(); + match &mut trace_attr.kind { + AttrKind::Normal(normal) => { + let NormalAttr { item, tokens } = &mut **normal; + item.path.segments[0].ident.name = sym::cfg_attr_trace; + // This makes the trace attributes unobservable to token-based proc macros. + *tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::default())); + } + AttrKind::DocComment(..) => unreachable!(), + } + let Some((cfg_predicate, expanded_attrs)) = rustc_parse::parse_cfg_attr(cfg_attr, &self.sess.psess) else { - return vec![]; + return vec![trace_attr]; }; // Lint on zero attributes in source. @@ -292,22 +308,21 @@ impl<'a> StripUnconfigured<'a> { } if !attr::cfg_matches(&cfg_predicate, &self.sess, self.lint_node_id, self.features) { - return vec![]; + return vec![trace_attr]; } if recursive { // We call `process_cfg_attr` recursively in case there's a // `cfg_attr` inside of another `cfg_attr`. E.g. // `#[cfg_attr(false, cfg_attr(true, some_attr))]`. - expanded_attrs + let expanded_attrs = expanded_attrs .into_iter() - .flat_map(|item| self.process_cfg_attr(&self.expand_cfg_attr_item(cfg_attr, item))) - .collect() + .flat_map(|item| self.process_cfg_attr(&self.expand_cfg_attr_item(cfg_attr, item))); + iter::once(trace_attr).chain(expanded_attrs).collect() } else { - expanded_attrs - .into_iter() - .map(|item| self.expand_cfg_attr_item(cfg_attr, item)) - .collect() + let expanded_attrs = + expanded_attrs.into_iter().map(|item| self.expand_cfg_attr_item(cfg_attr, item)); + iter::once(trace_attr).chain(expanded_attrs).collect() } } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 87f01be26c2..e2a55752850 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1941,7 +1941,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { let attr_name = attr.ident().unwrap().name; // `#[cfg]` and `#[cfg_attr]` are special - they are // eagerly evaluated. - if attr_name != sym::cfg && attr_name != sym::cfg_attr { + if attr_name != sym::cfg && attr_name != sym::cfg_attr_trace { self.cx.sess.psess.buffer_lint( UNUSED_ATTRIBUTES, attr.span, diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 5577c8902da..77ec598e62a 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -1,5 +1,6 @@ use std::borrow::Cow; use std::collections::hash_map::Entry; +use std::sync::Arc; use std::{mem, slice}; use ast::token::IdentIsRaw; @@ -388,7 +389,7 @@ pub fn compile_declarative_macro( node_id != DUMMY_NODE_ID, ) }; - let dummy_syn_ext = |guar| (mk_syn_ext(Box::new(DummyExpander(guar))), Vec::new()); + let dummy_syn_ext = |guar| (mk_syn_ext(Arc::new(DummyExpander(guar))), Vec::new()); let lhs_nm = Ident::new(sym::lhs, span); let rhs_nm = Ident::new(sym::rhs, span); @@ -582,7 +583,7 @@ pub fn compile_declarative_macro( }) .collect(); - let expander = Box::new(MacroRulesMacroExpander { + let expander = Arc::new(MacroRulesMacroExpander { name: ident, span, node_id, diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index e0269eb6903..ee6306e3961 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -394,8 +394,8 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>> symbol, suffix, span, - }) if symbol.as_str().starts_with('-') => { - let symbol = Symbol::intern(&symbol.as_str()[1..]); + }) if let Some(symbol) = symbol.as_str().strip_prefix('-') => { + let symbol = Symbol::intern(symbol); let integer = TokenKind::lit(token::Integer, symbol, suffix); let a = tokenstream::TokenTree::token_joint_hidden(Minus, span); let b = tokenstream::TokenTree::token_alone(integer, span); @@ -406,8 +406,8 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>> symbol, suffix, span, - }) if symbol.as_str().starts_with('-') => { - let symbol = Symbol::intern(&symbol.as_str()[1..]); + }) if let Some(symbol) = symbol.as_str().strip_prefix('-') => { + let symbol = Symbol::intern(symbol); let float = TokenKind::lit(token::Float, symbol, suffix); let a = tokenstream::TokenTree::token_joint_hidden(Minus, span); let b = tokenstream::TokenTree::token_alone(float, span); diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index d50fe8c6a3e..980f3946035 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -62,6 +62,8 @@ declare_features! ( (accepted, arbitrary_enum_discriminant, "1.66.0", Some(60553)), /// Allows using `const` operands in inline assembly. (accepted, asm_const, "1.82.0", Some(93332)), + /// Allows using `label` operands in inline assembly. + (accepted, asm_goto, "CURRENT_RUSTC_VERSION", Some(119364)), /// Allows using `sym` operands in inline assembly. (accepted, asm_sym, "1.66.0", Some(93333)), /// Allows the definition of associated constants in `trait` or `impl` blocks. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 40857e0066e..fd936458f11 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -661,6 +661,14 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "`rustc_never_type_options` is used to experiment with never type fallback and work on \ never type stabilization, and will never be stable" ), + rustc_attr!( + rustc_macro_edition_2021, + Normal, + template!(Word), + ErrorFollowing, + EncodeCrossCrate::No, + "makes spans in this macro edition 2021" + ), // ========================================================================== // Internal attributes: Runtime related: @@ -752,6 +760,14 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ template!(Word, List: r#""...""#), DuplicatesOk, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE ), + // Trace that is left when a `cfg_attr` attribute is expanded. + // The attribute is not gated, to avoid stability errors, but it cannot be used in stable or + // unstable code directly because `sym::cfg_attr_trace` is not a valid identifier, it can only + // be generated by the compiler. + ungated!( + cfg_attr_trace, Normal, template!(Word /* irrelevant */), DuplicatesOk, + EncodeCrossCrate::No + ), // ========================================================================== // Internal attributes, Diagnostics related: diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 3c61bfd1c93..4707daea089 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -372,8 +372,6 @@ declare_features! ( (unstable, asm_experimental_arch, "1.58.0", Some(93335)), /// Enables experimental register support in inline assembly. (unstable, asm_experimental_reg, "1.85.0", Some(133416)), - /// Allows using `label` operands in inline assembly. - (unstable, asm_goto, "1.78.0", Some(119364)), /// Allows using `label` operands in inline assembly together with output operands. (unstable, asm_goto_with_outputs, "1.85.0", Some(119364)), /// Allows the `may_unwind` option in inline assembly. @@ -568,6 +566,8 @@ declare_features! ( (incomplete, mut_ref, "1.79.0", Some(123076)), /// Allows using `#[naked]` on functions. (unstable, naked_functions, "1.9.0", Some(90957)), + /// Allows using `#[target_feature(enable = "...")]` on `#[naked]` on functions. + (unstable, naked_functions_target_feature, "1.86.0", Some(138568)), /// Allows specifying the as-needed link modifier (unstable, native_link_modifiers_as_needed, "1.53.0", Some(81490)), /// Allow negative trait implementations. diff --git a/compiler/rustc_fs_util/src/lib.rs b/compiler/rustc_fs_util/src/lib.rs index 4e9d21c900d..0df1b243d69 100644 --- a/compiler/rustc_fs_util/src/lib.rs +++ b/compiler/rustc_fs_util/src/lib.rs @@ -55,25 +55,31 @@ pub enum LinkOrCopy { Copy, } -/// Copies `p` into `q`, preferring to use hard-linking if possible. If -/// `q` already exists, it is removed first. +/// Copies `p` into `q`, preferring to use hard-linking if possible. /// The result indicates which of the two operations has been performed. pub fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(p: P, q: Q) -> io::Result<LinkOrCopy> { + // Creating a hard-link will fail if the destination path already exists. We could defensively + // call remove_file in this function, but that pessimizes callers who can avoid such calls. + // Incremental compilation calls this function a lot, and is able to avoid calls that + // would fail the first hard_link attempt. + let p = p.as_ref(); let q = q.as_ref(); - match fs::remove_file(q) { - Ok(()) => (), - Err(err) if err.kind() == io::ErrorKind::NotFound => (), - Err(err) => return Err(err), - } - match fs::hard_link(p, q) { - Ok(()) => Ok(LinkOrCopy::Link), - Err(_) => match fs::copy(p, q) { - Ok(_) => Ok(LinkOrCopy::Copy), - Err(e) => Err(e), - }, + let err = match fs::hard_link(p, q) { + Ok(()) => return Ok(LinkOrCopy::Link), + Err(err) => err, + }; + + if err.kind() == io::ErrorKind::AlreadyExists { + fs::remove_file(q)?; + if fs::hard_link(p, q).is_ok() { + return Ok(LinkOrCopy::Link); + } } + + // Hard linking failed, fall back to copying. + fs::copy(p, q).map(|_| LinkOrCopy::Copy) } #[cfg(any(unix, all(target_os = "wasi", target_env = "p1")))] diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 5cf231d5668..751c379b21a 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2949,7 +2949,7 @@ impl<'hir> TraitItem<'hir> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum TraitFn<'hir> { /// No default body in the trait, just a signature. - Required(&'hir [Ident]), + Required(&'hir [Option<Ident>]), /// Both signature and body are provided in the trait. Provided(BodyId), @@ -3354,7 +3354,9 @@ pub struct BareFnTy<'hir> { pub abi: ExternAbi, pub generic_params: &'hir [GenericParam<'hir>], pub decl: &'hir FnDecl<'hir>, - pub param_names: &'hir [Ident], + // `Option` because bare fn parameter names are optional. We also end up + // with `None` in some error cases, e.g. invalid parameter patterns. + pub param_names: &'hir [Option<Ident>], } #[derive(Debug, Clone, Copy, HashStable_Generic)] @@ -3755,7 +3757,10 @@ pub enum UseKind { /// One import, e.g., `use foo::bar` or `use foo::bar as baz`. /// Also produced for each element of a list `use`, e.g. /// `use foo::{a, b}` lowers to `use foo::a; use foo::b;`. - Single, + /// + /// The identifier is the name defined by the import. E.g. for `use + /// foo::bar` it is `bar`, for `use foo::bar as baz` it is `baz`. + Single(Ident), /// Glob import, e.g., `use foo::*`. Glob, @@ -3897,8 +3902,6 @@ impl ItemId { /// An item /// -/// The name might be a dummy name in case of anonymous items -/// /// For more details, see the [rust lang reference]. /// Note that the reference does not document nightly-only features. /// There may be also slight differences in the names and representation of AST nodes between @@ -3907,7 +3910,6 @@ impl ItemId { /// [rust lang reference]: https://doc.rust-lang.org/reference/items.html #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct Item<'hir> { - pub ident: Ident, pub owner_id: OwnerId, pub kind: ItemKind<'hir>, pub span: Span, @@ -3937,46 +3939,56 @@ impl<'hir> Item<'hir> { } expect_methods_self_kind! { - expect_extern_crate, Option<Symbol>, ItemKind::ExternCrate(s), *s; + expect_extern_crate, (Option<Symbol>, Ident), + ItemKind::ExternCrate(s, ident), (*s, *ident); expect_use, (&'hir UsePath<'hir>, UseKind), ItemKind::Use(p, uk), (p, *uk); - expect_static, (&'hir Ty<'hir>, Mutability, BodyId), - ItemKind::Static(ty, mutbl, body), (ty, *mutbl, *body); + expect_static, (Ident, &'hir Ty<'hir>, Mutability, BodyId), + ItemKind::Static(ident, ty, mutbl, body), (*ident, ty, *mutbl, *body); - expect_const, (&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId), - ItemKind::Const(ty, generics, body), (ty, generics, *body); + expect_const, (Ident, &'hir Ty<'hir>, &'hir Generics<'hir>, BodyId), + ItemKind::Const(ident, ty, generics, body), (*ident, ty, generics, *body); - expect_fn, (&FnSig<'hir>, &'hir Generics<'hir>, BodyId), - ItemKind::Fn { sig, generics, body, .. }, (sig, generics, *body); + expect_fn, (Ident, &FnSig<'hir>, &'hir Generics<'hir>, BodyId), + ItemKind::Fn { ident, sig, generics, body, .. }, (*ident, sig, generics, *body); - expect_macro, (&ast::MacroDef, MacroKind), ItemKind::Macro(def, mk), (def, *mk); + expect_macro, (Ident, &ast::MacroDef, MacroKind), + ItemKind::Macro(ident, def, mk), (*ident, def, *mk); - expect_mod, &'hir Mod<'hir>, ItemKind::Mod(m), m; + expect_mod, (Ident, &'hir Mod<'hir>), ItemKind::Mod(ident, m), (*ident, m); expect_foreign_mod, (ExternAbi, &'hir [ForeignItemRef]), ItemKind::ForeignMod { abi, items }, (*abi, items); expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm { asm, .. }, asm; - expect_ty_alias, (&'hir Ty<'hir>, &'hir Generics<'hir>), - ItemKind::TyAlias(ty, generics), (ty, generics); + expect_ty_alias, (Ident, &'hir Ty<'hir>, &'hir Generics<'hir>), + ItemKind::TyAlias(ident, ty, generics), (*ident, ty, generics); - expect_enum, (&EnumDef<'hir>, &'hir Generics<'hir>), ItemKind::Enum(def, generics), (def, generics); + expect_enum, (Ident, &EnumDef<'hir>, &'hir Generics<'hir>), + ItemKind::Enum(ident, def, generics), (*ident, def, generics); - expect_struct, (&VariantData<'hir>, &'hir Generics<'hir>), - ItemKind::Struct(data, generics), (data, generics); + expect_struct, (Ident, &VariantData<'hir>, &'hir Generics<'hir>), + ItemKind::Struct(ident, data, generics), (*ident, data, generics); - expect_union, (&VariantData<'hir>, &'hir Generics<'hir>), - ItemKind::Union(data, generics), (data, generics); + expect_union, (Ident, &VariantData<'hir>, &'hir Generics<'hir>), + ItemKind::Union(ident, data, generics), (*ident, data, generics); expect_trait, - (IsAuto, Safety, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]), - ItemKind::Trait(is_auto, safety, generics, bounds, items), - (*is_auto, *safety, generics, bounds, items); - - expect_trait_alias, (&'hir Generics<'hir>, GenericBounds<'hir>), - ItemKind::TraitAlias(generics, bounds), (generics, bounds); + ( + IsAuto, + Safety, + Ident, + &'hir Generics<'hir>, + GenericBounds<'hir>, + &'hir [TraitItemRef] + ), + ItemKind::Trait(is_auto, safety, ident, generics, bounds, items), + (*is_auto, *safety, *ident, generics, bounds, items); + + expect_trait_alias, (Ident, &'hir Generics<'hir>, GenericBounds<'hir>), + ItemKind::TraitAlias(ident, generics, bounds), (*ident, generics, bounds); expect_impl, &'hir Impl<'hir>, ItemKind::Impl(imp), imp; } @@ -4094,7 +4106,7 @@ pub enum ItemKind<'hir> { /// An `extern crate` item, with optional *original* crate name if the crate was renamed. /// /// E.g., `extern crate foo` or `extern crate foo_bar as foo`. - ExternCrate(Option<Symbol>), + ExternCrate(Option<Symbol>, Ident), /// `use foo::bar::*;` or `use foo::bar::baz as quux;` /// @@ -4104,11 +4116,12 @@ pub enum ItemKind<'hir> { Use(&'hir UsePath<'hir>, UseKind), /// A `static` item. - Static(&'hir Ty<'hir>, Mutability, BodyId), + Static(Ident, &'hir Ty<'hir>, Mutability, BodyId), /// A `const` item. - Const(&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId), + Const(Ident, &'hir Ty<'hir>, &'hir Generics<'hir>, BodyId), /// A function declaration. Fn { + ident: Ident, sig: FnSig<'hir>, generics: &'hir Generics<'hir>, body: BodyId, @@ -4118,9 +4131,9 @@ pub enum ItemKind<'hir> { has_body: bool, }, /// A MBE macro definition (`macro_rules!` or `macro`). - Macro(&'hir ast::MacroDef, MacroKind), + Macro(Ident, &'hir ast::MacroDef, MacroKind), /// A module. - Mod(&'hir Mod<'hir>), + Mod(Ident, &'hir Mod<'hir>), /// An external module, e.g. `extern { .. }`. ForeignMod { abi: ExternAbi, items: &'hir [ForeignItemRef] }, /// Module-level inline assembly (from `global_asm!`). @@ -4134,17 +4147,17 @@ pub enum ItemKind<'hir> { fake_body: BodyId, }, /// A type alias, e.g., `type Foo = Bar<u8>`. - TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>), - /// An enum definition, e.g., `enum Foo<A, B> {C<A>, D<B>}`. - Enum(EnumDef<'hir>, &'hir Generics<'hir>), + TyAlias(Ident, &'hir Ty<'hir>, &'hir Generics<'hir>), + /// An enum definition, e.g., `enum Foo<A, B> { C<A>, D<B> }`. + Enum(Ident, EnumDef<'hir>, &'hir Generics<'hir>), /// A struct definition, e.g., `struct Foo<A> {x: A}`. - Struct(VariantData<'hir>, &'hir Generics<'hir>), + Struct(Ident, VariantData<'hir>, &'hir Generics<'hir>), /// A union definition, e.g., `union Foo<A, B> {x: A, y: B}`. - Union(VariantData<'hir>, &'hir Generics<'hir>), + Union(Ident, VariantData<'hir>, &'hir Generics<'hir>), /// A trait definition. - Trait(IsAuto, Safety, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]), + Trait(IsAuto, Safety, Ident, &'hir Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]), /// A trait alias. - TraitAlias(&'hir Generics<'hir>, GenericBounds<'hir>), + TraitAlias(Ident, &'hir Generics<'hir>, GenericBounds<'hir>), /// An implementation, e.g., `impl<A> Trait for Foo { .. }`. Impl(&'hir Impl<'hir>), @@ -4173,16 +4186,39 @@ pub struct Impl<'hir> { } impl ItemKind<'_> { + pub fn ident(&self) -> Option<Ident> { + match *self { + ItemKind::ExternCrate(_, ident) + | ItemKind::Use(_, UseKind::Single(ident)) + | ItemKind::Static(ident, ..) + | ItemKind::Const(ident, ..) + | ItemKind::Fn { ident, .. } + | ItemKind::Macro(ident, ..) + | ItemKind::Mod(ident, ..) + | ItemKind::TyAlias(ident, ..) + | ItemKind::Enum(ident, ..) + | ItemKind::Struct(ident, ..) + | ItemKind::Union(ident, ..) + | ItemKind::Trait(_, _, ident, ..) + | ItemKind::TraitAlias(ident, ..) => Some(ident), + + ItemKind::Use(_, UseKind::Glob | UseKind::ListStem) + | ItemKind::ForeignMod { .. } + | ItemKind::GlobalAsm { .. } + | ItemKind::Impl(_) => None, + } + } + pub fn generics(&self) -> Option<&Generics<'_>> { Some(match self { ItemKind::Fn { generics, .. } - | ItemKind::TyAlias(_, generics) - | ItemKind::Const(_, generics, _) - | ItemKind::Enum(_, generics) - | ItemKind::Struct(_, generics) - | ItemKind::Union(_, generics) - | ItemKind::Trait(_, _, generics, _, _) - | ItemKind::TraitAlias(generics, _) + | ItemKind::TyAlias(_, _, generics) + | ItemKind::Const(_, _, generics, _) + | ItemKind::Enum(_, _, generics) + | ItemKind::Struct(_, _, generics) + | ItemKind::Union(_, _, generics) + | ItemKind::Trait(_, _, _, generics, _, _) + | ItemKind::TraitAlias(_, generics, _) | ItemKind::Impl(Impl { generics, .. }) => generics, _ => return None, }) @@ -4301,7 +4337,12 @@ impl ForeignItem<'_> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum ForeignItemKind<'hir> { /// A foreign function. - Fn(FnSig<'hir>, &'hir [Ident], &'hir Generics<'hir>), + /// + /// All argument idents are actually always present (i.e. `Some`), but + /// `&[Option<Ident>]` is used because of code paths shared with `TraitFn` + /// and `BareFnTy`. The sharing is due to all of these cases not allowing + /// arbitrary patterns for parameters. + Fn(FnSig<'hir>, &'hir [Option<Ident>], &'hir Generics<'hir>), /// A foreign static item (`static ext: u8`). Static(&'hir Ty<'hir>, Mutability, Safety), /// A foreign type. @@ -4374,8 +4415,8 @@ impl<'hir> OwnerNode<'hir> { match self { OwnerNode::Item(Item { kind: - ItemKind::Static(_, _, body) - | ItemKind::Const(_, _, body) + ItemKind::Static(_, _, _, body) + | ItemKind::Const(_, _, _, body) | ItemKind::Fn { body, .. }, .. }) @@ -4518,12 +4559,12 @@ impl<'hir> Node<'hir> { /// ``` pub fn ident(&self) -> Option<Ident> { match self { + Node::Item(item) => item.kind.ident(), Node::TraitItem(TraitItem { ident, .. }) | Node::ImplItem(ImplItem { ident, .. }) | Node::ForeignItem(ForeignItem { ident, .. }) | Node::Field(FieldDef { ident, .. }) | Node::Variant(Variant { ident, .. }) - | Node::Item(Item { ident, .. }) | Node::PathSegment(PathSegment { ident, .. }) => Some(*ident), Node::Lifetime(lt) => Some(lt.ident), Node::GenericParam(p) => Some(p.name.ident()), @@ -4599,9 +4640,9 @@ impl<'hir> Node<'hir> { pub fn ty(self) -> Option<&'hir Ty<'hir>> { match self { Node::Item(it) => match it.kind { - ItemKind::TyAlias(ty, _) - | ItemKind::Static(ty, _, _) - | ItemKind::Const(ty, _, _) => Some(ty), + ItemKind::TyAlias(_, ty, _) + | ItemKind::Static(_, ty, _, _) + | ItemKind::Const(_, ty, _, _) => Some(ty), ItemKind::Impl(impl_item) => Some(&impl_item.self_ty), _ => None, }, @@ -4621,7 +4662,7 @@ impl<'hir> Node<'hir> { pub fn alias_ty(self) -> Option<&'hir Ty<'hir>> { match self { - Node::Item(Item { kind: ItemKind::TyAlias(ty, ..), .. }) => Some(ty), + Node::Item(Item { kind: ItemKind::TyAlias(_, ty, _), .. }) => Some(ty), _ => None, } } @@ -4632,7 +4673,9 @@ impl<'hir> Node<'hir> { Node::Item(Item { owner_id, kind: - ItemKind::Const(_, _, body) | ItemKind::Static(.., body) | ItemKind::Fn { body, .. }, + ItemKind::Const(_, _, _, body) + | ItemKind::Static(.., body) + | ItemKind::Fn { body, .. }, .. }) | Node::TraitItem(TraitItem { @@ -4693,8 +4736,8 @@ impl<'hir> Node<'hir> { pub fn fn_kind(self) -> Option<FnKind<'hir>> { match self { Node::Item(i) => match i.kind { - ItemKind::Fn { sig, generics, .. } => { - Some(FnKind::ItemFn(i.ident, generics, sig.header)) + ItemKind::Fn { ident, sig, generics, .. } => { + Some(FnKind::ItemFn(ident, generics, sig.header)) } _ => None, }, @@ -4767,7 +4810,7 @@ mod size_asserts { static_assert_size!(ImplItem<'_>, 88); static_assert_size!(ImplItemKind<'_>, 40); static_assert_size!(Item<'_>, 88); - static_assert_size!(ItemKind<'_>, 56); + static_assert_size!(ItemKind<'_>, 64); static_assert_size!(LetStmt<'_>, 64); static_assert_size!(Param<'_>, 32); static_assert_size!(Pat<'_>, 72); diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 3ef645a5f61..506358341b5 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -533,34 +533,44 @@ pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) -> pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::Result { try_visit!(visitor.visit_id(item.hir_id())); - try_visit!(visitor.visit_ident(item.ident)); match item.kind { - ItemKind::ExternCrate(orig_name) => { + ItemKind::ExternCrate(orig_name, ident) => { visit_opt!(visitor, visit_name, orig_name); + try_visit!(visitor.visit_ident(ident)); } - ItemKind::Use(ref path, _) => { + ItemKind::Use(ref path, kind) => { try_visit!(visitor.visit_use(path, item.hir_id())); + match kind { + UseKind::Single(ident) => try_visit!(visitor.visit_ident(ident)), + UseKind::Glob | UseKind::ListStem => {} + } } - ItemKind::Static(ref typ, _, body) => { + ItemKind::Static(ident, ref typ, _, body) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_ty_unambig(typ)); try_visit!(visitor.visit_nested_body(body)); } - ItemKind::Const(ref typ, ref generics, body) => { + ItemKind::Const(ident, ref typ, ref generics, body) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_ty_unambig(typ)); try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_nested_body(body)); } - ItemKind::Fn { sig, generics, body: body_id, .. } => { + ItemKind::Fn { ident, sig, generics, body: body_id, .. } => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_fn( - FnKind::ItemFn(item.ident, generics, sig.header), + FnKind::ItemFn(ident, generics, sig.header), sig.decl, body_id, item.span, item.owner_id.def_id, )); } - ItemKind::Macro(..) => {} - ItemKind::Mod(ref module) => { + ItemKind::Macro(ident, _def, _kind) => { + try_visit!(visitor.visit_ident(ident)); + } + ItemKind::Mod(ident, ref module) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_mod(module, item.span, item.hir_id())); } ItemKind::ForeignMod { abi: _, items } => { @@ -573,11 +583,13 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: // typeck results set correctly. try_visit!(visitor.visit_nested_body(fake_body)); } - ItemKind::TyAlias(ref ty, ref generics) => { + ItemKind::TyAlias(ident, ref ty, ref generics) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_ty_unambig(ty)); try_visit!(visitor.visit_generics(generics)); } - ItemKind::Enum(ref enum_definition, ref generics) => { + ItemKind::Enum(ident, ref enum_definition, ref generics) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_enum_def(enum_definition)); } @@ -597,17 +609,20 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: try_visit!(visitor.visit_ty_unambig(self_ty)); walk_list!(visitor, visit_impl_item_ref, *items); } - ItemKind::Struct(ref struct_definition, ref generics) - | ItemKind::Union(ref struct_definition, ref generics) => { + ItemKind::Struct(ident, ref struct_definition, ref generics) + | ItemKind::Union(ident, ref struct_definition, ref generics) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_variant_data(struct_definition)); } - ItemKind::Trait(.., ref generics, bounds, trait_item_refs) => { + ItemKind::Trait(_is_auto, _safety, ident, ref generics, bounds, trait_item_refs) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_trait_item_ref, trait_item_refs); } - ItemKind::TraitAlias(ref generics, bounds) => { + ItemKind::TraitAlias(ident, ref generics, bounds) => { + try_visit!(visitor.visit_ident(ident)); try_visit!(visitor.visit_generics(generics)); walk_list!(visitor, visit_param_bound, bounds); } @@ -640,7 +655,9 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>( ForeignItemKind::Fn(ref sig, param_names, ref generics) => { try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_fn_decl(sig.decl)); - walk_list!(visitor, visit_ident, param_names.iter().copied()); + for ident in param_names.iter().copied() { + visit_opt!(visitor, visit_ident, ident); + } } ForeignItemKind::Static(ref typ, _, _) => { try_visit!(visitor.visit_ty_unambig(typ)); @@ -1154,7 +1171,9 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>( } TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => { try_visit!(visitor.visit_fn_decl(sig.decl)); - walk_list!(visitor, visit_ident, param_names.iter().copied()); + for ident in param_names.iter().copied() { + visit_opt!(visitor, visit_ident, ident); + } } TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => { try_visit!(visitor.visit_fn( diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 29f4d5b8076..e625514e9ff 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -322,7 +322,6 @@ language_item_table! { BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None; // Lang items needed for `format_args!()`. - FormatAlignment, sym::format_alignment, format_alignment, Target::Enum, GenericRequirement::None; FormatArgument, sym::format_argument, format_argument, Target::Struct, GenericRequirement::None; FormatArguments, sym::format_arguments, format_arguments, Target::Struct, GenericRequirement::None; FormatCount, sym::format_count, format_count, Target::Enum, GenericRequirement::None; diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml index 55a816a855a..e5017794d8f 100644 --- a/compiler/rustc_hir_analysis/Cargo.toml +++ b/compiler/rustc_hir_analysis/Cargo.toml @@ -28,7 +28,6 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } -rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index a266286664c..07b5837bd87 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -18,18 +18,17 @@ use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::middle::stability::EvalResult; use rustc_middle::ty::error::TypeErrorToStringExt; -use rustc_middle::ty::fold::{BottomUpFolder, fold_regions}; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{ - AdtDef, GenericArgKind, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, + AdtDef, BottomUpFolder, GenericArgKind, RegionKind, TypeFoldable, TypeSuperVisitable, + TypeVisitable, TypeVisitableExt, fold_regions, }; use rustc_session::lint::builtin::UNINHABITED_STATIC; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedDirective; use rustc_trait_selection::traits; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; -use rustc_type_ir::fold::TypeFoldable; use tracing::{debug, instrument}; use ty::TypingMode; use {rustc_attr_parsing as attr, rustc_hir as hir}; @@ -1715,7 +1714,7 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, opaque_def_id: LocalDefId) -> ErrorG opaques: Vec<DefId>, closures: Vec<DefId>, } - impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector { + impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector { fn visit_ty(&mut self, t: Ty<'tcx>) { match *t.kind() { ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 0a37a27b35b..84d07c711fa 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -12,10 +12,9 @@ use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisi use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::util::ExplicitSelf; use rustc_middle::ty::{ - self, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder, + self, BottomUpFolder, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, TypingMode, Upcast, }; use rustc_middle::{bug, span_bug}; @@ -1035,7 +1034,13 @@ fn report_trait_method_mismatch<'tcx>( let span = tcx .hir_body_param_names(body) .zip(sig.decl.inputs.iter()) - .map(|(param, ty)| param.span.to(ty.span)) + .map(|(param_name, ty)| { + if let Some(param_name) = param_name { + param_name.span.to(ty.span) + } else { + ty.span + } + }) .next() .unwrap_or(impl_err_span); diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index b4a16b2b805..d8ae4214527 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -153,10 +153,9 @@ pub(super) fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDef } // If `#[link_section]` is missing, then nothing to verify - let attrs = tcx.codegen_fn_attrs(id); - if attrs.link_section.is_none() { + let Some(link_section) = tcx.codegen_fn_attrs(id).link_section else { return; - } + }; // For the wasm32 target statics with `#[link_section]` other than `.init_array` // are placed into custom sections of the final output file, but this isn't like @@ -182,11 +181,8 @@ pub(super) fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDef // continue to work, but would no longer be necessary. if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id()) - && alloc.inner().provenance().ptrs().len() != 0 - && attrs - .link_section - .map(|link_section| !link_section.as_str().starts_with(".init_array")) - .unwrap() + && !alloc.inner().provenance().ptrs().is_empty() + && !link_section.as_str().starts_with(".init_array") { let msg = "statics with a custom `#[link_section]` must be a \ simple list of bytes on the wasm target with no \ diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index fd5ffdc2d7a..952af592311 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -16,10 +16,12 @@ use rustc_lint_defs::builtin::SUPERTRAIT_ITEM_SHADOWING_DEFINITION; use rustc_macros::LintDiagnostic; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::query::Providers; +use rustc_middle::traits::solve::NoSolution; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ - self, AdtKind, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, - TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast, + self, AdtKind, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFlags, + TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, + Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_session::parse::feature_err; @@ -34,8 +36,6 @@ use rustc_trait_selection::traits::{ self, FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc, }; -use rustc_type_ir::TypeFlags; -use rustc_type_ir::solve::NoSolution; use tracing::{debug, instrument}; use {rustc_ast as ast, rustc_hir as hir}; @@ -269,26 +269,26 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() } res } - hir::ItemKind::Fn { sig, .. } => { - check_item_fn(tcx, def_id, item.ident, item.span, sig.decl) + hir::ItemKind::Fn { ident, sig, .. } => { + check_item_fn(tcx, def_id, ident, item.span, sig.decl) } - hir::ItemKind::Static(ty, ..) => { + hir::ItemKind::Static(_, ty, ..) => { check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid) } - hir::ItemKind::Const(ty, ..) => { + hir::ItemKind::Const(_, ty, ..) => { check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid) } - hir::ItemKind::Struct(_, hir_generics) => { + hir::ItemKind::Struct(_, _, hir_generics) => { let res = check_type_defn(tcx, item, false); check_variances_for_type_defn(tcx, item, hir_generics); res } - hir::ItemKind::Union(_, hir_generics) => { + hir::ItemKind::Union(_, _, hir_generics) => { let res = check_type_defn(tcx, item, true); check_variances_for_type_defn(tcx, item, hir_generics); res } - hir::ItemKind::Enum(_, hir_generics) => { + hir::ItemKind::Enum(_, _, hir_generics) => { let res = check_type_defn(tcx, item, true); check_variances_for_type_defn(tcx, item, hir_generics); res @@ -297,7 +297,9 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() hir::ItemKind::TraitAlias(..) => check_trait(tcx, item), // `ForeignItem`s are handled separately. hir::ItemKind::ForeignMod { .. } => Ok(()), - hir::ItemKind::TyAlias(hir_ty, hir_generics) if tcx.type_alias_is_lazy(item.owner_id) => { + hir::ItemKind::TyAlias(_, hir_ty, hir_generics) + if tcx.type_alias_is_lazy(item.owner_id) => + { let res = enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| { let ty = tcx.type_of(def_id).instantiate_identity(); let item_ty = wfcx.normalize(hir_ty.span, Some(WellFormedLoc::Ty(def_id)), ty); @@ -822,10 +824,10 @@ fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool { /// /// In such cases, suggest using `Self` instead. fn check_dyn_incompatible_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem<'_>) { - let (trait_name, trait_def_id) = + let (trait_ident, trait_def_id) = match tcx.hir_node_by_def_id(tcx.hir_get_parent_item(item.hir_id()).def_id) { hir::Node::Item(item) => match item.kind { - hir::ItemKind::Trait(..) => (item.ident, item.owner_id), + hir::ItemKind::Trait(_, _, ident, ..) => (ident, item.owner_id), _ => return, }, _ => return, @@ -862,7 +864,7 @@ fn check_dyn_incompatible_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitI trait_should_be_self, "associated item referring to unboxed trait object for its own trait", ) - .with_span_label(trait_name.span, "in this trait") + .with_span_label(trait_ident.span, "in this trait") .with_multipart_suggestion( "you might have meant to use `Self` to refer to the implementing type", sugg, @@ -1520,7 +1522,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id struct CountParams { params: FxHashSet<u32>, } - impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for CountParams { + impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for CountParams { type Result = ControlFlow<()>; fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { if let ty::Param(param) = t.kind() { diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index c918abe4c07..1f3f0b754bb 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -250,13 +250,16 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() // trait, they *do* satisfy the repr(transparent) rules, and then we assume that everything else // in the compiler (in particular, all the call ABI logic) will treat them as repr(transparent) // even if they do not carry that attribute. - use rustc_type_ir::TyKind::*; match (source.kind(), target.kind()) { - (&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b)) if r_a == *r_b && mutbl_a == *mutbl_b => { + (&ty::Ref(r_a, _, mutbl_a), ty::Ref(r_b, _, mutbl_b)) + if r_a == *r_b && mutbl_a == *mutbl_b => + { Ok(()) } - (&RawPtr(_, a_mutbl), &RawPtr(_, b_mutbl)) if a_mutbl == b_mutbl => Ok(()), - (&Adt(def_a, args_a), &Adt(def_b, args_b)) if def_a.is_struct() && def_b.is_struct() => { + (&ty::RawPtr(_, a_mutbl), &ty::RawPtr(_, b_mutbl)) if a_mutbl == b_mutbl => Ok(()), + (&ty::Adt(def_a, args_a), &ty::Adt(def_b, args_b)) + if def_a.is_struct() && def_b.is_struct() => + { if def_a != def_b { let source_path = tcx.def_path_str(def_a.did()); let target_path = tcx.def_path_str(def_b.did()); diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index b5c6c2f3861..15e0a72fdcb 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -10,10 +10,9 @@ use rustc_errors::struct_span_code_err; use rustc_hir::LangItem; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, elaborate}; use rustc_session::parse::feature_err; use rustc_span::{ErrorGuaranteed, sym}; -use rustc_type_ir::elaborate; use tracing::debug; use crate::check::always_applicable; diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 0b7fc44460e..74ba4ffe25e 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -3,11 +3,10 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_errors::ErrorGuaranteed; -use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt}; use rustc_lint_defs::builtin::UNCOVERED_PARAM_IN_PROJECTION; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, + self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, }; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::{DefId, LocalDefId}; @@ -356,13 +355,20 @@ fn orphan_check<'tcx>( }) } OrphanCheckErr::NonLocalInputType(tys) => { - let generics = tcx.generics_of(impl_def_id); - let tys = tys - .into_iter() - .map(|(ty, is_target_ty)| { - (ty.fold_with(&mut TyVarReplacer { infcx: &infcx, generics }), is_target_ty) - }) - .collect(); + let tys = infcx.probe(|_| { + // Map the unconstrained args back to their params, + // ignoring any type unification errors. + for (arg, id_arg) in + std::iter::zip(args, ty::GenericArgs::identity_for_item(tcx, impl_def_id)) + { + let _ = infcx.at(&cause, ty::ParamEnv::empty()).eq( + DefineOpaqueTypes::No, + arg, + id_arg, + ); + } + infcx.resolve_vars_if_possible(tys) + }); OrphanCheckErr::NonLocalInputType(tys) } }) @@ -536,40 +542,3 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for UncoveredTyParamCollector<'_, 'tcx> { } } } - -struct TyVarReplacer<'cx, 'tcx> { - infcx: &'cx InferCtxt<'tcx>, - generics: &'tcx ty::Generics, -} - -impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for TyVarReplacer<'cx, 'tcx> { - fn cx(&self) -> TyCtxt<'tcx> { - self.infcx.tcx - } - - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if !ty.has_type_flags(ty::TypeFlags::HAS_TY_INFER) { - return ty; - } - let ty::Infer(ty::TyVar(vid)) = *ty.kind() else { - return ty.super_fold_with(self); - }; - let origin = self.infcx.type_var_origin(vid); - if let Some(def_id) = origin.param_def_id { - // The generics of an `impl` don't have a parent, we can index directly. - let index = self.generics.param_def_id_to_index[&def_id]; - let name = self.generics.own_params[index as usize].name; - - Ty::new_param(self.infcx.tcx, index, name) - } else { - ty - } - } - - fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - if !ct.has_type_flags(ty::TypeFlags::HAS_TY_INFER) { - return ct; - } - ct.super_fold_with(self) - } -} diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index e0e435dd6f0..075abc32594 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -33,9 +33,8 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; -use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::util::{Discr, IntTypeExt}; -use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypingMode}; +use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypingMode, fold_regions}; use rustc_middle::{bug, span_bug}; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName; @@ -248,13 +247,13 @@ fn reject_placeholder_type_signatures_in_item<'tcx>( item: &'tcx hir::Item<'tcx>, ) { let (generics, suggest) = match &item.kind { - hir::ItemKind::Union(_, generics) - | hir::ItemKind::Enum(_, generics) - | hir::ItemKind::TraitAlias(generics, _) - | hir::ItemKind::Trait(_, _, generics, ..) + hir::ItemKind::Union(_, _, generics) + | hir::ItemKind::Enum(_, _, generics) + | hir::ItemKind::TraitAlias(_, generics, _) + | hir::ItemKind::Trait(_, _, _, generics, ..) | hir::ItemKind::Impl(hir::Impl { generics, .. }) - | hir::ItemKind::Struct(_, generics) => (generics, true), - hir::ItemKind::TyAlias(_, generics) => (generics, false), + | hir::ItemKind::Struct(_, _, generics) => (generics, true), + hir::ItemKind::TyAlias(_, _, generics) => (generics, false), // `static`, `fn` and `const` are handled elsewhere to suggest appropriate type. _ => return, }; @@ -471,9 +470,9 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { .tcx .hir_expect_item(self.tcx.hir_get_parent_item(self.hir_id()).def_id); match &item.kind { - hir::ItemKind::Enum(_, generics) - | hir::ItemKind::Struct(_, generics) - | hir::ItemKind::Union(_, generics) => { + hir::ItemKind::Enum(_, _, generics) + | hir::ItemKind::Struct(_, _, generics) + | hir::ItemKind::Union(_, _, generics) => { let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics); let (lt_sp, sugg) = match generics.params { [] => (generics.span, format!("<{lt_name}>")), @@ -668,16 +667,16 @@ fn get_new_lifetime_name<'tcx>( #[instrument(level = "debug", skip_all)] fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { let it = tcx.hir_item(item_id); - debug!(item = %it.ident, id = %it.hir_id()); + debug!(item = ?it.kind.ident(), id = %it.hir_id()); let def_id = item_id.owner_id.def_id; let icx = ItemCtxt::new(tcx, def_id); match &it.kind { // These don't define types. - hir::ItemKind::ExternCrate(_) + hir::ItemKind::ExternCrate(..) | hir::ItemKind::Use(..) | hir::ItemKind::Macro(..) - | hir::ItemKind::Mod(_) + | hir::ItemKind::Mod(..) | hir::ItemKind::GlobalAsm { .. } => {} hir::ItemKind::ForeignMod { items, .. } => { for item in *items { @@ -737,7 +736,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { tcx.at(it.span).explicit_super_predicates_of(def_id); tcx.ensure_ok().predicates_of(def_id); } - hir::ItemKind::Struct(struct_def, _) | hir::ItemKind::Union(struct_def, _) => { + hir::ItemKind::Struct(_, struct_def, _) | hir::ItemKind::Union(_, struct_def, _) => { tcx.ensure_ok().generics_of(def_id); tcx.ensure_ok().type_of(def_id); tcx.ensure_ok().predicates_of(def_id); @@ -759,7 +758,7 @@ fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { tcx.ensure_ok().predicates_of(def_id); } - hir::ItemKind::Static(ty, ..) | hir::ItemKind::Const(ty, ..) => { + hir::ItemKind::Static(_, ty, ..) | hir::ItemKind::Const(_, ty, ..) => { tcx.ensure_ok().generics_of(def_id); tcx.ensure_ok().type_of(def_id); tcx.ensure_ok().predicates_of(def_id); @@ -1090,7 +1089,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { let repr = tcx.repr_options_of_def(def_id); let (kind, variants) = match &item.kind { - ItemKind::Enum(def, _) => { + ItemKind::Enum(_, def, _) => { let mut distance_from_explicit = 0; let variants = def .variants @@ -1118,7 +1117,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { (AdtKind::Enum, variants) } - ItemKind::Struct(def, _) | ItemKind::Union(def, _) => { + ItemKind::Struct(ident, def, _) | ItemKind::Union(ident, def, _) => { let adt_kind = match item.kind { ItemKind::Struct(..) => AdtKind::Struct, _ => AdtKind::Union, @@ -1126,7 +1125,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { let variants = std::iter::once(lower_variant( tcx, None, - item.ident, + *ident, ty::VariantDiscr::Relative(0), def, adt_kind, diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs index 7cbd31de6ba..c3f965d8456 100644 --- a/compiler/rustc_hir_analysis/src/collect/dump.rs +++ b/compiler/rustc_hir_analysis/src/collect/dump.rs @@ -134,7 +134,7 @@ pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) { }; tcx.vtable_entries(trait_ref) } - hir::ItemKind::TyAlias(_, _) => { + hir::ItemKind::TyAlias(..) => { let ty = tcx.type_of(def_id).instantiate_identity(); if ty.has_non_region_param() { tcx.dcx().span_err( diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 1c1a246cc15..6e07f0ff53c 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -1,14 +1,13 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_hir as hir; use rustc_infer::traits::util; -use rustc_middle::ty::fold::shift_vars; use rustc_middle::ty::{ self, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, + Upcast, shift_vars, }; use rustc_middle::{bug, span_bug}; use rustc_span::Span; use rustc_span::def_id::{DefId, LocalDefId}; -use rustc_type_ir::Upcast; use tracing::{debug, instrument}; use super::ItemCtxt; diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 2022127a15b..4bd89861a9e 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -163,7 +163,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen } } - ItemKind::Trait(_, _, _, self_bounds, ..) | ItemKind::TraitAlias(_, self_bounds) => { + ItemKind::Trait(_, _, _, _, self_bounds, ..) + | ItemKind::TraitAlias(_, _, self_bounds) => { is_trait = Some(self_bounds); } _ => {} @@ -615,7 +616,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>( let (generics, superbounds) = match item.kind { hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits), - hir::ItemKind::TraitAlias(generics, supertraits) => (generics, supertraits), + hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits), _ => span_bug!(item.span, "super_predicates invoked on non-trait"), }; @@ -959,7 +960,7 @@ pub(super) fn const_conditions<'tcx>( Node::Item(item) => match item.kind { hir::ItemKind::Impl(impl_) => (impl_.generics, None, false), hir::ItemKind::Fn { generics, .. } => (generics, None, false), - hir::ItemKind::Trait(_, _, generics, supertraits, _) => { + hir::ItemKind::Trait(_, _, _, generics, supertraits, _) => { (generics, Some((item.owner_id.def_id, supertraits)), false) } _ => bug!("const_conditions called on wrong item: {def_id:?}"), diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 883a1acdb30..9b0d57bd75b 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -617,7 +617,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { }); } - hir::ItemKind::ExternCrate(_) + hir::ItemKind::ExternCrate(..) | hir::ItemKind::Use(..) | hir::ItemKind::Macro(..) | hir::ItemKind::Mod(..) @@ -627,13 +627,13 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { // These sorts of items have no lifetime parameters at all. intravisit::walk_item(self, item); } - hir::ItemKind::TyAlias(_, generics) - | hir::ItemKind::Const(_, generics, _) - | hir::ItemKind::Enum(_, generics) - | hir::ItemKind::Struct(_, generics) - | hir::ItemKind::Union(_, generics) - | hir::ItemKind::Trait(_, _, generics, ..) - | hir::ItemKind::TraitAlias(generics, ..) + hir::ItemKind::TyAlias(_, _, generics) + | hir::ItemKind::Const(_, _, generics, _) + | hir::ItemKind::Enum(_, _, generics) + | hir::ItemKind::Struct(_, _, generics) + | hir::ItemKind::Union(_, _, generics) + | hir::ItemKind::Trait(_, _, _, generics, ..) + | hir::ItemKind::TraitAlias(_, generics, ..) | hir::ItemKind::Impl(&hir::Impl { generics, .. }) => { // These kinds of items have only early-bound lifetime parameters. self.visit_early(item.hir_id(), generics, |this| intravisit::walk_item(this, item)); diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 16caa4f6874..afda2c142e2 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -5,10 +5,9 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::VisitorExt; use rustc_hir::{self as hir, AmbigArg, HirId}; use rustc_middle::query::plumbing::CyclePlaceholder; -use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::print::with_forced_trimmed_paths; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, fold_regions}; use rustc_middle::{bug, span_bug}; use rustc_span::{DUMMY_SP, Ident, Span}; @@ -203,35 +202,35 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ }, Node::Item(item) => match item.kind { - ItemKind::Static(ty, .., body_id) => { + ItemKind::Static(ident, ty, .., body_id) => { if ty.is_suggestable_infer_ty() { infer_placeholder_type( icx.lowerer(), def_id, body_id, ty.span, - item.ident, + ident, "static variable", ) } else { icx.lower_ty(ty) } } - ItemKind::Const(ty, _, body_id) => { + ItemKind::Const(ident, ty, _, body_id) => { if ty.is_suggestable_infer_ty() { infer_placeholder_type( icx.lowerer(), def_id, body_id, ty.span, - item.ident, + ident, "constant", ) } else { icx.lower_ty(ty) } } - ItemKind::TyAlias(self_ty, _) => icx.lower_ty(self_ty), + ItemKind::TyAlias(_, self_ty, _) => icx.lower_ty(self_ty), ItemKind::Impl(hir::Impl { self_ty, .. }) => match self_ty.find_self_aliases() { spans if spans.len() > 0 => { let guar = tcx @@ -480,5 +479,5 @@ pub(crate) fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> } } } - HasTait.visit_ty_unambig(tcx.hir_expect_item(def_id).expect_ty_alias().0).is_break() + HasTait.visit_ty_unambig(tcx.hir_expect_item(def_id).expect_ty_alias().1).is_break() } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index 142078900f0..3dec1e286b4 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -258,9 +258,6 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> { self.tcx } fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { - if let hir::ExprKind::Closure(closure) = ex.kind { - self.check(closure.def_id); - } intravisit::walk_expr(self, ex); } fn visit_item(&mut self, it: &'tcx Item<'tcx>) { @@ -371,14 +368,8 @@ impl RpitConstraintChecker<'_> { // Use borrowck to get the type with unerased regions. let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types; debug!(?concrete_opaque_types); - for (&def_id, &concrete_type) in concrete_opaque_types { - if def_id != self.def_id { - // Ignore constraints for other opaque types. - continue; - } - + if let Some(&concrete_type) = concrete_opaque_types.get(&self.def_id) { debug!(?concrete_type, "found constraint"); - if concrete_type.ty != self.found.ty { if let Ok(d) = self.found.build_mismatch_error(&concrete_type, self.tcx) { d.emit(); @@ -395,9 +386,6 @@ impl<'tcx> intravisit::Visitor<'tcx> for RpitConstraintChecker<'tcx> { self.tcx } fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { - if let hir::ExprKind::Closure(closure) = ex.kind { - self.check(closure.def_id); - } intravisit::walk_expr(self, ex); } fn visit_item(&mut self, it: &'tcx Item<'tcx>) { diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs index 6a9ae0de1c1..53866aa27b1 100644 --- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs +++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs @@ -1,9 +1,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; -use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitor}; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitor}; use rustc_span::Span; -use rustc_type_ir::fold::TypeFoldable; use tracing::debug; #[derive(Clone, PartialEq, Eq, Hash, Debug)] diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index 78b20f9897c..b907ec090e5 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -7,10 +7,10 @@ use std::assert_matches::debug_assert_matches; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{ + self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, +}; use rustc_span::{ErrorGuaranteed, Span}; -use rustc_type_ir::visit::TypeVisitableExt; type RemapTable = FxHashMap<u32, u32>; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 60af36da6e2..f0dffd780bc 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -8,10 +8,12 @@ use rustc_hir::HirId; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::bug; -use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt, Upcast}; +use rustc_middle::ty::{ + self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, + TypeVisitor, Upcast, +}; use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym}; use rustc_trait_selection::traits; -use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use smallvec::SmallVec; use tracing::{debug, instrument}; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index 5fed2e35287..170500c7a16 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -49,10 +49,12 @@ pub(crate) fn validate_cmse_abi<'tcx>( Ok(Err(index)) => { // fn(x: u32, u32, u32, u16, y: u16) -> u32, // ^^^^^^ - let span = bare_fn_ty.param_names[index] - .span - .to(bare_fn_ty.decl.inputs[index].span) - .to(bare_fn_ty.decl.inputs.last().unwrap().span); + let span = if let Some(ident) = bare_fn_ty.param_names[index] { + ident.span.to(bare_fn_ty.decl.inputs[index].span) + } else { + bare_fn_ty.decl.inputs[index].span + } + .to(bare_fn_ty.decl.inputs.last().unwrap().span); let plural = bare_fn_ty.param_names.len() - index != 1; dcx.emit_err(errors::CmseInputsStackSpill { span, plural, abi }); } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 3eb4945ebf8..27643e715e6 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -4,15 +4,14 @@ use rustc_errors::struct_span_code_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS; -use rustc_middle::ty::fold::BottomUpFolder; +use rustc_middle::ty::elaborate::ClauseWithSupertraitSpan; use rustc_middle::ty::{ - self, DynKind, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable, + self, BottomUpFolder, DynKind, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast, }; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility; use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations}; -use rustc_type_ir::elaborate::ClauseWithSupertraitSpan; use smallvec::{SmallVec, smallvec}; use tracing::{debug, instrument}; @@ -177,7 +176,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .in_definition_order() // We only care about associated types. .filter(|item| item.kind == ty::AssocKind::Type) - // No RPITITs -- even with `async_fn_in_dyn_trait`, they are implicit. + // No RPITITs -- they're not dyn-compatible for now. .filter(|item| !item.is_impl_trait_in_trait()) // If the associated type has a `where Self: Sized` bound, // we do not need to constrain the associated type. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index fa061c80618..3b007c77198 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -901,12 +901,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .iter() .map(|(item, _)| format!("{} = Type", item.name)) .collect(); - let code = if snippet.ends_with('>') { + let code = if let Some(snippet) = snippet.strip_suffix('>') { // The user wrote `Trait<'a>` or similar and we don't have a type we can // suggest, but at least we can clue them to the correct syntax // `Trait<'a, Item = Type>` while accounting for the `<'a>` in the // suggestion. - format!("{}, {}>", &snippet[..snippet.len() - 1], types.join(", ")) + format!("{}, {}>", snippet, types.join(", ")) } else if in_expr_or_pat { // The user wrote `Iterator`, so we don't have a type we can suggest, but at // least we can clue them to the correct syntax `Iterator::<Item = Type>`. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index e78801dd601..55886312284 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -140,14 +140,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let generics = match tcx.hir_node_by_def_id(parent_item) { hir::Node::Item(hir::Item { - kind: hir::ItemKind::Struct(variant, generics), .. + kind: hir::ItemKind::Struct(_, variant, generics), + .. }) => { if !variant.fields().iter().any(|field| field.hir_id == parent_hir_id) { return false; } generics } - hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(def, generics), .. }) => { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, def, generics), .. }) => { if !def .variants .iter() @@ -267,7 +268,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::Node::Field(field) => { // Enums can't have unsized fields, fields can only have an unsized tail field. if let hir::Node::Item(hir::Item { - kind: hir::ItemKind::Struct(variant, _), .. + kind: hir::ItemKind::Struct(_, variant, _), .. }) = tcx.parent_hir_node(field.hir_id) && variant .fields() @@ -411,14 +412,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Applicability::MachineApplicable, ); if !is_dyn_compatible { - diag.note(format!("`{trait_name}` it is dyn-incompatible, so it can't be `dyn`")); + diag.note(format!( + "`{trait_name}` is dyn-incompatible, otherwise a trait object could be used" + )); } else { // No ampersand in suggestion if it's borrowed already let (dyn_str, paren_dyn_str) = if borrowed { ("dyn ", "(dyn ") } else { ("&dyn ", "&(dyn ") }; let sugg = if let hir::TyKind::TraitObject([_, _, ..], _) = self_ty.kind { - // There are more than one trait bound, we need surrounding parentheses. + // There is more than one trait bound, we need surrounding parentheses. vec![ (self_ty.span.shrink_to_lo(), paren_dyn_str.to_string()), (self_ty.span.shrink_to_hi(), ")".to_string()), diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 8fff6eb9f6e..76a880da418 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -36,11 +36,10 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::mir::interpret::LitToConstInput; -use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::print::PrintPolyTraitRefExt as _; use rustc_middle::ty::{ self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt, - TypeVisitableExt, TypingMode, + TypeVisitableExt, TypingMode, Upcast, fold_regions, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; @@ -50,7 +49,6 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::wf::object_region_bounds; use rustc_trait_selection::traits::{self, ObligationCtxt}; -use rustc_type_ir::Upcast; use tracing::{debug, instrument}; use self::errors::assoc_kind_str; diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index 0b1be8e4f7a..e27a81d4976 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -4,8 +4,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ObligationCause, WellFormedLoc}; use rustc_middle::bug; use rustc_middle::query::Providers; -use rustc_middle::ty::fold::fold_regions; -use rustc_middle::ty::{self, TyCtxt, TypingMode}; +use rustc_middle::ty::{self, TyCtxt, TypingMode, fold_regions}; use rustc_span::def_id::LocalDefId; use rustc_trait_selection::traits::{self, ObligationCtxt}; use tracing::debug; @@ -137,9 +136,9 @@ fn diagnostic_hir_wf_check<'tcx>( ref item => bug!("Unexpected TraitItem {:?}", item), }, hir::Node::Item(item) => match item.kind { - hir::ItemKind::TyAlias(ty, _) - | hir::ItemKind::Static(ty, _, _) - | hir::ItemKind::Const(ty, _, _) => vec![ty], + hir::ItemKind::TyAlias(_, ty, _) + | hir::ItemKind::Static(_, ty, _, _) + | hir::ItemKind::Const(_, ty, _, _) => vec![ty], hir::ItemKind::Impl(impl_) => match &impl_.of_trait { Some(t) => t .path diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index cb3cdc5e8d3..e7ecd727a85 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -252,7 +252,9 @@ pub fn lower_ty<'tcx>(tcx: TyCtxt<'tcx>, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { // def-ID that will be used to determine the traits/predicates in // scope. This is derived from the enclosing item-like thing. let env_def_id = tcx.hir_get_parent_item(hir_ty.hir_id); - collect::ItemCtxt::new(tcx, env_def_id.def_id).lower_ty(hir_ty) + collect::ItemCtxt::new(tcx, env_def_id.def_id) + .lowerer() + .lower_ty_maybe_return_type_notation(hir_ty) } /// This is for rustdoc. diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs index 0c9f5ba8b6f..d0a2a2230ab 100644 --- a/compiler/rustc_hir_analysis/src/outlives/utils.rs +++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs @@ -1,8 +1,8 @@ use rustc_data_structures::fx::FxIndexMap; +use rustc_middle::ty::outlives::{Component, push_outlives_components}; use rustc_middle::ty::{self, GenericArg, GenericArgKind, Region, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_span::Span; -use rustc_type_ir::outlives::{Component, push_outlives_components}; use smallvec::smallvec; /// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 3067766fb4d..ddaca89ccf8 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2,6 +2,7 @@ //! the definitions in this file have equivalents in `rustc_ast_pretty`. // tidy-alphabetical-start +#![feature(let_chains)] #![recursion_limit = "256"] // tidy-alphabetical-end @@ -559,7 +560,7 @@ impl<'a> State<'a> { self.print_attrs_as_outer(attrs); self.ann.pre(self, AnnNode::Item(item)); match item.kind { - hir::ItemKind::ExternCrate(orig_name) => { + hir::ItemKind::ExternCrate(orig_name, ident) => { self.head("extern crate"); if let Some(orig_name) = orig_name { self.print_name(orig_name); @@ -567,7 +568,7 @@ impl<'a> State<'a> { self.word("as"); self.space(); } - self.print_ident(item.ident); + self.print_ident(ident); self.word(";"); self.end(); // end inner head-block self.end(); // end outer head-block @@ -577,11 +578,11 @@ impl<'a> State<'a> { self.print_path(path, false); match kind { - hir::UseKind::Single => { - if path.segments.last().unwrap().ident != item.ident { + hir::UseKind::Single(ident) => { + if path.segments.last().unwrap().ident != ident { self.space(); self.word_space("as"); - self.print_ident(item.ident); + self.print_ident(ident); } self.word(";"); } @@ -591,12 +592,12 @@ impl<'a> State<'a> { self.end(); // end inner head-block self.end(); // end outer head-block } - hir::ItemKind::Static(ty, m, expr) => { + hir::ItemKind::Static(ident, ty, m, expr) => { self.head("static"); if m.is_mut() { self.word_space("mut"); } - self.print_ident(item.ident); + self.print_ident(ident); self.word_space(":"); self.print_type(ty); self.space(); @@ -607,9 +608,9 @@ impl<'a> State<'a> { self.word(";"); self.end(); // end the outer cbox } - hir::ItemKind::Const(ty, generics, expr) => { + hir::ItemKind::Const(ident, ty, generics, expr) => { self.head("const"); - self.print_ident(item.ident); + self.print_ident(ident); self.print_generic_params(generics.params); self.word_space(":"); self.print_type(ty); @@ -622,30 +623,23 @@ impl<'a> State<'a> { self.word(";"); self.end(); // end the outer cbox } - hir::ItemKind::Fn { sig, generics, body, .. } => { + hir::ItemKind::Fn { ident, sig, generics, body, .. } => { self.head(""); - self.print_fn( - sig.decl, - sig.header, - Some(item.ident.name), - generics, - &[], - Some(body), - ); + self.print_fn(sig.decl, sig.header, Some(ident.name), generics, &[], Some(body)); self.word(" "); self.end(); // need to close a box self.end(); // need to close a box self.ann.nested(self, Nested::Body(body)); } - hir::ItemKind::Macro(macro_def, _) => { - self.print_mac_def(macro_def, &item.ident, item.span, |_| {}); + hir::ItemKind::Macro(ident, macro_def, _) => { + self.print_mac_def(macro_def, &ident, item.span, |_| {}); } - hir::ItemKind::Mod(_mod) => { + hir::ItemKind::Mod(ident, mod_) => { self.head("mod"); - self.print_ident(item.ident); + self.print_ident(ident); self.nbsp(); self.bopen(); - self.print_mod(_mod, attrs); + self.print_mod(mod_, attrs); self.bclose(item.span); } hir::ItemKind::ForeignMod { abi, items } => { @@ -663,9 +657,9 @@ impl<'a> State<'a> { self.print_inline_asm(asm); self.end() } - hir::ItemKind::TyAlias(ty, generics) => { + hir::ItemKind::TyAlias(ident, ty, generics) => { self.head("type"); - self.print_ident(item.ident); + self.print_ident(ident); self.print_generic_params(generics.params); self.end(); // end the inner ibox @@ -676,16 +670,16 @@ impl<'a> State<'a> { self.word(";"); self.end(); // end the outer ibox } - hir::ItemKind::Enum(ref enum_definition, params) => { - self.print_enum_def(enum_definition, params, item.ident.name, item.span); + hir::ItemKind::Enum(ident, ref enum_definition, params) => { + self.print_enum_def(enum_definition, params, ident.name, item.span); } - hir::ItemKind::Struct(ref struct_def, generics) => { + hir::ItemKind::Struct(ident, ref struct_def, generics) => { self.head("struct"); - self.print_struct(struct_def, generics, item.ident.name, item.span, true); + self.print_struct(struct_def, generics, ident.name, item.span, true); } - hir::ItemKind::Union(ref struct_def, generics) => { + hir::ItemKind::Union(ident, ref struct_def, generics) => { self.head("union"); - self.print_struct(struct_def, generics, item.ident.name, item.span, true); + self.print_struct(struct_def, generics, ident.name, item.span, true); } hir::ItemKind::Impl(&hir::Impl { constness, @@ -733,12 +727,12 @@ impl<'a> State<'a> { } self.bclose(item.span); } - hir::ItemKind::Trait(is_auto, safety, generics, bounds, trait_items) => { + hir::ItemKind::Trait(is_auto, safety, ident, generics, bounds, trait_items) => { self.head(""); self.print_is_auto(is_auto); self.print_safety(safety); self.word_nbsp("trait"); - self.print_ident(item.ident); + self.print_ident(ident); self.print_generic_params(generics.params); self.print_bounds(":", bounds); self.print_where_clause(generics); @@ -749,9 +743,9 @@ impl<'a> State<'a> { } self.bclose(item.span); } - hir::ItemKind::TraitAlias(generics, bounds) => { + hir::ItemKind::TraitAlias(ident, generics, bounds) => { self.head("trait"); - self.print_ident(item.ident); + self.print_ident(ident); self.print_generic_params(generics.params); self.nbsp(); self.print_bounds("=", bounds); @@ -905,7 +899,7 @@ impl<'a> State<'a> { ident: Ident, m: &hir::FnSig<'_>, generics: &hir::Generics<'_>, - arg_names: &[Ident], + arg_names: &[Option<Ident>], body_id: Option<hir::BodyId>, ) { self.print_fn(m.decl, m.header, Some(ident.name), generics, arg_names, body_id); @@ -2128,7 +2122,7 @@ impl<'a> State<'a> { header: hir::FnHeader, name: Option<Symbol>, generics: &hir::Generics<'_>, - arg_names: &[Ident], + arg_names: &[Option<Ident>], body_id: Option<hir::BodyId>, ) { self.print_fn_header_info(header); @@ -2148,9 +2142,11 @@ impl<'a> State<'a> { s.print_implicit_self(&decl.implicit_self); } else { if let Some(arg_name) = arg_names.get(i) { - s.word(arg_name.to_string()); - s.word(":"); - s.space(); + if let Some(arg_name) = arg_name { + s.word(arg_name.to_string()); + s.word(":"); + s.space(); + } } else if let Some(body_id) = body_id { s.ann.nested(s, Nested::BodyParamPat(body_id, i)); s.word(":"); @@ -2456,7 +2452,7 @@ impl<'a> State<'a> { decl: &hir::FnDecl<'_>, name: Option<Symbol>, generic_params: &[hir::GenericParam<'_>], - arg_names: &[Ident], + arg_names: &[Option<Ident>], ) { self.ibox(INDENT_UNIT); self.print_formal_generic_params(generic_params); diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index f1afb7b712d..b2b90cb29e3 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -23,7 +23,6 @@ rustc_middle = { path = "../rustc_middle" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_trait_selection = { path = "../rustc_trait_selection" } -rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 2a24d626ac3..5e2daa69628 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -713,8 +713,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for id in self.tcx.hir_free_items() { if let Some(node) = self.tcx.hir_get_if_local(id.owner_id.into()) && let hir::Node::Item(item) = node - && let hir::ItemKind::Fn { .. } = item.kind - && item.ident.name == segment.ident.name + && let hir::ItemKind::Fn { ident, .. } = item.kind + && ident.name == segment.ident.name { err.span_label( self.tcx.def_span(id.owner_id), diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 5270c8ed356..8f5fddd19d7 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -40,13 +40,11 @@ use rustc_middle::mir::Mutability; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::cast::{CastKind, CastTy}; use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeAndMut, TypeVisitableExt, VariantDef}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeAndMut, TypeVisitableExt, VariantDef, elaborate}; use rustc_middle::{bug, span_bug}; use rustc_session::lint; -use rustc_span::def_id::LOCAL_CRATE; use rustc_span::{DUMMY_SP, Span, sym}; use rustc_trait_selection::infer::InferCtxtExt; -use rustc_type_ir::elaborate; use tracing::{debug, instrument}; use super::FnCtxt; @@ -806,7 +804,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { _ => return Err(CastError::NonScalar), }; if let ty::Adt(adt_def, _) = *self.expr_ty.kind() - && adt_def.did().krate != LOCAL_CRATE + && !adt_def.did().is_local() && adt_def.variants().iter().any(VariantDef::is_field_list_non_exhaustive) { return Err(CastError::ForeignNonExhaustiveAdt); diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 71a0664bbdf..a4776338f6c 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -12,13 +12,14 @@ use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, use rustc_infer::traits::{ObligationCauseCode, PredicateObligations}; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::span_bug; -use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; -use rustc_middle::ty::{self, GenericArgs, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor}; +use rustc_middle::ty::{ + self, ClosureKind, GenericArgs, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, + TypeVisitableExt, TypeVisitor, +}; use rustc_span::def_id::LocalDefId; use rustc_span::{DUMMY_SP, Span}; use rustc_trait_selection::error_reporting::traits::ArgKind; use rustc_trait_selection::traits; -use rustc_type_ir::ClosureKind; use tracing::{debug, instrument, trace}; use super::{CoroutineTypes, Expectation, FnCtxt, check_fn}; @@ -163,11 +164,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let resume_ty = liberated_sig.inputs().get(0).copied().unwrap_or(tcx.types.unit); let interior = self.next_ty_var(expr_span); - self.deferred_coroutine_interiors.borrow_mut().push(( - expr_def_id, - body.id(), - interior, - )); + self.deferred_coroutine_interiors.borrow_mut().push((expr_def_id, interior)); // Coroutines that come from coroutine closures have not yet determined // their kind ty, so make a fresh infer var which will be constrained diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index d7b5c1ed5e1..4cbc42b99ea 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -55,8 +55,7 @@ use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion, }; use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::visit::TypeVisitableExt; -use rustc_middle::ty::{self, AliasTy, GenericArgsRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, AliasTy, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span}; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index aa917ee07ff..41bdd0ca43e 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -6,9 +6,8 @@ use rustc_infer::infer::DefineOpaqueTypes; use rustc_middle::bug; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, AssocItem, Ty, TypeFoldable, TypeVisitableExt}; +use rustc_middle::ty::{self, AssocItem, BottomUpFolder, Ty, TypeFoldable, TypeVisitableExt}; use rustc_span::{DUMMY_SP, Ident, Span, sym}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::ObligationCause; @@ -722,8 +721,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, )) => { if let Some(hir::Node::Item(hir::Item { - ident, - kind: hir::ItemKind::Static(ty, ..) | hir::ItemKind::Const(ty, ..), + kind: + hir::ItemKind::Static(ident, ty, ..) + | hir::ItemKind::Const(ident, ty, ..), .. })) = self.tcx.hir_get_if_local(*def_id) { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 7c6bb495be3..a75f6f4caac 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1977,7 +1977,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Prohibit struct expressions when non-exhaustive flag is set. let adt = adt_ty.ty_adt_def().expect("`check_struct_path` returned non-ADT type"); - if !adt.did().is_local() && variant.is_field_list_non_exhaustive() { + if variant.field_list_has_applicable_non_exhaustive() { self.dcx() .emit_err(StructExprNonExhaustive { span: expr.span, what: adt.variant_descr() }); } @@ -2060,7 +2060,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // struct-like enums (yet...), but it's definitely not // a bug to have constructed one. if adt_kind != AdtKind::Enum { - tcx.check_stability(v_field.did, Some(expr.hir_id), field.span, None); + tcx.check_stability(v_field.did, Some(field.hir_id), field.span, None); } self.field_ty(field.span, v_field, args) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 35e687f2b0f..c71a5ea8b97 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -20,7 +20,7 @@ use rustc_middle::hir::place::ProjectionKind; pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection}; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::{ - self, AdtKind, BorrowKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, adjustment, + self, BorrowKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, adjustment, }; use rustc_middle::{bug, span_bug}; use rustc_span::{ErrorGuaranteed, Span}; @@ -1899,14 +1899,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx // to assume that more cases will be added to the variant in the future. This mean // that we should handle non-exhaustive SingleVariant the same way we would handle // a MultiVariant. - // If the variant is not local it must be defined in another crate. - let is_non_exhaustive = match def.adt_kind() { - AdtKind::Struct | AdtKind::Union => { - def.non_enum_variant().is_field_list_non_exhaustive() - } - AdtKind::Enum => def.is_variant_list_non_exhaustive(), - }; - def.variants().len() > 1 || (!def.did().is_local() && is_non_exhaustive) + def.variants().len() > 1 || def.variant_list_has_applicable_non_exhaustive() } else { false } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index c82f7a91168..d75c2853ba0 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -21,11 +21,9 @@ use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryRespons use rustc_infer::infer::{DefineOpaqueTypes, InferResult}; use rustc_lint::builtin::SELF_CONSTRUCTOR_FROM_OUTER_ITEM; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; -use rustc_middle::ty::fold::TypeFoldable; -use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::{ self, AdtKind, CanonicalUserType, GenericArgKind, GenericArgsRef, GenericParamDefKind, - IsIdentity, Ty, TyCtxt, UserArgs, UserSelfTy, + IsIdentity, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitableExt, UserArgs, UserSelfTy, }; use rustc_middle::{bug, span_bug}; use rustc_session::lint; @@ -635,18 +633,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let coroutines = std::mem::take(&mut *self.deferred_coroutine_interiors.borrow_mut()); debug!(?coroutines); - for &(expr_def_id, body_id, interior) in coroutines.iter() { - debug!(?expr_def_id); + let mut obligations = vec![]; + + for &(coroutine_def_id, interior) in coroutines.iter() { + debug!(?coroutine_def_id); // Create the `CoroutineWitness` type that we will unify with `interior`. let args = ty::GenericArgs::identity_for_item( self.tcx, - self.tcx.typeck_root_def_id(expr_def_id.to_def_id()), + self.tcx.typeck_root_def_id(coroutine_def_id.to_def_id()), ); - let witness = Ty::new_coroutine_witness(self.tcx, expr_def_id.to_def_id(), args); + let witness = Ty::new_coroutine_witness(self.tcx, coroutine_def_id.to_def_id(), args); // Unify `interior` with `witness` and collect all the resulting obligations. - let span = self.tcx.hir_body(body_id).value.span; + let span = self.tcx.hir_body_owned_by(coroutine_def_id).value.span; let ty::Infer(ty::InferTy::TyVar(_)) = interior.kind() else { span_bug!(span, "coroutine interior witness not infer: {:?}", interior.kind()) }; @@ -655,15 +655,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Will never define opaque types, as all we do is instantiate a type variable. .eq(DefineOpaqueTypes::Yes, interior, witness) .expect("Failed to unify coroutine interior type"); - let mut obligations = ok.obligations; - // Also collect the obligations that were unstalled by this unification. + obligations.extend(ok.obligations); + } + + // FIXME: Use a real visitor for unstalled obligations in the new solver. + if !coroutines.is_empty() { obligations .extend(self.fulfillment_cx.borrow_mut().drain_unstalled_obligations(&self.infcx)); - - let obligations = obligations.into_iter().map(|o| (o.predicate, o.cause)); - self.typeck_results.borrow_mut().coroutine_stalled_predicates.extend(obligations); } + + self.typeck_results + .borrow_mut() + .coroutine_stalled_predicates + .extend(obligations.into_iter().map(|o| (o.predicate, o.cause))); } #[instrument(skip(self), level = "debug")] diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index b8517701667..f4bd7ec701f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -15,11 +15,10 @@ use rustc_index::IndexVec; use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TypeTrace}; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::visit::TypeVisitableExt; -use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt}; +use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; use rustc_session::Session; -use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; +use rustc_span::{DUMMY_SP, Ident, Span, kw, sym}; use rustc_trait_selection::error_reporting::infer::{FailureCode, ObligationCauseExt}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext}; @@ -1136,7 +1135,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && self.tcx.def_kind(fn_def_id).is_fn_like() && let self_implicit = matches!(call_expr.kind, hir::ExprKind::MethodCall(..)) as usize - && let Some(arg) = + && let Some(Some(arg)) = self.tcx.fn_arg_names(fn_def_id).get(expected_idx.as_usize() + self_implicit) && arg.name != kw::SelfLower { @@ -2679,7 +2678,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { params.get(is_method as usize..params.len() - sig.decl.c_variadic as usize)?; debug_assert_eq!(params.len(), fn_inputs.len()); Some(( - fn_inputs.zip(params.iter().map(|param| FnParam::Name(param))).collect(), + fn_inputs.zip(params.iter().map(|&ident| FnParam::Name(ident))).collect(), generics, )) } @@ -2710,23 +2709,20 @@ impl<'tcx> Visitor<'tcx> for FindClosureArg<'tcx> { #[derive(Clone, Copy)] enum FnParam<'hir> { Param(&'hir hir::Param<'hir>), - Name(&'hir Ident), + Name(Option<Ident>), } + impl FnParam<'_> { fn span(&self) -> Span { match self { - Self::Param(x) => x.span, - Self::Name(x) => x.span, - } - } - - fn name(&self) -> Option<Symbol> { - match self { - Self::Param(x) if let hir::PatKind::Binding(_, _, ident, _) = x.pat.kind => { - Some(ident.name) + Self::Param(param) => param.span, + Self::Name(ident) => { + if let Some(ident) = ident { + ident.span + } else { + DUMMY_SP + } } - Self::Name(x) if x.name != kw::Empty => Some(x.name), - _ => None, } } @@ -2734,8 +2730,24 @@ impl FnParam<'_> { struct D<'a>(FnParam<'a>, usize); impl fmt::Display for D<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Some(name) = self.0.name() { - write!(f, "`{name}`") + // A "unique" param name is one that (a) exists, and (b) is guaranteed to be unique + // among the parameters, i.e. `_` does not count. + let unique_name = match self.0 { + FnParam::Param(param) + if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind => + { + Some(ident.name) + } + FnParam::Name(ident) + if let Some(ident) = ident + && ident.name != kw::Underscore => + { + Some(ident.name) + } + _ => None, + }; + if let Some(unique_name) = unique_name { + write!(f, "`{unique_name}`") } else { write!(f, "parameter #{}", self.1 + 1) } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs index dc10b53fd83..95b9cb3be62 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs @@ -1,13 +1,12 @@ //! A utility module to inspect currently ambiguous obligations in the current context. use rustc_infer::traits::{self, ObligationCause, PredicateObligations}; -use rustc_middle::traits::solve::Goal; +use rustc_middle::traits::solve::{Goal, GoalSource}; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_span::Span; use rustc_trait_selection::solve::inspect::{ InspectConfig, InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor, }; -use rustc_type_ir::solve::GoalSource; use tracing::{debug, instrument, trace}; use crate::FnCtxt; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 37aaaed5477..264719ca569 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -904,7 +904,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Assumes given function doesn't have a explicit return type. fn can_add_return_type(&self, fn_id: LocalDefId) -> bool { match self.tcx.hir_node_by_def_id(fn_id) { - Node::Item(&hir::Item { ident, .. }) => { + Node::Item(item) => { + let (ident, _, _, _) = item.expect_fn(); // This is less than ideal, it will not suggest a return type span on any // method called `main`, regardless of whether it is actually the entry point, // but it will still present it as the reason for the expected type. @@ -1532,30 +1533,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.may_coerce(blk_ty, *elem_ty) && blk.stmts.is_empty() && blk.rules == hir::BlockCheckMode::DefaultBlock + && let source_map = self.tcx.sess.source_map() + && let Ok(snippet) = source_map.span_to_snippet(blk.span) + && snippet.starts_with('{') + && snippet.ends_with('}') { - let source_map = self.tcx.sess.source_map(); - if let Ok(snippet) = source_map.span_to_snippet(blk.span) { - if snippet.starts_with('{') && snippet.ends_with('}') { - diag.multipart_suggestion_verbose( - "to create an array, use square brackets instead of curly braces", - vec![ - ( - blk.span - .shrink_to_lo() - .with_hi(rustc_span::BytePos(blk.span.lo().0 + 1)), - "[".to_string(), - ), - ( - blk.span - .shrink_to_hi() - .with_lo(rustc_span::BytePos(blk.span.hi().0 - 1)), - "]".to_string(), - ), - ], - Applicability::MachineApplicable, - ); - } - } + diag.multipart_suggestion_verbose( + "to create an array, use square brackets instead of curly braces", + vec![ + ( + blk.span + .shrink_to_lo() + .with_hi(rustc_span::BytePos(blk.span.lo().0 + 1)), + "[".to_string(), + ), + ( + blk.span + .shrink_to_hi() + .with_lo(rustc_span::BytePos(blk.span.hi().0 - 1)), + "]".to_string(), + ), + ], + Applicability::MachineApplicable, + ); } } } @@ -2983,7 +2983,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return false; } - let Ok(src) = self.tcx.sess.source_map().span_to_snippet(expr.span) else { + let span = if let hir::ExprKind::Lit(lit) = &expr.kind { lit.span } else { expr.span }; + let Ok(src) = self.tcx.sess.source_map().span_to_snippet(span) else { return false; }; @@ -3078,10 +3079,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Remove fractional part from literal, for example `42.0f32` into `42` let src = src.trim_end_matches(&checked_ty.to_string()); let len = src.split('.').next().unwrap().len(); - expr.span.with_lo(expr.span.lo() + BytePos(len as u32)) + span.with_lo(span.lo() + BytePos(len as u32)) } else { let len = src.trim_end_matches(&checked_ty.to_string()).len(); - expr.span.with_lo(expr.span.lo() + BytePos(len as u32)) + span.with_lo(span.lo() + BytePos(len as u32)) }, if expr.precedence() < ExprPrecedence::Unambiguous { // Readd `)` diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 0483164ca03..a614b4f00ff 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -15,9 +15,9 @@ use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCoercion, }; -use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{ - self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, UserArgs, + self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, + TypeVisitableExt, UserArgs, }; use rustc_middle::{bug, span_bug}; use rustc_span::{DUMMY_SP, Span}; diff --git a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs index 72f8793d783..0037d5ac042 100644 --- a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs +++ b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs @@ -367,20 +367,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .collect(); // Find an identifier with which this trait was imported (note that `_` doesn't count). - let any_id = import_items.iter().find_map(|item| { - if item.ident.name != kw::Underscore { Some(item.ident) } else { None } - }); - if let Some(any_id) = any_id { - if any_id.name == kw::Empty { - // Glob import, so just use its name. - return None; - } else { - return Some(format!("{any_id}")); + for item in import_items.iter() { + let (_, kind) = item.expect_use(); + match kind { + hir::UseKind::Single(ident) => { + if ident.name != kw::Underscore { + return Some(format!("{}", ident.name)); + } + } + hir::UseKind::Glob => return None, // Glob import, so just use its name. + hir::UseKind::ListStem => unreachable!(), } } - // All that is left is `_`! We need to use the full path. It doesn't matter which one we pick, - // so just take the first one. + // All that is left is `_`! We need to use the full path. It doesn't matter which one we + // pick, so just take the first one. match import_items[0].kind { ItemKind::Use(path, _) => Some( path.segments diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index ee01d78965d..0a01ec89a32 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -14,6 +14,7 @@ use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk, TyCtxtInferExt}; use rustc_infer::traits::ObligationCauseCode; use rustc_middle::middle::stability; use rustc_middle::query::Providers; +use rustc_middle::ty::elaborate::supertrait_def_ids; use rustc_middle::ty::fast_reject::{TreatParams, simplify_type}; use rustc_middle::ty::{ self, AssocItem, AssocItemContainer, GenericArgs, GenericArgsRef, GenericParamDefKind, @@ -34,7 +35,6 @@ use rustc_trait_selection::traits::query::method_autoderef::{ CandidateStep, MethodAutoderefBadTy, MethodAutoderefStepsResult, }; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt}; -use rustc_type_ir::elaborate::supertrait_def_ids; use smallvec::{SmallVec, smallvec}; use tracing::{debug, instrument}; diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 1a1540f505d..908c3ee2eb8 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -533,7 +533,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } _ => { - intravisit::walk_pat(self, p); + let _ = intravisit::walk_pat(self, p); } } ControlFlow::Continue(()) @@ -556,7 +556,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { method_name, sugg_let: None, }; - let_visitor.visit_body(&body); + let _ = let_visitor.visit_body(&body); if let Some(sugg_let) = let_visitor.sugg_let && let Some(self_ty) = self.node_ty_opt(sugg_let.init_hir_id) { @@ -1204,13 +1204,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } Some( Node::Item(hir::Item { - ident, - kind: hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..), + kind: + hir::ItemKind::Trait(_, _, ident, ..) + | hir::ItemKind::TraitAlias(ident, ..), .. }) // We may also encounter unsatisfied GAT or method bounds | Node::TraitItem(hir::TraitItem { ident, .. }) - | Node::ImplItem(hir::ImplItem { ident, .. }), + | Node::ImplItem(hir::ImplItem { ident, .. }) ) => { skip_list.insert(p); let entry = spanned_predicates.entry(ident.span); @@ -3765,7 +3766,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let self_first_arg = match method { hir::TraitFn::Required([ident, ..]) => { - ident.name == kw::SelfLower + matches!(ident, Some(Ident { name: kw::SelfLower, .. })) } hir::TraitFn::Provided(body_id) => { self.tcx.hir_body(*body_id).params.first().is_some_and( @@ -3960,8 +3961,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } Node::Item(hir::Item { - kind: hir::ItemKind::Trait(.., bounds, _), - ident, + kind: hir::ItemKind::Trait(_, _, ident, _, bounds, _), .. }) => { let (sp, sep, article) = if bounds.is_empty() { diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 1750c2af1c7..a473e14b244 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -15,7 +15,6 @@ use rustc_span::source_map::Spanned; use rustc_span::{Ident, Span, sym}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{FulfillmentError, Obligation, ObligationCtxt}; -use rustc_type_ir::TyKind::*; use tracing::debug; use {rustc_ast as ast, rustc_hir as hir}; @@ -519,7 +518,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { suggest_deref_binop(&mut err, lhs_deref_ty); } else if is_assign == IsAssign::No - && let Ref(region, lhs_deref_ty, mutbl) = lhs_ty.kind() + && let ty::Ref(region, lhs_deref_ty, mutbl) = lhs_ty.kind() { if self.type_is_copy_modulo_regions(self.param_env, *lhs_deref_ty) { suggest_deref_binop(&mut err, *lhs_deref_ty); @@ -536,7 +535,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, ); - if let Ref(region, rhs_deref_ty, mutbl) = rhs_ty.kind() { + if let ty::Ref(region, rhs_deref_ty, mutbl) = rhs_ty.kind() { let rhs_inv_mutbl = mutbl.invert(); let rhs_inv_mutbl_ty = Ty::new_ref(self.tcx, *region, *rhs_deref_ty, rhs_inv_mutbl); @@ -726,12 +725,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { |ty: Ty<'tcx>| ty.ty_adt_def().is_some_and(|ty_def| Some(ty_def.did()) == string_type); match (lhs_ty.kind(), rhs_ty.kind()) { - (&Ref(_, l_ty, _), &Ref(_, r_ty, _)) // &str or &String + &str, &String or &&str - if (*l_ty.kind() == Str || is_std_string(l_ty)) - && (*r_ty.kind() == Str + (&ty::Ref(_, l_ty, _), &ty::Ref(_, r_ty, _)) // &str or &String + &str, &String or &&str + if (*l_ty.kind() == ty::Str || is_std_string(l_ty)) + && (*r_ty.kind() == ty::Str || is_std_string(r_ty) || matches!( - r_ty.kind(), Ref(_, inner_ty, _) if *inner_ty.kind() == Str + r_ty.kind(), ty::Ref(_, inner_ty, _) if *inner_ty.kind() == ty::Str )) => { if let IsAssign::No = is_assign { // Do not supply this message if `&str += &str` @@ -755,8 +754,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } true } - (&Ref(_, l_ty, _), &Adt(..)) // Handle `&str` & `&String` + `String` - if (*l_ty.kind() == Str || is_std_string(l_ty)) && is_std_string(rhs_ty) => + (&ty::Ref(_, l_ty, _), &ty::Adt(..)) // Handle `&str` & `&String` + `String` + if (*l_ty.kind() == ty::Str || is_std_string(l_ty)) && is_std_string(rhs_ty) => { err.span_label( op.span, @@ -847,7 +846,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); } else { match actual.kind() { - Uint(_) if op == hir::UnOp::Neg => { + ty::Uint(_) if op == hir::UnOp::Neg => { err.note("unsigned values cannot be negated"); if let hir::ExprKind::Unary( @@ -881,8 +880,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } } - Str | Never | Char | Tuple(_) | Array(_, _) => {} - Ref(_, lty, _) if *lty.kind() == Str => {} + ty::Str | ty::Never | ty::Char | ty::Tuple(_) | ty::Array(_, _) => {} + ty::Ref(_, lty, _) if *lty.kind() == ty::Str => {} _ => { self.note_unmet_impls_on_type(&mut err, errors, true); } diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 7e6973259fe..f1f956779c9 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1250,7 +1250,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match opt_def_id { Some(def_id) => match self.tcx.hir_get_if_local(def_id) { Some(hir::Node::Item(hir::Item { - kind: hir::ItemKind::Const(_, _, body_id), + kind: hir::ItemKind::Const(_, _, _, body_id), .. })) => match self.tcx.hir_node(body_id.hir_id) { hir::Node::Expr(expr) => { @@ -1422,7 +1422,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.check_stability( variant.fields[FieldIdx::from_usize(i)].did, - Some(pat.hir_id), + Some(subpat.hir_id), subpat.span, None, ); @@ -1686,7 +1686,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .get(&ident) .map(|(i, f)| { self.write_field_index(field.hir_id, *i); - self.tcx.check_stability(f.did, Some(pat.hir_id), span, None); + self.tcx.check_stability(f.did, Some(field.hir_id), span, None); self.field_ty(span, f, args) }) .unwrap_or_else(|| { @@ -1724,7 +1724,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Require `..` if struct has non_exhaustive attribute. - let non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did().is_local(); + let non_exhaustive = variant.field_list_has_applicable_non_exhaustive(); if non_exhaustive && !has_rest_pat { self.error_foreign_non_exhaustive_spat(pat, adt.variant_descr(), fields.is_empty()); } diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs index 381606a9fb0..5b4fc51cec8 100644 --- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs +++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs @@ -7,8 +7,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_hir::{HirId, HirIdMap}; use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use rustc_middle::span_bug; -use rustc_middle::ty::visit::TypeVisitableExt; -use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode}; use rustc_span::Span; use rustc_span::def_id::LocalDefIdMap; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; @@ -60,7 +59,7 @@ pub(crate) struct TypeckRootCtxt<'tcx> { pub(super) deferred_asm_checks: RefCell<Vec<(&'tcx hir::InlineAsm<'tcx>, HirId)>>, - pub(super) deferred_coroutine_interiors: RefCell<Vec<(LocalDefId, hir::BodyId, Ty<'tcx>)>>, + pub(super) deferred_coroutine_interiors: RefCell<Vec<(LocalDefId, Ty<'tcx>)>>, pub(super) deferred_repeat_expr_checks: RefCell<Vec<(&'tcx hir::Expr<'tcx>, Ty<'tcx>, ty::Const<'tcx>)>>, diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 37f3786c00a..fc98a603dd8 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -1862,8 +1862,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// (1.) Are we borrowing data owned by the parent closure? We can determine if /// that is the case by checking if the parent capture is by move, EXCEPT if we -/// apply a deref projection, which means we're reborrowing a reference that we -/// captured by move. +/// apply a deref projection of an immutable reference, reborrows of immutable +/// references which aren't restricted to the LUB of the lifetimes of the deref +/// chain. This is why `&'short mut &'long T` can be reborrowed as `&'long T`. /// /// ```rust /// let x = &1i32; // Let's call this lifetime `'1`. @@ -1902,10 +1903,22 @@ fn should_reborrow_from_env_of_parent_coroutine_closure<'tcx>( ) -> bool { // (1.) (!parent_capture.is_by_ref() - && !matches!( - child_capture.place.projections.get(parent_capture.place.projections.len()), - Some(Projection { kind: ProjectionKind::Deref, .. }) - )) + // This is just inlined `place.deref_tys()` but truncated to just + // the child projections. Namely, look for a `&T` deref, since we + // can always extend `&'short mut &'long T` to `&'long T`. + && !child_capture + .place + .projections + .iter() + .enumerate() + .skip(parent_capture.place.projections.len()) + .any(|(idx, proj)| { + matches!(proj.kind, ProjectionKind::Deref) + && matches!( + child_capture.place.ty_before_projection(idx).kind(), + ty::Ref(.., ty::Mutability::Not) + ) + })) // (2.) || matches!(child_capture.info.capture_kind, UpvarCapture::ByRef(ty::BorrowKind::Mutable)) } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index d7d7d6a20ac..6a3417ae5d6 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -11,9 +11,9 @@ use rustc_hir::{self as hir, AmbigArg, HirId}; use rustc_middle::span_bug; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; -use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, fold_regions}; -use rustc_middle::ty::visit::TypeVisitableExt; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperFoldable}; +use rustc_middle::ty::{ + self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, fold_regions, +}; use rustc_span::{Span, sym}; use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded; use rustc_trait_selection::solve; diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs index 048981f0d5c..7b1eb0a82e3 100644 --- a/compiler/rustc_incremental/src/persist/work_product.rs +++ b/compiler/rustc_incremental/src/persist/work_product.rs @@ -3,7 +3,7 @@ //! [work products]: WorkProduct use std::fs as std_fs; -use std::path::Path; +use std::path::{Path, PathBuf}; use rustc_data_structures::unord::UnordMap; use rustc_fs_util::link_or_copy; @@ -20,6 +20,7 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( sess: &Session, cgu_name: &str, files: &[(&'static str, &Path)], + known_links: &[PathBuf], ) -> Option<(WorkProductId, WorkProduct)> { debug!(?cgu_name, ?files); sess.opts.incremental.as_ref()?; @@ -28,6 +29,10 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( for (ext, path) in files { let file_name = format!("{cgu_name}.{ext}"); let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name); + if known_links.contains(&path_in_incr_dir) { + let _ = saved_files.insert(ext.to_string(), file_name); + continue; + } match link_or_copy(path, &path_in_incr_dir) { Ok(_) => { let _ = saved_files.insert(ext.to_string(), file_name); diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 598409c9051..07934389158 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -7,7 +7,7 @@ use std::{fmt, iter, slice}; use Chunk::*; #[cfg(feature = "nightly")] -use rustc_macros::{Decodable_Generic, Encodable_Generic}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext}; use smallvec::{SmallVec, smallvec}; use crate::{Idx, IndexVec}; @@ -114,7 +114,7 @@ macro_rules! bit_relations_inherent_impls { /// to or greater than the domain size. All operations that involve two bitsets /// will panic if the bitsets have differing domain sizes. /// -#[cfg_attr(feature = "nightly", derive(Decodable_Generic, Encodable_Generic))] +#[cfg_attr(feature = "nightly", derive(Decodable_NoContext, Encodable_NoContext))] #[derive(Eq, PartialEq, Hash)] pub struct DenseBitSet<T> { domain_size: usize, @@ -1392,7 +1392,7 @@ impl<T: Idx> From<DenseBitSet<T>> for GrowableBitSet<T> { /// /// All operations that involve a row and/or column index will panic if the /// index exceeds the relevant bound. -#[cfg_attr(feature = "nightly", derive(Decodable_Generic, Encodable_Generic))] +#[cfg_attr(feature = "nightly", derive(Decodable_NoContext, Encodable_NoContext))] #[derive(Clone, Eq, PartialEq, Hash)] pub struct BitMatrix<R: Idx, C: Idx> { num_rows: usize, @@ -1816,7 +1816,7 @@ impl std::fmt::Debug for FiniteBitSet<u32> { /// A fixed-sized bitset type represented by an integer type. Indices outwith than the range /// representable by `T` are considered set. -#[cfg_attr(feature = "nightly", derive(Decodable_Generic, Encodable_Generic))] +#[cfg_attr(feature = "nightly", derive(Decodable_NoContext, Encodable_NoContext))] #[derive(Copy, Clone, Eq, PartialEq)] pub struct FiniteBitSet<T: FiniteBitSetTy>(pub T); diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index c47f27e871f..307110d9fbc 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -8,9 +8,9 @@ use rustc_data_structures::fx::FxHashMap; use rustc_index::Idx; use rustc_middle::bug; -use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{ - self, BoundVar, GenericArg, InferConst, List, Ty, TyCtxt, TypeFlags, TypeVisitableExt, + self, BoundVar, GenericArg, InferConst, List, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeFolder, + TypeSuperFoldable, TypeVisitableExt, }; use smallvec::SmallVec; use tracing::debug; diff --git a/compiler/rustc_infer/src/infer/canonical/instantiate.rs b/compiler/rustc_infer/src/infer/canonical/instantiate.rs index c10df2ec02e..f5ee5702d09 100644 --- a/compiler/rustc_infer/src/infer/canonical/instantiate.rs +++ b/compiler/rustc_infer/src/infer/canonical/instantiate.rs @@ -8,8 +8,7 @@ use rustc_macros::extension; use rustc_middle::bug; -use rustc_middle::ty::fold::{FnMutDelegate, TypeFoldable}; -use rustc_middle::ty::{self, GenericArgKind, TyCtxt}; +use rustc_middle::ty::{self, FnMutDelegate, GenericArgKind, TyCtxt, TypeFoldable}; use crate::infer::canonical::{Canonical, CanonicalVarValues}; diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs index fb5fc3a53fe..3be07dbe208 100644 --- a/compiler/rustc_infer/src/infer/canonical/mod.rs +++ b/compiler/rustc_infer/src/infer/canonical/mod.rs @@ -24,8 +24,7 @@ pub use instantiate::CanonicalExt; use rustc_index::IndexVec; pub use rustc_middle::infer::canonical::*; -use rustc_middle::ty::fold::TypeFoldable; -use rustc_middle::ty::{self, GenericArg, List, Ty, TyCtxt}; +use rustc_middle::ty::{self, GenericArg, List, Ty, TyCtxt, TypeFoldable}; use rustc_span::Span; use crate::infer::{InferCtxt, RegionVariableOrigin}; diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 8a61631c69c..d53f631cc07 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -13,8 +13,7 @@ use std::iter; use rustc_index::{Idx, IndexVec}; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::mir::ConstraintCategory; -use rustc_middle::ty::fold::TypeFoldable; -use rustc_middle::ty::{self, BoundVar, GenericArg, GenericArgKind, Ty, TyCtxt}; +use rustc_middle::ty::{self, BoundVar, GenericArg, GenericArgKind, Ty, TyCtxt, TypeFoldable}; use rustc_middle::{bug, span_bug}; use tracing::{debug, instrument}; diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index eae69ec3e0f..75affa13977 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -1,10 +1,9 @@ ///! Definition of `InferCtxtLike` from the librarified type layer. use rustc_hir::def_id::DefId; use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::relate::RelateResult; use rustc_middle::ty::relate::combine::PredicateEmittingRelation; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use super::{BoundRegionConversionTime, InferCtxt, RegionVariableOrigin, SubregionOrigin}; diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 74c8b463fc8..f2bb66ff736 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -35,8 +35,9 @@ use std::collections::hash_map::Entry; use rustc_data_structures::fx::FxHashMap; use rustc_middle::bug; -use rustc_middle::ty::fold::TypeFolder; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitableExt}; +use rustc_middle::ty::{ + self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, +}; use super::InferCtxt; diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 03c4614af13..91595de97f7 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -9,10 +9,9 @@ use rustc_data_structures::graph::implementation::{ use rustc_data_structures::intern::Interned; use rustc_data_structures::unord::UnordSet; use rustc_index::{IndexSlice, IndexVec}; -use rustc_middle::ty::fold::{TypeFoldable, fold_regions}; use rustc_middle::ty::{ self, ReBound, ReEarlyParam, ReErased, ReError, ReLateParam, RePlaceholder, ReStatic, ReVar, - Region, RegionVid, Ty, TyCtxt, + Region, RegionVid, Ty, TyCtxt, TypeFoldable, fold_regions, }; use rustc_middle::{bug, span_bug}; use rustc_span::Span; diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 537e8119ada..fa8dea064da 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -28,14 +28,11 @@ use rustc_middle::infer::canonical::{CanonicalQueryInput, CanonicalVarValues}; use rustc_middle::mir::ConstraintCategory; use rustc_middle::traits::select; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::fold::{ - BoundVarReplacerDelegate, TypeFoldable, TypeFolder, TypeSuperFoldable, fold_regions, -}; -use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ - self, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, GenericArgsRef, - GenericParamDefKind, InferConst, IntVid, PseudoCanonicalInput, Ty, TyCtxt, TyVid, - TypeVisitable, TypingEnv, TypingMode, + self, BoundVarReplacerDelegate, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, + GenericArgsRef, GenericParamDefKind, InferConst, IntVid, PseudoCanonicalInput, Ty, TyCtxt, + TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv, + TypingMode, fold_regions, }; use rustc_span::{Span, Symbol}; use snapshot::undo_log::InferCtxtUndoLogs; diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index f6ef3f40e62..3fa1923121a 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -5,9 +5,9 @@ use rustc_middle::bug; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::solve::Goal; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::{ - self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, + self, BottomUpFolder, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, + TypeVisitableExt, }; use rustc_span::Span; use tracing::{debug, instrument}; diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index ce2d07f4af9..e16212955ff 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -5,10 +5,9 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def_id::DefId; use rustc_middle::bug; use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::visit::MaxUniverse; use rustc_middle::ty::{ - self, AliasRelationDirection, InferConst, Term, Ty, TyCtxt, TypeVisitable, TypeVisitableExt, - TypingMode, + self, AliasRelationDirection, InferConst, MaxUniverse, Term, Ty, TyCtxt, TypeVisitable, + TypeVisitableExt, TypingMode, }; use rustc_span::Span; use tracing::{debug, instrument, warn}; diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index a12d83db91f..2143f72a3b0 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -1,9 +1,7 @@ //! Helper routines for higher-ranked things. See the `doc` module at //! the end of the file for details. -use rustc_middle::ty::fold::FnMutDelegate; -use rustc_middle::ty::visit::TypeVisitableExt; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, FnMutDelegate, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use tracing::{debug, instrument}; use super::RelateResult; diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 6ec2e0152f0..4a99c220975 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -1,7 +1,8 @@ use rustc_middle::bug; -use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable}; -use rustc_middle::ty::visit::TypeVisitableExt; -use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{ + self, Const, FallibleTypeFolder, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder, + TypeSuperFoldable, TypeVisitableExt, +}; use rustc_type_ir::data_structures::DelayedMap; use super::{FixupError, FixupResult, InferCtxt}; diff --git a/compiler/rustc_infer/src/infer/snapshot/fudge.rs b/compiler/rustc_infer/src/infer/snapshot/fudge.rs index 3a47b13665d..b5d3c26b05e 100644 --- a/compiler/rustc_infer/src/infer/snapshot/fudge.rs +++ b/compiler/rustc_infer/src/infer/snapshot/fudge.rs @@ -1,9 +1,11 @@ use std::ops::Range; use rustc_data_structures::{snapshot_vec as sv, unify as ut}; -use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; -use rustc_middle::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid}; -use rustc_type_ir::visit::TypeVisitableExt; +use rustc_middle::ty::{ + self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, + TypeSuperFoldable, +}; +use rustc_type_ir::TypeVisitableExt; use tracing::instrument; use ut::UnifyKey; diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index b346e193d0b..4335073d9bc 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -1,8 +1,8 @@ use std::fmt; -use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable}; -use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor, try_visit}; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{ + self, FallibleTypeFolder, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitor, try_visit, +}; use crate::traits; use crate::traits::project::Normalized; diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index 9c9660cf504..e3673935664 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -7,7 +7,6 @@ edition = "2024" # tidy-alphabetical-start rustc-rayon = { version = "0.5.0" } rustc-rayon-core = { version = "0.5.0" } -rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_ast_lowering = { path = "../rustc_ast_lowering" } rustc_ast_passes = { path = "../rustc_ast_passes" } @@ -41,7 +40,6 @@ rustc_privacy = { path = "../rustc_privacy" } rustc_query_impl = { path = "../rustc_query_impl" } rustc_query_system = { path = "../rustc_query_system" } rustc_resolve = { path = "../rustc_resolve" } -rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } @@ -52,6 +50,11 @@ rustc_ty_utils = { path = "../rustc_ty_utils" } tracing = "0.1" # tidy-alphabetical-end +[dev-dependencies] +# tidy-alphabetical-start +rustc_abi = { path = "../rustc_abi" } +# tidy-alphabetical-end + [features] # tidy-alphabetical-start llvm = ['dep:rustc_codegen_llvm'] diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl index adc7ed54e14..ffbe708ba8d 100644 --- a/compiler/rustc_interface/messages.ftl +++ b/compiler/rustc_interface/messages.ftl @@ -3,9 +3,6 @@ interface_abi_required_feature = .note = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! interface_abi_required_feature_issue = for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344> -interface_cant_emit_mir = - could not emit MIR: {$error} - interface_crate_name_does_not_match = `--crate-name` and `#[crate_name]` are required to match, but `{$crate_name}` != `{$attr_crate_name}` interface_crate_name_invalid = crate names cannot start with a `-`, but `{$crate_name}` has a leading hyphen diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index f66b9eb3a28..7c6b7157f71 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -14,6 +14,7 @@ use std::fmt; use rustc_errors::{DiagInner, TRACK_DIAGNOSTIC}; use rustc_middle::dep_graph::{DepNodeExt, TaskDepsRef}; use rustc_middle::ty::tls; +use rustc_query_impl::QueryCtxt; use rustc_query_system::dep_graph::dep_node::default_dep_kind_debug; use rustc_query_system::dep_graph::{DepContext, DepKind, DepNode}; @@ -41,9 +42,7 @@ fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { fn track_diagnostic<R>(diagnostic: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R { tls::with_context_opt(|icx| { if let Some(icx) = icx { - if let Some(diagnostics) = icx.diagnostics { - diagnostics.lock().extend(Some(diagnostic.clone())); - } + icx.tcx.dep_graph.record_diagnostic(QueryCtxt::new(icx.tcx), &diagnostic); // Diagnostics are tracked, we can ignore the dependency. let icx = tls::ImplicitCtxt { task_deps: TaskDepsRef::Ignore, ..icx.clone() }; diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index eed729a1777..ef0235b5577 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -74,12 +74,6 @@ pub struct TempsDirError; pub struct OutDirError; #[derive(Diagnostic)] -#[diag(interface_cant_emit_mir)] -pub struct CantEmitMIR { - pub error: io::Error, -} - -#[derive(Diagnostic)] #[diag(interface_rustc_error_fatal)] pub struct RustcErrorFatal { #[primary_span] diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index e47385d0899..3d6b6a594a2 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1078,6 +1078,15 @@ pub(crate) fn start_codegen<'tcx>( codegen_backend: &dyn CodegenBackend, tcx: TyCtxt<'tcx>, ) -> Box<dyn Any> { + // Hook for UI tests. + check_for_rustc_errors_attr(tcx); + + // Don't run this test assertions when not doing codegen. Compiletest tries to build + // build-fail tests in check mode first and expects it to not give an error in that case. + if tcx.sess.opts.output_types.should_codegen() { + rustc_symbol_mangling::test::report_symbol_names(tcx); + } + // Don't do code generation if there were any errors. Likewise if // there were any delayed bugs, because codegen will likely cause // more ICEs, obscuring the original problem. @@ -1085,9 +1094,6 @@ pub(crate) fn start_codegen<'tcx>( guar.raise_fatal(); } - // Hook for UI tests. - check_for_rustc_errors_attr(tcx); - info!("Pre-codegen\n{:?}", tcx.debug_stats()); let (metadata, need_metadata_module) = rustc_metadata::fs::encode_and_write_metadata(tcx); @@ -1096,20 +1102,8 @@ pub(crate) fn start_codegen<'tcx>( codegen_backend.codegen_crate(tcx, metadata, need_metadata_module) }); - // Don't run this test assertions when not doing codegen. Compiletest tries to build - // build-fail tests in check mode first and expects it to not give an error in that case. - if tcx.sess.opts.output_types.should_codegen() { - rustc_symbol_mangling::test::report_symbol_names(tcx); - } - info!("Post-codegen\n{:?}", tcx.debug_stats()); - if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) { - if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx) { - tcx.dcx().emit_fatal(errors::CantEmitMIR { error }); - } - } - // This must run after monomorphization so that all generic types // have been instantiated. if tcx.sess.opts.unstable_opts.print_type_sizes { diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml index d6014f5006a..7718f16984d 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -23,7 +23,6 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } -rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" unicode-security = "0.1.0" diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 918a42f3047..9dccd4a0552 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -441,7 +441,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { // so we will continue to exclude them for compatibility. // // The documentation on `ExternCrate` is not used at the moment so no need to warn for it. - if let hir::ItemKind::Impl(..) | hir::ItemKind::Use(..) | hir::ItemKind::ExternCrate(_) = + if let hir::ItemKind::Impl(..) | hir::ItemKind::Use(..) | hir::ItemKind::ExternCrate(..) = it.kind { return; @@ -545,21 +545,21 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations { return; } let (def, ty) = match item.kind { - hir::ItemKind::Struct(_, ast_generics) => { + hir::ItemKind::Struct(_, _, ast_generics) => { if !ast_generics.params.is_empty() { return; } let def = cx.tcx.adt_def(item.owner_id); (def, Ty::new_adt(cx.tcx, def, ty::List::empty())) } - hir::ItemKind::Union(_, ast_generics) => { + hir::ItemKind::Union(_, _, ast_generics) => { if !ast_generics.params.is_empty() { return; } let def = cx.tcx.adt_def(item.owner_id); (def, Ty::new_adt(cx.tcx, def, ty::List::empty())) } - hir::ItemKind::Enum(_, ast_generics) => { + hir::ItemKind::Enum(_, _, ast_generics) => { if !ast_generics.params.is_empty() { return; } @@ -1416,7 +1416,7 @@ impl TypeAliasBounds { impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - let hir::ItemKind::TyAlias(hir_ty, generics) = item.kind else { return }; + let hir::ItemKind::TyAlias(_, hir_ty, generics) = item.kind else { return }; // There must not be a where clause. if generics.predicates.is_empty() { @@ -2119,9 +2119,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { use rustc_middle::middle::resolve_bound_vars::ResolvedArg; let def_id = item.owner_id.def_id; - if let hir::ItemKind::Struct(_, hir_generics) - | hir::ItemKind::Enum(_, hir_generics) - | hir::ItemKind::Union(_, hir_generics) = item.kind + if let hir::ItemKind::Struct(_, _, hir_generics) + | hir::ItemKind::Enum(_, _, hir_generics) + | hir::ItemKind::Union(_, _, hir_generics) = item.kind { let inferred_outlives = cx.tcx.inferred_outlives_of(def_id); if inferred_outlives.is_empty() { @@ -2257,7 +2257,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { // generics, except for tuple struct, which have the `where` // after the fields of the struct. let full_where_span = - if let hir::ItemKind::Struct(hir::VariantData::Tuple(..), _) = item.kind { + if let hir::ItemKind::Struct(_, hir::VariantData::Tuple(..), _) = item.kind { where_span } else { hir_generics.span.shrink_to_hi().to(where_span) @@ -2582,34 +2582,35 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { ) -> Option<InitError> { let ty = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty).unwrap_or(ty); - use rustc_type_ir::TyKind::*; match ty.kind() { // Primitive types that don't like 0 as a value. - Ref(..) => Some("references must be non-null".into()), - Adt(..) if ty.is_box() => Some("`Box` must be non-null".into()), - FnPtr(..) => Some("function pointers must be non-null".into()), - Never => Some("the `!` type has no valid value".into()), - RawPtr(ty, _) if matches!(ty.kind(), Dynamic(..)) => + ty::Ref(..) => Some("references must be non-null".into()), + ty::Adt(..) if ty.is_box() => Some("`Box` must be non-null".into()), + ty::FnPtr(..) => Some("function pointers must be non-null".into()), + ty::Never => Some("the `!` type has no valid value".into()), + ty::RawPtr(ty, _) if matches!(ty.kind(), ty::Dynamic(..)) => // raw ptr to dyn Trait { Some("the vtable of a wide raw pointer must be non-null".into()) } // Primitive types with other constraints. - Bool if init == InitKind::Uninit => { + ty::Bool if init == InitKind::Uninit => { Some("booleans must be either `true` or `false`".into()) } - Char if init == InitKind::Uninit => { + ty::Char if init == InitKind::Uninit => { Some("characters must be a valid Unicode codepoint".into()) } - Int(_) | Uint(_) if init == InitKind::Uninit => { + ty::Int(_) | ty::Uint(_) if init == InitKind::Uninit => { Some("integers must be initialized".into()) } - Float(_) if init == InitKind::Uninit => Some("floats must be initialized".into()), - RawPtr(_, _) if init == InitKind::Uninit => { + ty::Float(_) if init == InitKind::Uninit => { + Some("floats must be initialized".into()) + } + ty::RawPtr(_, _) if init == InitKind::Uninit => { Some("raw pointers must be initialized".into()) } // Recurse and checks for some compound types. (but not unions) - Adt(adt_def, args) if !adt_def.is_union() => { + ty::Adt(adt_def, args) if !adt_def.is_union() => { // Handle structs. if adt_def.is_struct() { return variant_find_init_error( @@ -2675,11 +2676,11 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { // We couldn't find anything wrong here. None } - Tuple(..) => { + ty::Tuple(..) => { // Proceed recursively, check all fields. ty.tuple_fields().iter().find_map(|field| ty_find_init_error(cx, field, init)) } - Array(ty, len) => { + ty::Array(ty, len) => { if matches!(len.try_to_target_usize(cx.tcx), Some(v) if v > 0) { // Array length known at array non-empty -- recurse. ty_find_init_error(cx, *ty, init) diff --git a/compiler/rustc_lint/src/default_could_be_derived.rs b/compiler/rustc_lint/src/default_could_be_derived.rs index 58efca5e994..78d129642dc 100644 --- a/compiler/rustc_lint/src/default_could_be_derived.rs +++ b/compiler/rustc_lint/src/default_could_be_derived.rs @@ -93,7 +93,11 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived { let orig_fields = match cx.tcx.hir_get_if_local(type_def_id) { Some(hir::Node::Item(hir::Item { kind: - hir::ItemKind::Struct(hir::VariantData::Struct { fields, recovered: _ }, _generics), + hir::ItemKind::Struct( + _, + hir::VariantData::Struct { fields, recovered: _ }, + _generics, + ), .. })) => fields.iter().map(|f| (f.ident.name, f)).collect::<FxHashMap<_, _>>(), _ => return, diff --git a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs index 7ead8eafbd5..179f2bcf07f 100644 --- a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs +++ b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs @@ -1,6 +1,5 @@ use rustc_hir as hir; -use rustc_middle::ty::Ty; -use rustc_middle::ty::visit::TypeVisitableExt; +use rustc_middle::ty::{Ty, TypeVisitableExt}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{Span, sym}; diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index 6175415c31f..0494c78a7a9 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -270,14 +270,12 @@ fn structurally_same_type_impl<'tcx>( true } else { // Do a full, depth-first comparison between the two. - use rustc_type_ir::TyKind::*; - let is_primitive_or_pointer = - |ty: Ty<'tcx>| ty.is_primitive() || matches!(ty.kind(), RawPtr(..) | Ref(..)); + |ty: Ty<'tcx>| ty.is_primitive() || matches!(ty.kind(), ty::RawPtr(..) | ty::Ref(..)); ensure_sufficient_stack(|| { match (a.kind(), b.kind()) { - (&Adt(a_def, a_gen_args), &Adt(b_def, b_gen_args)) => { + (&ty::Adt(a_def, a_gen_args), &ty::Adt(b_def, b_gen_args)) => { // Only `repr(C)` types can be compared structurally. if !(a_def.repr().c() && b_def.repr().c()) { return false; @@ -308,30 +306,30 @@ fn structurally_same_type_impl<'tcx>( }, ) } - (Array(a_ty, a_len), Array(b_ty, b_len)) => { + (ty::Array(a_ty, a_len), ty::Array(b_ty, b_len)) => { // For arrays, we also check the length. a_len == b_len && structurally_same_type_impl( seen_types, tcx, typing_env, *a_ty, *b_ty, ckind, ) } - (Slice(a_ty), Slice(b_ty)) => { + (ty::Slice(a_ty), ty::Slice(b_ty)) => { structurally_same_type_impl(seen_types, tcx, typing_env, *a_ty, *b_ty, ckind) } - (RawPtr(a_ty, a_mutbl), RawPtr(b_ty, b_mutbl)) => { + (ty::RawPtr(a_ty, a_mutbl), ty::RawPtr(b_ty, b_mutbl)) => { a_mutbl == b_mutbl && structurally_same_type_impl( seen_types, tcx, typing_env, *a_ty, *b_ty, ckind, ) } - (Ref(_a_region, a_ty, a_mut), Ref(_b_region, b_ty, b_mut)) => { + (ty::Ref(_a_region, a_ty, a_mut), ty::Ref(_b_region, b_ty, b_mut)) => { // For structural sameness, we don't need the region to be same. a_mut == b_mut && structurally_same_type_impl( seen_types, tcx, typing_env, *a_ty, *b_ty, ckind, ) } - (FnDef(..), FnDef(..)) => { + (ty::FnDef(..), ty::FnDef(..)) => { let a_poly_sig = a.fn_sig(tcx); let b_poly_sig = b.fn_sig(tcx); @@ -354,35 +352,38 @@ fn structurally_same_type_impl<'tcx>( ckind, ) } - (Tuple(..), Tuple(..)) => { + (ty::Tuple(..), ty::Tuple(..)) => { // Tuples are not `repr(C)` so these cannot be compared structurally. false } // For these, it's not quite as easy to define structural-sameness quite so easily. // For the purposes of this lint, take the conservative approach and mark them as // not structurally same. - (Dynamic(..), Dynamic(..)) - | (Error(..), Error(..)) - | (Closure(..), Closure(..)) - | (Coroutine(..), Coroutine(..)) - | (CoroutineWitness(..), CoroutineWitness(..)) - | (Alias(ty::Projection, ..), Alias(ty::Projection, ..)) - | (Alias(ty::Inherent, ..), Alias(ty::Inherent, ..)) - | (Alias(ty::Opaque, ..), Alias(ty::Opaque, ..)) => false, + (ty::Dynamic(..), ty::Dynamic(..)) + | (ty::Error(..), ty::Error(..)) + | (ty::Closure(..), ty::Closure(..)) + | (ty::Coroutine(..), ty::Coroutine(..)) + | (ty::CoroutineWitness(..), ty::CoroutineWitness(..)) + | (ty::Alias(ty::Projection, ..), ty::Alias(ty::Projection, ..)) + | (ty::Alias(ty::Inherent, ..), ty::Alias(ty::Inherent, ..)) + | (ty::Alias(ty::Opaque, ..), ty::Alias(ty::Opaque, ..)) => false, // These definitely should have been caught above. - (Bool, Bool) | (Char, Char) | (Never, Never) | (Str, Str) => unreachable!(), + (ty::Bool, ty::Bool) + | (ty::Char, ty::Char) + | (ty::Never, ty::Never) + | (ty::Str, ty::Str) => unreachable!(), // An Adt and a primitive or pointer type. This can be FFI-safe if non-null // enum layout optimisation is being applied. - (Adt(..) | Pat(..), _) if is_primitive_or_pointer(b) => { + (ty::Adt(..) | ty::Pat(..), _) if is_primitive_or_pointer(b) => { if let Some(a_inner) = types::repr_nullable_ptr(tcx, typing_env, a, ckind) { a_inner == b } else { false } } - (_, Adt(..) | Pat(..)) if is_primitive_or_pointer(a) => { + (_, ty::Adt(..) | ty::Pat(..)) if is_primitive_or_pointer(a) => { if let Some(b_inner) = types::repr_nullable_ptr(tcx, typing_env, b, ckind) { b_inner == a } else { diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 0b3af7d6aba..c2404a7b843 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -506,9 +506,9 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for FunctionalVariances<'tcx> { self.tcx } - fn relate_with_variance<T: ty::relate::Relate<TyCtxt<'tcx>>>( + fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>( &mut self, - variance: rustc_type_ir::Variance, + variance: ty::Variance, _: ty::VarianceDiagInfo<TyCtxt<'tcx>>, a: T, b: T, diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 1f999bbea5f..b359ee790a5 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -308,18 +308,18 @@ impl<'tcx> LateLintPass<'tcx> for TypeIr { [.., penultimate, segment] if penultimate.res.opt_def_id().is_some_and(is_mod_inherent) => { - (segment.ident.span, item.ident.span, "*") + (segment.ident.span, item.kind.ident().unwrap().span, "*") } [.., segment] if path.res.iter().flat_map(Res::opt_def_id).any(is_mod_inherent) - && let rustc_hir::UseKind::Single = kind => + && let rustc_hir::UseKind::Single(ident) = kind => { let (lo, snippet) = match cx.tcx.sess.source_map().span_to_snippet(path.span).as_deref() { Ok("self") => (path.span, "*"), _ => (segment.ident.span.shrink_to_hi(), "::*"), }; - (lo, if segment.ident == item.ident { lo } else { item.ident.span }, snippet) + (lo, if segment.ident == ident { lo } else { ident.span }, snippet) } _ => return, }; diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs index 35db8632625..dea7c8ac708 100644 --- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs +++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs @@ -39,7 +39,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable { let def_id = item.owner_id.to_def_id(); // NOTE(nbdd0121): use `dyn_compatibility_violations` instead of `is_dyn_compatible` because // the latter will report `where_clause_object_safety` lint. - if let hir::ItemKind::Trait(_, _, _, _, _) = item.kind + if let hir::ItemKind::Trait(_, _, ident, ..) = item.kind && cx.tcx.is_dyn_compatible(def_id) { let direct_super_traits_iter = cx @@ -51,7 +51,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable { cx.emit_span_lint( MULTIPLE_SUPERTRAIT_UPCASTABLE, cx.tcx.def_span(def_id), - crate::lints::MultipleSupertraitUpcastable { ident: item.ident }, + crate::lints::MultipleSupertraitUpcastable { ident }, ); } } diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 0890890d12c..f8e0a94f9ec 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -181,10 +181,10 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { && parent_opt_item_name != Some(kw::Underscore) && let Some(parent) = parent.as_local() && let Node::Item(item) = cx.tcx.hir_node_by_def_id(parent) - && let ItemKind::Const(ty, _, _) = item.kind + && let ItemKind::Const(ident, ty, _, _) = item.kind && let TyKind::Tup(&[]) = ty.kind { - Some(item.ident.span) + Some(ident.span) } else { None }; @@ -238,7 +238,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { }, ) } - ItemKind::Macro(_macro, MacroKind::Bang) + ItemKind::Macro(_, _macro, MacroKind::Bang) if cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export) => { cx.emit_span_lint( diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 722779d3268..752636ccaf0 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -274,18 +274,13 @@ impl NonSnakeCase { let ident = ident.trim_start_matches('\''); let ident = ident.trim_matches('_'); - let mut allow_underscore = true; - ident.chars().all(|c| { - allow_underscore = match c { - '_' if !allow_underscore => return false, - '_' => false, - // It would be more obvious to use `c.is_lowercase()`, - // but some characters do not have a lowercase form - c if !c.is_uppercase() => true, - _ => return false, - }; - true - }) + if ident.contains("__") { + return false; + } + + // This correctly handles letters in languages with and without + // cases, as well as numbers and underscores. + !ident.chars().any(char::is_uppercase) } let name = ident.name.as_str(); @@ -420,8 +415,8 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { } fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { - if let hir::ItemKind::Mod(_) = it.kind { - self.check_snake_case(cx, "module", &it.ident); + if let hir::ItemKind::Mod(ident, _) = it.kind { + self.check_snake_case(cx, "module", &ident); } } @@ -429,7 +424,9 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(pnames)) = item.kind { self.check_snake_case(cx, "trait method", &item.ident); for param_name in pnames { - self.check_snake_case(cx, "variable", param_name); + if let Some(param_name) = param_name { + self.check_snake_case(cx, "variable", param_name); + } } } } @@ -503,11 +500,13 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals { fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { let attrs = cx.tcx.hir_attrs(it.hir_id()); match it.kind { - hir::ItemKind::Static(..) if !ast::attr::contains_name(attrs, sym::no_mangle) => { - NonUpperCaseGlobals::check_upper_case(cx, "static variable", &it.ident); + hir::ItemKind::Static(ident, ..) + if !ast::attr::contains_name(attrs, sym::no_mangle) => + { + NonUpperCaseGlobals::check_upper_case(cx, "static variable", &ident); } - hir::ItemKind::Const(..) => { - NonUpperCaseGlobals::check_upper_case(cx, "constant", &it.ident); + hir::ItemKind::Const(ident, ..) => { + NonUpperCaseGlobals::check_upper_case(cx, "constant", &ident); } _ => {} } diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 659f6d98f03..f836094191e 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -1,9 +1,8 @@ use rustc_hir::{self as hir, AmbigArg}; use rustc_infer::infer::TyCtxtInferExt; use rustc_macros::{LintDiagnostic, Subdiagnostic}; -use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::print::{PrintTraitPredicateExt as _, TraitPredPrintModifiersAndPath}; -use rustc_middle::ty::{self, Ty, TypeFoldable}; +use rustc_middle::ty::{self, BottomUpFolder, Ty, TypeFoldable}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{Span, kw}; use rustc_trait_selection::traits::{self, ObligationCtxt}; diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 6f3c32af5ef..7109fefbe78 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1193,9 +1193,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { }; } - let is_non_exhaustive = - def.non_enum_variant().is_field_list_non_exhaustive(); - if is_non_exhaustive && !def.did().is_local() { + if def.non_enum_variant().field_list_has_applicable_non_exhaustive() { return FfiUnsafe { ty, reason: if def.is_struct() { @@ -1248,14 +1246,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { }; } - use improper_ctypes::{ - check_non_exhaustive_variant, non_local_and_non_exhaustive, - }; + use improper_ctypes::check_non_exhaustive_variant; - let non_local_def = non_local_and_non_exhaustive(def); + let non_exhaustive = def.variant_list_has_applicable_non_exhaustive(); // Check the contained variants. let ret = def.variants().iter().try_for_each(|variant| { - check_non_exhaustive_variant(non_local_def, variant) + check_non_exhaustive_variant(non_exhaustive, variant) .map_break(|reason| FfiUnsafe { ty, reason, help: None })?; match self.check_variant_for_ffi(acc, ty, def, variant, args) { @@ -1422,7 +1418,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { fn check_for_opaque_ty(&mut self, sp: Span, ty: Ty<'tcx>) -> bool { struct ProhibitOpaqueTypes; - impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for ProhibitOpaqueTypes { + impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for ProhibitOpaqueTypes { type Result = ControlFlow<Ty<'tcx>>; fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { @@ -1564,7 +1560,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } } - impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for FnPtrFinder<'tcx> { + impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for FnPtrFinder<'tcx> { type Result = (); fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { @@ -1664,7 +1660,7 @@ impl ImproperCTypesDefinitions { && cx.tcx.sess.target.os == "aix" && !adt_def.all_fields().next().is_none() { - let struct_variant_data = item.expect_struct().0; + let struct_variant_data = item.expect_struct().1; for (index, ..) in struct_variant_data.fields().iter().enumerate() { // Struct fields (after the first field) are checked for the // power alignment rule, as fields after the first are likely @@ -1696,9 +1692,9 @@ impl ImproperCTypesDefinitions { impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { match item.kind { - hir::ItemKind::Static(ty, ..) - | hir::ItemKind::Const(ty, ..) - | hir::ItemKind::TyAlias(ty, ..) => { + hir::ItemKind::Static(_, ty, ..) + | hir::ItemKind::Const(_, ty, ..) + | hir::ItemKind::TyAlias(_, ty, ..) => { self.check_ty_maybe_containing_foreign_fnptr( cx, ty, @@ -1765,7 +1761,7 @@ declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]); impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences { fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) { - if let hir::ItemKind::Enum(ref enum_definition, _) = it.kind { + if let hir::ItemKind::Enum(_, ref enum_definition, _) = it.kind { let t = cx.tcx.type_of(it.owner_id).instantiate_identity(); let ty = cx.tcx.erase_regions(t); let Ok(layout) = cx.layout_of(ty) else { return }; diff --git a/compiler/rustc_lint/src/types/improper_ctypes.rs b/compiler/rustc_lint/src/types/improper_ctypes.rs index 1030101c545..13afa540afc 100644 --- a/compiler/rustc_lint/src/types/improper_ctypes.rs +++ b/compiler/rustc_lint/src/types/improper_ctypes.rs @@ -15,13 +15,13 @@ use crate::fluent_generated as fluent; /// so we don't need the lint to account for it. /// e.g. going from enum Foo { A, B, C } to enum Foo { A, B, C, D(u32) }. pub(crate) fn check_non_exhaustive_variant( - non_local_def: bool, + non_exhaustive_variant_list: bool, variant: &ty::VariantDef, ) -> ControlFlow<DiagMessage, ()> { // non_exhaustive suggests it is possible that someone might break ABI // see: https://github.com/rust-lang/rust/issues/44109#issuecomment-537583344 // so warn on complex enums being used outside their crate - if non_local_def { + if non_exhaustive_variant_list { // which is why we only warn about really_tagged_union reprs from https://rust.tf/rfc2195 // with an enum like `#[repr(u8)] enum Enum { A(DataA), B(DataB), }` // but exempt enums with unit ctors like C's (e.g. from rust-bindgen) @@ -30,8 +30,7 @@ pub(crate) fn check_non_exhaustive_variant( } } - let non_exhaustive_variant_fields = variant.is_field_list_non_exhaustive(); - if non_exhaustive_variant_fields && !variant.def_id.is_local() { + if variant.field_list_has_applicable_non_exhaustive() { return ControlFlow::Break(fluent::lint_improper_ctypes_non_exhaustive_variant); } @@ -42,10 +41,3 @@ fn variant_has_complex_ctor(variant: &ty::VariantDef) -> bool { // CtorKind::Const means a "unit" ctor !matches!(variant.ctor_kind(), Some(CtorKind::Const)) } - -// non_exhaustive suggests it is possible that someone might break ABI -// see: https://github.com/rust-lang/rust/issues/44109#issuecomment-537583344 -// so warn on complex enums being used outside their crate -pub(crate) fn non_local_and_non_exhaustive(def: ty::AdtDef<'_>) -> bool { - def.is_variant_list_non_exhaustive() && !def.did().is_local() -} diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index 3d1f3b2cd4d..6692ea73540 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -241,7 +241,7 @@ fn main() { println!("cargo:rustc-link-lib=kstat"); } - if (target.starts_with("arm") && !target.contains("freebsd")) + if (target.starts_with("arm") && !target.contains("freebsd")) && !target.contains("ohos") || target.starts_with("mips-") || target.starts_with("mipsel-") || target.starts_with("powerpc-") @@ -371,6 +371,7 @@ fn main() { || target.contains("freebsd") || target.contains("windows-gnullvm") || target.contains("aix") + || target.contains("ohos") { "c++" } else if target.contains("netbsd") && llvm_static_stdcpp.is_some() { diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp index 0471baa1f9c..b8884486c33 100644 --- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp @@ -78,6 +78,13 @@ struct LLVMRustCoverageCodeRegion { }; // Must match the layout of +// `rustc_codegen_llvm::coverageinfo::ffi::ExpansionRegion`. +struct LLVMRustCoverageExpansionRegion { + LLVMRustCoverageSpan Span; + uint32_t ExpandedFileID; +}; + +// Must match the layout of // `rustc_codegen_llvm::coverageinfo::ffi::BranchRegion`. struct LLVMRustCoverageBranchRegion { LLVMRustCoverageSpan Span; @@ -151,6 +158,8 @@ extern "C" void LLVMRustCoverageWriteFunctionMappingsToBuffer( const unsigned *VirtualFileMappingIDs, size_t NumVirtualFileMappingIDs, const LLVMRustCounterExpression *RustExpressions, size_t NumExpressions, const LLVMRustCoverageCodeRegion *CodeRegions, size_t NumCodeRegions, + const LLVMRustCoverageExpansionRegion *ExpansionRegions, + size_t NumExpansionRegions, const LLVMRustCoverageBranchRegion *BranchRegions, size_t NumBranchRegions, const LLVMRustCoverageMCDCBranchRegion *MCDCBranchRegions, size_t NumMCDCBranchRegions, @@ -179,6 +188,13 @@ extern "C" void LLVMRustCoverageWriteFunctionMappingsToBuffer( Region.Span.ColumnStart, Region.Span.LineEnd, Region.Span.ColumnEnd)); } + // Expansion regions: + for (const auto &Region : ArrayRef(ExpansionRegions, NumExpansionRegions)) { + MappingRegions.push_back(coverage::CounterMappingRegion::makeExpansion( + Region.Span.FileID, Region.ExpandedFileID, Region.Span.LineStart, + Region.Span.ColumnStart, Region.Span.LineEnd, Region.Span.ColumnEnd)); + } + // Branch regions: for (const auto &Region : ArrayRef(BranchRegions, NumBranchRegions)) { MappingRegions.push_back(coverage::CounterMappingRegion::makeBranchRegion( diff --git a/compiler/rustc_log/Cargo.toml b/compiler/rustc_log/Cargo.toml index 30f6e9ba805..c673d51a1d4 100644 --- a/compiler/rustc_log/Cargo.toml +++ b/compiler/rustc_log/Cargo.toml @@ -11,11 +11,6 @@ tracing-subscriber = { version = "0.3.3", default-features = false, features = [ tracing-tree = "0.3.1" # tidy-alphabetical-end -[dev-dependencies] -# tidy-alphabetical-start -rustc_span = { path = "../rustc_span" } -# tidy-alphabetical-end - [features] # tidy-alphabetical-start max_level_info = ['tracing/max_level_info'] diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index d0ef82f4a6c..49dd388f14c 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -9,17 +9,12 @@ //! [dependencies] //! rustc_ast = { path = "../rust/compiler/rustc_ast" } //! rustc_log = { path = "../rust/compiler/rustc_log" } -//! rustc_span = { path = "../rust/compiler/rustc_span" } //! ``` //! //! ``` //! fn main() { //! rustc_log::init_logger(rustc_log::LoggerConfig::from_env("LOG")).unwrap(); -//! -//! let edition = rustc_span::edition::Edition::Edition2021; -//! rustc_span::create_session_globals_then(edition, None, || { -//! /* ... */ -//! }); +//! /* ... */ //! } //! ``` //! diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 44ba064dd82..edb25e79904 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -74,8 +74,8 @@ decl_derive!( hash_stable::hash_stable_no_context_derive ); -decl_derive!([Decodable_Generic] => serialize::decodable_generic_derive); -decl_derive!([Encodable_Generic] => serialize::encodable_generic_derive); +decl_derive!([Decodable_NoContext] => serialize::decodable_nocontext_derive); +decl_derive!([Encodable_NoContext] => serialize::encodable_nocontext_derive); decl_derive!([Decodable] => serialize::decodable_derive); decl_derive!([Encodable] => serialize::encodable_derive); decl_derive!([TyDecodable] => serialize::type_decodable_derive); diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs index 2c33a0ac0aa..673e6cd618f 100644 --- a/compiler/rustc_macros/src/serialize.rs +++ b/compiler/rustc_macros/src/serialize.rs @@ -6,16 +6,11 @@ use syn::spanned::Spanned; pub(super) fn type_decodable_derive( mut s: synstructure::Structure<'_>, ) -> proc_macro2::TokenStream { + if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { + s.add_impl_generic(parse_quote! { 'tcx }); + } let decoder_ty = quote! { __D }; - let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { - quote! { <I = ::rustc_middle::ty::TyCtxt<'tcx>> } - } else if s.ast().generics.type_params().any(|ty| ty.ident == "I") { - quote! { <I = I> } - } else { - quote! {} - }; - - s.add_impl_generic(parse_quote! { #decoder_ty: ::rustc_type_ir::codec::TyDecoder #bound }); + s.add_impl_generic(parse_quote! { #decoder_ty: ::rustc_middle::ty::codec::TyDecoder<'tcx> }); s.add_bounds(synstructure::AddBounds::Fields); s.underscore_const(true); @@ -45,12 +40,12 @@ pub(super) fn decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro decodable_body(s, decoder_ty) } -pub(super) fn decodable_generic_derive( +pub(super) fn decodable_nocontext_derive( mut s: synstructure::Structure<'_>, ) -> proc_macro2::TokenStream { let decoder_ty = quote! { __D }; s.add_impl_generic(parse_quote! { #decoder_ty: ::rustc_serialize::Decoder }); - s.add_bounds(synstructure::AddBounds::Generics); + s.add_bounds(synstructure::AddBounds::Fields); s.underscore_const(true); decodable_body(s, decoder_ty) @@ -132,16 +127,11 @@ fn decode_field(field: &syn::Field) -> proc_macro2::TokenStream { pub(super) fn type_encodable_derive( mut s: synstructure::Structure<'_>, ) -> proc_macro2::TokenStream { - let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { - quote! { <I = ::rustc_middle::ty::TyCtxt<'tcx>> } - } else if s.ast().generics.type_params().any(|ty| ty.ident == "I") { - quote! { <I = I> } - } else { - quote! {} - }; - let encoder_ty = quote! { __E }; - s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_type_ir::codec::TyEncoder #bound }); + if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { + s.add_impl_generic(parse_quote! { 'tcx }); + } + s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_middle::ty::codec::TyEncoder<'tcx> }); s.add_bounds(synstructure::AddBounds::Fields); s.underscore_const(true); @@ -171,12 +161,12 @@ pub(super) fn encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro encodable_body(s, encoder_ty, false) } -pub(super) fn encodable_generic_derive( +pub(super) fn encodable_nocontext_derive( mut s: synstructure::Structure<'_>, ) -> proc_macro2::TokenStream { let encoder_ty = quote! { __E }; s.add_impl_generic(parse_quote! { #encoder_ty: ::rustc_serialize::Encoder }); - s.add_bounds(synstructure::AddBounds::Generics); + s.add_bounds(synstructure::AddBounds::Fields); s.underscore_const(true); encodable_body(s, encoder_ty, false) diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs index bc3b82c2893..c4f584dca43 100644 --- a/compiler/rustc_macros/src/type_foldable.rs +++ b/compiler/rustc_macros/src/type_foldable.rs @@ -38,16 +38,16 @@ pub(super) fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_m bind.to_token_stream() } else { quote! { - ::rustc_middle::ty::fold::TypeFoldable::try_fold_with(#bind, __folder)? + ::rustc_middle::ty::TypeFoldable::try_fold_with(#bind, __folder)? } } }) }); s.bound_impl( - quote!(::rustc_middle::ty::fold::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>>), + quote!(::rustc_middle::ty::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>>), quote! { - fn try_fold_with<__F: ::rustc_middle::ty::fold::FallibleTypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>( + fn try_fold_with<__F: ::rustc_middle::ty::FallibleTypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>( self, __folder: &mut __F ) -> Result<Self, __F::Error> { diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs index a7906d50d0f..fb37e1a39ed 100644 --- a/compiler/rustc_macros/src/type_visitable.rs +++ b/compiler/rustc_macros/src/type_visitable.rs @@ -36,12 +36,12 @@ pub(super) fn type_visitable_derive( s.add_bounds(synstructure::AddBounds::Generics); let body_visit = s.each(|bind| { quote! { - match ::rustc_middle::ty::visit::VisitorResult::branch( - ::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor) + match ::rustc_middle::ty::VisitorResult::branch( + ::rustc_middle::ty::TypeVisitable::visit_with(#bind, __visitor) ) { ::core::ops::ControlFlow::Continue(()) => {}, ::core::ops::ControlFlow::Break(r) => { - return ::rustc_middle::ty::visit::VisitorResult::from_residual(r); + return ::rustc_middle::ty::VisitorResult::from_residual(r); }, } } @@ -49,14 +49,14 @@ pub(super) fn type_visitable_derive( s.bind_with(|_| synstructure::BindStyle::Move); s.bound_impl( - quote!(::rustc_middle::ty::visit::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>>), + quote!(::rustc_middle::ty::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>>), quote! { - fn visit_with<__V: ::rustc_middle::ty::visit::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>( + fn visit_with<__V: ::rustc_middle::ty::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>( &self, __visitor: &mut __V ) -> __V::Result { match *self { #body_visit } - <__V::Result as ::rustc_middle::ty::visit::VisitorResult>::output() + <__V::Result as ::rustc_middle::ty::VisitorResult>::output() } }, ) diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index a8821640f04..08dcc3d519a 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -6,7 +6,6 @@ edition = "2024" [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" -libc = "0.2" libloading = "0.8.0" odht = { version = "0.3.1", features = ["nightly"] } rustc_abi = { path = "../rustc_abi" } @@ -27,7 +26,11 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -rustc_type_ir = { path = "../rustc_type_ir" } tempfile = "3.2" tracing = "0.1" # tidy-alphabetical-end + +[target.'cfg(target_os = "aix")'.dependencies] +# tidy-alphabetical-start +libc = "0.2" +# tidy-alphabetical-end diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 6ffbebfffd5..4610a571da0 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -386,13 +386,11 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { } } -impl<'a, 'tcx> TyDecoder for DecodeContext<'a, 'tcx> { +impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> { const CLEAR_CROSS_CRATE: bool = true; - type I = TyCtxt<'tcx>; - #[inline] - fn interner(&self) -> Self::I { + fn interner(&self) -> TyCtxt<'tcx> { self.tcx() } @@ -1055,15 +1053,15 @@ impl<'a> CrateMetadataRef<'a> { attributes.iter().cloned().map(Symbol::intern).collect::<Vec<_>>(); ( trait_name, - SyntaxExtensionKind::Derive(Box::new(DeriveProcMacro { client })), + SyntaxExtensionKind::Derive(Arc::new(DeriveProcMacro { client })), helper_attrs, ) } ProcMacro::Attr { name, client } => { - (name, SyntaxExtensionKind::Attr(Box::new(AttrProcMacro { client })), Vec::new()) + (name, SyntaxExtensionKind::Attr(Arc::new(AttrProcMacro { client })), Vec::new()) } ProcMacro::Bang { name, client } => { - (name, SyntaxExtensionKind::Bang(Box::new(BangProcMacro { client })), Vec::new()) + (name, SyntaxExtensionKind::Bang(Arc::new(BangProcMacro { client })), Vec::new()) } }; @@ -1320,7 +1318,7 @@ impl<'a> CrateMetadataRef<'a> { .expect("argument names not encoded for a function") .decode((self, sess)) .nth(0) - .is_some_and(|ident| ident.name == kw::SelfLower) + .is_some_and(|ident| matches!(ident, Some(Ident { name: kw::SelfLower, .. }))) } fn get_associated_item_or_field_def_ids(self, id: DefIndex) -> impl Iterator<Item = DefId> { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 57c941976e4..7ab3d432bdf 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -378,11 +378,9 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for [u8] { } } -impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> { +impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> { const CLEAR_CROSS_CRATE: bool = true; - type I = TyCtxt<'tcx>; - fn position(&self) -> usize { self.opaque.position() } @@ -845,9 +843,8 @@ fn analyze_attr(attr: &impl AttributeExt, state: &mut AnalyzeAttrState<'_>) -> b } } } - } else if attr.path().starts_with(&[sym::diagnostic]) && attr.path().len() == 2 { - should_encode = - rustc_feature::is_stable_diagnostic_attribute(attr.path()[1], state.features); + } else if let &[sym::diagnostic, seg] = &*attr.path() { + should_encode = rustc_feature::is_stable_diagnostic_attribute(seg, state.features); } else { should_encode = true; } @@ -1838,7 +1835,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_macro(&mut self, def_id: LocalDefId) { let tcx = self.tcx; - let hir::ItemKind::Macro(macro_def, _) = tcx.hir_expect_item(def_id).kind else { bug!() }; + let (_, macro_def, _) = tcx.hir_expect_item(def_id).expect_macro(); self.tables.is_macro_rules.set(def_id.local_def_index, macro_def.macro_rules); record!(self.tables.macro_definition[def_id.to_def_id()] <- &*macro_def.body); } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 5536c93f84a..dc453b1e747 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -443,7 +443,7 @@ define_tables! { rendered_const: Table<DefIndex, LazyValue<String>>, rendered_precise_capturing_args: Table<DefIndex, LazyArray<PreciseCapturingArgKind<Symbol, Symbol>>>, asyncness: Table<DefIndex, ty::Asyncness>, - fn_arg_names: Table<DefIndex, LazyArray<Ident>>, + fn_arg_names: Table<DefIndex, LazyArray<Option<Ident>>>, coroutine_kind: Table<DefIndex, hir::CoroutineKind>, coroutine_for_closure: Table<DefIndex, RawDefId>, coroutine_by_move_body_def_id: Table<DefIndex, RawDefId>, diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 7525aeb9227..f967d8b92c7 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -79,6 +79,7 @@ rustc_query_append!(define_dep_nodes![ [] fn Null() -> (), /// We use this to create a forever-red node. [] fn Red() -> (), + [] fn SideEffect() -> (), [] fn TraitSelect() -> (), [] fn CompileCodegenUnit() -> (), [] fn CompileMonoItem() -> (), diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 2090c3e6da6..c927538b4cf 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -46,6 +46,7 @@ impl Deps for DepsType { const DEP_KIND_NULL: DepKind = dep_kinds::Null; const DEP_KIND_RED: DepKind = dep_kinds::Red; + const DEP_KIND_SIDE_EFFECT: DepKind = dep_kinds::SideEffect; const DEP_KIND_MAX: u16 = dep_node::DEP_KIND_VARIANTS - 1; } diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 73c0af84a9f..52f155a16b8 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -280,10 +280,11 @@ impl<'tcx> TyCtxt<'tcx> { }) } - pub fn hir_body_param_names(self, id: BodyId) -> impl Iterator<Item = Ident> { - self.hir_body(id).params.iter().map(|arg| match arg.pat.kind { - PatKind::Binding(_, _, ident, _) => ident, - _ => Ident::empty(), + pub fn hir_body_param_names(self, id: BodyId) -> impl Iterator<Item = Option<Ident>> { + self.hir_body(id).params.iter().map(|param| match param.pat.kind { + PatKind::Binding(_, _, ident, _) => Some(ident), + PatKind::Wild => Some(Ident::new(kw::Underscore, param.pat.span)), + _ => None, }) } @@ -384,7 +385,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn hir_get_module(self, module: LocalModDefId) -> (&'tcx Mod<'tcx>, Span, HirId) { let hir_id = HirId::make_owner(module.to_local_def_id()); match self.hir_owner_node(hir_id.owner) { - OwnerNode::Item(&Item { span, kind: ItemKind::Mod(m), .. }) => (m, span, hir_id), + OwnerNode::Item(&Item { span, kind: ItemKind::Mod(_, m), .. }) => (m, span, hir_id), OwnerNode::Crate(item) => (item, item.spans.inner_span, hir_id), node => panic!("not a module: {node:?}"), } @@ -846,7 +847,7 @@ impl<'tcx> TyCtxt<'tcx> { // A `Ctor` doesn't have an identifier itself, but its parent // struct/variant does. Compare with `hir::Map::span`. Node::Ctor(..) => match self.parent_hir_node(id) { - Node::Item(item) => Some(item.ident), + Node::Item(item) => Some(item.kind.ident().unwrap()), Node::Variant(variant) => Some(variant.ident), _ => unreachable!(), }, @@ -893,18 +894,14 @@ impl<'hir> Map<'hir> { } fn named_span(item_span: Span, ident: Ident, generics: Option<&Generics<'_>>) -> Span { - if ident.name != kw::Empty { - let mut span = until_within(item_span, ident.span); - if let Some(g) = generics - && !g.span.is_dummy() - && let Some(g_span) = g.span.find_ancestor_inside(item_span) - { - span = span.to(g_span); - } - span - } else { - item_span + let mut span = until_within(item_span, ident.span); + if let Some(g) = generics + && !g.span.is_dummy() + && let Some(g_span) = g.span.find_ancestor_inside(item_span) + { + span = span.to(g_span); } + span } let span = match self.tcx.hir_node(hir_id) { @@ -935,7 +932,7 @@ impl<'hir> Map<'hir> { }) => until_within(*outer_span, generics.where_clause_span), // Constants and Statics. Node::Item(Item { - kind: ItemKind::Const(ty, ..) | ItemKind::Static(ty, ..), + kind: ItemKind::Const(_, ty, ..) | ItemKind::Static(_, ty, ..), span: outer_span, .. }) @@ -956,7 +953,7 @@ impl<'hir> Map<'hir> { }) => until_within(*outer_span, ty.span), // With generics and bounds. Node::Item(Item { - kind: ItemKind::Trait(_, _, generics, bounds, _), + kind: ItemKind::Trait(_, _, _, generics, bounds, _), span: outer_span, .. }) @@ -976,7 +973,13 @@ impl<'hir> Map<'hir> { // SyntaxContext of the path. path.span.find_ancestor_in_same_ctxt(item.span).unwrap_or(item.span) } - _ => named_span(item.span, item.ident, item.kind.generics()), + _ => { + if let Some(ident) = item.kind.ident() { + named_span(item.span, ident, item.kind.generics()) + } else { + item.span + } + } }, Node::Variant(variant) => named_span(variant.span, variant.ident, None), Node::ImplItem(item) => named_span(item.span, item.ident, Some(item.generics)), @@ -1173,15 +1176,14 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh { debugger_visualizers.hash_stable(&mut hcx, &mut stable_hasher); if tcx.sess.opts.incremental.is_some() { let definitions = tcx.untracked().definitions.freeze(); - let mut owner_spans: Vec<_> = krate - .owners - .iter_enumerated() - .filter_map(|(def_id, info)| { - let _ = info.as_owner()?; + let mut owner_spans: Vec<_> = tcx + .hir_crate_items(()) + .definitions() + .map(|def_id| { let def_path_hash = definitions.def_path_hash(def_id); let span = tcx.source_span(def_id); debug_assert_eq!(span.parent(), None); - Some((def_path_hash, span)) + (def_path_hash, span) }) .collect(); owner_spans.sort_unstable_by_key(|bn| bn.0); @@ -1326,7 +1328,7 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> { self.items.push(item.item_id()); // Items that are modules are handled here instead of in visit_mod. - if let ItemKind::Mod(module) = &item.kind { + if let ItemKind::Mod(_, module) = &item.kind { self.submodules.push(item.owner_id); // A module collector does not recurse inside nested modules. if self.crate_collector { diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index b5f3a0e1482..0ae774ebee7 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -59,8 +59,8 @@ macro_rules! TrivialLiftImpls { macro_rules! TrivialTypeTraversalImpls { ($($ty:ty),+ $(,)?) => { $( - impl<'tcx> $crate::ty::fold::TypeFoldable<$crate::ty::TyCtxt<'tcx>> for $ty { - fn try_fold_with<F: $crate::ty::fold::FallibleTypeFolder<$crate::ty::TyCtxt<'tcx>>>( + impl<'tcx> $crate::ty::TypeFoldable<$crate::ty::TyCtxt<'tcx>> for $ty { + fn try_fold_with<F: $crate::ty::FallibleTypeFolder<$crate::ty::TyCtxt<'tcx>>>( self, _: &mut F, ) -> ::std::result::Result<Self, F::Error> { @@ -68,7 +68,7 @@ macro_rules! TrivialTypeTraversalImpls { } #[inline] - fn fold_with<F: $crate::ty::fold::TypeFolder<$crate::ty::TyCtxt<'tcx>>>( + fn fold_with<F: $crate::ty::TypeFolder<$crate::ty::TyCtxt<'tcx>>>( self, _: &mut F, ) -> Self { @@ -76,14 +76,14 @@ macro_rules! TrivialTypeTraversalImpls { } } - impl<'tcx> $crate::ty::visit::TypeVisitable<$crate::ty::TyCtxt<'tcx>> for $ty { + impl<'tcx> $crate::ty::TypeVisitable<$crate::ty::TyCtxt<'tcx>> for $ty { #[inline] - fn visit_with<F: $crate::ty::visit::TypeVisitor<$crate::ty::TyCtxt<'tcx>>>( + fn visit_with<F: $crate::ty::TypeVisitor<$crate::ty::TyCtxt<'tcx>>>( &self, _: &mut F) -> F::Result { - <F::Result as ::rustc_middle::ty::visit::VisitorResult>::output() + <F::Result as ::rustc_middle::ty::VisitorResult>::output() } } )+ diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index a94ead161c3..0cc72a261a5 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -174,6 +174,7 @@ impl CodegenFnAttrs { /// * `#[linkage]` is present pub fn contains_extern_indicator(&self) -> bool { self.flags.contains(CodegenFnAttrFlags::NO_MANGLE) + || self.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) || self.export_name.is_some() || match self.linkage { // These are private, so make sure we don't try to consider diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 923160cc0cc..34b27c2e1cc 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -6,7 +6,7 @@ use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, Typ use rustc_session::RemapFileNameExt; use rustc_session::config::RemapPathScopeComponents; use rustc_span::{DUMMY_SP, Span, Symbol}; -use rustc_type_ir::visit::TypeVisitableExt; +use rustc_type_ir::TypeVisitableExt; use super::interpret::ReportedErrorInfo; use crate::mir::interpret::{AllocId, ConstAllocation, ErrorHandled, Scalar, alloc_range}; diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 8c6b11a681e..e26575b552e 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -194,7 +194,6 @@ pub struct Mapping { #[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub struct FunctionCoverageInfo { pub function_source_hash: u64, - pub body_span: Span, /// Used in conjunction with `priority_list` to create physical counters /// and counter expressions, after MIR optimizations. diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index aed38414ab1..57aafbb26bc 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -16,8 +16,7 @@ use rustc_abi::{Align, HasDataLayout, Size}; use rustc_ast::Mutability; use rustc_data_structures::intern::Interned; use rustc_macros::HashStable; -use rustc_serialize::{Decodable, Encodable}; -use rustc_type_ir::{TyDecoder, TyEncoder}; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use super::{ AllocId, BadBytesAccess, CtfeProvenance, InterpErrorKind, InterpResult, Pointer, @@ -112,7 +111,7 @@ struct AllocFlags { all_zero: bool, } -impl<E: TyEncoder> Encodable<E> for AllocFlags { +impl<E: Encoder> Encodable<E> for AllocFlags { fn encode(&self, encoder: &mut E) { // Make sure Align::MAX can be stored with the high 2 bits unset. const { @@ -131,7 +130,7 @@ impl<E: TyEncoder> Encodable<E> for AllocFlags { } } -impl<D: TyDecoder> Decodable<D> for AllocFlags { +impl<D: Decoder> Decodable<D> for AllocFlags { fn decode(decoder: &mut D) -> Self { let flags: u8 = Decodable::decode(decoder); let align = flags & 0b0011_1111; @@ -173,7 +172,7 @@ fn all_zero(buf: &[u8]) -> bool { } /// Custom encoder for [`Allocation`] to more efficiently represent the case where all bytes are 0. -impl<Prov: Provenance, Extra, Bytes, E: TyEncoder> Encodable<E> for Allocation<Prov, Extra, Bytes> +impl<Prov: Provenance, Extra, Bytes, E: Encoder> Encodable<E> for Allocation<Prov, Extra, Bytes> where Bytes: AllocBytes, ProvenanceMap<Prov>: Encodable<E>, @@ -193,7 +192,7 @@ where } } -impl<Prov: Provenance, Extra, Bytes, D: TyDecoder> Decodable<D> for Allocation<Prov, Extra, Bytes> +impl<Prov: Provenance, Extra, Bytes, D: Decoder> Decodable<D> for Allocation<Prov, Extra, Bytes> where Bytes: AllocBytes, ProvenanceMap<Prov>: Decodable<D>, diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs index fea5038e6dd..20492cda4e2 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation/init_mask.rs @@ -5,9 +5,8 @@ use std::ops::Range; use std::{hash, iter}; use rustc_abi::Size; -use rustc_macros::{HashStable, TyDecodable, TyEncodable}; -use rustc_serialize::{Decodable, Encodable}; -use rustc_type_ir::{TyDecoder, TyEncoder}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable}; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use super::AllocRange; @@ -19,13 +18,13 @@ type Block = u64; /// possible. Currently, if all the blocks have the same value, then the mask represents either a /// fully initialized or fully uninitialized const allocation, so we can only store that single /// value. -#[derive(Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] +#[derive(Clone, Debug, Eq, PartialEq, Encodable_NoContext, Decodable_NoContext, Hash, HashStable)] pub struct InitMask { blocks: InitMaskBlocks, len: Size, } -#[derive(Clone, Debug, Eq, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] +#[derive(Clone, Debug, Eq, PartialEq, Encodable_NoContext, Decodable_NoContext, Hash, HashStable)] enum InitMaskBlocks { Lazy { /// Whether the lazy init mask is fully initialized or uninitialized. @@ -194,7 +193,7 @@ struct InitMaskMaterialized { // and also produces more output when the high bits of each `u64` are occupied. // Note: There is probably a remaining optimization for masks that do not use an entire // `Block`. -impl<E: TyEncoder> Encodable<E> for InitMaskMaterialized { +impl<E: Encoder> Encodable<E> for InitMaskMaterialized { fn encode(&self, encoder: &mut E) { encoder.emit_usize(self.blocks.len()); for block in &self.blocks { @@ -204,7 +203,7 @@ impl<E: TyEncoder> Encodable<E> for InitMaskMaterialized { } // This implementation is deliberately not derived, see the matching `Encodable` impl. -impl<D: TyDecoder> Decodable<D> for InitMaskMaterialized { +impl<D: Decoder> Decodable<D> for InitMaskMaterialized { fn decode(decoder: &mut D) -> Self { let num_blocks = decoder.read_usize(); let mut blocks = Vec::with_capacity(num_blocks); diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index effedf854e4..c2438af6a1e 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -105,7 +105,7 @@ enum AllocDiscriminant { Static, } -pub fn specialized_encode_alloc_id<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>>( +pub fn specialized_encode_alloc_id<'tcx, E: TyEncoder<'tcx>>( encoder: &mut E, tcx: TyCtxt<'tcx>, alloc_id: AllocId, @@ -175,7 +175,7 @@ impl<'s> AllocDecodingSession<'s> { /// Decodes an `AllocId` in a thread-safe way. pub fn decode_alloc_id<'tcx, D>(&self, decoder: &mut D) -> AllocId where - D: TyDecoder<I = TyCtxt<'tcx>>, + D: TyDecoder<'tcx>, { // Read the index of the allocation. let idx = usize::try_from(decoder.read_u32()).unwrap(); diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 78749428c6d..4222a68e544 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -10,8 +10,7 @@ use super::{ }; use crate::mir; use crate::query::TyCtxtEnsureOk; -use crate::ty::visit::TypeVisitableExt; -use crate::ty::{self, GenericArgs, TyCtxt}; +use crate::ty::{self, GenericArgs, TyCtxt, TypeVisitableExt}; impl<'tcx> TyCtxt<'tcx> { /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 83857ab6c5c..4dfb362f3a2 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -32,10 +32,9 @@ pub use self::query::*; use crate::mir::interpret::{AllocRange, Scalar}; use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::print::{FmtPrinter, Printer, pretty_print_const, with_no_trimmed_paths}; -use crate::ty::visit::TypeVisitableExt; use crate::ty::{ - self, AdtDef, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypingEnv, - UserTypeAnnotationIndex, + self, GenericArg, GenericArgsRef, Instance, InstanceKind, List, Ty, TyCtxt, TypeVisitableExt, + TypingEnv, UserTypeAnnotationIndex, }; mod basic_blocks; @@ -791,7 +790,7 @@ impl<T> ClearCrossCrate<T> { const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0; const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1; -impl<E: TyEncoder, T: Encodable<E>> Encodable<E> for ClearCrossCrate<T> { +impl<'tcx, E: TyEncoder<'tcx>, T: Encodable<E>> Encodable<E> for ClearCrossCrate<T> { #[inline] fn encode(&self, e: &mut E) { if E::CLEAR_CROSS_CRATE { @@ -807,7 +806,7 @@ impl<E: TyEncoder, T: Encodable<E>> Encodable<E> for ClearCrossCrate<T> { } } } -impl<D: TyDecoder, T: Decodable<D>> Decodable<D> for ClearCrossCrate<T> { +impl<'tcx, D: TyDecoder<'tcx>, T: Decodable<D>> Decodable<D> for ClearCrossCrate<T> { #[inline] fn decode(d: &mut D) -> ClearCrossCrate<T> { if D::CLEAR_CROSS_CRATE { @@ -1483,53 +1482,10 @@ pub struct UserTypeProjections { pub contents: Vec<UserTypeProjection>, } -impl<'tcx> UserTypeProjections { - pub fn none() -> Self { - UserTypeProjections { contents: vec![] } - } - - pub fn is_empty(&self) -> bool { - self.contents.is_empty() - } - +impl UserTypeProjections { pub fn projections(&self) -> impl Iterator<Item = &UserTypeProjection> + ExactSizeIterator { self.contents.iter() } - - pub fn push_user_type(mut self, base_user_type: UserTypeAnnotationIndex) -> Self { - self.contents.push(UserTypeProjection { base: base_user_type, projs: vec![] }); - self - } - - fn map_projections(mut self, f: impl FnMut(UserTypeProjection) -> UserTypeProjection) -> Self { - self.contents = self.contents.into_iter().map(f).collect(); - self - } - - pub fn index(self) -> Self { - self.map_projections(|pat_ty_proj| pat_ty_proj.index()) - } - - pub fn subslice(self, from: u64, to: u64) -> Self { - self.map_projections(|pat_ty_proj| pat_ty_proj.subslice(from, to)) - } - - pub fn deref(self) -> Self { - self.map_projections(|pat_ty_proj| pat_ty_proj.deref()) - } - - pub fn leaf(self, field: FieldIdx) -> Self { - self.map_projections(|pat_ty_proj| pat_ty_proj.leaf(field)) - } - - pub fn variant( - self, - adt_def: AdtDef<'tcx>, - variant_index: VariantIdx, - field_index: FieldIdx, - ) -> Self { - self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field_index)) - } } /// Encodes the effect of a user-supplied type annotation on the @@ -1554,42 +1510,6 @@ pub struct UserTypeProjection { pub projs: Vec<ProjectionKind>, } -impl UserTypeProjection { - pub(crate) fn index(mut self) -> Self { - self.projs.push(ProjectionElem::Index(())); - self - } - - pub(crate) fn subslice(mut self, from: u64, to: u64) -> Self { - self.projs.push(ProjectionElem::Subslice { from, to, from_end: true }); - self - } - - pub(crate) fn deref(mut self) -> Self { - self.projs.push(ProjectionElem::Deref); - self - } - - pub(crate) fn leaf(mut self, field: FieldIdx) -> Self { - self.projs.push(ProjectionElem::Field(field, ())); - self - } - - pub(crate) fn variant( - mut self, - adt_def: AdtDef<'_>, - variant_index: VariantIdx, - field_index: FieldIdx, - ) -> Self { - self.projs.push(ProjectionElem::Downcast( - Some(adt_def.variant(variant_index).name), - variant_index, - )); - self.projs.push(ProjectionElem::Field(field_index, ())); - self - } -} - rustc_index::newtype_index! { #[derive(HashStable)] #[encodable] diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 573f7895da2..5a038b27337 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -620,9 +620,8 @@ fn write_function_coverage_info( function_coverage_info: &coverage::FunctionCoverageInfo, w: &mut dyn io::Write, ) -> io::Result<()> { - let coverage::FunctionCoverageInfo { body_span, mappings, .. } = function_coverage_info; + let coverage::FunctionCoverageInfo { mappings, .. } = function_coverage_info; - writeln!(w, "{INDENT}coverage body span: {body_span:?}")?; for coverage::Mapping { kind, span } in mappings { writeln!(w, "{INDENT}coverage {kind:?} => {span:?};")?; } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 50494355e3e..5a9fe10938a 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -13,8 +13,7 @@ use rustc_span::{Span, Symbol}; use smallvec::SmallVec; use super::{ConstValue, SourceInfo}; -use crate::ty::fold::fold_regions; -use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt}; +use crate::ty::{self, CoroutineArgsExt, OpaqueHiddenType, Ty, TyCtxt, fold_regions}; rustc_index::newtype_index! { #[derive(HashStable)] diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index f05a798949b..d59b6df44ed 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -774,6 +774,15 @@ impl BorrowKind { } } +impl<'tcx> NullOp<'tcx> { + pub fn ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + match self { + NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) => tcx.types.usize, + NullOp::UbChecks | NullOp::ContractChecks => tcx.types.bool, + } + } +} + impl<'tcx> UnOp { pub fn ty(&self, tcx: TyCtxt<'tcx>, arg_ty: Ty<'tcx>) -> Ty<'tcx> { match self { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 94a5a3769a3..527c18addbe 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1410,7 +1410,7 @@ rustc_queries! { desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) } } - query fn_arg_names(def_id: DefId) -> &'tcx [rustc_span::Ident] { + query fn_arg_names(def_id: DefId) -> &'tcx [Option<rustc_span::Ident>] { desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) } separate_provide_extern } diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index d9035efaf56..14e3ce8bef6 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -11,7 +11,7 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId, Stab use rustc_hir::definitions::DefPathHash; use rustc_index::{Idx, IndexVec}; use rustc_macros::{Decodable, Encodable}; -use rustc_query_system::query::QuerySideEffects; +use rustc_query_system::query::QuerySideEffect; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::Session; @@ -55,9 +55,9 @@ pub struct OnDiskCache { // The complete cache data in serialized form. serialized_data: RwLock<Option<Mmap>>, - // Collects all `QuerySideEffects` created during the current compilation + // Collects all `QuerySideEffect` created during the current compilation // session. - current_side_effects: Lock<FxHashMap<DepNodeIndex, QuerySideEffects>>, + current_side_effects: Lock<FxHashMap<DepNodeIndex, QuerySideEffect>>, file_index_to_stable_id: FxHashMap<SourceFileIndex, EncodedSourceFileId>, @@ -68,7 +68,7 @@ pub struct OnDiskCache { // `serialized_data`. query_result_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>, - // A map from dep-node to the position of any associated `QuerySideEffects` in + // A map from dep-node to the position of any associated `QuerySideEffect` in // `serialized_data`. prev_side_effects_index: FxHashMap<SerializedDepNodeIndex, AbsoluteBytePos>, @@ -270,10 +270,10 @@ impl OnDiskCache { .current_side_effects .borrow() .iter() - .map(|(dep_node_index, side_effects)| { + .map(|(dep_node_index, side_effect)| { let pos = AbsoluteBytePos::new(encoder.position()); let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index()); - encoder.encode_tagged(dep_node_index, side_effects); + encoder.encode_tagged(dep_node_index, side_effect); (dep_node_index, pos) }) @@ -352,24 +352,23 @@ impl OnDiskCache { }) } - /// Loads a `QuerySideEffects` created during the previous compilation session. - pub fn load_side_effects( + /// Loads a `QuerySideEffect` created during the previous compilation session. + pub fn load_side_effect( &self, tcx: TyCtxt<'_>, dep_node_index: SerializedDepNodeIndex, - ) -> QuerySideEffects { - let side_effects: Option<QuerySideEffects> = + ) -> Option<QuerySideEffect> { + let side_effect: Option<QuerySideEffect> = self.load_indexed(tcx, dep_node_index, &self.prev_side_effects_index); - - side_effects.unwrap_or_default() + side_effect } - /// Stores a `QuerySideEffects` emitted during the current compilation session. - /// Anything stored like this will be available via `load_side_effects` in + /// Stores a `QuerySideEffect` emitted during the current compilation session. + /// Anything stored like this will be available via `load_side_effect` in /// the next compilation session. - pub fn store_side_effects(&self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects) { + pub fn store_side_effect(&self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) { let mut current_side_effects = self.current_side_effects.borrow_mut(); - let prev = current_side_effects.insert(dep_node_index, side_effects); + let prev = current_side_effects.insert(dep_node_index, side_effect); debug_assert!(prev.is_none()); } @@ -395,21 +394,6 @@ impl OnDiskCache { opt_value } - /// Stores side effect emitted during computation of an anonymous query. - /// Since many anonymous queries can share the same `DepNode`, we aggregate - /// them -- as opposed to regular queries where we assume that there is a - /// 1:1 relationship between query-key and `DepNode`. - pub fn store_side_effects_for_anon_node( - &self, - dep_node_index: DepNodeIndex, - side_effects: QuerySideEffects, - ) { - let mut current_side_effects = self.current_side_effects.borrow_mut(); - - let x = current_side_effects.entry(dep_node_index).or_default(); - x.append(side_effects); - } - fn load_indexed<'tcx, T>( &self, tcx: TyCtxt<'tcx>, @@ -518,8 +502,7 @@ where value } -impl<'a, 'tcx> TyDecoder for CacheDecoder<'a, 'tcx> { - type I = TyCtxt<'tcx>; +impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> { const CLEAR_CROSS_CRATE: bool = false; #[inline] @@ -943,8 +926,7 @@ impl<'a, 'tcx> SpanEncoder for CacheEncoder<'a, 'tcx> { } } -impl<'a, 'tcx> TyEncoder for CacheEncoder<'a, 'tcx> { - type I = TyCtxt<'tcx>; +impl<'a, 'tcx> TyEncoder<'tcx> for CacheEncoder<'a, 'tcx> { const CLEAR_CROSS_CRATE: bool = false; #[inline] diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index f7b98d935d4..bbcd509c558 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -28,6 +28,7 @@ use tracing::instrument; use crate::middle::region; use crate::mir::interpret::AllocId; use crate::mir::{self, BinOp, BorrowKind, FakeReadCause, UnOp}; +use crate::thir::visit::for_each_immediate_subpat; use crate::ty::adjustment::PointerCoercion; use crate::ty::layout::IntegerExt; use crate::ty::{ @@ -672,27 +673,7 @@ impl<'tcx> Pat<'tcx> { return; } - use PatKind::*; - match &self.kind { - Wild - | Never - | Range(..) - | Binding { subpattern: None, .. } - | Constant { .. } - | Error(_) => {} - AscribeUserType { subpattern, .. } - | Binding { subpattern: Some(subpattern), .. } - | Deref { subpattern } - | DerefPattern { subpattern, .. } - | ExpandedConstant { subpattern, .. } => subpattern.walk_(it), - Leaf { subpatterns } | Variant { subpatterns, .. } => { - subpatterns.iter().for_each(|field| field.pattern.walk_(it)) - } - Or { pats } => pats.iter().for_each(|p| p.walk_(it)), - Array { box prefix, slice, box suffix } | Slice { box prefix, slice, box suffix } => { - prefix.iter().chain(slice.as_deref()).chain(suffix.iter()).for_each(|p| p.walk_(it)) - } - } + for_each_immediate_subpat(self, |p| p.walk_(it)); } /// Whether the pattern has a `PatKind::Error` nested within. @@ -783,8 +764,12 @@ pub enum PatKind<'tcx> { var: LocalVarId, ty: Ty<'tcx>, subpattern: Option<Box<Pat<'tcx>>>, + /// Is this the leftmost occurrence of the binding, i.e., is `var` the /// `HirId` of this pattern? + /// + /// (The same binding can occur multiple times in different branches of + /// an or-pattern, but only one of them will be primary.) is_primary: bool, }, diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index d208692f4e7..7d62ab7970d 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -240,36 +240,45 @@ pub fn walk_pat<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>( visitor: &mut V, pat: &'thir Pat<'tcx>, ) { - use PatKind::*; + for_each_immediate_subpat(pat, |p| visitor.visit_pat(p)); +} + +/// Invokes `callback` on each immediate subpattern of `pat`, if any. +/// A building block for assembling THIR pattern visitors. +pub(crate) fn for_each_immediate_subpat<'a, 'tcx>( + pat: &'a Pat<'tcx>, + mut callback: impl FnMut(&'a Pat<'tcx>), +) { match &pat.kind { - AscribeUserType { subpattern, ascription: _ } - | Deref { subpattern } - | DerefPattern { subpattern, .. } - | Binding { subpattern: Some(subpattern), .. } => visitor.visit_pat(subpattern), - Binding { .. } | Wild | Never | Error(_) => {} - Variant { subpatterns, adt_def: _, args: _, variant_index: _ } | Leaf { subpatterns } => { - for subpattern in subpatterns { - visitor.visit_pat(&subpattern.pattern); + PatKind::Wild + | PatKind::Binding { subpattern: None, .. } + | PatKind::Constant { value: _ } + | PatKind::Range(_) + | PatKind::Never + | PatKind::Error(_) => {} + + PatKind::AscribeUserType { subpattern, .. } + | PatKind::Binding { subpattern: Some(subpattern), .. } + | PatKind::Deref { subpattern } + | PatKind::DerefPattern { subpattern, .. } + | PatKind::ExpandedConstant { subpattern, .. } => callback(subpattern), + + PatKind::Variant { subpatterns, .. } | PatKind::Leaf { subpatterns } => { + for field_pat in subpatterns { + callback(&field_pat.pattern); } } - Constant { value: _ } => {} - ExpandedConstant { def_id: _, is_inline: _, subpattern } => visitor.visit_pat(subpattern), - Range(_) => {} - Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => { - for subpattern in prefix.iter() { - visitor.visit_pat(subpattern); - } - if let Some(pat) = slice { - visitor.visit_pat(pat); - } - for subpattern in suffix.iter() { - visitor.visit_pat(subpattern); + + PatKind::Slice { prefix, slice, suffix } | PatKind::Array { prefix, slice, suffix } => { + for pat in prefix.iter().chain(slice.as_deref()).chain(suffix) { + callback(pat); } } - Or { pats } => { - for pat in pats.iter() { - visitor.visit_pat(pat); + + PatKind::Or { pats } => { + for pat in pats { + callback(pat); } } - }; + } } diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 9c74f6263b3..145561b76c4 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -3,9 +3,9 @@ use rustc_macros::HashStable; use rustc_type_ir as ir; pub use rustc_type_ir::solve::*; -use crate::ty::visit::try_visit; use crate::ty::{ self, FallibleTypeFolder, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, + try_visit, }; pub type Goal<'tcx, P> = ir::solve::Goal<TyCtxt<'tcx>, P>; diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index 8e54a9d487d..05c19db4caa 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs @@ -6,8 +6,7 @@ use rustc_span::sym; use crate::error::StrictCoherenceNeedsNegativeCoherence; use crate::ty::fast_reject::SimplifiedType; -use crate::ty::visit::TypeVisitableExt; -use crate::ty::{self, TyCtxt}; +use crate::ty::{self, TyCtxt, TypeVisitableExt}; /// A per-trait graph of impls in specialization order. At the moment, this /// graph forms a tree rooted with the trait itself, with all other nodes diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index c1dc6a894ca..cb245c0aec4 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -327,11 +327,22 @@ impl<'tcx> AdtDef<'tcx> { } /// Returns `true` if the variant list of this ADT is `#[non_exhaustive]`. + /// + /// Note that this function will return `true` even if the ADT has been + /// defined in the crate currently being compiled. If that's not what you + /// want, see [`Self::variant_list_has_applicable_non_exhaustive`]. #[inline] pub fn is_variant_list_non_exhaustive(self) -> bool { self.flags().contains(AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE) } + /// Returns `true` if the variant list of this ADT is `#[non_exhaustive]` + /// and has been defined in another crate. + #[inline] + pub fn variant_list_has_applicable_non_exhaustive(self) -> bool { + self.is_variant_list_non_exhaustive() && !self.did().is_local() + } + /// Returns the kind of the ADT. #[inline] pub fn adt_kind(self) -> AdtKind { diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index fe42a224d9f..74b34afe616 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -14,9 +14,8 @@ use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::LocalDefId; use rustc_serialize::{Decodable, Encodable}; -use rustc_span::Span; use rustc_span::source_map::Spanned; -pub use rustc_type_ir::{TyDecoder, TyEncoder}; +use rustc_span::{Span, SpanDecoder, SpanEncoder}; use crate::arena::ArenaAllocatable; use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos}; @@ -31,13 +30,45 @@ use crate::ty::{self, AdtDef, GenericArgsRef, Ty, TyCtxt}; /// This offset is also chosen so that the first byte is never < 0x80. pub const SHORTHAND_OFFSET: usize = 0x80; -pub trait EncodableWithShorthand<E: TyEncoder>: Copy + Eq + Hash { +pub trait TyEncoder<'tcx>: SpanEncoder { + const CLEAR_CROSS_CRATE: bool; + + fn position(&self) -> usize; + + fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize>; + + fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize>; + + fn encode_alloc_id(&mut self, alloc_id: &AllocId); +} + +pub trait TyDecoder<'tcx>: SpanDecoder { + const CLEAR_CROSS_CRATE: bool; + + fn interner(&self) -> TyCtxt<'tcx>; + + fn cached_ty_for_shorthand<F>(&mut self, shorthand: usize, or_insert_with: F) -> Ty<'tcx> + where + F: FnOnce(&mut Self) -> Ty<'tcx>; + + fn with_position<F, R>(&mut self, pos: usize, f: F) -> R + where + F: FnOnce(&mut Self) -> R; + + fn positioned_at_shorthand(&self) -> bool { + (self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0 + } + + fn decode_alloc_id(&mut self) -> AllocId; +} + +pub trait EncodableWithShorthand<'tcx, E: TyEncoder<'tcx>>: Copy + Eq + Hash { type Variant: Encodable<E>; fn variant(&self) -> &Self::Variant; } #[allow(rustc::usage_of_ty_tykind)] -impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> EncodableWithShorthand<E> for Ty<'tcx> { +impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for Ty<'tcx> { type Variant = ty::TyKind<'tcx>; #[inline] @@ -46,7 +77,7 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> EncodableWithShorthand<E> for Ty<'tcx } } -impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> EncodableWithShorthand<E> for ty::PredicateKind<'tcx> { +impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for ty::PredicateKind<'tcx> { type Variant = ty::PredicateKind<'tcx>; #[inline] @@ -65,16 +96,16 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> EncodableWithShorthand<E> for ty::Pre /// /// `Decodable` can still be implemented in cases where `Decodable` is required /// by a trait bound. -pub trait RefDecodable<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> { +pub trait RefDecodable<'tcx, D: TyDecoder<'tcx>> { fn decode(d: &mut D) -> &'tcx Self; } /// Encode the given value or a previously cached shorthand. pub fn encode_with_shorthand<'tcx, E, T, M>(encoder: &mut E, value: &T, cache: M) where - E: TyEncoder<I = TyCtxt<'tcx>>, + E: TyEncoder<'tcx>, M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<T, usize>, - T: EncodableWithShorthand<E>, + T: EncodableWithShorthand<'tcx, E>, // The discriminant and shorthand must have the same size. T::Variant: DiscriminantKind<Discriminant = isize>, { @@ -108,13 +139,13 @@ where } } -impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for Ty<'tcx> { +impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for Ty<'tcx> { fn encode(&self, e: &mut E) { encode_with_shorthand(e, self, TyEncoder::type_shorthands); } } -impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Predicate<'tcx> { +impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Predicate<'tcx> { fn encode(&self, e: &mut E) { let kind = self.kind(); kind.bound_vars().encode(e); @@ -122,76 +153,72 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Predicate<'tcx> } } -impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Clause<'tcx> { +impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Clause<'tcx> { fn encode(&self, e: &mut E) { self.as_predicate().encode(e); } } -impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Region<'tcx> { +impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Region<'tcx> { fn encode(&self, e: &mut E) { self.kind().encode(e); } } -impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Const<'tcx> { +impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Const<'tcx> { fn encode(&self, e: &mut E) { self.0.0.encode(e); } } -impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Pattern<'tcx> { +impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Pattern<'tcx> { fn encode(&self, e: &mut E) { self.0.0.encode(e); } } -impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::ValTree<'tcx> { +impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::ValTree<'tcx> { fn encode(&self, e: &mut E) { self.0.0.encode(e); } } -impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ConstAllocation<'tcx> { +impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ConstAllocation<'tcx> { fn encode(&self, e: &mut E) { self.inner().encode(e) } } -impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for AdtDef<'tcx> { +impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AdtDef<'tcx> { fn encode(&self, e: &mut E) { self.0.0.encode(e) } } -impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for AllocId { +impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AllocId { fn encode(&self, e: &mut E) { e.encode_alloc_id(self) } } -impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for CtfeProvenance { +impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for CtfeProvenance { fn encode(&self, e: &mut E) { self.into_parts().encode(e); } } -impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::ParamEnv<'tcx> { +impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::ParamEnv<'tcx> { fn encode(&self, e: &mut E) { self.caller_bounds().encode(e); } } #[inline] -fn decode_arena_allocable< - 'tcx, - D: TyDecoder<I = TyCtxt<'tcx>>, - T: ArenaAllocatable<'tcx> + Decodable<D>, ->( +fn decode_arena_allocable<'tcx, D: TyDecoder<'tcx>, T: ArenaAllocatable<'tcx> + Decodable<D>>( decoder: &mut D, ) -> &'tcx T where - D: TyDecoder, + D: TyDecoder<'tcx>, { decoder.interner().arena.alloc(Decodable::decode(decoder)) } @@ -199,18 +226,18 @@ where #[inline] fn decode_arena_allocable_slice< 'tcx, - D: TyDecoder<I = TyCtxt<'tcx>>, + D: TyDecoder<'tcx>, T: ArenaAllocatable<'tcx> + Decodable<D>, >( decoder: &mut D, ) -> &'tcx [T] where - D: TyDecoder, + D: TyDecoder<'tcx>, { decoder.interner().arena.alloc_from_iter(<Vec<T> as Decodable<D>>::decode(decoder)) } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for Ty<'tcx> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Ty<'tcx> { #[allow(rustc::usage_of_ty_tykind)] fn decode(decoder: &mut D) -> Ty<'tcx> { // Handle shorthands first, if we have a usize > 0x80. @@ -229,7 +256,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for Ty<'tcx> { } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Predicate<'tcx> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Predicate<'tcx> { fn decode(decoder: &mut D) -> ty::Predicate<'tcx> { let bound_vars = Decodable::decode(decoder); // Handle shorthands first, if we have a usize > 0x80. @@ -249,14 +276,14 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Predicate<'tcx> } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Clause<'tcx> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Clause<'tcx> { fn decode(decoder: &mut D) -> ty::Clause<'tcx> { let pred: ty::Predicate<'tcx> = Decodable::decode(decoder); pred.expect_clause() } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for GenericArgsRef<'tcx> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for GenericArgsRef<'tcx> { fn decode(decoder: &mut D) -> Self { let len = decoder.read_usize(); let tcx = decoder.interner(); @@ -266,7 +293,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for GenericArgsRef<'tcx> } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for mir::Place<'tcx> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for mir::Place<'tcx> { fn decode(decoder: &mut D) -> Self { let local: mir::Local = Decodable::decode(decoder); let len = decoder.read_usize(); @@ -277,13 +304,13 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for mir::Place<'tcx> { } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Region<'tcx> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Region<'tcx> { fn decode(decoder: &mut D) -> Self { ty::Region::new_from_kind(decoder.interner(), Decodable::decode(decoder)) } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for CanonicalVarInfos<'tcx> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CanonicalVarInfos<'tcx> { fn decode(decoder: &mut D) -> Self { let len = decoder.read_usize(); decoder.interner().mk_canonical_var_infos_from_iter( @@ -292,26 +319,26 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for CanonicalVarInfos<'t } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for AllocId { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AllocId { fn decode(decoder: &mut D) -> Self { decoder.decode_alloc_id() } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for CtfeProvenance { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CtfeProvenance { fn decode(decoder: &mut D) -> Self { let parts = Decodable::decode(decoder); CtfeProvenance::from_parts(parts) } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::SymbolName<'tcx> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::SymbolName<'tcx> { fn decode(decoder: &mut D) -> Self { ty::SymbolName::new(decoder.interner(), decoder.read_str()) } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::ParamEnv<'tcx> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::ParamEnv<'tcx> { fn decode(d: &mut D) -> Self { let caller_bounds = Decodable::decode(d); ty::ParamEnv::new(caller_bounds) @@ -320,7 +347,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::ParamEnv<'tcx> { macro_rules! impl_decodable_via_ref { ($($t:ty,)+) => { - $(impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for $t { + $(impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for $t { fn decode(decoder: &mut D) -> Self { RefDecodable::decode(decoder) } @@ -328,7 +355,7 @@ macro_rules! impl_decodable_via_ref { } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<Ty<'tcx>> { +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<Ty<'tcx>> { fn decode(decoder: &mut D) -> &'tcx Self { let len = decoder.read_usize(); decoder @@ -337,7 +364,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<Ty } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::PolyExistentialPredicate<'tcx>> { fn decode(decoder: &mut D) -> &'tcx Self { @@ -348,38 +375,38 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Const<'tcx> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Const<'tcx> { fn decode(decoder: &mut D) -> Self { let kind: ty::ConstKind<'tcx> = Decodable::decode(decoder); decoder.interner().mk_ct_from_kind(kind) } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Pattern<'tcx> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Pattern<'tcx> { fn decode(decoder: &mut D) -> Self { decoder.interner().mk_pat(Decodable::decode(decoder)) } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::ValTree<'tcx> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::ValTree<'tcx> { fn decode(decoder: &mut D) -> Self { decoder.interner().intern_valtree(Decodable::decode(decoder)) } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ConstAllocation<'tcx> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ConstAllocation<'tcx> { fn decode(decoder: &mut D) -> Self { decoder.interner().mk_const_alloc(Decodable::decode(decoder)) } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for AdtDef<'tcx> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AdtDef<'tcx> { fn decode(decoder: &mut D) -> Self { decoder.interner().mk_adt_def_from_data(Decodable::decode(decoder)) } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [(ty::Clause<'tcx>, Span)] { +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [(ty::Clause<'tcx>, Span)] { fn decode(decoder: &mut D) -> &'tcx Self { decoder .interner() @@ -388,9 +415,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [(ty::Claus } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> - for [(ty::PolyTraitRef<'tcx>, Span)] -{ +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [(ty::PolyTraitRef<'tcx>, Span)] { fn decode(decoder: &mut D) -> &'tcx Self { decoder .interner() @@ -399,7 +424,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [Spanned<MonoItem<'tcx>>] { +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [Spanned<MonoItem<'tcx>>] { fn decode(decoder: &mut D) -> &'tcx Self { decoder .interner() @@ -408,9 +433,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [Spanned<Mo } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> - for ty::List<ty::BoundVariableKind> -{ +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::BoundVariableKind> { fn decode(decoder: &mut D) -> &'tcx Self { let len = decoder.read_usize(); decoder.interner().mk_bound_variable_kinds_from_iter( @@ -419,7 +442,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty::Const<'tcx>> { +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::Const<'tcx>> { fn decode(decoder: &mut D) -> &'tcx Self { let len = decoder.read_usize(); decoder.interner().mk_const_list_from_iter( @@ -428,7 +451,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<ty } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::ListWithCachedTypeInfo<ty::Clause<'tcx>> { fn decode(decoder: &mut D) -> &'tcx Self { @@ -439,7 +462,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<FieldIdx> { +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<FieldIdx> { fn decode(decoder: &mut D) -> &'tcx Self { let len = decoder.read_usize(); decoder @@ -448,7 +471,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<Fi } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<LocalDefId> { +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<LocalDefId> { fn decode(decoder: &mut D) -> &'tcx Self { let len = decoder.read_usize(); decoder.interner().mk_local_def_ids_from_iter( @@ -457,15 +480,13 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<Lo } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for &'tcx ty::List<LocalDefId> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for &'tcx ty::List<LocalDefId> { fn decode(d: &mut D) -> Self { RefDecodable::decode(d) } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> - for ty::List<(VariantIdx, FieldIdx)> -{ +impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<(VariantIdx, FieldIdx)> { fn decode(decoder: &mut D) -> &'tcx Self { let len = decoder.read_usize(); decoder.interner().mk_offset_of_from_iter( @@ -503,14 +524,14 @@ macro_rules! impl_arena_allocatable_decoder { ([]$args:tt) => {}; ([decode $(, $attrs:ident)*] [$name:ident: $ty:ty]) => { - impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for $ty { + impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for $ty { #[inline] fn decode(decoder: &mut D) -> &'tcx Self { decode_arena_allocable(decoder) } } - impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [$ty] { + impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [$ty] { #[inline] fn decode(decoder: &mut D) -> &'tcx Self { decode_arena_allocable_slice(decoder) @@ -532,14 +553,14 @@ arena_types!(impl_arena_allocatable_decoders); macro_rules! impl_arena_copy_decoder { (<$tcx:tt> $($ty:ty,)*) => { - $(impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for $ty { + $(impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for $ty { #[inline] fn decode(decoder: &mut D) -> &'tcx Self { decoder.interner().arena.alloc(Decodable::decode(decoder)) } } - impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [$ty] { + impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [$ty] { #[inline] fn decode(decoder: &mut D) -> &'tcx Self { decoder.interner().arena.alloc_from_iter(<Vec<_> as Decodable<D>>::decode(decoder)) diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index d30520a0222..ae1c6c670cb 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -34,7 +34,7 @@ impl<'tcx> rustc_type_ir::inherent::IntoKind for Const<'tcx> { } } -impl<'tcx> rustc_type_ir::visit::Flags for Const<'tcx> { +impl<'tcx> rustc_type_ir::Flags for Const<'tcx> { fn flags(&self) -> TypeFlags { self.0.flags } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a2472157d0e..f54dd2b0040 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -49,11 +49,10 @@ use rustc_session::{Limit, MetadataKind, Session}; use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId}; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; use rustc_type_ir::TyKind::*; -use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::lang_items::TraitSolverLangItem; pub use rustc_type_ir::lift::Lift; use rustc_type_ir::{ - CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo, elaborate, search_graph, + CollectAndApply, Interner, TypeFlags, TypeFoldable, WithCachedTypeInfo, elaborate, search_graph, }; use tracing::{debug, instrument}; diff --git a/compiler/rustc_middle/src/ty/context/tls.rs b/compiler/rustc_middle/src/ty/context/tls.rs index eaab8474dd2..5fc80bc7936 100644 --- a/compiler/rustc_middle/src/ty/context/tls.rs +++ b/compiler/rustc_middle/src/ty/context/tls.rs @@ -1,8 +1,6 @@ use std::{mem, ptr}; -use rustc_data_structures::sync::{self, Lock}; -use rustc_errors::DiagInner; -use thin_vec::ThinVec; +use rustc_data_structures::sync; use super::{GlobalCtxt, TyCtxt}; use crate::dep_graph::TaskDepsRef; @@ -22,10 +20,6 @@ pub struct ImplicitCtxt<'a, 'tcx> { /// `ty::query::plumbing` when executing a query. pub query: Option<QueryJobId>, - /// Where to store diagnostics for the current query job, if any. - /// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query. - pub diagnostics: Option<&'a Lock<ThinVec<DiagInner>>>, - /// Used to prevent queries from calling too deeply. pub query_depth: usize, @@ -37,13 +31,7 @@ pub struct ImplicitCtxt<'a, 'tcx> { impl<'a, 'tcx> ImplicitCtxt<'a, 'tcx> { pub fn new(gcx: &'tcx GlobalCtxt<'tcx>) -> Self { let tcx = TyCtxt { gcx }; - ImplicitCtxt { - tcx, - query: None, - diagnostics: None, - query_depth: 0, - task_deps: TaskDepsRef::Ignore, - } + ImplicitCtxt { tcx, query: None, query_depth: 0, task_deps: TaskDepsRef::Ignore } } } diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 881381a5ee6..d3abb3d64b8 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -142,8 +142,8 @@ pub fn suggest_arbitrary_trait_bound<'tcx>( if let Some((name, term)) = associated_ty { // FIXME: this case overlaps with code in TyCtxt::note_and_explain_type_err. // That should be extracted into a helper function. - if constraint.ends_with('>') { - constraint = format!("{}, {} = {}>", &constraint[..constraint.len() - 1], name, term); + if let Some(stripped) = constraint.strip_suffix('>') { + constraint = format!("{stripped}, {name} = {term}>"); } else { constraint.push_str(&format!("<{name} = {term}>")); } @@ -641,21 +641,19 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsSuggestableVisitor<'tcx> { } } - Alias(Projection, AliasTy { def_id, .. }) => { - if self.tcx.def_kind(def_id) != DefKind::AssocTy { - return ControlFlow::Break(()); - } + Alias(Projection, AliasTy { def_id, .. }) + if self.tcx.def_kind(def_id) != DefKind::AssocTy => + { + return ControlFlow::Break(()); } - Param(param) => { - // FIXME: It would be nice to make this not use string manipulation, - // but it's pretty hard to do this, since `ty::ParamTy` is missing - // sufficient info to determine if it is synthetic, and we don't - // always have a convenient way of getting `ty::Generics` at the call - // sites we invoke `IsSuggestable::is_suggestable`. - if param.name.as_str().starts_with("impl ") { - return ControlFlow::Break(()); - } + // FIXME: It would be nice to make this not use string manipulation, + // but it's pretty hard to do this, since `ty::ParamTy` is missing + // sufficient info to determine if it is synthetic, and we don't + // always have a convenient way of getting `ty::Generics` at the call + // sites we invoke `IsSuggestable::is_suggestable`. + Param(param) if param.name.as_str().starts_with("impl ") => { + return ControlFlow::Break(()); } _ => {} @@ -733,17 +731,13 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> { } } - Param(param) => { - // FIXME: It would be nice to make this not use string manipulation, - // but it's pretty hard to do this, since `ty::ParamTy` is missing - // sufficient info to determine if it is synthetic, and we don't - // always have a convenient way of getting `ty::Generics` at the call - // sites we invoke `IsSuggestable::is_suggestable`. - if param.name.as_str().starts_with("impl ") { - return Err(()); - } - - t + // FIXME: It would be nice to make this not use string manipulation, + // but it's pretty hard to do this, since `ty::ParamTy` is missing + // sufficient info to determine if it is synthetic, and we don't + // always have a convenient way of getting `ty::Generics` at the call + // sites we invoke `IsSuggestable::is_suggestable`. + Param(param) if param.name.as_str().starts_with("impl ") => { + return Err(()); } _ => t, diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index ecca1d44907..f25c48cf42a 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -1,8 +1,9 @@ use tracing::debug; use crate::query::Providers; -use crate::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; -use crate::ty::{self, Ty, TyCtxt, TypeFlags, TypeVisitableExt}; +use crate::ty::{ + self, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, +}; pub(super) fn provide(providers: &mut Providers) { *providers = Providers { erase_regions_ty, ..*providers }; diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 4ea4050ed8b..dc2c9e3d9f1 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -1,12 +1,11 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_hir::def_id::DefId; use rustc_type_ir::data_structures::DelayedMap; -pub use rustc_type_ir::fold::{ - FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable, fold_regions, shift_region, - shift_vars, -}; -use crate::ty::{self, Binder, BoundTy, Ty, TyCtxt, TypeVisitableExt}; +use crate::ty::{ + self, Binder, BoundTy, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeVisitableExt, +}; /////////////////////////////////////////////////////////////////////////// // Some sample folders @@ -129,7 +128,7 @@ where ty::Bound(debruijn, bound_ty) if debruijn == self.current_index => { let ty = self.delegate.replace_ty(bound_ty); debug_assert!(!ty.has_vars_bound_above(ty::INNERMOST)); - ty::fold::shift_vars(self.tcx, ty, self.current_index.as_u32()) + ty::shift_vars(self.tcx, ty, self.current_index.as_u32()) } _ => { if !t.has_vars_bound_at_or_above(self.current_index) { @@ -169,7 +168,7 @@ where ty::ConstKind::Bound(debruijn, bound_const) if debruijn == self.current_index => { let ct = self.delegate.replace_const(bound_const); debug_assert!(!ct.has_vars_bound_above(ty::INNERMOST)); - ty::fold::shift_vars(self.tcx, ct, self.current_index.as_u32()) + ty::shift_vars(self.tcx, ct, self.current_index.as_u32()) } _ => ct.super_fold_with(self), } diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index f24910477dc..e87859a55ed 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -8,16 +8,16 @@ use std::ptr::NonNull; use rustc_data_structures::intern::Interned; use rustc_errors::{DiagArgValue, IntoDiagArg}; use rustc_hir::def_id::DefId; -use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, extension}; +use rustc_macros::{HashStable, TyDecodable, TyEncodable, extension}; use rustc_serialize::{Decodable, Encodable}; use rustc_type_ir::WithCachedTypeInfo; use smallvec::SmallVec; use crate::ty::codec::{TyDecoder, TyEncoder}; -use crate::ty::fold::{FallibleTypeFolder, TypeFoldable}; -use crate::ty::visit::{TypeVisitable, TypeVisitor, VisitorResult, walk_visitable_list}; use crate::ty::{ - self, ClosureArgs, CoroutineArgs, CoroutineClosureArgs, InlineConstArgs, Lift, List, Ty, TyCtxt, + self, ClosureArgs, CoroutineArgs, CoroutineClosureArgs, FallibleTypeFolder, InlineConstArgs, + Lift, List, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitor, VisitorResult, + walk_visitable_list, }; pub type GenericArgKind<'tcx> = rustc_type_ir::GenericArgKind<TyCtxt<'tcx>>; @@ -334,13 +334,13 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for GenericArg<'tcx> { } } -impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for GenericArg<'tcx> { +impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for GenericArg<'tcx> { fn encode(&self, e: &mut E) { self.unpack().encode(e) } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for GenericArg<'tcx> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for GenericArg<'tcx> { fn decode(d: &mut D) -> GenericArg<'tcx> { GenericArgKind::decode(d).pack() } diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 4a5f6d80f24..32988965a35 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -43,6 +43,7 @@ //! This code should only compile in modules where the uninhabitedness of `Foo` //! is visible. +use rustc_span::sym; use rustc_type_ir::TyKind::*; use tracing::instrument; @@ -84,6 +85,21 @@ impl<'tcx> VariantDef { InhabitedPredicate::all( tcx, self.fields.iter().map(|field| { + // Unstable fields are always considered to be inhabited. In the future, + // this could be extended to be conditional on the field being unstable + // only within the module that's querying the inhabitedness, like: + // `let pred = pred.or(InhabitedPredicate::IsUnstable(field.did));` + // but this is unnecessary for now, since it would only affect nightly-only + // code or code within the standard library itself. + // HACK: We filter out `rustc_private` fields since with the flag + // `-Zforce-unstable-if-unmarked` we consider all unmarked fields to be + // unstable when building the compiler. + if tcx + .lookup_stability(field.did) + .is_some_and(|stab| stab.is_unstable() && stab.feature != sym::rustc_private) + { + return InhabitedPredicate::True; + } let pred = tcx.type_of(field.did).instantiate_identity().inhabited_predicate(tcx); if adt.is_enum() { return pred; @@ -107,7 +123,7 @@ impl<'tcx> Ty<'tcx> { // For now, unions are always considered inhabited Adt(adt, _) if adt.is_union() => InhabitedPredicate::True, // Non-exhaustive ADTs from other crates are always considered inhabited - Adt(adt, _) if adt.is_variant_list_non_exhaustive() && !adt.did().is_local() => { + Adt(adt, _) if adt.variant_list_has_applicable_non_exhaustive() => { InhabitedPredicate::True } Never => InhabitedPredicate::False, diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index b99148f3368..980d20f9d3b 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -712,10 +712,7 @@ impl<'tcx> Instance<'tcx> { .. }) ); - // We also need to generate a shim if this is an AFIT. - let needs_rpitit_shim = - tcx.return_position_impl_trait_in_trait_shim_data(def).is_some(); - if needs_track_caller_shim || needs_rpitit_shim { + if needs_track_caller_shim { if tcx.is_closure_like(def) { debug!( " => vtable fn pointer created for closure with #[track_caller]: {:?} for method {:?} {:?}", diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ad9d32fd6c1..6bdd0a0647d 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -33,6 +33,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; +use rustc_data_structures::unord::UnordMap; use rustc_errors::{Diag, ErrorGuaranteed}; use rustc_hir::LangItem; use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; @@ -68,7 +69,7 @@ pub use self::context::{ CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, tls, }; -pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; +pub use self::fold::*; pub use self::instance::{Instance, InstanceKind, ReifyReason, ShortInstance, UnusedGenericParams}; pub use self::list::{List, ListWithCachedTypeInfo}; pub use self::opaque_types::OpaqueTypeKey; @@ -98,13 +99,14 @@ pub use self::typeck_results::{ CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, IsIdentity, Rust2024IncompatiblePatInfo, TypeckResults, UserType, UserTypeAnnotationIndex, UserTypeKind, }; -pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; +pub use self::visit::*; use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; use crate::metadata::ModChild; use crate::middle::privacy::EffectiveVisibilities; use crate::mir::{Body, CoroutineLayout}; use crate::query::{IntoQueryParam, Providers}; use crate::ty; +use crate::ty::codec::{TyDecoder, TyEncoder}; pub use crate::ty::diagnostics::*; use crate::ty::fast_reject::SimplifiedType; use crate::ty::util::Discr; @@ -116,7 +118,6 @@ pub mod codec; pub mod error; pub mod fast_reject; pub mod flags; -pub mod fold; pub mod inhabitedness; pub mod layout; pub mod normalize_erasing_regions; @@ -126,7 +127,6 @@ pub mod relate; pub mod significant_drop_order; pub mod trait_def; pub mod util; -pub mod visit; pub mod vtable; pub mod walk; @@ -138,6 +138,7 @@ mod context; mod diagnostics; mod elaborate_impl; mod erase_regions; +mod fold; mod generic_args; mod generics; mod impls_ty; @@ -148,12 +149,12 @@ mod opaque_types; mod parameterized; mod predicate; mod region; -mod return_position_impl_trait_in_trait; mod rvalue_scopes; mod structural_impls; #[allow(hidden_glob_reexports)] mod sty; mod typeck_results; +mod visit; // Data types @@ -168,7 +169,7 @@ pub struct ResolverGlobalCtxt { /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. pub expn_that_defined: FxHashMap<LocalDefId, ExpnId>, pub effective_visibilities: EffectiveVisibilities, - pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>, + pub extern_crate_map: UnordMap<LocalDefId, CrateNum>, pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>, pub module_children: LocalDefIdMap<Vec<ModChild>>, pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>, @@ -442,7 +443,7 @@ impl<'tcx> rustc_type_ir::inherent::IntoKind for Ty<'tcx> { } } -impl<'tcx> rustc_type_ir::visit::Flags for Ty<'tcx> { +impl<'tcx> rustc_type_ir::Flags for Ty<'tcx> { fn flags(&self) -> TypeFlags { self.0.flags } @@ -549,13 +550,13 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Term<'tcx> { } } -impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for Term<'tcx> { +impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for Term<'tcx> { fn encode(&self, e: &mut E) { self.unpack().encode(e) } } -impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for Term<'tcx> { +impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Term<'tcx> { fn decode(d: &mut D) -> Self { let res: TermKind<'tcx> = Decodable::decode(d); res.pack() @@ -938,7 +939,7 @@ impl rustc_type_ir::inherent::PlaceholderLike for PlaceholderConst { pub type Clauses<'tcx> = &'tcx ListWithCachedTypeInfo<Clause<'tcx>>; -impl<'tcx> rustc_type_ir::visit::Flags for Clauses<'tcx> { +impl<'tcx> rustc_type_ir::Flags for Clauses<'tcx> { fn flags(&self) -> TypeFlags { (**self).flags() } @@ -1207,12 +1208,23 @@ impl VariantDef { } } - /// Is this field list non-exhaustive? + /// Returns `true` if the field list of this variant is `#[non_exhaustive]`. + /// + /// Note that this function will return `true` even if the type has been + /// defined in the crate currently being compiled. If that's not what you + /// want, see [`Self::field_list_has_applicable_non_exhaustive`]. #[inline] pub fn is_field_list_non_exhaustive(&self) -> bool { self.flags.intersects(VariantFlags::IS_FIELD_LIST_NON_EXHAUSTIVE) } + /// Returns `true` if the field list of this variant is `#[non_exhaustive]` + /// and the type has been defined in another crate. + #[inline] + pub fn field_list_has_applicable_non_exhaustive(&self) -> bool { + self.is_field_list_non_exhaustive() && !self.def_id.is_local() + } + /// Computes the `Ident` of this variant by looking up the `Span` pub fn ident(&self, tcx: TyCtxt<'_>) -> Ident { Ident::new(self.name, tcx.def_ident_span(self.def_id).unwrap()) diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index e86e01451fe..f2a4a5a4ecf 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -11,8 +11,10 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use tracing::{debug, instrument}; use crate::traits::query::NoSolution; -use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder}; -use crate::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt}; +use crate::ty::{ + self, EarlyBinder, FallibleTypeFolder, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeFolder, + TypeVisitableExt, +}; #[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)] pub enum NormalizationError<'tcx> { diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index cf789807bb0..56c44c8a84c 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -4,8 +4,9 @@ use rustc_span::def_id::DefId; use tracing::{debug, instrument, trace}; use crate::error::ConstNotUsedTraitAlias; -use crate::ty::fold::{TypeFolder, TypeSuperFoldable}; -use crate::ty::{self, GenericArg, GenericArgKind, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{ + self, GenericArg, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, +}; pub type OpaqueTypeKey<'tcx> = rustc_type_ir::OpaqueTypeKey<TyCtxt<'tcx>>; diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 1674ca4cfc5..02e316dfc3d 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -63,7 +63,7 @@ impl<'tcx> rustc_type_ir::inherent::IntoKind for Predicate<'tcx> { } } -impl<'tcx> rustc_type_ir::visit::Flags for Predicate<'tcx> { +impl<'tcx> rustc_type_ir::Flags for Predicate<'tcx> { fn flags(&self) -> TypeFlags { self.0.flags } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 72924c0dd4b..3ef8ecc59e4 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2945,7 +2945,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { } } - impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for RegionNameCollector<'tcx> { + impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for RegionNameCollector<'tcx> { fn visit_region(&mut self, r: ty::Region<'tcx>) { trace!("address: {:p}", r.0.0); @@ -3406,20 +3406,18 @@ define_print_and_forward_display! { } fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, Namespace, DefId)) { - // Iterate all local crate items no matter where they are defined. + // Iterate all (non-anonymous) local crate items no matter where they are defined. for id in tcx.hir_free_items() { if matches!(tcx.def_kind(id.owner_id), DefKind::Use) { continue; } let item = tcx.hir_item(id); - if item.ident.name == kw::Empty { - continue; - } + let Some(ident) = item.kind.ident() else { continue }; let def_id = item.owner_id.to_def_id(); let ns = tcx.def_kind(def_id).ns().unwrap_or(Namespace::TypeNS); - collect_fn(&item.ident, ns, def_id); + collect_fn(&ident, ns, def_id); } // Now take care of extern crate items. diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 14a2e5befe6..fb52cf96b02 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -26,7 +26,7 @@ impl<'tcx> rustc_type_ir::inherent::IntoKind for Region<'tcx> { } } -impl<'tcx> rustc_type_ir::visit::Flags for Region<'tcx> { +impl<'tcx> rustc_type_ir::Flags for Region<'tcx> { fn flags(&self) -> TypeFlags { self.type_flags() } diff --git a/compiler/rustc_middle/src/ty/return_position_impl_trait_in_trait.rs b/compiler/rustc_middle/src/ty/return_position_impl_trait_in_trait.rs deleted file mode 100644 index 568e504b940..00000000000 --- a/compiler/rustc_middle/src/ty/return_position_impl_trait_in_trait.rs +++ /dev/null @@ -1,95 +0,0 @@ -use rustc_hir::def_id::DefId; - -use crate::ty::{self, ExistentialPredicateStableCmpExt, TyCtxt}; - -impl<'tcx> TyCtxt<'tcx> { - /// Given a `def_id` of a trait or impl method, compute whether that method needs to - /// have an RPITIT shim applied to it for it to be dyn compatible. If so, return the - /// `def_id` of the RPITIT, and also the args of trait method that returns the RPITIT. - /// - /// NOTE that these args are not, in general, the same as than the RPITIT's args. They - /// are a subset of those args, since they do not include the late-bound lifetimes of - /// the RPITIT. Depending on the context, these will need to be dealt with in different - /// ways -- in codegen, it's okay to fill them with ReErased. - pub fn return_position_impl_trait_in_trait_shim_data( - self, - def_id: DefId, - ) -> Option<(DefId, ty::EarlyBinder<'tcx, ty::GenericArgsRef<'tcx>>)> { - let assoc_item = self.opt_associated_item(def_id)?; - - let (trait_item_def_id, opt_impl_def_id) = match assoc_item.container { - ty::AssocItemContainer::Impl => { - (assoc_item.trait_item_def_id?, Some(self.parent(def_id))) - } - ty::AssocItemContainer::Trait => (def_id, None), - }; - - let sig = self.fn_sig(trait_item_def_id); - - // Check if the trait returns an RPITIT. - let ty::Alias(ty::Projection, ty::AliasTy { def_id, .. }) = - *sig.skip_binder().skip_binder().output().kind() - else { - return None; - }; - if !self.is_impl_trait_in_trait(def_id) { - return None; - } - - let args = if let Some(impl_def_id) = opt_impl_def_id { - // Rebase the args from the RPITIT onto the impl trait ref, so we can later - // substitute them with the method args of the *impl* method, since that's - // the instance we're building a vtable shim for. - ty::GenericArgs::identity_for_item(self, trait_item_def_id).rebase_onto( - self, - self.parent(trait_item_def_id), - self.impl_trait_ref(impl_def_id) - .expect("expected impl trait ref from parent of impl item") - .instantiate_identity() - .args, - ) - } else { - // This is when we have a default trait implementation. - ty::GenericArgs::identity_for_item(self, trait_item_def_id) - }; - - Some((def_id, ty::EarlyBinder::bind(args))) - } - - /// Given a `DefId` of an RPITIT and its args, return the existential predicates - /// that corresponds to the RPITIT's bounds with the self type erased. - pub fn item_bounds_to_existential_predicates( - self, - def_id: DefId, - args: ty::GenericArgsRef<'tcx>, - ) -> &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> { - let mut bounds: Vec<_> = self - .item_self_bounds(def_id) - .iter_instantiated(self, args) - .filter_map(|clause| { - clause - .kind() - .map_bound(|clause| match clause { - ty::ClauseKind::Trait(trait_pred) => Some(ty::ExistentialPredicate::Trait( - ty::ExistentialTraitRef::erase_self_ty(self, trait_pred.trait_ref), - )), - ty::ClauseKind::Projection(projection_pred) => { - Some(ty::ExistentialPredicate::Projection( - ty::ExistentialProjection::erase_self_ty(self, projection_pred), - )) - } - ty::ClauseKind::TypeOutlives(_) => { - // Type outlives bounds don't really turn into anything, - // since we must use an intersection region for the `dyn*`'s - // region anyways. - None - } - _ => unreachable!("unexpected clause in item bounds: {clause:?}"), - }) - .transpose() - }) - .collect(); - bounds.sort_by(|a, b| a.skip_binder().stable_cmp(self, &b.skip_binder())); - self.mk_poly_existential_predicates(&bounds) - } -} diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index f1d03d0a659..60fd531b4d0 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -11,16 +11,16 @@ use rustc_hir::def::Namespace; use rustc_hir::def_id::LocalDefId; use rustc_span::Span; use rustc_span::source_map::Spanned; -use rustc_type_ir::ConstKind; -use rustc_type_ir::visit::{VisitorResult, try_visit}; +use rustc_type_ir::{ConstKind, VisitorResult, try_visit}; use super::print::PrettyPrinter; use super::{GenericArg, GenericArgKind, Pattern, Region}; use crate::mir::PlaceElem; -use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use crate::ty::print::{FmtPrinter, Printer, with_no_trimmed_paths}; -use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; -use crate::ty::{self, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; +use crate::ty::{ + self, FallibleTypeFolder, InferConst, Lift, Term, TermKind, Ty, TyCtxt, TypeFoldable, + TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, +}; impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index ce563c59251..74a94d82784 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -16,8 +16,7 @@ use rustc_hir::def_id::DefId; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, extension}; use rustc_span::{DUMMY_SP, Span, Symbol, sym}; use rustc_type_ir::TyKind::*; -use rustc_type_ir::visit::TypeVisitableExt; -use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind, elaborate}; +use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind, TypeVisitableExt, elaborate}; use tracing::instrument; use ty::util::{AsyncDropGlueMorphology, IntTypeExt}; diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 0c68913904f..c0d4130336e 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -23,11 +23,10 @@ use super::TypingEnv; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::mir; use crate::query::Providers; -use crate::ty::fold::fold_regions; use crate::ty::layout::{FloatExt, IntegerExt}; use crate::ty::{ self, Asyncness, FallibleTypeFolder, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeFoldable, - TypeFolder, TypeSuperFoldable, TypeVisitableExt, Upcast, + TypeFolder, TypeSuperFoldable, TypeVisitableExt, Upcast, fold_regions, }; #[derive(Copy, Clone, Debug)] diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 95256b55bb4..e3b7a258c39 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -1,10 +1,11 @@ use std::ops::ControlFlow; use rustc_data_structures::fx::FxIndexSet; -use rustc_type_ir::fold::TypeFoldable; -pub use rustc_type_ir::visit::*; +use rustc_type_ir::TypeFoldable; -use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags}; +use crate::ty::{ + self, Binder, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitor, +}; /////////////////////////////////////////////////////////////////////////// // Region folder diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml index d70d70a31a4..1534865cdd3 100644 --- a/compiler/rustc_mir_build/Cargo.toml +++ b/compiler/rustc_mir_build/Cargo.toml @@ -5,14 +5,12 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -either = "1.5.0" itertools = "0.12" rustc_abi = { path = "../rustc_abi" } rustc_apfloat = "0.2.0" rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } -rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } diff --git a/compiler/rustc_mir_build/src/builder/block.rs b/compiler/rustc_mir_build/src/builder/block.rs index 7c76e02fcef..a71196f79d7 100644 --- a/compiler/rustc_mir_build/src/builder/block.rs +++ b/compiler/rustc_mir_build/src/builder/block.rs @@ -199,19 +199,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { None, Some((Some(&destination), initializer_span)), ); - this.visit_primary_bindings( - pattern, - UserTypeProjections::none(), - &mut |this, _, _, node, span, _, _| { - this.storage_live_binding( - block, - node, - span, - OutsideGuard, - ScheduleDrops::Yes, - ); - }, - ); + this.visit_primary_bindings(pattern, &mut |this, node, span| { + this.storage_live_binding( + block, + node, + span, + OutsideGuard, + ScheduleDrops::Yes, + ); + }); let else_block_span = this.thir[*else_block].span; let (matching, failure) = this.in_if_then_scope(last_remainder_scope, else_block_span, |this| { @@ -295,20 +291,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }); debug!("ast_block_stmts: pattern={:?}", pattern); - this.visit_primary_bindings( - pattern, - UserTypeProjections::none(), - &mut |this, _, _, node, span, _, _| { - this.storage_live_binding( - block, - node, - span, - OutsideGuard, - ScheduleDrops::Yes, - ); - this.schedule_drop_for_binding(node, span, OutsideGuard); - }, - ) + this.visit_primary_bindings(pattern, &mut |this, node, span| { + this.storage_live_binding( + block, + node, + span, + OutsideGuard, + ScheduleDrops::Yes, + ); + this.schedule_drop_for_binding(node, span, OutsideGuard); + }) } // Enter the visibility scope, after evaluating the initializer. diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs index f743ea60a45..64d092e0354 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -105,23 +105,19 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx> return Const::Ty(Ty::new_error(tcx, guar), ty::Const::new_error(tcx, guar)); } - let trunc = |n, width: ty::UintTy| { - let width = width - .normalize(tcx.data_layout.pointer_size.bits().try_into().unwrap()) - .bit_width() - .unwrap(); - let width = Size::from_bits(width); + let lit_ty = match *ty.kind() { + ty::Pat(base, _) => base, + _ => ty, + }; + + let trunc = |n| { + let width = lit_ty.primitive_size(tcx); trace!("trunc {} with size {} and shift {}", n, width.bits(), 128 - width.bits()); let result = width.truncate(n); trace!("trunc result: {}", result); ConstValue::Scalar(Scalar::from_uint(result, width)) }; - let lit_ty = match *ty.kind() { - ty::Pat(base, _) => base, - _ => ty, - }; - let value = match (lit, lit_ty.kind()) { (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { let s = s.as_str(); @@ -149,11 +145,10 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx> (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => { ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1))) } - (ast::LitKind::Int(n, _), ty::Uint(ui)) if !neg => trunc(n.get(), *ui), - (ast::LitKind::Int(n, _), ty::Int(i)) => trunc( - if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() }, - i.to_unsigned(), - ), + (ast::LitKind::Int(n, _), ty::Uint(_)) if !neg => trunc(n.get()), + (ast::LitKind::Int(n, _), ty::Int(_)) => { + trunc(if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() }) + } (ast::LitKind::Float(n, _), ty::Float(fty)) => { parse_float_into_constval(*n, *fty, neg).unwrap() } diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index c6f3e22e95f..f2ce0c46dd3 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -273,12 +273,12 @@ impl<'tcx> MatchPairTree<'tcx> { let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| { i == variant_index - || !v - .inhabited_predicate(cx.tcx, adt_def) - .instantiate(cx.tcx, args) - .apply_ignore_module(cx.tcx, cx.infcx.typing_env(cx.param_env)) - }) && (adt_def.did().is_local() - || !adt_def.is_variant_list_non_exhaustive()); + || !v.inhabited_predicate(cx.tcx, adt_def).instantiate(cx.tcx, args).apply( + cx.tcx, + cx.infcx.typing_env(cx.param_env), + cx.def_id.into(), + ) + }) && !adt_def.variant_list_has_applicable_non_exhaustive(); if irrefutable { None } else { Some(TestCase::Variant { adt_def, variant_index }) } } diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index b05052a3455..ea341b604e0 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -5,6 +5,11 @@ //! This also includes code for pattern bindings in `let` statements and //! function parameters. +use std::assert_matches::assert_matches; +use std::borrow::Borrow; +use std::mem; +use std::sync::Arc; + use rustc_abi::VariantIdx; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -19,6 +24,7 @@ use tracing::{debug, instrument}; use crate::builder::ForGuard::{self, OutsideGuard, RefWithinGuard}; use crate::builder::expr::as_place::PlaceBuilder; +use crate::builder::matches::user_ty::ProjectedUserTypesNode; use crate::builder::scope::DropKind; use crate::builder::{ BlockAnd, BlockAndExtension, Builder, GuardFrame, GuardFrameLocal, LocalsForNode, @@ -27,13 +33,9 @@ use crate::builder::{ // helper functions, broken out by category: mod match_pair; mod test; +mod user_ty; mod util; -use std::assert_matches::assert_matches; -use std::borrow::Borrow; -use std::mem; -use std::sync::Arc; - /// Arguments to [`Builder::then_else_break_inner`] that are usually forwarded /// to recursive invocations. #[derive(Clone, Copy)] @@ -755,24 +757,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { guard: Option<ExprId>, opt_match_place: Option<(Option<&Place<'tcx>>, Span)>, ) -> Option<SourceScope> { - self.visit_primary_bindings( + self.visit_primary_bindings_special( pattern, - UserTypeProjections::none(), - &mut |this, name, mode, var, span, ty, user_ty| { - if visibility_scope.is_none() { - visibility_scope = - Some(this.new_source_scope(scope_span, LintLevel::Inherited)); - } + &ProjectedUserTypesNode::None, + &mut |this, name, mode, var, span, ty, user_tys| { + let vis_scope = *visibility_scope + .get_or_insert_with(|| this.new_source_scope(scope_span, LintLevel::Inherited)); let source_info = SourceInfo { span, scope: this.source_scope }; - let visibility_scope = visibility_scope.unwrap(); + let user_tys = user_tys.build_user_type_projections(); + this.declare_binding( source_info, - visibility_scope, + vis_scope, name, mode, var, ty, - user_ty, + user_tys, ArmHasGuard(guard.is_some()), opt_match_place.map(|(x, y)| (x.cloned(), y)), pattern.span, @@ -848,13 +849,35 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - /// Visit all of the primary bindings in a patterns, that is, visit the - /// leftmost occurrence of each variable bound in a pattern. A variable - /// will occur more than once in an or-pattern. + /// Visits all of the "primary" bindings in a pattern, i.e. the leftmost + /// occurrence of each variable bound by the pattern. + /// See [`PatKind::Binding::is_primary`] for more context. + /// + /// This variant provides only the limited subset of binding data needed + /// by its callers, and should be a "pure" visit without side-effects. pub(super) fn visit_primary_bindings( &mut self, pattern: &Pat<'tcx>, - pattern_user_ty: UserTypeProjections, + f: &mut impl FnMut(&mut Self, LocalVarId, Span), + ) { + pattern.walk_always(|pat| { + if let PatKind::Binding { var, is_primary: true, .. } = pat.kind { + f(self, var, pat.span); + } + }) + } + + /// Visits all of the "primary" bindings in a pattern, while preparing + /// additional user-type-annotation data needed by `declare_bindings`. + /// + /// This also has the side-effect of pushing all user type annotations + /// onto `canonical_user_type_annotations`, so that they end up in MIR + /// even if they aren't associated with any bindings. + #[instrument(level = "debug", skip(self, f))] + fn visit_primary_bindings_special( + &mut self, + pattern: &Pat<'tcx>, + user_tys: &ProjectedUserTypesNode<'_>, f: &mut impl FnMut( &mut Self, Symbol, @@ -862,20 +885,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { LocalVarId, Span, Ty<'tcx>, - UserTypeProjections, + &ProjectedUserTypesNode<'_>, ), ) { - debug!( - "visit_primary_bindings: pattern={:?} pattern_user_ty={:?}", - pattern, pattern_user_ty - ); + // Avoid having to write the full method name at each recursive call. + let visit_subpat = |this: &mut Self, subpat, user_tys: &_, f: &mut _| { + this.visit_primary_bindings_special(subpat, user_tys, f) + }; + match pattern.kind { PatKind::Binding { name, mode, var, ty, ref subpattern, is_primary, .. } => { if is_primary { - f(self, name, mode, var, pattern.span, ty, pattern_user_ty.clone()); + f(self, name, mode, var, pattern.span, ty, user_tys); } if let Some(subpattern) = subpattern.as_ref() { - self.visit_primary_bindings(subpattern, pattern_user_ty, f); + visit_subpat(self, subpattern, user_tys, f); } } @@ -884,17 +908,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let from = u64::try_from(prefix.len()).unwrap(); let to = u64::try_from(suffix.len()).unwrap(); for subpattern in prefix.iter() { - self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f); + visit_subpat(self, subpattern, &user_tys.index(), f); } if let Some(subpattern) = slice { - self.visit_primary_bindings( - subpattern, - pattern_user_ty.clone().subslice(from, to), - f, - ); + visit_subpat(self, subpattern, &user_tys.subslice(from, to), f); } for subpattern in suffix.iter() { - self.visit_primary_bindings(subpattern, pattern_user_ty.clone().index(), f); + visit_subpat(self, subpattern, &user_tys.index(), f); } } @@ -905,11 +925,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | PatKind::Error(_) => {} PatKind::Deref { ref subpattern } => { - self.visit_primary_bindings(subpattern, pattern_user_ty.deref(), f); + visit_subpat(self, subpattern, &user_tys.deref(), f); } PatKind::DerefPattern { ref subpattern, .. } => { - self.visit_primary_bindings(subpattern, UserTypeProjections::none(), f); + visit_subpat(self, subpattern, &ProjectedUserTypesNode::None, f); } PatKind::AscribeUserType { @@ -925,28 +945,31 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Note that the variance doesn't apply here, as we are tracking the effect // of `user_ty` on any bindings contained with subpattern. + // Caution: Pushing this user type here is load-bearing even for + // patterns containing no bindings, to ensure that the type ends + // up represented in MIR _somewhere_. let base_user_ty = self.canonical_user_type_annotations.push(annotation.clone()); - let subpattern_user_ty = pattern_user_ty.push_user_type(base_user_ty); - self.visit_primary_bindings(subpattern, subpattern_user_ty, f) + let subpattern_user_tys = user_tys.push_user_type(base_user_ty); + visit_subpat(self, subpattern, &subpattern_user_tys, f) } PatKind::ExpandedConstant { ref subpattern, .. } => { - self.visit_primary_bindings(subpattern, pattern_user_ty, f) + visit_subpat(self, subpattern, user_tys, f) } PatKind::Leaf { ref subpatterns } => { for subpattern in subpatterns { - let subpattern_user_ty = pattern_user_ty.clone().leaf(subpattern.field); - debug!("visit_primary_bindings: subpattern_user_ty={:?}", subpattern_user_ty); - self.visit_primary_bindings(&subpattern.pattern, subpattern_user_ty, f); + let subpattern_user_tys = user_tys.leaf(subpattern.field); + debug!("visit_primary_bindings: subpattern_user_tys={subpattern_user_tys:?}"); + visit_subpat(self, &subpattern.pattern, &subpattern_user_tys, f); } } PatKind::Variant { adt_def, args: _, variant_index, ref subpatterns } => { for subpattern in subpatterns { - let subpattern_user_ty = - pattern_user_ty.clone().variant(adt_def, variant_index, subpattern.field); - self.visit_primary_bindings(&subpattern.pattern, subpattern_user_ty, f); + let subpattern_user_tys = + user_tys.variant(adt_def, variant_index, subpattern.field); + visit_subpat(self, &subpattern.pattern, &subpattern_user_tys, f); } } PatKind::Or { ref pats } => { @@ -955,7 +978,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // `let (x | y) = ...`, the primary binding of `y` occurs in // the right subpattern for subpattern in pats.iter() { - self.visit_primary_bindings(subpattern, pattern_user_ty.clone(), f); + visit_subpat(self, subpattern, user_tys, f); } } } @@ -2747,7 +2770,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { mode: BindingMode, var_id: LocalVarId, var_ty: Ty<'tcx>, - user_ty: UserTypeProjections, + user_ty: Option<Box<UserTypeProjections>>, has_guard: ArmHasGuard, opt_match_place: Option<(Option<Place<'tcx>>, Span)>, pat_span: Span, @@ -2757,7 +2780,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let local = LocalDecl { mutability: mode.1, ty: var_ty, - user_ty: if user_ty.is_empty() { None } else { Some(Box::new(user_ty)) }, + user_ty, source_info, local_info: ClearCrossCrate::Set(Box::new(LocalInfo::User(BindingForm::Var( VarBindingForm { diff --git a/compiler/rustc_mir_build/src/builder/matches/user_ty.rs b/compiler/rustc_mir_build/src/builder/matches/user_ty.rs new file mode 100644 index 00000000000..df9f93ac328 --- /dev/null +++ b/compiler/rustc_mir_build/src/builder/matches/user_ty.rs @@ -0,0 +1,140 @@ +//! Helper code for building a linked list of user-type projections on the +//! stack while visiting a THIR pattern. +//! +//! This avoids having to repeatedly clone a partly-built [`UserTypeProjections`] +//! at every step of the traversal, which is what the previous code was doing. + +use std::assert_matches::assert_matches; +use std::iter; + +use rustc_abi::{FieldIdx, VariantIdx}; +use rustc_middle::mir::{ProjectionElem, UserTypeProjection, UserTypeProjections}; +use rustc_middle::ty::{AdtDef, UserTypeAnnotationIndex}; +use rustc_span::Symbol; + +/// One of a list of "operations" that can be used to lazily build projections +/// of user-specified types. +#[derive(Clone, Debug)] +pub(crate) enum ProjectedUserTypesOp { + PushUserType { base: UserTypeAnnotationIndex }, + + Index, + Subslice { from: u64, to: u64 }, + Deref, + Leaf { field: FieldIdx }, + Variant { name: Symbol, variant: VariantIdx, field: FieldIdx }, +} + +#[derive(Debug)] +pub(crate) enum ProjectedUserTypesNode<'a> { + None, + Chain { parent: &'a Self, op: ProjectedUserTypesOp }, +} + +impl<'a> ProjectedUserTypesNode<'a> { + pub(crate) fn push_user_type(&'a self, base: UserTypeAnnotationIndex) -> Self { + // Pushing a base user type always causes the chain to become non-empty. + Self::Chain { parent: self, op: ProjectedUserTypesOp::PushUserType { base } } + } + + /// Push another projection op onto the chain, but only if it is already non-empty. + fn maybe_push(&'a self, op_fn: impl FnOnce() -> ProjectedUserTypesOp) -> Self { + match self { + Self::None => Self::None, + Self::Chain { .. } => Self::Chain { parent: self, op: op_fn() }, + } + } + + pub(crate) fn index(&'a self) -> Self { + self.maybe_push(|| ProjectedUserTypesOp::Index) + } + + pub(crate) fn subslice(&'a self, from: u64, to: u64) -> Self { + self.maybe_push(|| ProjectedUserTypesOp::Subslice { from, to }) + } + + pub(crate) fn deref(&'a self) -> Self { + self.maybe_push(|| ProjectedUserTypesOp::Deref) + } + + pub(crate) fn leaf(&'a self, field: FieldIdx) -> Self { + self.maybe_push(|| ProjectedUserTypesOp::Leaf { field }) + } + + pub(crate) fn variant( + &'a self, + adt_def: AdtDef<'_>, + variant: VariantIdx, + field: FieldIdx, + ) -> Self { + self.maybe_push(|| { + let name = adt_def.variant(variant).name; + ProjectedUserTypesOp::Variant { name, variant, field } + }) + } + + /// Traverses the chain of nodes to yield each op in the chain. + /// Because this walks from child node to parent node, the ops are + /// naturally yielded in "reverse" order. + fn iter_ops_reversed(&'a self) -> impl Iterator<Item = &'a ProjectedUserTypesOp> { + let mut next = self; + iter::from_fn(move || match next { + Self::None => None, + Self::Chain { parent, op } => { + next = parent; + Some(op) + } + }) + } + + /// Assembles this chain of user-type projections into a proper data structure. + pub(crate) fn build_user_type_projections(&self) -> Option<Box<UserTypeProjections>> { + // If we know there's nothing to do, just return None immediately. + if matches!(self, Self::None) { + return None; + } + + let ops_reversed = self.iter_ops_reversed().cloned().collect::<Vec<_>>(); + // The "first" op should always be `PushUserType`. + // Other projections are only added if there is at least one user type. + assert_matches!(ops_reversed.last(), Some(ProjectedUserTypesOp::PushUserType { .. })); + + let mut projections = vec![]; + for op in ops_reversed.into_iter().rev() { + match op { + ProjectedUserTypesOp::PushUserType { base } => { + projections.push(UserTypeProjection { base, projs: vec![] }) + } + + ProjectedUserTypesOp::Index => { + for p in &mut projections { + p.projs.push(ProjectionElem::Index(())) + } + } + ProjectedUserTypesOp::Subslice { from, to } => { + for p in &mut projections { + p.projs.push(ProjectionElem::Subslice { from, to, from_end: true }) + } + } + ProjectedUserTypesOp::Deref => { + for p in &mut projections { + p.projs.push(ProjectionElem::Deref) + } + } + ProjectedUserTypesOp::Leaf { field } => { + for p in &mut projections { + p.projs.push(ProjectionElem::Field(field, ())) + } + } + ProjectedUserTypesOp::Variant { name, variant, field } => { + for p in &mut projections { + p.projs.push(ProjectionElem::Downcast(Some(name), variant)); + p.projs.push(ProjectionElem::Field(field, ())); + } + } + } + } + + Some(Box::new(UserTypeProjections { contents: projections })) + } +} diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 2909dea98b7..c8b69a6ec62 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -563,7 +563,7 @@ fn construct_const<'a, 'tcx>( // Figure out what primary body this item has. let (span, const_ty_span) = match tcx.hir_node(hir_id) { Node::Item(hir::Item { - kind: hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _, _), + kind: hir::ItemKind::Static(_, ty, _, _) | hir::ItemKind::Const(_, ty, _, _), span, .. }) diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 27ff01b4803..e56c0ae92ca 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -305,27 +305,25 @@ impl DropTree { } /// Builds the MIR for a given drop tree. - /// - /// `blocks` should have the same length as `self.drops`, and may have its - /// first value set to some already existing block. fn build_mir<'tcx, T: DropTreeBuilder<'tcx>>( &mut self, cfg: &mut CFG<'tcx>, - blocks: &mut IndexVec<DropIdx, Option<BasicBlock>>, - ) { + root_node: Option<BasicBlock>, + ) -> IndexVec<DropIdx, Option<BasicBlock>> { debug!("DropTree::build_mir(drops = {:#?})", self); - assert_eq!(blocks.len(), self.drops.len()); - self.assign_blocks::<T>(cfg, blocks); - self.link_blocks(cfg, blocks) + let mut blocks = self.assign_blocks::<T>(cfg, root_node); + self.link_blocks(cfg, &mut blocks); + + blocks } /// Assign blocks for all of the drops in the drop tree that need them. fn assign_blocks<'tcx, T: DropTreeBuilder<'tcx>>( &mut self, cfg: &mut CFG<'tcx>, - blocks: &mut IndexVec<DropIdx, Option<BasicBlock>>, - ) { + root_node: Option<BasicBlock>, + ) -> IndexVec<DropIdx, Option<BasicBlock>> { // StorageDead statements can share blocks with each other and also with // a Drop terminator. We iterate through the drops to find which drops // need their own block. @@ -342,8 +340,11 @@ impl DropTree { Own, } + let mut blocks = IndexVec::from_elem(None, &self.drops); + blocks[ROOT_NODE] = root_node; + let mut needs_block = IndexVec::from_elem(Block::None, &self.drops); - if blocks[ROOT_NODE].is_some() { + if root_node.is_some() { // In some cases (such as drops for `continue`) the root node // already has a block. In this case, make sure that we don't // override it. @@ -385,6 +386,8 @@ impl DropTree { debug!("assign_blocks: blocks = {:#?}", blocks); assert!(entry_points.is_empty()); + + blocks } fn link_blocks<'tcx>( @@ -1574,10 +1577,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> { span: Span, continue_block: Option<BasicBlock>, ) -> Option<BlockAnd<()>> { - let mut blocks = IndexVec::from_elem(None, &drops.drops); - blocks[ROOT_NODE] = continue_block; - - drops.build_mir::<ExitScopes>(&mut self.cfg, &mut blocks); + let blocks = drops.build_mir::<ExitScopes>(&mut self.cfg, continue_block); let is_coroutine = self.coroutine.is_some(); // Link the exit drop tree to unwind drop tree. @@ -1633,8 +1633,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> { let drops = &mut self.scopes.coroutine_drops; let cfg = &mut self.cfg; let fn_span = self.fn_span; - let mut blocks = IndexVec::from_elem(None, &drops.drops); - drops.build_mir::<CoroutineDrop>(cfg, &mut blocks); + let blocks = drops.build_mir::<CoroutineDrop>(cfg, None); if let Some(root_block) = blocks[ROOT_NODE] { cfg.terminate( root_block, @@ -1670,9 +1669,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> { fn_span: Span, resume_block: &mut Option<BasicBlock>, ) { - let mut blocks = IndexVec::from_elem(None, &drops.drops); - blocks[ROOT_NODE] = *resume_block; - drops.build_mir::<Unwind>(cfg, &mut blocks); + let blocks = drops.build_mir::<Unwind>(cfg, *resume_block); if let (None, Some(resume)) = (*resume_block, blocks[ROOT_NODE]) { cfg.terminate(resume, SourceInfo::outermost(fn_span), TerminatorKind::UnwindResume); diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 17b22f25dbb..0e16f871b16 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -613,9 +613,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNo diag.span_note(span, fluent::mir_build_def_note); } - let is_variant_list_non_exhaustive = matches!(self.ty.kind(), - ty::Adt(def, _) if def.is_variant_list_non_exhaustive() && !def.did().is_local()); - if is_variant_list_non_exhaustive { + let is_non_exhaustive = matches!(self.ty.kind(), + ty::Adt(def, _) if def.variant_list_has_applicable_non_exhaustive()); + if is_non_exhaustive { diag.note(fluent::mir_build_non_exhaustive_type_note); } else { diag.note(fluent::mir_build_type_note); diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index cbd29ba837e..095d3e75da1 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1044,7 +1044,6 @@ fn find_fallback_pattern_typo<'tcx>( if let DefKind::Use = cx.tcx.def_kind(item.owner_id) { // Look for consts being re-exported. let item = cx.tcx.hir_expect_item(item.owner_id.def_id); - let use_name = item.ident.name; let hir::ItemKind::Use(path, _) = item.kind else { continue; }; @@ -1064,8 +1063,9 @@ fn find_fallback_pattern_typo<'tcx>( { // The const is accessible only through the re-export, point at // the `use`. - imported.push(use_name); - imported_spans.push(item.ident.span); + let ident = item.kind.ident().unwrap(); + imported.push(ident.name); + imported_spans.push(ident.span); } } } diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml index fb8d0ac5e74..9e4b4534dcc 100644 --- a/compiler/rustc_mir_transform/Cargo.toml +++ b/compiler/rustc_mir_transform/Cargo.toml @@ -26,7 +26,6 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } -rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 9cd7045a0a2..89a306c6104 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -178,7 +178,7 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>( ), }; - ( + Some(( FieldIdx::from_usize(child_field_idx + num_args), ( FieldIdx::from_usize(parent_field_idx + num_args), @@ -186,9 +186,10 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>( peel_deref, child_precise_captures, ), - ) + )) }, ) + .flatten() .collect(); if coroutine_kind == ty::ClosureKind::FnOnce { @@ -312,10 +313,46 @@ impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> { self.super_place(place, context, location); } + fn visit_statement(&mut self, statement: &mut mir::Statement<'tcx>, location: mir::Location) { + // Remove fake borrows of closure captures if that capture has been + // replaced with a by-move version of that capture. + // + // For example, imagine we capture `Foo` in the parent and `&Foo` + // in the child. We will emit two fake borrows like: + // + // ``` + // _2 = &fake shallow (*(_1.0: &Foo)); + // _3 = &fake shallow (_1.0: &Foo); + // ``` + // + // However, since this transform is responsible for replacing + // `_1.0: &Foo` with `_1.0: Foo`, that makes the second fake borrow + // obsolete, and we should replace it with a nop. + // + // As a side-note, we don't actually even care about fake borrows + // here at all since they're fully a MIR borrowck artifact, and we + // don't need to borrowck by-move MIR bodies. But it's best to preserve + // as much as we can between these two bodies :) + if let mir::StatementKind::Assign(box (_, rvalue)) = &statement.kind + && let mir::Rvalue::Ref(_, mir::BorrowKind::Fake(mir::FakeBorrowKind::Shallow), place) = + rvalue + && let mir::PlaceRef { + local: ty::CAPTURE_STRUCT_LOCAL, + projection: [mir::ProjectionElem::Field(idx, _)], + } = place.as_ref() + && let Some(&(_, _, true, _)) = self.field_remapping.get(&idx) + { + statement.kind = mir::StatementKind::Nop; + } + + self.super_statement(statement, location); + } + fn visit_local_decl(&mut self, local: mir::Local, local_decl: &mut mir::LocalDecl<'tcx>) { // Replace the type of the self arg. if local == ty::CAPTURE_STRUCT_LOCAL { local_decl.ty = self.by_move_coroutine_ty; } + self.super_local_decl(local, local_decl); } } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 1ccae0fd7fe..572dbae8fd2 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -107,7 +107,6 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir: mir_body.function_coverage_info = Some(Box::new(FunctionCoverageInfo { function_source_hash: hir_info.function_source_hash, - body_span: hir_info.body_span, node_flow_data, priority_list, diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 981dedd5b5c..0a54c780f31 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -872,8 +872,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { self.simplify_place_projection(place, location); return self.new_pointer(*place, AddressKind::Address(mutbl)); } - Rvalue::WrapUnsafeBinder(ref mut op, _) => { - return self.simplify_operand(op, location); + Rvalue::WrapUnsafeBinder(ref mut op, ty) => { + let value = self.simplify_operand(op, location)?; + Value::Cast { + kind: CastKind::Transmute, + value, + from: op.ty(self.local_decls, self.tcx), + to: ty, + } } // Operations. diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs index 7d77fffa83f..29a9133abe9 100644 --- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs +++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use std::collections::hash_map; use std::rc::Rc; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::Subdiagnostic; use rustc_hir::CRATE_HIR_ID; @@ -25,7 +25,6 @@ use rustc_mir_dataflow::{Analysis, MaybeReachable, ResultsCursor}; use rustc_session::lint::builtin::TAIL_EXPR_DROP_ORDER; use rustc_session::lint::{self}; use rustc_span::{DUMMY_SP, Span, Symbol}; -use rustc_type_ir::data_structures::IndexMap; use tracing::debug; fn place_has_common_prefix<'tcx>(left: &Place<'tcx>, right: &Place<'tcx>) -> bool { @@ -199,7 +198,7 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body< // and, for each block, the vector of locations. // // We group them per-block because they tend to scheduled in the same drop ladder block. - let mut bid_per_block = IndexMap::default(); + let mut bid_per_block = FxIndexMap::default(); let mut bid_places = UnordSet::new(); let mut ty_dropped_components = UnordMap::default(); @@ -455,8 +454,8 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body< } /// Extract binding names if available for diagnosis -fn collect_user_names(body: &Body<'_>) -> IndexMap<Local, Symbol> { - let mut names = IndexMap::default(); +fn collect_user_names(body: &Body<'_>) -> FxIndexMap<Local, Symbol> { + let mut names = FxIndexMap::default(); for var_debug_info in &body.var_debug_info { if let mir::VarDebugInfoContents::Place(place) = &var_debug_info.value && let Some(local) = place.local_or_deref_local() @@ -470,9 +469,9 @@ fn collect_user_names(body: &Body<'_>) -> IndexMap<Local, Symbol> { /// Assign names for anonymous or temporary values for diagnosis fn assign_observables_names( locals: impl IntoIterator<Item = Local>, - user_names: &IndexMap<Local, Symbol>, -) -> IndexMap<Local, (String, bool)> { - let mut names = IndexMap::default(); + user_names: &FxIndexMap<Local, Symbol>, +) -> FxIndexMap<Local, (String, bool)> { + let mut names = FxIndexMap::default(); let mut assigned_names = FxHashSet::default(); let mut idx = 0u64; let mut fresh_name = || { diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 9db37bf5a07..0d9d0368d37 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -5,7 +5,6 @@ use rustc_index::IndexSlice; use rustc_middle::mir::*; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt}; -use rustc_type_ir::TyKind::*; use tracing::instrument; use super::simplify::simplify_cfg; @@ -293,13 +292,13 @@ fn can_cast( ) -> bool { let from_scalar = ScalarInt::try_from_uint(src_val.into(), src_layout.size).unwrap(); let v = match src_layout.ty.kind() { - Uint(_) => from_scalar.to_uint(src_layout.size), - Int(_) => from_scalar.to_int(src_layout.size) as u128, + ty::Uint(_) => from_scalar.to_uint(src_layout.size), + ty::Int(_) => from_scalar.to_int(src_layout.size) as u128, _ => unreachable!("invalid int"), }; let size = match *cast_ty.kind() { - Int(t) => Integer::from_int_ty(&tcx, t).size(), - Uint(t) => Integer::from_uint_ty(&tcx, t).size(), + ty::Int(t) => Integer::from_int_ty(&tcx, t).size(), + ty::Uint(t) => Integer::from_uint_ty(&tcx, t).size(), _ => unreachable!("invalid int"), }; let v = size.truncate(v); diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 34074a84e28..c9771467e49 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -8,7 +8,6 @@ use rustc_hir::lang_items::LangItem; use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::*; use rustc_middle::query::Providers; -use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{ self, CoroutineArgs, CoroutineArgsExt, EarlyBinder, GenericArgs, Ty, TyCtxt, }; @@ -718,12 +717,6 @@ fn build_call_shim<'tcx>( let def_id = instance.def_id(); - let rpitit_shim = if let ty::InstanceKind::ReifyShim(..) = instance { - tcx.return_position_impl_trait_in_trait_shim_data(def_id) - } else { - None - }; - let sig = tcx.fn_sig(def_id); let sig = sig.map_bound(|sig| tcx.instantiate_bound_regions_with_erased(sig)); @@ -779,30 +772,7 @@ fn build_call_shim<'tcx>( let mut local_decls = local_decls_for_sig(&sig, span); let source_info = SourceInfo::outermost(span); - let mut destination = Place::return_place(); - if let Some((rpitit_def_id, fn_args)) = rpitit_shim { - let rpitit_args = - fn_args.instantiate_identity().extend_to(tcx, rpitit_def_id, |param, _| { - match param.kind { - ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), - ty::GenericParamDefKind::Type { .. } - | ty::GenericParamDefKind::Const { .. } => { - unreachable!("rpitit should have no addition ty/ct") - } - } - }); - let dyn_star_ty = Ty::new_dynamic( - tcx, - tcx.item_bounds_to_existential_predicates(rpitit_def_id, rpitit_args), - tcx.lifetimes.re_erased, - ty::DynStar, - ); - destination = local_decls.push(local_decls[RETURN_PLACE].clone()).into(); - local_decls[RETURN_PLACE].ty = dyn_star_ty; - let mut inputs_and_output = sig.inputs_and_output.to_vec(); - *inputs_and_output.last_mut().unwrap() = dyn_star_ty; - sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output); - } + let destination = Place::return_place(); let rcvr_place = || { assert!(rcvr_adjustment.is_some()); @@ -921,23 +891,7 @@ fn build_call_shim<'tcx>( ); } // BB #1/#2 - return - // NOTE: If this is an RPITIT in dyn, we also want to coerce - // the return type of the function into a `dyn*`. - let stmts = if rpitit_shim.is_some() { - vec![Statement { - source_info, - kind: StatementKind::Assign(Box::new(( - Place::return_place(), - Rvalue::Cast( - CastKind::PointerCoercion(PointerCoercion::DynStar, CoercionSource::Implicit), - Operand::Move(destination), - sig.output(), - ), - ))), - }] - } else { - vec![] - }; + let stmts = vec![]; block(&mut blocks, stmts, TerminatorKind::Return, false); if let Some(Adjustment::RefMut) = rcvr_adjustment { // BB #3 - drop if closure panics diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 4ac3a268c9c..231d7c2ef02 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -13,11 +13,10 @@ use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{ - self, CoroutineArgsExt, InstanceKind, ScalarInt, Ty, TyCtxt, TypeVisitableExt, Variance, + self, CoroutineArgsExt, InstanceKind, ScalarInt, Ty, TyCtxt, TypeVisitableExt, Upcast, Variance, }; use rustc_middle::{bug, span_bug}; use rustc_trait_selection::traits::ObligationCtxt; -use rustc_type_ir::Upcast; use crate::util::{self, is_within_packed}; diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 9cae7f27947..bbb4a162027 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -1,13 +1,11 @@ use std::cmp::Ordering; use rustc_type_ir::data_structures::{HashMap, ensure_sufficient_stack}; -use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_type_ir::inherent::*; use rustc_type_ir::solve::{Goal, QueryInput}; -use rustc_type_ir::visit::TypeVisitableExt; use rustc_type_ir::{ self as ty, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, InferCtxtLike, - Interner, + Interner, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; use crate::delegate::SolverDelegate; diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs index 408742747c2..f8215a228f5 100644 --- a/compiler/rustc_next_trait_solver/src/coherence.rs +++ b/compiler/rustc_next_trait_solver/src/coherence.rs @@ -3,8 +3,10 @@ use std::ops::ControlFlow; use derive_where::derive_where; use rustc_type_ir::inherent::*; -use rustc_type_ir::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor}; -use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; +use rustc_type_ir::{ + self as ty, InferCtxtLike, Interner, TrivialTypeTraversalImpls, TypeVisitable, + TypeVisitableExt, TypeVisitor, +}; use tracing::instrument; /// Whether we do the orphan check relative to this crate or to some remote crate. @@ -94,6 +96,8 @@ pub fn trait_ref_is_local_or_fundamental<I: Interner>(tcx: I, trait_ref: ty::Tra trait_ref.def_id.is_local() || tcx.trait_is_fundamental(trait_ref.def_id) } +TrivialTypeTraversalImpls! { IsFirstInputType, } + #[derive(Debug, Copy, Clone)] pub enum IsFirstInputType { No, diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs index 850d86d91e8..259b39e2b9e 100644 --- a/compiler/rustc_next_trait_solver/src/delegate.rs +++ b/compiler/rustc_next_trait_solver/src/delegate.rs @@ -1,8 +1,7 @@ use std::ops::Deref; -use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::solve::{Certainty, Goal, NoSolution}; -use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; +use rustc_type_ir::{self as ty, InferCtxtLike, Interner, TypeFoldable}; pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized { type Infcx: InferCtxtLike<Interner = Self::Interner>; diff --git a/compiler/rustc_next_trait_solver/src/resolve.rs b/compiler/rustc_next_trait_solver/src/resolve.rs index 71c87714745..992c5ddf504 100644 --- a/compiler/rustc_next_trait_solver/src/resolve.rs +++ b/compiler/rustc_next_trait_solver/src/resolve.rs @@ -1,8 +1,9 @@ use rustc_type_ir::data_structures::DelayedMap; -use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_type_ir::inherent::*; -use rustc_type_ir::visit::TypeVisitableExt; -use rustc_type_ir::{self as ty, InferCtxtLike, Interner}; +use rustc_type_ir::{ + self as ty, InferCtxtLike, Interner, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeVisitableExt, +}; use crate::delegate::SolverDelegate; diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index bfb590e8767..384a304c4a9 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -3,11 +3,11 @@ pub(super) mod structural_traits; use derive_where::derive_where; -use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; -use rustc_type_ir::visit::TypeVisitableExt as _; -use rustc_type_ir::{self as ty, Interner, TypingMode, Upcast as _, elaborate}; +use rustc_type_ir::{ + self as ty, Interner, TypeFoldable, TypeVisitableExt as _, TypingMode, Upcast as _, elaborate, +}; use tracing::{debug, instrument}; use super::trait_goals::TraitGoalProvenVia; diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 93804b14125..a5142de2d39 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -3,10 +3,12 @@ use derive_where::derive_where; use rustc_type_ir::data_structures::HashMap; -use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; -use rustc_type_ir::{self as ty, Interner, Movability, Mutability, Upcast as _, elaborate}; +use rustc_type_ir::{ + self as ty, Interner, Movability, Mutability, TypeFoldable, TypeFolder, TypeSuperFoldable, + Upcast as _, elaborate, +}; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use tracing::instrument; diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index ce53a3968c7..ac6b521f665 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -12,10 +12,11 @@ use std::iter; use rustc_index::IndexVec; -use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::inherent::*; use rustc_type_ir::relate::solver_relating::RelateExt; -use rustc_type_ir::{self as ty, Canonical, CanonicalVarValues, InferCtxtLike, Interner}; +use rustc_type_ir::{ + self as ty, Canonical, CanonicalVarValues, InferCtxtLike, Interner, TypeFoldable, +}; use tracing::{debug, instrument, trace}; use crate::canonicalizer::Canonicalizer; diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index e48ee71c858..0322c9e4ab0 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -2,16 +2,18 @@ use std::ops::ControlFlow; use derive_where::derive_where; #[cfg(feature = "nightly")] -use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use rustc_type_ir::data_structures::{HashMap, HashSet, ensure_sufficient_stack}; use rustc_type_ir::fast_reject::DeepRejectCtxt; -use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_type_ir::inherent::*; use rustc_type_ir::relate::Relate; use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::search_graph::PathKind; -use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; -use rustc_type_ir::{self as ty, CanonicalVarValues, InferCtxtLike, Interner, TypingMode}; +use rustc_type_ir::{ + self as ty, CanonicalVarValues, InferCtxtLike, Interner, TypeFoldable, TypeFolder, + TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, + TypingMode, +}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use tracing::{instrument, trace}; @@ -129,7 +131,10 @@ where #[derive_where(Clone, Debug, Default; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] struct NestedGoals<I: Interner> { /// These normalizes-to goals are treated specially during the evaluation /// loop. In each iteration we take the RHS of the projection, replace it with diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs index 60c20762a30..817dffa127b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs @@ -2,9 +2,8 @@ //! behaves differently depending on the current `TypingMode`. use rustc_index::bit_set::GrowableBitSet; -use rustc_type_ir::fold::fold_regions; use rustc_type_ir::inherent::*; -use rustc_type_ir::{self as ty, Interner, TypingMode}; +use rustc_type_ir::{self as ty, Interner, TypingMode, fold_regions}; use crate::delegate::SolverDelegate; use crate::solve::{Certainty, EvalCtxt, Goal, NoSolution, QueryResult, inspect}; diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 12a55664641..b72f776e5cb 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -5,9 +5,9 @@ use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::solve::CanonicalResponse; -use rustc_type_ir::visit::TypeVisitableExt as _; use rustc_type_ir::{ - self as ty, Interner, Movability, TraitPredicate, TypingMode, Upcast as _, elaborate, + self as ty, Interner, Movability, TraitPredicate, TypeVisitableExt as _, TypingMode, + Upcast as _, elaborate, }; use tracing::{instrument, trace}; diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 716ababb008..c1cca1186af 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2874,7 +2874,12 @@ impl<'a> Parser<'a> { first_pat } - pub(crate) fn maybe_recover_unexpected_block_label(&mut self) -> bool { + /// If `loop_header` is `Some` and an unexpected block label is encountered, + /// it is suggested to be moved just before `loop_header`, else it is suggested to be removed. + pub(crate) fn maybe_recover_unexpected_block_label( + &mut self, + loop_header: Option<Span>, + ) -> bool { // Check for `'a : {` if !(self.check_lifetime() && self.look_ahead(1, |t| *t == token::Colon) @@ -2885,16 +2890,28 @@ impl<'a> Parser<'a> { let label = self.eat_label().expect("just checked if a label exists"); self.bump(); // eat `:` let span = label.ident.span.to(self.prev_token.span); - self.dcx() + let mut diag = self + .dcx() .struct_span_err(span, "block label not supported here") - .with_span_label(span, "not supported here") - .with_tool_only_span_suggestion( + .with_span_label(span, "not supported here"); + if let Some(loop_header) = loop_header { + diag.multipart_suggestion( + "if you meant to label the loop, move this label before the loop", + vec![ + (label.ident.span.until(self.token.span), String::from("")), + (loop_header.shrink_to_lo(), format!("{}: ", label.ident)), + ], + Applicability::MachineApplicable, + ); + } else { + diag.tool_only_span_suggestion( label.ident.span.until(self.token.span), "remove this block label", "", Applicability::MachineApplicable, - ) - .emit(); + ); + } + diag.emit(); true } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 9b2d562a69e..c48f91643e8 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -17,6 +17,7 @@ use rustc_ast::{ self as ast, AnonConst, Arm, AttrStyle, AttrVec, BinOp, BinOpKind, BlockCheckMode, CaptureBy, ClosureBinder, DUMMY_NODE_ID, Expr, ExprField, ExprKind, FnDecl, FnRetTy, Label, MacCall, MetaItemLit, Movability, Param, RangeLimits, StmtKind, Ty, TyKind, UnOp, UnsafeBinderCastKind, + YieldKind, }; use rustc_ast_pretty::pprust; use rustc_data_structures::stack::ensure_sufficient_stack; @@ -1310,6 +1311,15 @@ impl<'a> Parser<'a> { return self.parse_match_block(lo, match_span, self_arg, MatchKind::Postfix); } + // Parse a postfix `yield`. + if self.eat_keyword(exp!(Yield)) { + let yield_span = self.prev_token.span; + self.psess.gated_spans.gate(sym::yield_expr, yield_span); + return Ok( + self.mk_expr(lo.to(yield_span), ExprKind::Yield(YieldKind::Postfix(self_arg))) + ); + } + let fn_span_lo = self.token.span; let mut seg = self.parse_path_segment(PathStyle::Expr, None)?; self.check_trailing_angle_brackets(&seg, &[exp!(OpenParen)]); @@ -1884,7 +1894,7 @@ impl<'a> Parser<'a> { /// Parse `"yield" expr?`. fn parse_expr_yield(&mut self) -> PResult<'a, P<Expr>> { let lo = self.prev_token.span; - let kind = ExprKind::Yield(self.parse_expr_opt()?); + let kind = ExprKind::Yield(YieldKind::Prefix(self.parse_expr_opt()?)); let span = lo.to(self.prev_token.span); self.psess.gated_spans.gate(sym::yield_expr, span); let expr = self.mk_expr(span, kind); @@ -2286,7 +2296,7 @@ impl<'a> Parser<'a> { }); } - let (attrs, blk) = self.parse_block_common(lo, blk_mode, true)?; + let (attrs, blk) = self.parse_block_common(lo, blk_mode, true, None)?; Ok(self.mk_expr_with_attrs(blk.span, ExprKind::Block(blk, opt_label), attrs)) } @@ -2588,7 +2598,8 @@ impl<'a> Parser<'a> { } /// Parses the condition of a `if` or `while` expression. - fn parse_expr_cond(&mut self) -> PResult<'a, P<Expr>> { + // Public because it is used in rustfmt forks such as https://github.com/tucant/rustfmt/blob/30c83df9e1db10007bdd16dafce8a86b404329b2/src/parse/macros/html.rs#L57 for custom if expressions. + pub fn parse_expr_cond(&mut self) -> PResult<'a, P<Expr>> { let attrs = self.parse_outer_attributes()?; let (mut cond, _) = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, attrs)?; @@ -2850,7 +2861,11 @@ impl<'a> Parser<'a> { )); } - let (attrs, loop_block) = self.parse_inner_attrs_and_block()?; + let (attrs, loop_block) = self.parse_inner_attrs_and_block( + // Only suggest moving erroneous block label to the loop header + // if there is not already a label there + opt_label.is_none().then_some(lo), + )?; let kind = ExprKind::ForLoop { pat, iter: expr, body: loop_block, label: opt_label, kind }; @@ -2893,11 +2908,17 @@ impl<'a> Parser<'a> { err.span_label(lo, "while parsing the condition of this `while` expression"); err })?; - let (attrs, body) = self.parse_inner_attrs_and_block().map_err(|mut err| { - err.span_label(lo, "while parsing the body of this `while` expression"); - err.span_label(cond.span, "this `while` condition successfully parsed"); - err - })?; + let (attrs, body) = self + .parse_inner_attrs_and_block( + // Only suggest moving erroneous block label to the loop header + // if there is not already a label there + opt_label.is_none().then_some(lo), + ) + .map_err(|mut err| { + err.span_label(lo, "while parsing the body of this `while` expression"); + err.span_label(cond.span, "this `while` condition successfully parsed"); + err + })?; self.recover_loop_else("while", lo)?; @@ -2911,7 +2932,11 @@ impl<'a> Parser<'a> { /// Parses `loop { ... }` (`loop` token already eaten). fn parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> { let loop_span = self.prev_token.span; - let (attrs, body) = self.parse_inner_attrs_and_block()?; + let (attrs, body) = self.parse_inner_attrs_and_block( + // Only suggest moving erroneous block label to the loop header + // if there is not already a label there + opt_label.is_none().then_some(lo), + )?; self.recover_loop_else("loop", lo)?; Ok(self.mk_expr_with_attrs( lo.to(self.prev_token.span), @@ -2961,7 +2986,7 @@ impl<'a> Parser<'a> { Applicability::MaybeIncorrect, // speculative ); } - if self.maybe_recover_unexpected_block_label() { + if self.maybe_recover_unexpected_block_label(None) { e.cancel(); self.bump(); } else { @@ -3375,7 +3400,7 @@ impl<'a> Parser<'a> { /// Parses a `try {...}` expression (`try` token already eaten). fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> { - let (attrs, body) = self.parse_inner_attrs_and_block()?; + let (attrs, body) = self.parse_inner_attrs_and_block(None)?; if self.eat_keyword(exp!(Catch)) { Err(self.dcx().create_err(errors::CatchAfterTry { span: self.prev_token.span })) } else { @@ -3423,7 +3448,7 @@ impl<'a> Parser<'a> { } let capture_clause = self.parse_capture_clause()?; let decl_span = lo.to(self.prev_token.span); - let (attrs, body) = self.parse_inner_attrs_and_block()?; + let (attrs, body) = self.parse_inner_attrs_and_block(None)?; let kind = ExprKind::Gen(capture_clause, body, kind, decl_span); Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs)) } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 2388463ecfc..f4df4044dd2 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2529,7 +2529,7 @@ impl<'a> Parser<'a> { *sig_hi = self.prev_token.span; (AttrVec::new(), None) } else if self.check(exp!(OpenBrace)) || self.token.is_whole_block() { - self.parse_block_common(self.token.span, BlockCheckMode::Default, false) + self.parse_block_common(self.token.span, BlockCheckMode::Default, false, None) .map(|(attrs, body)| (attrs, Some(body)))? } else if self.token == token::Eq { // Recover `fn foo() = $expr;`. diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 323c0c1d6d0..a79b4048288 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1374,7 +1374,7 @@ impl<'a> Parser<'a> { self.psess.gated_spans.gate(sym::inline_const_pat, span); } self.expect_keyword(exp!(Const))?; - let (attrs, blk) = self.parse_inner_attrs_and_block()?; + let (attrs, blk) = self.parse_inner_attrs_and_block(None)?; let anon_const = AnonConst { id: DUMMY_NODE_ID, value: self.mk_expr(blk.span, ExprKind::Block(blk, None)), diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 0896bd88b4c..0fe247078d5 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -482,7 +482,7 @@ impl<'a> Parser<'a> { /// Parses a block. No inner attributes are allowed. pub fn parse_block(&mut self) -> PResult<'a, P<Block>> { - let (attrs, block) = self.parse_inner_attrs_and_block()?; + let (attrs, block) = self.parse_inner_attrs_and_block(None)?; if let [.., last] = &*attrs { let suggest_to_outer = match &last.kind { ast::AttrKind::Normal(attr) => attr.item.is_valid_for_outer_style(), @@ -660,22 +660,32 @@ impl<'a> Parser<'a> { Err(self.error_block_no_opening_brace_msg(Cow::from(msg))) } - /// Parses a block. Inner attributes are allowed. - pub(super) fn parse_inner_attrs_and_block(&mut self) -> PResult<'a, (AttrVec, P<Block>)> { - self.parse_block_common(self.token.span, BlockCheckMode::Default, true) + /// Parses a block. Inner attributes are allowed, block labels are not. + /// + /// If `loop_header` is `Some` and an unexpected block label is encountered, + /// it is suggested to be moved just before `loop_header`, else it is suggested to be removed. + pub(super) fn parse_inner_attrs_and_block( + &mut self, + loop_header: Option<Span>, + ) -> PResult<'a, (AttrVec, P<Block>)> { + self.parse_block_common(self.token.span, BlockCheckMode::Default, true, loop_header) } - /// Parses a block. Inner attributes are allowed. + /// Parses a block. Inner attributes are allowed, block labels are not. + /// + /// If `loop_header` is `Some` and an unexpected block label is encountered, + /// it is suggested to be moved just before `loop_header`, else it is suggested to be removed. pub(super) fn parse_block_common( &mut self, lo: Span, blk_mode: BlockCheckMode, can_be_struct_literal: bool, + loop_header: Option<Span>, ) -> PResult<'a, (AttrVec, P<Block>)> { maybe_whole!(self, NtBlock, |block| (AttrVec::new(), block)); let maybe_ident = self.prev_token.clone(); - self.maybe_recover_unexpected_block_label(); + self.maybe_recover_unexpected_block_label(loop_header); if !self.eat(exp!(OpenBrace)) { return self.error_block_no_opening_brace(); } diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 86f673c100c..9ecde2a9eb5 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -16,7 +16,7 @@ use rustc_span::{Span, Symbol, sym}; use crate::{errors, parse_in}; pub fn check_attr(psess: &ParseSess, attr: &Attribute) { - if attr.is_doc_comment() { + if attr.is_doc_comment() || attr.has_name(sym::cfg_attr_trace) { return; } diff --git a/compiler/rustc_parse_format/Cargo.toml b/compiler/rustc_parse_format/Cargo.toml index a39cca716d2..289e062fb5e 100644 --- a/compiler/rustc_parse_format/Cargo.toml +++ b/compiler/rustc_parse_format/Cargo.toml @@ -5,6 +5,10 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -rustc_index = { path = "../rustc_index", default-features = false } rustc_lexer = { path = "../rustc_lexer" } # tidy-alphabetical-end + +[target.'cfg(target_pointer_width = "64")'.dev-dependencies] +# tidy-alphabetical-start +rustc_index = { path = "../rustc_index", default-features = false } +# tidy-alphabetical-end diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 5b8a2fe52d3..97931742985 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -1105,7 +1105,7 @@ fn unescape_string(string: &str) -> Option<String> { } // Assert a reasonable size for `Piece` -#[cfg(target_pointer_width = "64")] +#[cfg(all(test, target_pointer_width = "64"))] rustc_index::static_assert_size!(Piece<'_>, 16); #[cfg(test)] diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index ed498d9d344..06398dd4f72 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -811,8 +811,8 @@ passes_unused_duplicate = passes_unused_empty_lints_note = attribute `{$name}` with an empty list has no effect -passes_unused_linker_warnings_note = - the `linker_warnings` lint can only be controlled at the root of a crate that needs to be linked +passes_unused_linker_messages_note = + the `linker_messages` lint can only be controlled at the root of a crate that needs to be linked passes_unused_multiple = multiple `{$name}` attributes diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ece5a53aaa9..9238c73cdb1 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -272,6 +272,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::forbid | sym::cfg | sym::cfg_attr + | sym::cfg_attr_trace // need to be fixed | sym::cfi_encoding // FIXME(cfi_encoding) | sym::pointee // FIXME(derive_coerce_pointee) @@ -575,6 +576,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // conditional compilation sym::cfg, sym::cfg_attr, + sym::cfg_attr_trace, // testing (allowed here so better errors can be generated in `rustc_builtin_macros::test`) sym::test, sym::ignore, @@ -598,7 +600,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { sym::repr, // code generation sym::cold, - sym::target_feature, // documentation sym::doc, ]; @@ -624,6 +625,21 @@ impl<'tcx> CheckAttrVisitor<'tcx> { _ => {} } + if other_attr.has_name(sym::target_feature) { + if !self.tcx.features().naked_functions_target_feature() { + feature_err( + &self.tcx.sess, + sym::naked_functions_target_feature, + other_attr.span(), + "`#[target_feature(/* ... */)]` is currently unstable on `#[naked]` functions", + ).emit(); + + return; + } else { + continue; + } + } + if !ALLOW_LIST.iter().any(|name| other_attr.has_name(*name)) { self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute { span: other_attr.span(), @@ -743,7 +759,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { match target { Target::Struct => { if let Some(ItemLike::Item(hir::Item { - kind: hir::ItemKind::Struct(hir::VariantData::Struct { fields, .. }, _), + kind: hir::ItemKind::Struct(_, hir::VariantData::Struct { fields, .. }, _), .. })) = item && !fields.is_empty() @@ -952,8 +968,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { tcx.dcx().emit_err(errors::DocAliasBadLocation { span, attr_str, location }); return; } - let item_name = self.tcx.hir_name(hir_id); - if item_name == doc_alias { + if self.tcx.hir_opt_name(hir_id) == Some(doc_alias) { tcx.dcx().emit_err(errors::DocAliasNotAnAlias { span, attr_str }); return; } @@ -1019,7 +1034,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { _ => None, }; match item_kind { - Some(ItemKind::Mod(module)) => { + Some(ItemKind::Mod(_, module)) => { if !module.item_ids.is_empty() { self.dcx().emit_err(errors::DocKeywordEmptyMod { span: meta.span() }); return; @@ -1072,9 +1087,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { return; }; match item.kind { - ItemKind::Enum(_, generics) | ItemKind::Struct(_, generics) + ItemKind::Enum(_, _, generics) | ItemKind::Struct(_, _, generics) if generics.params.len() != 0 => {} - ItemKind::Trait(_, _, generics, _, items) + ItemKind::Trait(_, _, _, generics, _, items) if generics.params.len() != 0 || items.iter().any(|item| matches!(item.kind, AssocItemKind::Type)) => {} _ => { @@ -2203,7 +2218,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { fn check_rustc_std_internal_symbol(&self, attr: &Attribute, span: Span, target: Target) { match target { - Target::Fn | Target::Static => {} + Target::Fn | Target::Static | Target::ForeignFn | Target::ForeignStatic => {} _ => { self.tcx .dcx() @@ -2293,7 +2308,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } else { // special case when `#[macro_export]` is applied to a macro 2.0 - let (macro_definition, _) = self.tcx.hir_node(hir_id).expect_item().expect_macro(); + let (_, macro_definition, _) = self.tcx.hir_node(hir_id).expect_item().expect_macro(); let is_decl_macro = !macro_definition.macro_rules; if is_decl_macro { @@ -2387,7 +2402,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { .iter() .all(|kind| matches!(kind, CrateType::Rlib | CrateType::Staticlib)); if never_needs_link { - errors::UnusedNote::LinkerWarningsBinaryCrateOnly + errors::UnusedNote::LinkerMessagesBinaryCrateOnly } else { return; } @@ -2624,7 +2639,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { // Historically we've run more checks on non-exported than exported macros, // so this lets us continue to run them while maintaining backwards compatibility. // In the long run, the checks should be harmonized. - if let ItemKind::Macro(macro_def, _) = item.kind { + if let ItemKind::Macro(_, macro_def, _) = item.kind { let def_id = item.owner_id.to_def_id(); if macro_def.macro_rules && !self.tcx.has_attr(def_id, sym::macro_export) { check_non_exported_macro_for_invalid_attrs(self.tcx, item); @@ -2641,7 +2656,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { // only `#[cfg]` and `#[cfg_attr]` are allowed, but it should be removed // if we allow more attributes (e.g., tool attributes and `allow/deny/warn`) // in where clauses. After that, only `self.check_attributes` should be enough. - const ATTRS_ALLOWED: &[Symbol] = &[sym::cfg, sym::cfg_attr]; + const ATTRS_ALLOWED: &[Symbol] = &[sym::cfg, sym::cfg_attr, sym::cfg_attr_trace]; let spans = self .tcx .hir_attrs(where_predicate.hir_id) @@ -2736,7 +2751,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { } fn is_c_like_enum(item: &Item<'_>) -> bool { - if let ItemKind::Enum(ref def, _) = item.kind { + if let ItemKind::Enum(_, ref def, _) = item.kind { for variant in def.variants { match variant.data { hir::VariantData::Unit(..) => { /* continue */ } @@ -2784,7 +2799,7 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { .map(|id| tcx.hir_item(id)) .find(|item| !item.span.is_dummy()) // Skip prelude `use`s .map(|item| errors::ItemFollowingInnerAttr { - span: item.ident.span, + span: if let Some(ident) = item.kind.ident() { ident.span } else { item.span }, kind: item.kind.descr(), }); let err = tcx.dcx().create_err(errors::InvalidAttrAtCrateLevel { diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 7029c60c343..f77e1db42d4 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -751,7 +751,7 @@ fn check_item<'tcx>( match tcx.def_kind(id.owner_id) { DefKind::Enum => { let item = tcx.hir_item(id); - if let hir::ItemKind::Enum(ref enum_def, _) = item.kind { + if let hir::ItemKind::Enum(_, ref enum_def, _) = item.kind { if let Some(comes_from_allow) = allow_dead_code { worklist.extend( enum_def.variants.iter().map(|variant| (variant.def_id, comes_from_allow)), @@ -806,7 +806,7 @@ fn check_item<'tcx>( } DefKind::Struct => { let item = tcx.hir_item(id); - if let hir::ItemKind::Struct(ref variant_data, _) = item.kind + if let hir::ItemKind::Struct(_, ref variant_data, _) = item.kind && let Some(ctor_def_id) = variant_data.ctor_def_id() { struct_constructors.insert(ctor_def_id, item.owner_id.def_id); @@ -987,7 +987,7 @@ impl<'tcx> DeadVisitor<'tcx> { && let Some(enum_did) = tcx.opt_parent(may_variant.to_def_id()) && let Some(enum_local_id) = enum_did.as_local() && let Node::Item(item) = tcx.hir_node_by_def_id(enum_local_id) - && let ItemKind::Enum(_, _) = item.kind + && let ItemKind::Enum(..) = item.kind { enum_local_id } else { @@ -1062,7 +1062,7 @@ impl<'tcx> DeadVisitor<'tcx> { let tuple_fields = if let Some(parent_id) = parent_item && let node = tcx.hir_node_by_def_id(parent_id) && let hir::Node::Item(hir::Item { - kind: hir::ItemKind::Struct(hir::VariantData::Tuple(fields, _, _), _), + kind: hir::ItemKind::Struct(_, hir::VariantData::Tuple(fields, _, _), _), .. }) = node { @@ -1132,7 +1132,7 @@ impl<'tcx> DeadVisitor<'tcx> { return; } dead_codes.sort_by_key(|v| v.level); - for group in dead_codes[..].chunk_by(|a, b| a.level == b.level) { + for group in dead_codes.chunk_by(|a, b| a.level == b.level) { self.lint_at_single_level(&group, participle, Some(def_id), report_on); } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index b8359c27e53..a72f40cd843 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -770,8 +770,8 @@ pub(crate) enum UnusedNote { NoLints { name: Symbol }, #[note(passes_unused_default_method_body_const_note)] DefaultMethodBodyConst, - #[note(passes_unused_linker_warnings_note)] - LinkerWarningsBinaryCrateOnly, + #[note(passes_unused_linker_messages_note)] + LinkerMessagesBinaryCrateOnly, } #[derive(LintDiagnostic)] diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 599a08bac20..321e5729b72 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -184,9 +184,7 @@ impl<'tcx> ReachableContext<'tcx> { CodegenFnAttrs::EMPTY }; let is_extern = codegen_attrs.contains_extern_indicator(); - let std_internal = - codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL); - if is_extern || std_internal { + if is_extern { self.reachable_symbols.insert(search_item); } } else { @@ -206,7 +204,7 @@ impl<'tcx> ReachableContext<'tcx> { } } - hir::ItemKind::Const(_, _, init) => { + hir::ItemKind::Const(_, _, _, init) => { // Only things actually ending up in the final constant value are reachable // for codegen. Everything else is only needed during const-eval, so even if // const-eval happens in a downstream crate, all they need is @@ -234,7 +232,7 @@ impl<'tcx> ReachableContext<'tcx> { // These are normal, nothing reachable about these // inherently and their children are already in the // worklist, as determined by the privacy pass - hir::ItemKind::ExternCrate(_) + hir::ItemKind::ExternCrate(..) | hir::ItemKind::Use(..) | hir::ItemKind::TyAlias(..) | hir::ItemKind::Macro(..) @@ -426,7 +424,6 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { } let codegen_attrs = tcx.codegen_fn_attrs(def_id); codegen_attrs.contains_extern_indicator() - || codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) // FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by // `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their // `SymbolExportLevel::Rust` export level but may end up being exported in dylibs. diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index aea4386295f..9e55914f8f2 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -430,7 +430,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { kind = AnnotationKind::DeprecationProhibited; const_stab_inherit = InheritConstStability::Yes; } - hir::ItemKind::Struct(ref sd, _) => { + hir::ItemKind::Struct(_, ref sd, _) => { if let Some(ctor_def_id) = sd.ctor_def_id() { self.annotate( ctor_def_id, @@ -773,10 +773,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { match item.kind { - hir::ItemKind::ExternCrate(_) => { + hir::ItemKind::ExternCrate(_, ident) => { // compiler-generated `extern crate` items have a dummy span. // `std` is still checked for the `restricted-std` feature. - if item.span.is_dummy() && item.ident.name != sym::std { + if item.span.is_dummy() && ident.name != sym::std { return; } diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index eeea724a29b..176dcbf6da4 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -5,6 +5,7 @@ // tidy-alphabetical-start #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] +#![allow(unused_crate_dependencies)] #![cfg_attr(feature = "rustc", feature(let_chains))] // tidy-alphabetical-end diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 88194c737a6..a25a80cd45f 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::{ }; use rustc_middle::{bug, span_bug}; use rustc_session::lint; -use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; +use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, sym}; use crate::constructor::Constructor::*; use crate::constructor::{ @@ -150,9 +150,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { /// Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`. pub fn is_foreign_non_exhaustive_enum(&self, ty: RevealedTy<'tcx>) -> bool { match ty.kind() { - ty::Adt(def, ..) => { - def.is_enum() && def.is_variant_list_non_exhaustive() && !def.did().is_local() - } + ty::Adt(def, ..) => def.variant_list_has_applicable_non_exhaustive(), _ => false, } } @@ -232,7 +230,11 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx); let is_uninhabited = cx.is_uninhabited(*ty); - let skip = is_uninhabited && !is_visible; + let is_unstable = + cx.tcx.lookup_stability(field.did).is_some_and(|stab| { + stab.is_unstable() && stab.feature != sym::rustc_private + }); + let skip = is_uninhabited && (!is_visible || is_unstable); (ty, PrivateUninhabitedField(skip)) }); cx.dropless_arena.alloc_from_iter(tys) diff --git a/compiler/rustc_pattern_analysis/tests/complexity.rs b/compiler/rustc_pattern_analysis/tests/complexity.rs index abd1ec24d93..93aecafe48d 100644 --- a/compiler/rustc_pattern_analysis/tests/complexity.rs +++ b/compiler/rustc_pattern_analysis/tests/complexity.rs @@ -1,5 +1,7 @@ //! Test the pattern complexity limit. +#![allow(unused_crate_dependencies)] + use common::*; use rustc_pattern_analysis::MatchArm; use rustc_pattern_analysis::pat::DeconstructedPat; diff --git a/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs b/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs index 61ce0fd11e7..3b8f346ef19 100644 --- a/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs +++ b/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs @@ -1,5 +1,7 @@ //! Test exhaustiveness checking. +#![allow(unused_crate_dependencies)] + use common::*; use rustc_pattern_analysis::MatchArm; use rustc_pattern_analysis::pat::{DeconstructedPat, WitnessPat}; diff --git a/compiler/rustc_pattern_analysis/tests/intersection.rs b/compiler/rustc_pattern_analysis/tests/intersection.rs index 45674338efd..8e6f84dcbc8 100644 --- a/compiler/rustc_pattern_analysis/tests/intersection.rs +++ b/compiler/rustc_pattern_analysis/tests/intersection.rs @@ -1,5 +1,7 @@ //! Test the computation of arm intersections. +#![allow(unused_crate_dependencies)] + use common::*; use rustc_pattern_analysis::MatchArm; use rustc_pattern_analysis::pat::DeconstructedPat; diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index cf32f237b86..ed00d97c31d 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -574,7 +574,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { // privacy and mark them reachable. DefKind::Macro(_) => { let item = self.tcx.hir_expect_item(def_id); - if let hir::ItemKind::Macro(MacroDef { macro_rules: false, .. }, _) = item.kind { + if let hir::ItemKind::Macro(_, MacroDef { macro_rules: false, .. }, _) = item.kind { if vis.is_accessible_from(module, self.tcx) { self.update(def_id, macro_ev, Level::Reachable); } @@ -598,8 +598,8 @@ impl<'tcx> EmbargoVisitor<'tcx> { DefKind::Struct | DefKind::Union => { // While structs and unions have type privacy, their fields do not. let item = self.tcx.hir_expect_item(def_id); - if let hir::ItemKind::Struct(ref struct_def, _) - | hir::ItemKind::Union(ref struct_def, _) = item.kind + if let hir::ItemKind::Struct(_, ref struct_def, _) + | hir::ItemKind::Union(_, ref struct_def, _) = item.kind { for field in struct_def.fields() { let field_vis = self.tcx.local_visibility(field.def_id); @@ -653,7 +653,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { | hir::ItemKind::GlobalAsm { .. } => {} // The interface is empty, and all nested items are processed by `visit_item`. hir::ItemKind::Mod(..) => {} - hir::ItemKind::Macro(macro_def, _) => { + hir::ItemKind::Macro(_, macro_def, _) => { if let Some(item_ev) = item_ev { self.update_reachability_from_macro(item.owner_id.def_id, macro_def, item_ev); } @@ -724,7 +724,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } } } - hir::ItemKind::Enum(ref def, _) => { + hir::ItemKind::Enum(_, ref def, _) => { if let Some(item_ev) = item_ev { self.reach(item.owner_id.def_id, item_ev).generics().predicates(); } @@ -762,7 +762,8 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } } } - hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { + hir::ItemKind::Struct(_, ref struct_def, _) + | hir::ItemKind::Union(_, ref struct_def, _) => { if let Some(item_ev) = item_ev { self.reach(item.owner_id.def_id, item_ev).generics().predicates(); for field in struct_def.fields() { @@ -866,7 +867,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TestReachabilityVisitor<'a, 'tcx> { self.effective_visibility_diagnostic(item.owner_id.def_id); match item.kind { - hir::ItemKind::Enum(ref def, _) => { + hir::ItemKind::Enum(_, ref def, _) => { for variant in def.variants.iter() { self.effective_visibility_diagnostic(variant.def_id); if let Some(ctor_def_id) = variant.data.ctor_def_id() { @@ -877,7 +878,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TestReachabilityVisitor<'a, 'tcx> { } } } - hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => { + hir::ItemKind::Struct(_, ref def, _) | hir::ItemKind::Union(_, ref def, _) => { if let Some(ctor_def_id) = def.ctor_def_id() { self.effective_visibility_diagnostic(ctor_def_id); } @@ -1361,12 +1362,12 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { GenericParamDefKind::Lifetime => {} GenericParamDefKind::Type { has_default, .. } => { if has_default { - self.visit(self.tcx.type_of(param.def_id).instantiate_identity()); + let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity()); } } // FIXME(generic_const_exprs): May want to look inside const here GenericParamDefKind::Const { .. } => { - self.visit(self.tcx.type_of(param.def_id).instantiate_identity()); + let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity()); } } } @@ -1381,19 +1382,19 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { // consider the ones that the user wrote. This is important // for the inferred outlives rules; see // `tests/ui/rfc-2093-infer-outlives/privacy.rs`. - self.visit_predicates(self.tcx.explicit_predicates_of(self.item_def_id)); + let _ = self.visit_predicates(self.tcx.explicit_predicates_of(self.item_def_id)); self } fn bounds(&mut self) -> &mut Self { self.in_primary_interface = false; - self.visit_clauses(self.tcx.explicit_item_bounds(self.item_def_id).skip_binder()); + let _ = self.visit_clauses(self.tcx.explicit_item_bounds(self.item_def_id).skip_binder()); self } fn ty(&mut self) -> &mut Self { self.in_primary_interface = true; - self.visit(self.tcx.type_of(self.item_def_id).instantiate_identity()); + let _ = self.visit(self.tcx.type_of(self.item_def_id).instantiate_identity()); self } @@ -1636,7 +1637,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { } DefKind::Enum => { let item = tcx.hir_item(id); - if let hir::ItemKind::Enum(ref def, _) = item.kind { + if let hir::ItemKind::Enum(_, ref def, _) = item.kind { self.check_unnameable(item.owner_id.def_id, effective_vis); self.check(item.owner_id.def_id, item_visibility, effective_vis) @@ -1674,8 +1675,8 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> { // Subitems of structs and unions have their own publicity. DefKind::Struct | DefKind::Union => { let item = tcx.hir_item(id); - if let hir::ItemKind::Struct(ref struct_def, _) - | hir::ItemKind::Union(ref struct_def, _) = item.kind + if let hir::ItemKind::Struct(_, ref struct_def, _) + | hir::ItemKind::Union(_, ref struct_def, _) = item.kind { self.check_unnameable(item.owner_id.def_id, effective_vis); self.check(item.owner_id.def_id, item_visibility, effective_vis) @@ -1785,7 +1786,7 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { let module = tcx.hir_module_items(module_def_id); for def_id in module.definitions() { - rustc_ty_utils::sig_types::walk_types(tcx, def_id, &mut visitor); + let _ = rustc_ty_utils::sig_types::walk_types(tcx, def_id, &mut visitor); if let Some(body_id) = tcx.hir_maybe_body_owned_by(def_id) { visitor.visit_nested_body(body_id.id()); @@ -1798,7 +1799,11 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) { let trait_ref = tcx.impl_trait_ref(id.owner_id.def_id).unwrap(); let trait_ref = trait_ref.instantiate_identity(); visitor.span = item.path.span; - visitor.visit_def_id(trait_ref.def_id, "trait", &trait_ref.print_only_trait_path()); + let _ = visitor.visit_def_id( + trait_ref.def_id, + "trait", + &trait_ref.print_only_trait_path(), + ); } } } diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index c85156e059e..e5cceacf15d 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -5,10 +5,8 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -measureme = "11" -rustc_attr_data_structures = { path = "../rustc_attr_data_structures" } +measureme = "12.0.1" rustc_data_structures = { path = "../rustc_data_structures" } -rustc_errors = { path = "../rustc_errors" } rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } @@ -17,6 +15,5 @@ rustc_query_system = { path = "../rustc_query_system" } rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } -thin-vec = "0.2.12" tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index f98d6421307..2b8457ace8e 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -5,9 +5,7 @@ use std::num::NonZero; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::sync::Lock; use rustc_data_structures::unord::UnordMap; -use rustc_errors::DiagInner; use rustc_hashes::Hash64; use rustc_index::Idx; use rustc_middle::bug; @@ -19,20 +17,20 @@ use rustc_middle::query::Key; use rustc_middle::query::on_disk_cache::{ AbsoluteBytePos, CacheDecoder, CacheEncoder, EncodedDepNodeIndex, }; +use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::print::with_reduced_queries; use rustc_middle::ty::tls::{self, ImplicitCtxt}; -use rustc_middle::ty::{self, TyCtxt, TyEncoder}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_query_system::dep_graph::{DepNodeParams, HasDepContext}; use rustc_query_system::ich::StableHashingContext; use rustc_query_system::query::{ - QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffects, QueryStackFrame, + QueryCache, QueryConfig, QueryContext, QueryJobId, QueryMap, QuerySideEffect, QueryStackFrame, force_query, }; use rustc_query_system::{QueryOverflow, QueryOverflowNote}; use rustc_serialize::{Decodable, Encodable}; use rustc_session::Limit; use rustc_span::def_id::LOCAL_CRATE; -use thin_vec::ThinVec; use crate::QueryConfigRestored; @@ -92,43 +90,31 @@ impl QueryContext for QueryCtxt<'_> { } // Interactions with on_disk_cache - fn load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects { + fn load_side_effect( + self, + prev_dep_node_index: SerializedDepNodeIndex, + ) -> Option<QuerySideEffect> { self.query_system .on_disk_cache .as_ref() - .map(|c| c.load_side_effects(self.tcx, prev_dep_node_index)) - .unwrap_or_default() + .and_then(|c| c.load_side_effect(self.tcx, prev_dep_node_index)) } #[inline(never)] #[cold] - fn store_side_effects(self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects) { + fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect) { if let Some(c) = self.query_system.on_disk_cache.as_ref() { - c.store_side_effects(dep_node_index, side_effects) - } - } - - #[inline(never)] - #[cold] - fn store_side_effects_for_anon_node( - self, - dep_node_index: DepNodeIndex, - side_effects: QuerySideEffects, - ) { - if let Some(c) = self.query_system.on_disk_cache.as_ref() { - c.store_side_effects_for_anon_node(dep_node_index, side_effects) + c.store_side_effect(dep_node_index, side_effect) } } /// Executes a job by changing the `ImplicitCtxt` to point to the - /// new query job while it executes. It returns the diagnostics - /// captured during execution and the actual result. + /// new query job while it executes. #[inline(always)] fn start_query<R>( self, token: QueryJobId, depth_limit: bool, - diagnostics: Option<&Lock<ThinVec<DiagInner>>>, compute: impl FnOnce() -> R, ) -> R { // The `TyCtxt` stored in TLS has the same global interner lifetime @@ -143,7 +129,6 @@ impl QueryContext for QueryCtxt<'_> { let new_icx = ImplicitCtxt { tcx: self.tcx, query: Some(token), - diagnostics, query_depth: current_icx.query_depth + depth_limit as usize, task_deps: current_icx.task_deps, }; @@ -500,7 +485,7 @@ where is_anon, is_eval_always, fingerprint_style, - force_from_dep_node: Some(|tcx, dep_node| { + force_from_dep_node: Some(|tcx, dep_node, _| { force_from_dep_node(Q::config(tcx), tcx, dep_node) }), try_load_from_on_disk_cache: Some(|tcx, dep_node| { @@ -802,7 +787,7 @@ macro_rules! define_queries { is_anon: false, is_eval_always: false, fingerprint_style: FingerprintStyle::Unit, - force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)), + force_from_dep_node: Some(|_, dep_node, _| bug!("force_from_dep_node: encountered {:?}", dep_node)), try_load_from_on_disk_cache: None, name: &"Null", } @@ -814,12 +799,26 @@ macro_rules! define_queries { is_anon: false, is_eval_always: false, fingerprint_style: FingerprintStyle::Unit, - force_from_dep_node: Some(|_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node)), + force_from_dep_node: Some(|_, dep_node, _| bug!("force_from_dep_node: encountered {:?}", dep_node)), try_load_from_on_disk_cache: None, name: &"Red", } } + pub(crate) fn SideEffect<'tcx>() -> DepKindStruct<'tcx> { + DepKindStruct { + is_anon: false, + is_eval_always: false, + fingerprint_style: FingerprintStyle::Unit, + force_from_dep_node: Some(|tcx, _, prev_index| { + tcx.dep_graph.force_diagnostic_node(QueryCtxt::new(tcx), prev_index); + true + }), + try_load_from_on_disk_cache: None, + name: &"SideEffect", + } + } + pub(crate) fn TraitSelect<'tcx>() -> DepKindStruct<'tcx> { DepKindStruct { is_anon: true, diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml index 3e8ccb51021..78710efb7a9 100644 --- a/compiler/rustc_query_system/Cargo.toml +++ b/compiler/rustc_query_system/Cargo.toml @@ -22,6 +22,5 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } -thin-vec = "0.2.12" tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index 9d3368607a2..c0b3bd43e25 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -64,7 +64,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableOrd, use rustc_hir::definitions::DefPathHash; use rustc_macros::{Decodable, Encodable}; -use super::{DepContext, FingerprintStyle}; +use super::{DepContext, FingerprintStyle, SerializedDepNodeIndex}; use crate::ich::StableHashingContext; /// This serves as an index into arrays built by `make_dep_kind_array`. @@ -275,7 +275,8 @@ pub struct DepKindStruct<Tcx: DepContext> { /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode` /// is actually a `DefPathHash`, and can therefore just look up the corresponding /// `DefId` in `tcx.def_path_hash_to_def_id`. - pub force_from_dep_node: Option<fn(tcx: Tcx, dep_node: DepNode) -> bool>, + pub force_from_dep_node: + Option<fn(tcx: Tcx, dep_node: DepNode, prev_index: SerializedDepNodeIndex) -> bool>, /// Invoke a query to put the on-disk cached value in memory. pub try_load_from_on_disk_cache: Option<fn(Tcx, DepNode)>, diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 3109d53cd2c..bfd8b320715 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -5,13 +5,14 @@ use std::marker::PhantomData; use std::sync::Arc; use std::sync::atomic::{AtomicU32, Ordering}; -use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::profiling::{QueryInvocationId, SelfProfilerRef}; use rustc_data_structures::sharded::{self, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{AtomicU64, Lock}; use rustc_data_structures::unord::UnordMap; +use rustc_errors::DiagInner; use rustc_index::IndexVec; use rustc_macros::{Decodable, Encodable}; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; @@ -24,7 +25,7 @@ use super::serialized::{GraphEncoder, SerializedDepGraph, SerializedDepNodeIndex use super::{DepContext, DepKind, DepNode, Deps, HasDepContext, WorkProductId}; use crate::dep_graph::edges::EdgesVec; use crate::ich::StableHashingContext; -use crate::query::{QueryContext, QuerySideEffects}; +use crate::query::{QueryContext, QuerySideEffect}; #[derive(Clone)] pub struct DepGraph<D: Deps> { @@ -91,8 +92,6 @@ pub(crate) struct DepGraphData<D: Deps> { colors: DepNodeColorMap, - processed_side_effects: Lock<FxHashSet<DepNodeIndex>>, - /// When we load, there may be `.o` files, cached MIR, or other such /// things available to us. If we find that they are not dirty, we /// load the path to the file storing those work-products here into @@ -174,7 +173,6 @@ impl<D: Deps> DepGraph<D> { previous_work_products: prev_work_products, dep_node_debug: Default::default(), current, - processed_side_effects: Default::default(), previous: prev_graph, colors, debug_loaded_from_disk: Default::default(), @@ -535,6 +533,32 @@ impl<D: Deps> DepGraph<D> { } } + /// This encodes a diagnostic by creating a node with an unique index and assoicating + /// `diagnostic` with it, for use in the next session. + #[inline] + pub fn record_diagnostic<Qcx: QueryContext>(&self, qcx: Qcx, diagnostic: &DiagInner) { + if let Some(ref data) = self.data { + D::read_deps(|task_deps| match task_deps { + TaskDepsRef::EvalAlways | TaskDepsRef::Ignore => return, + TaskDepsRef::Forbid | TaskDepsRef::Allow(..) => { + self.read_index(data.encode_diagnostic(qcx, diagnostic)); + } + }) + } + } + /// This forces a diagnostic node green by running its side effect. `prev_index` would + /// refer to a node created used `encode_diagnostic` in the previous session. + #[inline] + pub fn force_diagnostic_node<Qcx: QueryContext>( + &self, + qcx: Qcx, + prev_index: SerializedDepNodeIndex, + ) { + if let Some(ref data) = self.data { + data.force_diagnostic_node(qcx, prev_index); + } + } + /// Create a node when we force-feed a value into the query cache. /// This is used to remove cycles during type-checking const generic parameters. /// @@ -656,6 +680,57 @@ impl<D: Deps> DepGraphData<D> { pub(crate) fn mark_debug_loaded_from_disk(&self, dep_node: DepNode) { self.debug_loaded_from_disk.lock().insert(dep_node); } + + /// This encodes a diagnostic by creating a node with an unique index and assoicating + /// `diagnostic` with it, for use in the next session. + #[inline] + fn encode_diagnostic<Qcx: QueryContext>( + &self, + qcx: Qcx, + diagnostic: &DiagInner, + ) -> DepNodeIndex { + // Use `send` so we get an unique index, even though the dep node is not. + let dep_node_index = self.current.encoder.send( + DepNode { + kind: D::DEP_KIND_SIDE_EFFECT, + hash: PackedFingerprint::from(Fingerprint::ZERO), + }, + Fingerprint::ZERO, + // We want the side effect node to always be red so it will be forced and emit the + // diagnostic. + std::iter::once(DepNodeIndex::FOREVER_RED_NODE).collect(), + ); + let side_effect = QuerySideEffect::Diagnostic(diagnostic.clone()); + qcx.store_side_effect(dep_node_index, side_effect); + dep_node_index + } + + /// This forces a diagnostic node green by running its side effect. `prev_index` would + /// refer to a node created used `encode_diagnostic` in the previous session. + #[inline] + fn force_diagnostic_node<Qcx: QueryContext>( + &self, + qcx: Qcx, + prev_index: SerializedDepNodeIndex, + ) { + D::with_deps(TaskDepsRef::Ignore, || { + let side_effect = qcx.load_side_effect(prev_index).unwrap(); + + match &side_effect { + QuerySideEffect::Diagnostic(diagnostic) => { + qcx.dep_context().sess().dcx().emit_diagnostic(diagnostic.clone()); + } + } + + // Promote the previous diagnostics to the current session. + let index = self.current.promote_node_and_deps_to_current(&self.previous, prev_index); + // FIXME: Can this race with a parallel compiler? + qcx.store_side_effect(index, side_effect); + + // Mark the node as green. + self.colors.insert(prev_index, DepNodeColor::Green(index)); + }) + } } impl<D: Deps> DepGraph<D> { @@ -794,7 +869,7 @@ impl<D: Deps> DepGraphData<D> { // We failed to mark it green, so we try to force the query. debug!("trying to force dependency {dep_dep_node:?}"); - if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node, frame) { + if !qcx.dep_context().try_force_from_dep_node(*dep_dep_node, parent_dep_node_index, frame) { // The DepNode could not be forced. debug!("dependency {dep_dep_node:?} could not be forced"); return None; @@ -867,16 +942,6 @@ impl<D: Deps> DepGraphData<D> { // ... emitting any stored diagnostic ... - // FIXME: Store the fact that a node has diagnostics in a bit in the dep graph somewhere - // Maybe store a list on disk and encode this fact in the DepNodeState - let side_effects = qcx.load_side_effects(prev_dep_node_index); - - if side_effects.maybe_any() { - qcx.dep_context().dep_graph().with_query_deserialization(|| { - self.emit_side_effects(qcx, dep_node_index, side_effects) - }); - } - // ... and finally storing a "Green" entry in the color map. // Multiple threads can all write the same color here self.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index)); @@ -884,33 +949,6 @@ impl<D: Deps> DepGraphData<D> { debug!("successfully marked {dep_node:?} as green"); Some(dep_node_index) } - - /// Atomically emits some loaded diagnostics. - /// This may be called concurrently on multiple threads for the same dep node. - #[cold] - #[inline(never)] - fn emit_side_effects<Qcx: QueryContext<Deps = D>>( - &self, - qcx: Qcx, - dep_node_index: DepNodeIndex, - side_effects: QuerySideEffects, - ) { - let mut processed = self.processed_side_effects.lock(); - - if processed.insert(dep_node_index) { - // We were the first to insert the node in the set so this thread - // must process side effects - - // Promote the previous diagnostics to the current session. - qcx.store_side_effects(dep_node_index, side_effects.clone()); - - let dcx = qcx.dep_context().sess().dcx(); - - for diagnostic in side_effects.diagnostics { - dcx.emit_diagnostic(diagnostic); - } - } - } } impl<D: Deps> DepGraph<D> { diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs index e564ae0cec7..e3d64d1c0f8 100644 --- a/compiler/rustc_query_system/src/dep_graph/mod.rs +++ b/compiler/rustc_query_system/src/dep_graph/mod.rs @@ -58,10 +58,15 @@ pub trait DepContext: Copy { /// dep-node or when the query kind outright does not support it. #[inline] #[instrument(skip(self, frame), level = "debug")] - fn try_force_from_dep_node(self, dep_node: DepNode, frame: Option<&MarkFrame<'_>>) -> bool { + fn try_force_from_dep_node( + self, + dep_node: DepNode, + prev_index: SerializedDepNodeIndex, + frame: Option<&MarkFrame<'_>>, + ) -> bool { let cb = self.dep_kind_info(dep_node.kind); if let Some(f) = cb.force_from_dep_node { - match panic::catch_unwind(panic::AssertUnwindSafe(|| f(self, dep_node))) { + match panic::catch_unwind(panic::AssertUnwindSafe(|| f(self, dep_node, prev_index))) { Err(value) => { if !value.is::<rustc_errors::FatalErrorMarker>() { print_markframe_trace(self.dep_graph(), frame); @@ -101,6 +106,9 @@ pub trait Deps { /// We use this to create a forever-red node. const DEP_KIND_RED: DepKind; + /// We use this to create a side effect node. + const DEP_KIND_SIDE_EFFECT: DepKind; + /// This is the highest value a `DepKind` can have. It's used during encoding to /// pack information into the unused bits. const DEP_KIND_MAX: u16; diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs index 7490a3f3503..2ed0c810b75 100644 --- a/compiler/rustc_query_system/src/query/mod.rs +++ b/compiler/rustc_query_system/src/query/mod.rs @@ -11,14 +11,12 @@ mod caches; pub use self::caches::{DefIdCache, DefaultCache, QueryCache, SingleCache, VecCache}; mod config; -use rustc_data_structures::sync::Lock; use rustc_errors::DiagInner; use rustc_hashes::Hash64; use rustc_hir::def::DefKind; use rustc_macros::{Decodable, Encodable}; use rustc_span::Span; use rustc_span::def_id::DefId; -use thin_vec::ThinVec; pub use self::config::{HashResult, QueryConfig}; use crate::dep_graph::{DepKind, DepNodeIndex, HasDepContext, SerializedDepNodeIndex}; @@ -64,33 +62,22 @@ impl QueryStackFrame { } } -/// Tracks 'side effects' for a particular query. +/// Track a 'side effects' for a particular query. /// This struct is saved to disk along with the query result, /// and loaded from disk if we mark the query as green. /// This allows us to 'replay' changes to global state /// that would otherwise only occur if we actually /// executed the query method. -#[derive(Debug, Clone, Default, Encodable, Decodable)] -pub struct QuerySideEffects { - /// Stores any diagnostics emitted during query execution. - /// These diagnostics will be re-emitted if we mark - /// the query as green. - pub(super) diagnostics: ThinVec<DiagInner>, -} - -impl QuerySideEffects { - /// Returns true if there might be side effects. - #[inline] - pub fn maybe_any(&self) -> bool { - let QuerySideEffects { diagnostics } = self; - // Use `has_capacity` so that the destructor for `self.diagnostics` can be skipped - // if `maybe_any` is known to be false. - diagnostics.has_capacity() - } - pub fn append(&mut self, other: QuerySideEffects) { - let QuerySideEffects { diagnostics } = self; - diagnostics.extend(other.diagnostics); - } +/// +/// Each side effect gets an unique dep node index which is added +/// as a dependency of the query which had the effect. +#[derive(Debug, Encodable, Decodable)] +pub enum QuerySideEffect { + /// Stores a diagnostic emitted during query execution. + /// This diagnostic will be re-emitted if we mark + /// the query as green, as that query will have the side + /// effect dep node as a dependency. + Diagnostic(DiagInner), } pub trait QueryContext: HasDepContext { @@ -101,29 +88,19 @@ pub trait QueryContext: HasDepContext { fn collect_active_jobs(self) -> QueryMap; - /// Load side effects associated to the node in the previous session. - fn load_side_effects(self, prev_dep_node_index: SerializedDepNodeIndex) -> QuerySideEffects; - - /// Register diagnostics for the given node, for use in next session. - fn store_side_effects(self, dep_node_index: DepNodeIndex, side_effects: QuerySideEffects); - - /// Register diagnostics for the given node, for use in next session. - fn store_side_effects_for_anon_node( + /// Load a side effect associated to the node in the previous session. + fn load_side_effect( self, - dep_node_index: DepNodeIndex, - side_effects: QuerySideEffects, - ); + prev_dep_node_index: SerializedDepNodeIndex, + ) -> Option<QuerySideEffect>; + + /// Register a side effect for the given node, for use in next session. + fn store_side_effect(self, dep_node_index: DepNodeIndex, side_effect: QuerySideEffect); /// Executes a job by changing the `ImplicitCtxt` to point to the - /// new query job while it executes. It returns the diagnostics - /// captured during execution and the actual result. - fn start_query<R>( - self, - token: QueryJobId, - depth_limit: bool, - diagnostics: Option<&Lock<ThinVec<DiagInner>>>, - compute: impl FnOnce() -> R, - ) -> R; + /// new query job while it executes. + fn start_query<R>(self, token: QueryJobId, depth_limit: bool, compute: impl FnOnce() -> R) + -> R; fn depth_limit_error(self, job: QueryJobId); } diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 18aae8c00b2..7578cb5e2ae 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -12,11 +12,9 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sharded::Sharded; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_data_structures::sync::Lock; use rustc_data_structures::{outline, sync}; use rustc_errors::{Diag, FatalError, StashKey}; use rustc_span::{DUMMY_SP, Span}; -use thin_vec::ThinVec; use tracing::instrument; use super::QueryConfig; @@ -25,9 +23,7 @@ use crate::dep_graph::{DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeP use crate::ich::StableHashingContext; use crate::query::caches::QueryCache; use crate::query::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, report_cycle}; -use crate::query::{ - QueryContext, QueryMap, QuerySideEffects, QueryStackFrame, SerializedDepNodeIndex, -}; +use crate::query::{QueryContext, QueryMap, QueryStackFrame, SerializedDepNodeIndex}; pub struct QueryState<K> { active: Sharded<FxHashMap<K, QueryResult>>, @@ -470,7 +466,7 @@ where } let prof_timer = qcx.dep_context().profiler().query_provider(); - let result = qcx.start_query(job_id, query.depth_limit(), None, || query.compute(qcx, key)); + let result = qcx.start_query(job_id, query.depth_limit(), || query.compute(qcx, key)); let dep_node_index = qcx.dep_context().dep_graph().next_virtual_depnode_index(); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); @@ -507,7 +503,7 @@ where // The diagnostics for this query will be promoted to the current session during // `try_mark_green()`, so we can ignore them here. - if let Some(ret) = qcx.start_query(job_id, false, None, || { + if let Some(ret) = qcx.start_query(job_id, false, || { try_load_from_disk_and_cache_in_memory(query, dep_graph_data, qcx, &key, dep_node) }) { return ret; @@ -515,43 +511,31 @@ where } let prof_timer = qcx.dep_context().profiler().query_provider(); - let diagnostics = Lock::new(ThinVec::new()); - let (result, dep_node_index) = - qcx.start_query(job_id, query.depth_limit(), Some(&diagnostics), || { - if query.anon() { - return dep_graph_data.with_anon_task_inner( - *qcx.dep_context(), - query.dep_kind(), - || query.compute(qcx, key), - ); - } + let (result, dep_node_index) = qcx.start_query(job_id, query.depth_limit(), || { + if query.anon() { + return dep_graph_data.with_anon_task_inner( + *qcx.dep_context(), + query.dep_kind(), + || query.compute(qcx, key), + ); + } - // `to_dep_node` is expensive for some `DepKind`s. - let dep_node = - dep_node_opt.unwrap_or_else(|| query.construct_dep_node(*qcx.dep_context(), &key)); + // `to_dep_node` is expensive for some `DepKind`s. + let dep_node = + dep_node_opt.unwrap_or_else(|| query.construct_dep_node(*qcx.dep_context(), &key)); - dep_graph_data.with_task( - dep_node, - (qcx, query), - key, - |(qcx, query), key| query.compute(qcx, key), - query.hash_result(), - ) - }); + dep_graph_data.with_task( + dep_node, + (qcx, query), + key, + |(qcx, query), key| query.compute(qcx, key), + query.hash_result(), + ) + }); prof_timer.finish_with_query_invocation_id(dep_node_index.into()); - let side_effects = QuerySideEffects { diagnostics: diagnostics.into_inner() }; - - if std::intrinsics::unlikely(side_effects.maybe_any()) { - if query.anon() { - qcx.store_side_effects_for_anon_node(dep_node_index, side_effects); - } else { - qcx.store_side_effects(dep_node_index, side_effects); - } - } - (result, dep_node_index) } diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 817aa5b4385..558a01713dc 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -26,10 +26,6 @@ resolve_associated_fn_with_similar_name_exists = resolve_associated_type_with_similar_name_exists = there is an associated type with a similar name -resolve_attempt_to_define_builtin_macro_twice = - attempted to define built-in macro more than once - .note = previously defined here - resolve_attempt_to_use_non_constant_value_in_constant = attempt to use a non-constant value in a constant diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 42fe01b1c84..763e9207a12 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1115,6 +1115,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } }); } else { + #[allow(rustc::potential_query_instability)] // FIXME for ident in single_imports.iter().cloned() { let result = self.r.maybe_resolve_ident_in_module( ModuleOrUniformRoot::Module(module), diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 41f4254eede..5361af98f3c 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -6,6 +6,7 @@ use rustc_ast::{ }; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, MultiSpan, SuggestionStyle, @@ -1467,6 +1468,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return; } + #[allow(rustc::potential_query_instability)] // FIXME let unused_macro = self.unused_macros.iter().find_map(|(def_id, (_, unused_ident))| { if unused_ident.name == ident.name { Some((def_id, unused_ident)) } else { None } }); @@ -2863,18 +2865,11 @@ fn show_candidates( } else { // Get the unique item kinds and if there's only one, we use the right kind name // instead of the more generic "items". - let mut kinds = accessible_path_strings + let kinds = accessible_path_strings .iter() .map(|(_, descr, _, _, _)| *descr) - .collect::<FxHashSet<&str>>() - .into_iter(); - let kind = if let Some(kind) = kinds.next() - && let None = kinds.next() - { - kind - } else { - "item" - }; + .collect::<UnordSet<&str>>(); + let kind = if let Some(kind) = kinds.get_only() { kind } else { "item" }; let s = if kind.ends_with('s') { "es" } else { "s" }; ("one of these", kind, s, String::new(), "") diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 2ae6892bc93..e26b300f13e 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -966,15 +966,6 @@ pub(crate) struct StaticLifetimeIsReserved { } #[derive(Diagnostic)] -#[diag(resolve_attempt_to_define_builtin_macro_twice, code = E0773)] -pub(crate) struct AttemptToDefineBuiltinMacroTwice { - #[primary_span] - pub(crate) span: Span, - #[note] - pub(crate) note_span: Span, -} - -#[derive(Diagnostic)] #[diag(resolve_variable_is_not_bound_in_all_patterns, code = E0408)] pub(crate) struct VariableIsNotBoundInAllPatterns { #[primary_span] diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 5f0a2a597e9..27d63198836 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -946,6 +946,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Check if one of single imports can still define the name, // if it can then our result is not determined and can be invalidated. + #[allow(rustc::potential_query_instability)] // FIXME for single_import in &resolution.single_imports { if ignore_import == Some(*single_import) { // This branch handles a cycle in single imports. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index f3f6c551580..6056a69ee71 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -18,6 +18,7 @@ use rustc_ast::visit::{ }; use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; +use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, DiagArgValue, ErrorGuaranteed, IntoDiagArg, StashKey, Suggestions, @@ -47,8 +48,6 @@ mod diagnostics; type Res = def::Res<NodeId>; -type IdentMap<T> = FxHashMap<Ident, T>; - use diagnostics::{ElisionFnParameter, LifetimeElisionCandidate, MissingLifetime}; #[derive(Copy, Clone, Debug)] @@ -273,8 +272,8 @@ impl RibKind<'_> { /// resolving, the name is looked up from inside out. #[derive(Debug)] pub(crate) struct Rib<'ra, R = Res> { - pub bindings: IdentMap<R>, - pub patterns_with_skipped_bindings: FxHashMap<DefId, Vec<(Span, Result<(), ErrorGuaranteed>)>>, + pub bindings: FxHashMap<Ident, R>, + pub patterns_with_skipped_bindings: UnordMap<DefId, Vec<(Span, Result<(), ErrorGuaranteed>)>>, pub kind: RibKind<'ra>, } @@ -1605,12 +1604,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // for better diagnostics. let mut forward_ty_ban_rib_const_param_ty = Rib { bindings: forward_ty_ban_rib.bindings.clone(), - patterns_with_skipped_bindings: FxHashMap::default(), + patterns_with_skipped_bindings: Default::default(), kind: RibKind::ForwardGenericParamBan(ForwardGenericParamBanReason::ConstParamTy), }; let mut forward_const_ban_rib_const_param_ty = Rib { bindings: forward_const_ban_rib.bindings.clone(), - patterns_with_skipped_bindings: FxHashMap::default(), + patterns_with_skipped_bindings: Default::default(), kind: RibKind::ForwardGenericParamBan(ForwardGenericParamBanReason::ConstParamTy), }; // We'll ban these with a `ConstParamTy` rib, so just clear these ribs for better @@ -2334,7 +2333,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let local_candidates = self.lifetime_elision_candidates.take(); if let Some(candidates) = local_candidates { - let distinct: FxHashSet<_> = candidates.iter().map(|(res, _)| *res).collect(); + let distinct: UnordSet<_> = candidates.iter().map(|(res, _)| *res).collect(); let lifetime_count = distinct.len(); if lifetime_count != 0 { parameter_info.push(ElisionFnParameter { @@ -2358,14 +2357,13 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } })); } - let mut distinct_iter = distinct.into_iter(); - if let Some(res) = distinct_iter.next() { + if !distinct.is_empty() { match elision_lifetime { // We are the first parameter to bind lifetimes. Elision::None => { - if distinct_iter.next().is_none() { + if let Some(res) = distinct.get_only() { // We have a single lifetime => success. - elision_lifetime = Elision::Param(res) + elision_lifetime = Elision::Param(*res) } else { // We have multiple lifetimes => error. elision_lifetime = Elision::Err; @@ -2890,6 +2888,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { break; } + #[allow(rustc::potential_query_instability)] // FIXME seen_bindings .extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span))); } @@ -4004,7 +4003,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } } - fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut IdentMap<Res> { + fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut FxHashMap<Ident, Res> { &mut self.ribs[ns].last_mut().unwrap().bindings } @@ -5202,6 +5201,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut late_resolution_visitor = LateResolutionVisitor::new(self); late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID)); visit::walk_crate(&mut late_resolution_visitor, krate); + #[allow(rustc::potential_query_instability)] // FIXME for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() { self.lint_buffer.buffer_lint( lint::builtin::UNUSED_LABELS, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 84858cfc1b1..3d666055a94 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -830,6 +830,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { if let Some(rib) = &self.last_block_rib && let RibKind::Normal = rib.kind { + #[allow(rustc::potential_query_instability)] // FIXME for (ident, &res) in &rib.bindings { if let Res::Local(_) = res && path.len() == 1 @@ -1018,6 +1019,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { if let Some(err_code) = err.code { if err_code == E0425 { for label_rib in &self.label_ribs { + #[allow(rustc::potential_query_instability)] // FIXME for (label_ident, node_id) in &label_rib.bindings { let ident = path.last().unwrap().ident; if format!("'{ident}") == label_ident.to_string() { @@ -1177,7 +1179,10 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let [segment] = path else { return }; let None = following_seg else { return }; for rib in self.ribs[ValueNS].iter().rev() { - for (def_id, spans) in &rib.patterns_with_skipped_bindings { + let patterns_with_skipped_bindings = self.r.tcx.with_stable_hashing_context(|hcx| { + rib.patterns_with_skipped_bindings.to_sorted(&hcx, true) + }); + for (def_id, spans) in patterns_with_skipped_bindings { if let DefKind::Struct | DefKind::Variant = self.r.tcx.def_kind(*def_id) && let Some(fields) = self.r.field_idents(*def_id) { @@ -2052,7 +2057,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { if self .r .extern_crate_map - .iter() + .items() // FIXME: This doesn't include impls like `impl Default for String`. .flat_map(|(_, crate_)| self.r.tcx.implementations_of_trait((*crate_, default_trait))) .filter_map(|(_, simplified_self_ty)| *simplified_self_ty) @@ -2212,12 +2217,11 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { .delegation_fn_sigs .get(&def_id) .is_some_and(|sig| sig.has_self), - None => self - .r - .tcx - .fn_arg_names(def_id) - .first() - .is_some_and(|ident| ident.name == kw::SelfLower), + None => { + self.r.tcx.fn_arg_names(def_id).first().is_some_and(|&ident| { + matches!(ident, Some(Ident { name: kw::SelfLower, .. })) + }) + } }; if has_self { return Some(AssocSuggestion::MethodWithSelf { called }); @@ -2261,6 +2265,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { }; // Locals and type parameters + #[allow(rustc::potential_query_instability)] // FIXME for (ident, &res) in &rib.bindings { if filter_fn(res) && ident.span.ctxt() == rib_ctxt { names.push(TypoSuggestion::typo_from_ident(*ident, res)); @@ -2788,6 +2793,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let within_scope = self.is_label_valid_from_rib(rib_index); let rib = &self.label_ribs[rib_index]; + #[allow(rustc::potential_query_instability)] // FIXME let names = rib .bindings .iter() @@ -2799,6 +2805,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // Upon finding a similar name, get the ident that it was from - the span // contained within helps make a useful diagnostic. In addition, determine // whether this candidate is within scope. + #[allow(rustc::potential_query_instability)] // FIXME let (ident, _) = rib.bindings.iter().find(|(ident, _)| ident.name == symbol).unwrap(); (*ident, within_scope) }) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 495ce843fcd..ff31af0025b 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -9,7 +9,6 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::diagnostic_outside_of_impl)] -#![allow(rustc::potential_query_instability)] #![allow(rustc::untranslatable_diagnostic)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] @@ -47,6 +46,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::FreezeReadGuard; +use rustc_data_structures::unord::UnordMap; use rustc_errors::{Applicability, Diag, ErrCode, ErrorGuaranteed}; use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind}; use rustc_feature::BUILTIN_ATTRIBUTES; @@ -1010,12 +1010,6 @@ impl ExternPreludeEntry<'_> { } } -/// Used for better errors for E0773 -enum BuiltinMacroState { - NotYetSeen(SyntaxExtensionKind), - AlreadySeen(Span), -} - struct DeriveData { resolutions: Vec<DeriveResolution>, helper_attrs: Vec<(usize, Ident)>, @@ -1046,7 +1040,7 @@ pub struct Resolver<'ra, 'tcx> { graph_root: Module<'ra>, prelude: Option<Module<'ra>>, - extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'ra>>, + extern_prelude: FxIndexMap<Ident, ExternPreludeEntry<'ra>>, /// N.B., this is used only for better diagnostics, not name resolution itself. field_names: LocalDefIdMap<Vec<Ident>>, @@ -1079,7 +1073,7 @@ pub struct Resolver<'ra, 'tcx> { extra_lifetime_params_map: NodeMap<Vec<(Ident, NodeId, LifetimeRes)>>, /// `CrateNum` resolutions of `extern crate` items. - extern_crate_map: FxHashMap<LocalDefId, CrateNum>, + extern_crate_map: UnordMap<LocalDefId, CrateNum>, module_children: LocalDefIdMap<Vec<ModChild>>, trait_map: NodeMap<Vec<TraitCandidate>>, @@ -1102,7 +1096,7 @@ pub struct Resolver<'ra, 'tcx> { /// some AST passes can generate identifiers that only resolve to local or /// lang items. empty_module: Module<'ra>, - module_map: FxHashMap<DefId, Module<'ra>>, + module_map: FxIndexMap<DefId, Module<'ra>>, binding_parent_modules: FxHashMap<NameBinding<'ra>, Module<'ra>>, underscore_disambiguator: u32, @@ -1134,9 +1128,9 @@ pub struct Resolver<'ra, 'tcx> { used_extern_options: FxHashSet<Symbol>, macro_names: FxHashSet<Ident>, - builtin_macros: FxHashMap<Symbol, BuiltinMacroState>, + builtin_macros: FxHashMap<Symbol, SyntaxExtensionKind>, registered_tools: &'tcx RegisteredTools, - macro_use_prelude: FxHashMap<Symbol, NameBinding<'ra>>, + macro_use_prelude: FxIndexMap<Symbol, NameBinding<'ra>>, macro_map: FxHashMap<DefId, MacroData>, dummy_ext_bang: Arc<SyntaxExtension>, dummy_ext_derive: Arc<SyntaxExtension>, @@ -1145,7 +1139,7 @@ pub struct Resolver<'ra, 'tcx> { ast_transform_scopes: FxHashMap<LocalExpnId, Module<'ra>>, unused_macros: FxHashMap<LocalDefId, (NodeId, Ident)>, /// A map from the macro to all its potentially unused arms. - unused_macro_rules: FxIndexMap<LocalDefId, FxHashMap<usize, (Ident, Span)>>, + unused_macro_rules: FxIndexMap<LocalDefId, UnordMap<usize, (Ident, Span)>>, proc_macro_stubs: FxHashSet<LocalDefId>, /// Traces collected during macro resolution and validated when it's complete. single_segment_macro_resolutions: @@ -1259,7 +1253,7 @@ impl<'ra> ResolverArenas<'ra> { expn_id: ExpnId, span: Span, no_implicit_prelude: bool, - module_map: &mut FxHashMap<DefId, Module<'ra>>, + module_map: &mut FxIndexMap<DefId, Module<'ra>>, module_self_bindings: &mut FxHashMap<Module<'ra>, NameBinding<'ra>>, ) -> Module<'ra> { let module = Module(Interned::new_unchecked(self.modules.alloc(ModuleData::new( @@ -1404,7 +1398,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { arenas: &'ra ResolverArenas<'ra>, ) -> Resolver<'ra, 'tcx> { let root_def_id = CRATE_DEF_ID.to_def_id(); - let mut module_map = FxHashMap::default(); + let mut module_map = FxIndexMap::default(); let mut module_self_bindings = FxHashMap::default(); let graph_root = arenas.new_module( None, @@ -1421,8 +1415,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ExpnId::root(), DUMMY_SP, true, - &mut FxHashMap::default(), - &mut FxHashMap::default(), + &mut Default::default(), + &mut Default::default(), ); let mut def_id_to_node_id = IndexVec::default(); @@ -1437,7 +1431,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut invocation_parents = FxHashMap::default(); invocation_parents.insert(LocalExpnId::ROOT, InvocationParent::ROOT); - let mut extern_prelude: FxHashMap<Ident, ExternPreludeEntry<'_>> = tcx + let mut extern_prelude: FxIndexMap<Ident, ExternPreludeEntry<'_>> = tcx .sess .opts .externs @@ -1536,7 +1530,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { macro_names: FxHashSet::default(), builtin_macros: Default::default(), registered_tools, - macro_use_prelude: FxHashMap::default(), + macro_use_prelude: Default::default(), macro_map: FxHashMap::default(), dummy_ext_bang: Arc::new(SyntaxExtension::dummy_bang(edition)), dummy_ext_derive: Arc::new(SyntaxExtension::dummy_derive(edition)), diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 984dfff3ea5..c4304a7a6df 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -8,7 +8,7 @@ use std::sync::Arc; use rustc_ast::expand::StrippedCfgItem; use rustc_ast::{self as ast, Crate, NodeId, attr}; use rustc_ast_pretty::pprust; -use rustc_attr_parsing::StabilityLevel; +use rustc_attr_parsing::{AttributeKind, StabilityLevel, find_attr}; use rustc_data_structures::intern::Interned; use rustc_errors::{Applicability, StashKey}; use rustc_expand::base::{ @@ -40,9 +40,9 @@ use crate::errors::{ }; use crate::imports::Import; use crate::{ - BindingKey, BuiltinMacroState, DeriveData, Determinacy, Finalize, InvocationParent, MacroData, - ModuleKind, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult, - ResolutionError, Resolver, ScopeSet, Segment, ToNameBinding, Used, + BindingKey, DeriveData, Determinacy, Finalize, InvocationParent, MacroData, ModuleKind, + ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult, ResolutionError, + Resolver, ScopeSet, Segment, ToNameBinding, Used, }; type Res = def::Res<NodeId>; @@ -194,7 +194,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { } fn register_builtin_macro(&mut self, name: Symbol, ext: SyntaxExtensionKind) { - if self.builtin_macros.insert(name, BuiltinMacroState::NotYetSeen(ext)).is_some() { + if self.builtin_macros.insert(name, ext).is_some() { self.dcx().bug(format!("built-in macro `{name}` was already registered")); } } @@ -323,6 +323,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { } fn check_unused_macros(&mut self) { + #[allow(rustc::potential_query_instability)] // FIXME for (_, &(node_id, ident)) in self.unused_macros.iter() { self.lint_buffer.buffer_lint( UNUSED_MACROS, @@ -333,10 +334,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { } for (&def_id, unused_arms) in self.unused_macro_rules.iter() { - let mut unused_arms = unused_arms.iter().collect::<Vec<_>>(); - unused_arms.sort_by_key(|&(&arm_i, _)| arm_i); - - for (&arm_i, &(ident, rule_span)) in unused_arms { + for (&arm_i, &(ident, rule_span)) in unused_arms.to_sorted_stable_ord() { if self.unused_macros.contains_key(&def_id) { // We already lint the entire macro as unused continue; @@ -1127,22 +1125,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { edition, ); + // The #[rustc_macro_edition_2021] attribute is used by the pin!() macro + // as a temporary workaround for a regression in expressiveness in Rust 2024. + // See https://github.com/rust-lang/rust/issues/138718. + if find_attr!(attrs.iter(), AttributeKind::RustcMacroEdition2021) { + ext.edition = Edition::Edition2021; + } + if let Some(builtin_name) = ext.builtin_name { // The macro was marked with `#[rustc_builtin_macro]`. - if let Some(builtin_macro) = self.builtin_macros.get_mut(&builtin_name) { + if let Some(builtin_ext_kind) = self.builtin_macros.get(&builtin_name) { // The macro is a built-in, replace its expander function // while still taking everything else from the source code. - // If we already loaded this builtin macro, give a better error message than 'no such builtin macro'. - match mem::replace(builtin_macro, BuiltinMacroState::AlreadySeen(span)) { - BuiltinMacroState::NotYetSeen(builtin_ext) => { - ext.kind = builtin_ext; - rule_spans = Vec::new(); - } - BuiltinMacroState::AlreadySeen(note_span) => { - self.dcx() - .emit_err(errors::AttemptToDefineBuiltinMacroTwice { span, note_span }); - } - } + ext.kind = builtin_ext_kind.clone(); + rule_spans = Vec::new(); } else { self.dcx().emit_err(errors::CannotFindBuiltinMacroWithName { span, ident }); } diff --git a/compiler/rustc_sanitizers/Cargo.toml b/compiler/rustc_sanitizers/Cargo.toml index 900cd4243b1..66488bc9625 100644 --- a/compiler/rustc_sanitizers/Cargo.toml +++ b/compiler/rustc_sanitizers/Cargo.toml @@ -8,7 +8,6 @@ bitflags = "2.5.0" tracing = "0.1" twox-hash = "1.6.3" rustc_abi = { path = "../rustc_abi" } -rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_hir = { path = "../rustc_hir" } rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index b711c238d59..129a32c6edd 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -9,10 +9,9 @@ use std::iter; use rustc_hir as hir; use rustc_hir::LangItem; use rustc_middle::bug; -use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{ self, ExistentialPredicateStableCmpExt as _, Instance, InstanceKind, IntTy, List, TraitRef, Ty, - TyCtxt, TypeFoldable, TypeVisitableExt, UintTy, + TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, UintTy, }; use rustc_span::def_id::DefId; use rustc_span::sym; diff --git a/compiler/rustc_serialize/src/leb128.rs b/compiler/rustc_serialize/src/leb128.rs index 4a475805697..954c1f728f2 100644 --- a/compiler/rustc_serialize/src/leb128.rs +++ b/compiler/rustc_serialize/src/leb128.rs @@ -155,3 +155,6 @@ impl_read_signed_leb128!(read_i32_leb128, i32); impl_read_signed_leb128!(read_i64_leb128, i64); impl_read_signed_leb128!(read_i128_leb128, i128); impl_read_signed_leb128!(read_isize_leb128, isize); + +#[cfg(test)] +mod tests; diff --git a/compiler/rustc_serialize/tests/leb128.rs b/compiler/rustc_serialize/src/leb128/tests.rs index aef55d15e60..8434cd1e2e1 100644 --- a/compiler/rustc_serialize/tests/leb128.rs +++ b/compiler/rustc_serialize/src/leb128/tests.rs @@ -1,6 +1,6 @@ -use rustc_serialize::Decoder; -use rustc_serialize::leb128::*; -use rustc_serialize::opaque::{MAGIC_END_BYTES, MemDecoder}; +use super::*; +use crate::Decoder; +use crate::opaque::{MAGIC_END_BYTES, MemDecoder}; macro_rules! impl_test_unsigned_leb128 { ($test_name:ident, $write_fn_name:ident, $read_fn_name:ident, $int_ty:ident) => { diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index 13c1a273eb8..34be35e36ac 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -16,6 +16,10 @@ #![feature(rustdoc_internals)] // tidy-alphabetical-end +// Allows macros to refer to this crate as `::rustc_serialize`. +#[cfg(test)] +extern crate self as rustc_serialize; + pub use self::serialize::{Decodable, Decoder, Encodable, Encoder}; mod serialize; diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs index d4907b69b72..81f6266f8d1 100644 --- a/compiler/rustc_serialize/src/opaque.rs +++ b/compiler/rustc_serialize/src/opaque.rs @@ -451,3 +451,6 @@ impl<'a> Decodable<MemDecoder<'a>> for IntEncodedWithFixedSize { IntEncodedWithFixedSize(u64::from_le_bytes(bytes)) } } + +#[cfg(test)] +mod tests; diff --git a/compiler/rustc_serialize/tests/opaque.rs b/compiler/rustc_serialize/src/opaque/tests.rs index 0543e176ae5..11401d24595 100644 --- a/compiler/rustc_serialize/tests/opaque.rs +++ b/compiler/rustc_serialize/src/opaque/tests.rs @@ -1,13 +1,12 @@ -#![allow(rustc::internal)] - use std::fmt::Debug; use std::fs; -use rustc_macros::{Decodable_Generic, Encodable_Generic}; -use rustc_serialize::opaque::{FileEncoder, MemDecoder}; -use rustc_serialize::{Decodable, Encodable}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext}; + +use crate::opaque::{FileEncoder, MemDecoder}; +use crate::{Decodable, Encodable}; -#[derive(PartialEq, Clone, Debug, Encodable_Generic, Decodable_Generic)] +#[derive(PartialEq, Clone, Debug, Encodable_NoContext, Decodable_NoContext)] struct Struct { a: (), b: u8, @@ -210,7 +209,7 @@ fn test_struct() { }]); } -#[derive(PartialEq, Clone, Debug, Encodable_Generic, Decodable_Generic)] +#[derive(PartialEq, Clone, Debug, Encodable_NoContext, Decodable_NoContext)] enum Enum { Variant1, Variant2(usize, u32), @@ -259,7 +258,7 @@ fn test_tuples() { #[test] fn test_unit_like_struct() { - #[derive(Encodable_Generic, Decodable_Generic, PartialEq, Debug)] + #[derive(Encodable_NoContext, Decodable_NoContext, PartialEq, Debug)] struct UnitLikeStruct; check_round_trip(vec![UnitLikeStruct]); @@ -267,7 +266,7 @@ fn test_unit_like_struct() { #[test] fn test_box() { - #[derive(Encodable_Generic, Decodable_Generic, PartialEq, Debug)] + #[derive(Encodable_NoContext, Decodable_NoContext, PartialEq, Debug)] struct A { foo: Box<[bool]>, } @@ -280,12 +279,12 @@ fn test_box() { fn test_cell() { use std::cell::{Cell, RefCell}; - #[derive(Encodable_Generic, Decodable_Generic, PartialEq, Debug)] + #[derive(Encodable_NoContext, Decodable_NoContext, PartialEq, Debug)] struct A { baz: isize, } - #[derive(Encodable_Generic, Decodable_Generic, PartialEq, Debug)] + #[derive(Encodable_NoContext, Decodable_NoContext, PartialEq, Debug)] struct B { foo: Cell<bool>, bar: RefCell<A>, diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 34755249b60..43b78423c72 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -44,7 +44,7 @@ pub mod sigpipe; pub const PRINT_KINDS: &[(&str, PrintKind)] = &[ // tidy-alphabetical-start - ("all-target-specs-json", PrintKind::AllTargetSpecs), + ("all-target-specs-json", PrintKind::AllTargetSpecsJson), ("calling-conventions", PrintKind::CallingConventions), ("cfg", PrintKind::Cfg), ("check-cfg", PrintKind::CheckCfg), @@ -63,7 +63,7 @@ pub const PRINT_KINDS: &[(&str, PrintKind)] = &[ ("target-features", PrintKind::TargetFeatures), ("target-libdir", PrintKind::TargetLibdir), ("target-list", PrintKind::TargetList), - ("target-spec-json", PrintKind::TargetSpec), + ("target-spec-json", PrintKind::TargetSpecJson), ("tls-models", PrintKind::TlsModels), // tidy-alphabetical-end ]; @@ -873,27 +873,29 @@ pub struct PrintRequest { #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum PrintKind { + // tidy-alphabetical-start + AllTargetSpecsJson, + CallingConventions, + Cfg, + CheckCfg, + CodeModels, + CrateName, + DeploymentTarget, FileNames, HostTuple, + LinkArgs, + NativeStaticLibs, + RelocationModels, + SplitDebuginfo, + StackProtectorStrategies, Sysroot, - TargetLibdir, - CrateName, - Cfg, - CheckCfg, - CallingConventions, - TargetList, TargetCPUs, TargetFeatures, - RelocationModels, - CodeModels, + TargetLibdir, + TargetList, + TargetSpecJson, TlsModels, - TargetSpec, - AllTargetSpecs, - NativeStaticLibs, - StackProtectorStrategies, - LinkArgs, - SplitDebuginfo, - DeploymentTarget, + // tidy-alphabetical-end } #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Default)] @@ -2030,49 +2032,13 @@ fn collect_print_requests( prints.extend(matches.opt_strs("print").into_iter().map(|req| { let (req, out) = split_out_file_name(&req); - let kind = match PRINT_KINDS.iter().find(|&&(name, _)| name == req) { - Some((_, PrintKind::TargetSpec)) => { - if unstable_opts.unstable_options { - PrintKind::TargetSpec - } else { - early_dcx.early_fatal( - "the `-Z unstable-options` flag must also be passed to \ - enable the target-spec-json print option", - ); - } - } - Some((_, PrintKind::AllTargetSpecs)) => { - if unstable_opts.unstable_options { - PrintKind::AllTargetSpecs - } else { - early_dcx.early_fatal( - "the `-Z unstable-options` flag must also be passed to \ - enable the all-target-specs-json print option", - ); - } - } - Some((_, PrintKind::CheckCfg)) => { - if unstable_opts.unstable_options { - PrintKind::CheckCfg - } else { - early_dcx.early_fatal( - "the `-Z unstable-options` flag must also be passed to \ - enable the check-cfg print option", - ); - } - } - Some(&(_, print_kind)) => print_kind, - None => { - let prints = - PRINT_KINDS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>(); - let prints = prints.join(", "); - - let mut diag = - early_dcx.early_struct_fatal(format!("unknown print request: `{req}`")); - #[allow(rustc::diagnostic_outside_of_impl)] - diag.help(format!("valid print requests are: {prints}")); - diag.emit() - } + let kind = if let Some((print_name, print_kind)) = + PRINT_KINDS.iter().find(|&&(name, _)| name == req) + { + check_print_request_stability(early_dcx, unstable_opts, (print_name, *print_kind)); + *print_kind + } else { + emit_unknown_print_request_help(early_dcx, req) }; let out = out.unwrap_or(OutFileName::Stdout); @@ -2091,6 +2057,40 @@ fn collect_print_requests( prints } +fn check_print_request_stability( + early_dcx: &EarlyDiagCtxt, + unstable_opts: &UnstableOptions, + (print_name, print_kind): (&str, PrintKind), +) { + match print_kind { + PrintKind::AllTargetSpecsJson | PrintKind::CheckCfg | PrintKind::TargetSpecJson + if !unstable_opts.unstable_options => + { + early_dcx.early_fatal(format!( + "the `-Z unstable-options` flag must also be passed to enable the `{print_name}` \ + print option" + )); + } + _ => {} + } +} + +fn emit_unknown_print_request_help(early_dcx: &EarlyDiagCtxt, req: &str) -> ! { + let prints = PRINT_KINDS.iter().map(|(name, _)| format!("`{name}`")).collect::<Vec<_>>(); + let prints = prints.join(", "); + + let mut diag = early_dcx.early_struct_fatal(format!("unknown print request: `{req}`")); + #[allow(rustc::diagnostic_outside_of_impl)] + diag.help(format!("valid print requests are: {prints}")); + + if req == "lints" { + diag.help(format!("use `-Whelp` to print a list of lints")); + } + + diag.help(format!("for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information")); + diag.emit() +} + pub fn parse_target_triple(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> TargetTuple { match matches.opt_str("target") { Some(target) if target.ends_with(".json") => { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 804b46a9bec..b3be4b611f0 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -389,7 +389,7 @@ top_level_options!( /// /// This directory is what the virtual `/rustc/$hash` is translated back to, /// if Rust was built with path remapping to `/rustc/$hash` enabled - /// (the `rust.remap-debuginfo` option in `config.toml`). + /// (the `rust.remap-debuginfo` option in `bootstrap.toml`). real_rust_source_base_dir: Option<PathBuf> [TRACKED_NO_CRATE_HASH], edition: Edition [TRACKED], @@ -2525,7 +2525,7 @@ written to standard error output)"), "for every macro invocation, print its name and arguments (default: no)"), track_diagnostics: bool = (false, parse_bool, [UNTRACKED], "tracks where in rustc a diagnostic was emitted"), - // Diagnostics are considered side-effects of a query (see `QuerySideEffects`) and are saved + // Diagnostics are considered side-effects of a query (see `QuerySideEffect`) and are saved // alongside query results and changes to translation options can affect diagnostics - so // translation options should be tracked. translate_additional_ftl: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED], diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml index a11df9a9c9b..b2149a03a8e 100644 --- a/compiler/rustc_smir/Cargo.toml +++ b/compiler/rustc_smir/Cargo.toml @@ -6,7 +6,6 @@ edition = "2024" [dependencies] # tidy-alphabetical-start rustc_abi = { path = "../rustc_abi" } -rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_hir = { path = "../rustc_hir" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 64982b858c6..62027caa353 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -982,6 +982,8 @@ pub struct ExpnData { /// Should debuginfo for the macro be collapsed to the outermost expansion site (in other /// words, was the macro definition annotated with `#[collapse_debuginfo]`)? pub(crate) collapse_debuginfo: bool, + /// When true, we do not display the note telling people to use the `-Zmacro-backtrace` flag. + pub hide_backtrace: bool, } impl !PartialEq for ExpnData {} @@ -1000,6 +1002,7 @@ impl ExpnData { allow_internal_unsafe: bool, local_inner_macros: bool, collapse_debuginfo: bool, + hide_backtrace: bool, ) -> ExpnData { ExpnData { kind, @@ -1014,6 +1017,7 @@ impl ExpnData { allow_internal_unsafe, local_inner_macros, collapse_debuginfo, + hide_backtrace, } } @@ -1038,6 +1042,7 @@ impl ExpnData { allow_internal_unsafe: false, local_inner_macros: false, collapse_debuginfo: false, + hide_backtrace: false, } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8a8bec35d81..210966bed62 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -591,6 +591,7 @@ symbols! { cfg_accessible, cfg_attr, cfg_attr_multi, + cfg_attr_trace: "<cfg_attr>", // must not be a valid identifier cfg_boolean_literals, cfg_contract_checks, cfg_doctest, @@ -1002,7 +1003,6 @@ symbols! { forbid, forget, format, - format_alignment, format_args, format_args_capture, format_args_macro, @@ -1375,6 +1375,7 @@ symbols! { naked, naked_asm, naked_functions, + naked_functions_target_feature, name, names, native_link_modifiers, @@ -1793,6 +1794,7 @@ symbols! { rustc_lint_opt_ty, rustc_lint_query_instability, rustc_lint_untracked_query_information, + rustc_macro_edition_2021, rustc_macro_transparency, rustc_main, rustc_mir, diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml index 90ddf4c8a04..12fe6b719f9 100644 --- a/compiler/rustc_symbol_mangling/Cargo.toml +++ b/compiler/rustc_symbol_mangling/Cargo.toml @@ -9,7 +9,6 @@ punycode = "0.4.0" rustc-demangle = "0.1.21" rustc_abi = { path = "../rustc_abi" } -rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hashes = { path = "../rustc_hashes" } diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index c4558b5ce8b..c9b15151a2c 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -112,6 +112,8 @@ mod v0; pub mod errors; pub mod test; +pub use v0::mangle_internal_symbol; + /// This function computes the symbol name for the given `instance` and the /// given instantiating crate. That is, if you know that instance X is /// instantiated in crate Y, this is the symbol name this instance would have. @@ -183,6 +185,39 @@ fn compute_symbol_name<'tcx>( CodegenFnAttrs::EMPTY }; + if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) { + // Items marked as #[rustc_std_internal_symbol] need to have a fixed + // symbol name because it is used to import items from another crate + // without a direct dependency. As such it is not possible to look up + // the mangled name for the `Instance` from the crate metadata of the + // defining crate. + // Weak lang items automatically get #[rustc_std_internal_symbol] + // applied by the code computing the CodegenFnAttrs. + // We are mangling all #[rustc_std_internal_symbol] items that don't + // also have #[no_mangle] as a combination of the rustc version and the + // unmangled linkage name. This is to ensure that if we link against a + // staticlib compiled by a different rustc version, we don't get symbol + // conflicts or even UB due to a different implementation/ABI. Rust + // staticlibs currently export all symbols, including those that are + // hidden in cdylibs. + // We are using the v0 symbol mangling scheme here as we need to be + // consistent across all crates and in some contexts the legacy symbol + // mangling scheme can't be used. For example both the GCC backend and + // Rust-for-Linux don't support some of the characters used by the + // legacy symbol mangling scheme. + let name = if tcx.is_foreign_item(def_id) { + if let Some(name) = attrs.link_name { name } else { tcx.item_name(def_id) } + } else { + if let Some(name) = attrs.export_name { name } else { tcx.item_name(def_id) } + }; + + if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) { + return name.to_string(); + } else { + return v0::mangle_internal_symbol(tcx, name.as_str()); + } + } + // Foreign items by default use no mangling for their symbol name. There's a // few exceptions to this rule though: // @@ -198,6 +233,8 @@ fn compute_symbol_name<'tcx>( // is present we mangle everything on wasm because the demangled form will // show up in the `wasm-import-name` custom attribute in LLVM IR. // + // * `#[rustc_std_internal_symbol]` mangles the symbol name in a special way + // both for exports and imports through foreign items. This is handled above. // [1]: https://bugs.llvm.org/show_bug.cgi?id=44316 if tcx.is_foreign_item(def_id) && (!tcx.sess.target.is_like_wasm diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index bc3923e4b4d..d824a23279b 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -1,4 +1,5 @@ use std::fmt::Write; +use std::hash::Hasher; use std::iter; use std::ops::Range; @@ -6,6 +7,8 @@ use rustc_abi::{ExternAbi, Integer}; use rustc_data_structures::base_n::ToBaseN; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::intern::Interned; +use rustc_data_structures::stable_hasher::StableHasher; +use rustc_hashes::Hash64; use rustc_hir as hir; use rustc_hir::def::CtorKind; use rustc_hir::def_id::{CrateNum, DefId}; @@ -70,6 +73,54 @@ pub(super) fn mangle<'tcx>( std::mem::take(&mut cx.out) } +pub fn mangle_internal_symbol<'tcx>(tcx: TyCtxt<'tcx>, item_name: &str) -> String { + if item_name == "rust_eh_personality" { + // rust_eh_personality must not be renamed as LLVM hard-codes the name + return "rust_eh_personality".to_owned(); + } else if item_name == "__rust_no_alloc_shim_is_unstable" { + // Temporary back compat hack to give people the chance to migrate to + // include #[rustc_std_internal_symbol]. + return "__rust_no_alloc_shim_is_unstable".to_owned(); + } + + let prefix = "_R"; + let mut cx: SymbolMangler<'_> = SymbolMangler { + tcx, + start_offset: prefix.len(), + paths: FxHashMap::default(), + types: FxHashMap::default(), + consts: FxHashMap::default(), + binders: vec![], + out: String::from(prefix), + }; + + cx.path_append_ns( + |cx| { + cx.push("C"); + cx.push_disambiguator({ + let mut hasher = StableHasher::new(); + // Incorporate the rustc version to ensure #[rustc_std_internal_symbol] functions + // get a different symbol name depending on the rustc version. + // + // RUSTC_FORCE_RUSTC_VERSION is ignored here as otherwise different we would get an + // abi incompatibility with the standard library. + hasher.write(tcx.sess.cfg_version.as_bytes()); + + let hash: Hash64 = hasher.finish(); + hash.as_u64() + }); + cx.push_ident("__rustc"); + Ok(()) + }, + 'v', + 0, + item_name, + ) + .unwrap(); + + std::mem::take(&mut cx.out) +} + pub(super) fn mangle_typeid_for_trait_ref<'tcx>( tcx: TyCtxt<'tcx>, trait_ref: ty::ExistentialTraitRef<'tcx>, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 1887134c575..263646d8347 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -3342,7 +3342,10 @@ impl Target { ); } "arm" => { - check!(self.llvm_floatabi.is_some(), "ARM targets must specify their float ABI",) + check!( + self.llvm_floatabi.is_some(), + "ARM targets must set `llvm-floatabi` to `hard` or `soft`", + ) } _ => {} } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_cygwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_cygwin.rs index 8da4fe6b8b1..eac4caf41c8 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_cygwin.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_cygwin.rs @@ -18,7 +18,7 @@ pub(crate) fn target() -> Target { description: Some("64-bit x86 Cygwin".into()), tier: Some(3), host_tools: Some(false), - std: None, + std: Some(true), }, } } diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 6d3b6608ea2..a96caf227f7 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -603,13 +603,18 @@ static CSKY_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ static LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("d", Unstable(sym::loongarch_target_feature), &["f"]), + ("div32", Unstable(sym::loongarch_target_feature), &[]), ("f", Unstable(sym::loongarch_target_feature), &[]), ("frecipe", Unstable(sym::loongarch_target_feature), &[]), + ("lam-bh", Unstable(sym::loongarch_target_feature), &[]), + ("lamcas", Unstable(sym::loongarch_target_feature), &[]), ("lasx", Unstable(sym::loongarch_target_feature), &["lsx"]), ("lbt", Unstable(sym::loongarch_target_feature), &[]), + ("ld-seq-sa", Unstable(sym::loongarch_target_feature), &[]), ("lsx", Unstable(sym::loongarch_target_feature), &["d"]), ("lvz", Unstable(sym::loongarch_target_feature), &[]), ("relax", Unstable(sym::loongarch_target_feature), &[]), + ("scq", Unstable(sym::loongarch_target_feature), &[]), ("ual", Unstable(sym::loongarch_target_feature), &[]), // tidy-alphabetical-end ]; @@ -918,6 +923,28 @@ impl Target { _ => unreachable!(), } } + "loongarch64" => { + // LoongArch handles ABI in a very sane way, being fully explicit via `llvm_abiname` + // about what the intended ABI is. + match &*self.llvm_abiname { + "ilp32d" | "lp64d" => { + // Requires d (which implies f), incompatible with nothing. + FeatureConstraints { required: &["d"], incompatible: &[] } + } + "ilp32f" | "lp64f" => { + // Requires f, incompatible with nothing. + FeatureConstraints { required: &["f"], incompatible: &[] } + } + "ilp32s" | "lp64s" => { + // The soft-float ABI does not require any features and is also not + // incompatible with any features. Rust targets explicitly specify the + // LLVM ABI names, which allows for enabling hard-float support even on + // soft-float targets, and ensures that the ABI behavior is as expected. + NOTHING + } + _ => unreachable!(), + } + } _ => NOTHING, } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index baf2489b2b8..40f8af1f691 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -1466,7 +1466,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypesVisitor<'tcx> { + impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypesVisitor<'tcx> { fn visit_ty(&mut self, t: Ty<'tcx>) { if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) { let span = self.tcx.def_span(def_id); @@ -2026,7 +2026,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } LetVisitor { span }.visit_body(body).break_value() } - hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _, _), .. }) => { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(_, ty, _, _), .. }) => { Some(&ty.peel_refs().kind) } _ => None, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index 40958ec1088..0bcb5f6f3b2 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -18,7 +18,7 @@ use rustc_middle::ty::{ TypeFoldable, TypeFolder, TypeSuperFoldable, TypeckResults, }; use rustc_span::{BytePos, DUMMY_SP, FileName, Ident, Span, sym}; -use rustc_type_ir::visit::TypeVisitableExt; +use rustc_type_ir::TypeVisitableExt; use tracing::{debug, instrument, warn}; use super::nice_region_error::placeholder_error::Highlighted; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs index 5a303c3cd03..139b2997136 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs @@ -77,7 +77,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { match arg.kind { hir::TyKind::BareFn(_) => { self.current_index.shift_in(1); - intravisit::walk_ty(self, arg); + let _ = intravisit::walk_ty(self, arg); self.current_index.shift_out(1); return ControlFlow::Continue(()); } @@ -85,7 +85,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { hir::TyKind::TraitObject(bounds, ..) => { for bound in bounds { self.current_index.shift_in(1); - self.visit_poly_trait_ref(bound); + let _ = self.visit_poly_trait_ref(bound); self.current_index.shift_out(1); } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs index cc2ab1c3432..74205922851 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs @@ -71,7 +71,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } } - impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for HighlightBuilder<'tcx> { + impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for HighlightBuilder<'tcx> { fn visit_region(&mut self, r: ty::Region<'tcx>) { if !r.has_name() && self.counter <= 3 { self.highlight.highlighting_region(r, self.counter); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs index 245764c94ab..00f053fa599 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs @@ -3,8 +3,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_middle::ty::fold::fold_regions; -use rustc_middle::ty::{self, Binder, Region, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, Binder, Region, Ty, TyCtxt, TypeFoldable, fold_regions}; use rustc_span::Span; use tracing::instrument; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index d673e5672a0..59c93db9c8f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -338,7 +338,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .. }, hir::PathSegment { - ident: assoc_item_name, + ident: assoc_item_ident, res: Res::Def(_, item_id), .. }, @@ -368,17 +368,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some(local_def_id) = data.trait_ref.def_id.as_local() && let hir::Node::Item(hir::Item { - ident: trait_name, - kind: hir::ItemKind::Trait(_, _, _, _, trait_item_refs), + kind: hir::ItemKind::Trait(_, _, trait_ident, _, _, trait_item_refs), .. }) = self.tcx.hir_node_by_def_id(local_def_id) && let Some(method_ref) = trait_item_refs .iter() - .find(|item_ref| item_ref.ident == *assoc_item_name) + .find(|item_ref| item_ref.ident == *assoc_item_ident) { err.span_label( method_ref.span, - format!("`{trait_name}::{assoc_item_name}` defined here"), + format!("`{trait_ident}::{assoc_item_ident}` defined here"), ); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index e2bdd52ba7c..07a67cde3be 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -18,12 +18,14 @@ use rustc_middle::traits::SignatureMismatchData; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::print::{ PrintPolyTraitPredicateExt, PrintTraitPredicateExt as _, PrintTraitRefExt as _, with_forced_trimmed_paths, }; -use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast}; +use rustc_middle::ty::{ + self, TraitRef, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, + Upcast, +}; use rustc_middle::{bug, span_bug}; use rustc_span::{BytePos, DUMMY_SP, STDLIB_STABLE_CRATES, Span, Symbol, sym}; use tracing::{debug, instrument}; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index 4d87a93be0c..98df09b6f7b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -419,7 +419,12 @@ pub fn report_dyn_incompatibility<'tcx>( ) -> Diag<'tcx> { let trait_str = tcx.def_path_str(trait_def_id); let trait_span = tcx.hir_get_if_local(trait_def_id).and_then(|node| match node { - hir::Node::Item(item) => Some(item.ident.span), + hir::Node::Item(item) => match item.kind { + hir::ItemKind::Trait(_, _, ident, ..) | hir::ItemKind::TraitAlias(ident, _, _) => { + Some(ident.span) + } + _ => unreachable!(), + }, _ => None, }); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index dce85b43df1..dc8022b95c3 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -267,8 +267,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let node = self.tcx.hir_node_by_def_id(body_id); match node { hir::Node::Item(hir::Item { - ident, - kind: hir::ItemKind::Trait(_, _, generics, bounds, _), + kind: hir::ItemKind::Trait(_, _, ident, generics, bounds, _), .. }) if self_ty == self.tcx.types.self_param => { assert!(param_ty); @@ -282,7 +281,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { None, projection, trait_pred, - Some((ident, bounds)), + Some((&ident, bounds)), ); return; } @@ -331,7 +330,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } hir::Node::Item(hir::Item { kind: - hir::ItemKind::Trait(_, _, generics, ..) + hir::ItemKind::Trait(_, _, _, generics, ..) | hir::ItemKind::Impl(hir::Impl { generics, .. }), .. }) if projection.is_some() => { @@ -352,15 +351,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { hir::Node::Item(hir::Item { kind: - hir::ItemKind::Struct(_, generics) - | hir::ItemKind::Enum(_, generics) - | hir::ItemKind::Union(_, generics) - | hir::ItemKind::Trait(_, _, generics, ..) + hir::ItemKind::Struct(_, _, generics) + | hir::ItemKind::Enum(_, _, generics) + | hir::ItemKind::Union(_, _, generics) + | hir::ItemKind::Trait(_, _, _, generics, ..) | hir::ItemKind::Impl(hir::Impl { generics, .. }) | hir::ItemKind::Fn { generics, .. } - | hir::ItemKind::TyAlias(_, generics) - | hir::ItemKind::Const(_, generics, _) - | hir::ItemKind::TraitAlias(generics, _), + | hir::ItemKind::TyAlias(_, _, generics) + | hir::ItemKind::Const(_, _, generics, _) + | hir::ItemKind::TraitAlias(_, generics, _), .. }) | hir::Node::TraitItem(hir::TraitItem { generics, .. }) @@ -390,13 +389,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some((name, term)) = associated_ty { // FIXME: this case overlaps with code in TyCtxt::note_and_explain_type_err. // That should be extracted into a helper function. - if constraint.ends_with('>') { - constraint = format!( - "{}, {} = {}>", - &constraint[..constraint.len() - 1], - name, - term - ); + if let Some(stripped) = constraint.strip_suffix('>') { + constraint = format!("{stripped}, {name} = {term}>"); } else { constraint.push_str(&format!("<{name} = {term}>")); } @@ -417,15 +411,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { hir::Node::Item(hir::Item { kind: - hir::ItemKind::Struct(_, generics) - | hir::ItemKind::Enum(_, generics) - | hir::ItemKind::Union(_, generics) - | hir::ItemKind::Trait(_, _, generics, ..) + hir::ItemKind::Struct(_, _, generics) + | hir::ItemKind::Enum(_, _, generics) + | hir::ItemKind::Union(_, _, generics) + | hir::ItemKind::Trait(_, _, _, generics, ..) | hir::ItemKind::Impl(hir::Impl { generics, .. }) | hir::ItemKind::Fn { generics, .. } - | hir::ItemKind::TyAlias(_, generics) - | hir::ItemKind::Const(_, generics, _) - | hir::ItemKind::TraitAlias(generics, _), + | hir::ItemKind::TyAlias(_, _, generics) + | hir::ItemKind::Const(_, _, generics, _) + | hir::ItemKind::TraitAlias(_, generics, _), .. }) if !param_ty => { // Missing generic type parameter bound. @@ -847,7 +841,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { name.to_string() } Some(hir::Node::Item(hir::Item { - ident, kind: hir::ItemKind::Fn { .. }, .. + kind: hir::ItemKind::Fn { ident, .. }, .. })) => { err.span_label(ident.span, "consider calling this function"); ident.to_string() @@ -1593,20 +1587,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some(typeck_results) = &self.typeck_results && let ty = typeck_results.expr_ty_adjusted(base) && let ty::FnDef(def_id, _args) = ty.kind() - && let Some(hir::Node::Item(hir::Item { ident, span, vis_span, .. })) = - self.tcx.hir_get_if_local(*def_id) + && let Some(hir::Node::Item(item)) = self.tcx.hir_get_if_local(*def_id) { + let (ident, _, _, _) = item.expect_fn(); let msg = format!("alternatively, consider making `fn {ident}` asynchronous"); - if vis_span.is_empty() { + if item.vis_span.is_empty() { err.span_suggestion_verbose( - span.shrink_to_lo(), + item.span.shrink_to_lo(), msg, "async ", Applicability::MaybeIncorrect, ); } else { err.span_suggestion_verbose( - vis_span.shrink_to_hi(), + item.vis_span.shrink_to_hi(), msg, " async", Applicability::MaybeIncorrect, @@ -1998,10 +1992,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .iter() .enumerate() .map(|(i, ident)| { - if ident.name.is_empty() || ident.name == kw::SelfLower { - format!("arg{i}") - } else { + if let Some(ident) = ident + && !matches!(ident, Ident { name: kw::Underscore | kw::SelfLower, .. }) + { format!("{ident}") + } else { + format!("arg{i}") } }) .collect(); @@ -3305,8 +3301,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut is_auto_trait = false; match tcx.hir_get_if_local(data.impl_or_alias_def_id) { Some(Node::Item(hir::Item { - kind: hir::ItemKind::Trait(is_auto, ..), - ident, + kind: hir::ItemKind::Trait(is_auto, _, ident, ..), .. })) => { // FIXME: we should do something else so that it works even on crate foreign diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index fe859eb53cd..7159397c4b1 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -516,7 +516,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { match self.tcx.parent_hir_node(self.tcx.local_def_id_to_hir_id(anon_reg.scope)) { hir::Node::Item(hir::Item { - kind: hir::ItemKind::Trait(_, _, generics, ..), + kind: hir::ItemKind::Trait(_, _, _, generics, ..), .. }) | hir::Node::Item(hir::Item { diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 5cf0600ade8..84ac229b743 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -15,7 +15,7 @@ use tracing::instrument; use crate::infer::at::ToTrace; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; -use crate::traits::{self, Obligation, ObligationCause, ObligationCtxt, SelectionContext}; +use crate::traits::{self, Obligation, ObligationCause, ObligationCtxt}; #[extension(pub trait InferCtxtExt<'tcx>)] impl<'tcx> InferCtxt<'tcx> { @@ -122,9 +122,6 @@ impl<'tcx> InferCtxt<'tcx> { /// - If this returns `Some([errors..])`, then the trait has an impl for /// the self type, but some nested obligations do not hold. /// - If this returns `None`, no implementation that applies could be found. - /// - /// FIXME(-Znext-solver): Due to the recursive nature of the new solver, - /// this will probably only ever return `Some([])` or `None`. fn type_implements_trait_shallow( &self, trait_def_id: DefId, @@ -132,20 +129,29 @@ impl<'tcx> InferCtxt<'tcx> { param_env: ty::ParamEnv<'tcx>, ) -> Option<Vec<traits::FulfillmentError<'tcx>>> { self.probe(|_snapshot| { - let mut selcx = SelectionContext::new(self); - match selcx.select(&Obligation::new( + let ocx = ObligationCtxt::new_with_diagnostics(self); + ocx.register_obligation(Obligation::new( self.tcx, ObligationCause::dummy(), param_env, ty::TraitRef::new(self.tcx, trait_def_id, [ty]), - )) { - Ok(Some(selection)) => { - let ocx = ObligationCtxt::new_with_diagnostics(self); - ocx.register_obligations(selection.nested_obligations()); - Some(ocx.select_all_or_error()) + )); + let errors = ocx.select_where_possible(); + // Find the original predicate in the list of predicates that could definitely not be fulfilled. + // If it is in that list, then we know this doesn't even shallowly implement the trait. + // If it is not in that list, it was fulfilled, but there may be nested obligations, which we don't care about here. + for error in &errors { + let Some(trait_clause) = error.obligation.predicate.as_trait_clause() else { + continue; + }; + let Some(bound_ty) = trait_clause.self_ty().no_bound_vars() else { continue }; + if trait_clause.def_id() == trait_def_id + && ocx.eq(&ObligationCause::dummy(), param_env, bound_ty, ty).is_ok() + { + return None; } - Ok(None) | Err(_) => None, } + Some(errors) }) } } diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index e69bad095e3..af5a60027ba 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -8,8 +8,7 @@ use rustc_infer::infer::canonical::{ }; use rustc_infer::infer::{InferCtxt, RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::solve::Goal; -use rustc_middle::ty::fold::TypeFoldable; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt as _}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use rustc_type_ir::TypingMode; use rustc_type_ir::solve::{Certainty, NoSolution}; diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 4b1bc316d5f..48a05ad29fb 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -15,8 +15,7 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_macros::extension; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::solve::{Certainty, Goal, GoalSource, NoSolution, QueryResult}; -use rustc_middle::ty::visit::{VisitorResult, try_visit}; -use rustc_middle::ty::{TyCtxt, TypeFoldable}; +use rustc_middle::ty::{TyCtxt, TypeFoldable, VisitorResult, try_visit}; use rustc_middle::{bug, ty}; use rustc_next_trait_solver::resolve::EagerResolver; use rustc_next_trait_solver::solve::inspect::{self, instantiate_canonical_state}; diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 3b40882ef57..4c7172c3278 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -17,8 +17,9 @@ use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal}; use rustc_middle::traits::specialization_graph::OverlapMode; use rustc_middle::ty::fast_reject::DeepRejectCtxt; -use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode}; +use rustc_middle::ty::{ + self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, +}; pub use rustc_next_trait_solver::coherence::*; use rustc_next_trait_solver::solve::SolverDelegateEvalExt; use rustc_span::{DUMMY_SP, Span, sym}; diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 3fceada2510..78a45243983 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -9,7 +9,6 @@ use std::ops::ControlFlow; use rustc_errors::FatalError; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_middle::bug; use rustc_middle::query::Providers; use rustc_middle::ty::{ self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, @@ -807,31 +806,8 @@ fn contains_illegal_impl_trait_in_trait<'tcx>( let ty = tcx.liberate_late_bound_regions(fn_def_id, ty); if tcx.asyncness(fn_def_id).is_async() { - // FIXME(async_fn_in_dyn_trait): Think of a better way to unify these code paths - // to issue an appropriate feature suggestion when users try to use AFIDT. - // Obviously we must only do this once AFIDT is finished enough to actually be usable. - if tcx.features().async_fn_in_dyn_trait() { - let ty::Alias(ty::Projection, proj) = *ty.kind() else { - bug!("expected async fn in trait to return an RPITIT"); - }; - assert!(tcx.is_impl_trait_in_trait(proj.def_id)); - - // FIXME(async_fn_in_dyn_trait): We should check that this bound is legal too, - // and stop relying on `async fn` in the definition. - for bound in tcx.item_bounds(proj.def_id).instantiate(tcx, proj.args) { - if let Some(violation) = bound - .visit_with(&mut IllegalRpititVisitor { tcx, allowed: Some(proj) }) - .break_value() - { - return Some(violation); - } - } - - None - } else { - // Rendering the error as a separate `async-specific` message is better. - Some(MethodViolationCode::AsyncFn) - } + // Rendering the error as a separate `async-specific` message is better. + Some(MethodViolationCode::AsyncFn) } else { ty.visit_with(&mut IllegalRpititVisitor { tcx, allowed: None }).break_value() } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 105cb917571..de337710b5e 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -32,11 +32,9 @@ pub use rustc_infer::traits::*; use rustc_middle::query::Providers; use rustc_middle::span_bug; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::fold::TypeFoldable; -use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::{ - self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, - TypeSuperVisitable, TypingMode, Upcast, + self, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypingMode, Upcast, }; use rustc_span::def_id::DefId; use rustc_span::{DUMMY_SP, Span}; diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 4d9cf6620d6..6057b66c483 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -7,19 +7,17 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::DefKind; use rustc_hir::lang_items::LangItem; +use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::infer::resolve::OpportunisticRegionResolver; -use rustc_infer::infer::{DefineOpaqueTypes, RegionVariableOrigin}; use rustc_infer::traits::{ObligationCauseCode, PredicateObligations}; use rustc_middle::traits::select::OverflowError; use rustc_middle::traits::{BuiltinImplSource, ImplSource, ImplSourceUserDefinedData}; use rustc_middle::ty::fast_reject::DeepRejectCtxt; -use rustc_middle::ty::fold::TypeFoldable; -use rustc_middle::ty::visit::TypeVisitableExt; -use rustc_middle::ty::{self, Term, Ty, TyCtxt, TypingMode, Upcast}; +use rustc_middle::ty::{ + self, Term, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, TypingMode, Upcast, +}; use rustc_middle::{bug, span_bug}; use rustc_span::sym; -use rustc_type_ir::elaborate; -use thin_vec::thin_vec; use tracing::{debug, instrument}; use super::{ @@ -63,9 +61,6 @@ enum ProjectionCandidate<'tcx> { /// Bounds specified on an object type Object(ty::PolyProjectionPredicate<'tcx>), - /// Built-in bound for a dyn async fn in trait - ObjectRpitit, - /// From an "impl" (or a "pseudo-impl" returned by select) Select(Selection<'tcx>), } @@ -743,7 +738,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( ) { debug!("assemble_candidates_from_trait_def(..)"); let mut ambiguous = false; - selcx.for_each_item_bound( + let _ = selcx.for_each_item_bound( obligation.predicate.self_ty(), |selcx, clause, _| { let Some(clause) = clause.as_projection_clause() else { @@ -832,16 +827,6 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>( env_predicates, false, ); - - // `dyn Trait` automagically project their AFITs to `dyn* Future`. - if tcx.is_impl_trait_in_trait(obligation.predicate.def_id) - && let Some(out_trait_def_id) = data.principal_def_id() - && let rpitit_trait_def_id = tcx.parent(obligation.predicate.def_id) - && elaborate::supertrait_def_ids(tcx, out_trait_def_id) - .any(|trait_def_id| trait_def_id == rpitit_trait_def_id) - { - candidate_set.push_candidate(ProjectionCandidate::ObjectRpitit); - } } #[instrument( @@ -1273,8 +1258,6 @@ fn confirm_candidate<'cx, 'tcx>( ProjectionCandidate::Select(impl_source) => { confirm_select_candidate(selcx, obligation, impl_source) } - - ProjectionCandidate::ObjectRpitit => confirm_object_rpitit_candidate(selcx, obligation), }; // When checking for cycle during evaluation, we compare predicates with @@ -2070,45 +2053,6 @@ fn confirm_impl_candidate<'cx, 'tcx>( } } -fn confirm_object_rpitit_candidate<'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, - obligation: &ProjectionTermObligation<'tcx>, -) -> Progress<'tcx> { - let tcx = selcx.tcx(); - let mut obligations = thin_vec![]; - - // Compute an intersection lifetime for all the input components of this GAT. - let intersection = - selcx.infcx.next_region_var(RegionVariableOrigin::MiscVariable(obligation.cause.span)); - for component in obligation.predicate.args { - match component.unpack() { - ty::GenericArgKind::Lifetime(lt) => { - obligations.push(obligation.with(tcx, ty::OutlivesPredicate(lt, intersection))); - } - ty::GenericArgKind::Type(ty) => { - obligations.push(obligation.with(tcx, ty::OutlivesPredicate(ty, intersection))); - } - ty::GenericArgKind::Const(_ct) => { - // Consts have no outlives... - } - } - } - - Progress { - term: Ty::new_dynamic( - tcx, - tcx.item_bounds_to_existential_predicates( - obligation.predicate.def_id, - obligation.predicate.args, - ), - intersection, - ty::DynStar, - ) - .into(), - obligations, - } -} - // Get obligations corresponding to the predicates from the where-clause of the // associated type itself. fn assoc_ty_own_obligations<'cx, 'tcx>( diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 6bf76eaee5c..165c63f3745 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -7,9 +7,10 @@ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_infer::traits::PredicateObligations; use rustc_macros::extension; pub use rustc_middle::traits::query::NormalizationResult; -use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; -use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt}; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor, TypingMode}; +use rustc_middle::ty::{ + self, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, + TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, +}; use rustc_span::DUMMY_SP; use tracing::{debug, info, instrument}; diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs index 68feb19c55b..4bdf04311a0 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs @@ -3,8 +3,7 @@ use std::fmt; use rustc_errors::ErrorGuaranteed; use rustc_infer::traits::PredicateObligations; use rustc_middle::traits::query::NoSolution; -use rustc_middle::ty::fold::TypeFoldable; -use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; +use rustc_middle::ty::{ParamEnvAnd, TyCtxt, TypeFoldable}; use rustc_span::Span; use crate::infer::canonical::{ diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs index 2f6bbd7f4cf..f2a6ce855b4 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs @@ -3,8 +3,7 @@ use std::fmt; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::query::NoSolution; pub use rustc_middle::traits::query::type_op::{DeeplyNormalize, Normalize}; -use rustc_middle::ty::fold::TypeFoldable; -use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_span::Span; use crate::infer::canonical::{CanonicalQueryInput, CanonicalQueryResponse}; diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index a8d8003ead6..fc352499146 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -176,7 +176,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // normalization, so try to deduplicate when possible to avoid // unnecessary ambiguity. let mut distinct_normalized_bounds = FxHashSet::default(); - self.for_each_item_bound::<!>( + let _ = self.for_each_item_bound::<!>( placeholder_trait_predicate.self_ty(), |selcx, bound, idx| { let Some(bound) = bound.as_trait_clause() else { diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 4cd6781ab89..4404324d5cd 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -616,12 +616,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { for assoc_type in assoc_types { let defs: &ty::Generics = tcx.generics_of(assoc_type); - // When `async_fn_in_dyn_trait` is enabled, we don't need to check the - // RPITIT for compatibility, since it's not provided by the user. - if tcx.features().async_fn_in_dyn_trait() && tcx.is_impl_trait_in_trait(assoc_type) { - continue; - } - if !defs.own_params.is_empty() { tcx.dcx().span_delayed_bug( obligation.cause.span, diff --git a/compiler/rustc_transmute/src/layout/dfa.rs b/compiler/rustc_transmute/src/layout/dfa.rs index a29baade42f..af568171f91 100644 --- a/compiler/rustc_transmute/src/layout/dfa.rs +++ b/compiler/rustc_transmute/src/layout/dfa.rs @@ -55,6 +55,7 @@ where #[derive(Hash, Eq, PartialEq, PartialOrd, Ord, Copy, Clone)] pub(crate) struct State(u32); +#[cfg(test)] #[derive(Hash, Eq, PartialEq, Clone, Copy)] pub(crate) enum Transition<R> where @@ -70,6 +71,7 @@ impl fmt::Debug for State { } } +#[cfg(test)] impl<R> fmt::Debug for Transition<R> where R: Ref, @@ -166,6 +168,7 @@ impl State { } } +#[cfg(test)] impl<R> From<nfa::Transition<R>> for Transition<R> where R: Ref, diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml index 7e96b64408c..ce08b300cc8 100644 --- a/compiler/rustc_ty_utils/Cargo.toml +++ b/compiler/rustc_ty_utils/Cargo.toml @@ -7,7 +7,6 @@ edition = "2024" # tidy-alphabetical-start itertools = "0.12" rustc_abi = { path = "../rustc_abi" } -rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } @@ -21,6 +20,5 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_trait_selection = { path = "../rustc_trait_selection" } -rustc_type_ir = { path = "../rustc_type_ir" } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index a726ebae6fe..48d5a4a0fcb 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -55,31 +55,6 @@ fn fn_sig_for_fn_abi<'tcx>( sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output); } - // Modify `fn() -> impl Future` to `fn() -> dyn* Future`. - if let ty::InstanceKind::ReifyShim(def_id, _) = instance.def - && let Some((rpitit_def_id, fn_args)) = - tcx.return_position_impl_trait_in_trait_shim_data(def_id) - { - let fn_args = fn_args.instantiate(tcx, args); - let rpitit_args = - fn_args.extend_to(tcx, rpitit_def_id, |param, _| match param.kind { - ty::GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), - ty::GenericParamDefKind::Type { .. } - | ty::GenericParamDefKind::Const { .. } => { - unreachable!("rpitit should have no addition ty/ct") - } - }); - let dyn_star_ty = Ty::new_dynamic( - tcx, - tcx.item_bounds_to_existential_predicates(rpitit_def_id, rpitit_args), - tcx.lifetimes.re_erased, - ty::DynStar, - ); - let mut inputs_and_output = sig.inputs_and_output.to_vec(); - *inputs_and_output.last_mut().unwrap() = dyn_star_ty; - sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output); - } - sig } ty::Closure(def_id, args) => { diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index aeaa83c77b5..088d5e76b86 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -6,8 +6,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_middle::bug; use rustc_middle::query::Providers; -use rustc_middle::ty::fold::fold_regions; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt, fold_regions}; use rustc_span::Span; pub(crate) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 90b3517eded..962e1353ebc 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -7,11 +7,10 @@ use rustc_middle::query::Providers; use rustc_middle::traits::{BuiltinImplSource, CodegenObligationError}; use rustc_middle::ty::util::AsyncDropGlueMorphology; use rustc_middle::ty::{ - self, GenericArgsRef, Instance, PseudoCanonicalInput, TyCtxt, TypeVisitableExt, + self, ClosureKind, GenericArgsRef, Instance, PseudoCanonicalInput, TyCtxt, TypeVisitableExt, }; use rustc_span::sym; use rustc_trait_selection::traits; -use rustc_type_ir::ClosureKind; use tracing::debug; use traits::translate_args; diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index d6f9277813d..5bb96f90029 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -4,10 +4,8 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_middle::span_bug; -use rustc_middle::ty::visit::{VisitorResult, try_visit}; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt, TypeVisitable, VisitorResult, try_visit}; use rustc_span::Span; -use rustc_type_ir::visit::TypeVisitable; use tracing::{instrument, trace}; pub trait SpannedTypeVisitor<'tcx> { diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index bb61f4bee66..9dc4f11e456 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -5,8 +5,9 @@ use rustc_hir::def::DefKind; use rustc_index::bit_set::DenseBitSet; use rustc_middle::bug; use rustc_middle::query::Providers; -use rustc_middle::ty::fold::fold_regions; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast}; +use rustc_middle::ty::{ + self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Upcast, fold_regions, +}; use rustc_span::DUMMY_SP; use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_trait_selection::traits; @@ -14,49 +15,49 @@ use tracing::instrument; #[instrument(level = "debug", skip(tcx), ret)] fn sized_constraint_for_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> { - use rustc_type_ir::TyKind::*; - match ty.kind() { // these are always sized - Bool - | Char - | Int(..) - | Uint(..) - | Float(..) - | RawPtr(..) - | Ref(..) - | FnDef(..) - | FnPtr(..) - | Array(..) - | Closure(..) - | CoroutineClosure(..) - | Coroutine(..) - | CoroutineWitness(..) - | Never - | Dynamic(_, _, ty::DynStar) => None, + ty::Bool + | ty::Char + | ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::RawPtr(..) + | ty::Ref(..) + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::Array(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) + | ty::CoroutineWitness(..) + | ty::Never + | ty::Dynamic(_, _, ty::DynStar) => None, // these are never sized - Str | Slice(..) | Dynamic(_, _, ty::Dyn) | Foreign(..) => Some(ty), + ty::Str | ty::Slice(..) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => Some(ty), - Pat(ty, _) => sized_constraint_for_ty(tcx, *ty), + ty::Pat(ty, _) => sized_constraint_for_ty(tcx, *ty), - Tuple(tys) => tys.last().and_then(|&ty| sized_constraint_for_ty(tcx, ty)), + ty::Tuple(tys) => tys.last().and_then(|&ty| sized_constraint_for_ty(tcx, ty)), // recursive case - Adt(adt, args) => adt.sized_constraint(tcx).and_then(|intermediate| { + ty::Adt(adt, args) => adt.sized_constraint(tcx).and_then(|intermediate| { let ty = intermediate.instantiate(tcx, args); sized_constraint_for_ty(tcx, ty) }), // these can be sized or unsized. - Param(..) | Alias(..) | Error(_) => Some(ty), + ty::Param(..) | ty::Alias(..) | ty::Error(_) => Some(ty), // We cannot instantiate the binder, so just return the *original* type back, // but only if the inner type has a sized constraint. Thus we skip the binder, // but don't actually use the result from `sized_constraint_for_ty`. - UnsafeBinder(inner_ty) => sized_constraint_for_ty(tcx, inner_ty.skip_binder()).map(|_| ty), + ty::UnsafeBinder(inner_ty) => { + sized_constraint_for_ty(tcx, inner_ty.skip_binder()).map(|_| ty) + } - Placeholder(..) | Bound(..) | Infer(..) => { + ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) => { bug!("unexpected type `{ty:?}` in sized_constraint_for_ty") } } diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index 0d0092ea1aa..e9055940310 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -5,7 +5,7 @@ use std::ops::{ControlFlow, Deref}; use derive_where::derive_where; #[cfg(feature = "nightly")] -use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use tracing::instrument; use crate::data_structures::SsoHashSet; @@ -57,7 +57,7 @@ where macro_rules! impl_binder_encode_decode { ($($t:ty),+ $(,)?) => { $( - impl<I: Interner, E: crate::TyEncoder<I = I>> rustc_serialize::Encodable<E> for ty::Binder<I, $t> + impl<I: Interner, E: rustc_serialize::Encoder> rustc_serialize::Encodable<E> for ty::Binder<I, $t> where $t: rustc_serialize::Encodable<E>, I::BoundVarKinds: rustc_serialize::Encodable<E>, @@ -67,7 +67,7 @@ macro_rules! impl_binder_encode_decode { self.as_ref().skip_binder().encode(e); } } - impl<I: Interner, D: crate::TyDecoder<I = I>> rustc_serialize::Decodable<D> for ty::Binder<I, $t> + impl<I: Interner, D: rustc_serialize::Decoder> rustc_serialize::Decodable<D> for ty::Binder<I, $t> where $t: TypeVisitable<I> + rustc_serialize::Decodable<D>, I::BoundVarKinds: rustc_serialize::Decodable<D>, @@ -112,7 +112,7 @@ where pub fn bind_with_vars(value: T, bound_vars: I::BoundVarKinds) -> Binder<I, T> { if cfg!(debug_assertions) { let mut validator = ValidateBoundVars::new(bound_vars); - value.visit_with(&mut validator); + let _ = value.visit_with(&mut validator); } Binder { value, bound_vars } } @@ -196,7 +196,7 @@ impl<I: Interner, T> Binder<I, T> { let value = f(value); if cfg!(debug_assertions) { let mut validator = ValidateBoundVars::new(bound_vars); - value.visit_with(&mut validator); + let _ = value.visit_with(&mut validator); } Binder { value, bound_vars } } @@ -209,7 +209,7 @@ impl<I: Interner, T> Binder<I, T> { let value = f(value)?; if cfg!(debug_assertions) { let mut validator = ValidateBoundVars::new(bound_vars); - value.visit_with(&mut validator); + let _ = value.visit_with(&mut validator); } Ok(Binder { value, bound_vars }) } @@ -342,7 +342,10 @@ impl<I: Interner> TypeVisitor<I> for ValidateBoundVars<I> { #[derive_where(PartialOrd; I: Interner, T: Ord)] #[derive_where(Hash; I: Interner, T: Hash)] #[derive_where(Debug; I: Interner, T: Debug)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub struct EarlyBinder<I: Interner, T> { value: T, #[derive_where(skip(Debug))] @@ -859,7 +862,7 @@ impl<'a, I: Interner> ArgFolder<'a, I> { if self.binders_passed == 0 || !val.has_escaping_bound_vars() { val } else { - ty::fold::shift_vars(self.cx, val, self.binders_passed) + ty::shift_vars(self.cx, val, self.binders_passed) } } @@ -867,7 +870,7 @@ impl<'a, I: Interner> ArgFolder<'a, I> { if self.binders_passed == 0 || !region.has_escaping_bound_vars() { region } else { - ty::fold::shift_region(self.cx, region, self.binders_passed) + ty::shift_region(self.cx, region, self.binders_passed) } } } diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index 24b2ebc1fbe..03d3194f106 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -4,7 +4,7 @@ use std::ops::Index; use derive_where::derive_where; #[cfg(feature = "nightly")] -use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use crate::inherent::*; @@ -16,7 +16,10 @@ use crate::{self as ty, Interner, TypingMode, UniverseIndex}; #[derive_where(Eq; I: Interner, V: Eq)] #[derive_where(Debug; I: Interner, V: fmt::Debug)] #[derive_where(Copy; I: Interner, V: Copy)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub struct CanonicalQueryInput<I: Interner, V> { pub canonical: Canonical<I, V>, pub typing_mode: TypingMode<I>, @@ -32,7 +35,10 @@ pub struct CanonicalQueryInput<I: Interner, V> { #[derive_where(Debug; I: Interner, V: fmt::Debug)] #[derive_where(Copy; I: Interner, V: Copy)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub struct Canonical<I: Interner, V> { pub value: V, pub max_universe: UniverseIndex, @@ -85,7 +91,10 @@ impl<I: Interner, V: fmt::Display> fmt::Display for Canonical<I, V> { /// with fresh inference variables replacing the canonical values. #[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub struct CanonicalVarInfo<I: Interner> { pub kind: CanonicalVarKind<I>, } @@ -139,7 +148,10 @@ impl<I: Interner> CanonicalVarInfo<I> { /// that analyzes type-like values. #[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub enum CanonicalVarKind<I: Interner> { /// Some kind of type inference variable. Ty(CanonicalTyVarKind), @@ -213,7 +225,10 @@ impl<I: Interner> CanonicalVarKind<I> { /// know what set of types a given type variable can be unified with. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub enum CanonicalTyVarKind { /// General type variable `?T` that can be unified with arbitrary types. General(UniverseIndex), @@ -235,7 +250,10 @@ pub enum CanonicalTyVarKind { /// variables. You will need to supply it later to instantiate the /// canonicalized query response. #[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] pub struct CanonicalVarValues<I: Interner> { pub var_values: I::GenericArgs, diff --git a/compiler/rustc_type_ir/src/codec.rs b/compiler/rustc_type_ir/src/codec.rs deleted file mode 100644 index f443f596373..00000000000 --- a/compiler/rustc_type_ir/src/codec.rs +++ /dev/null @@ -1,61 +0,0 @@ -use rustc_data_structures::fx::FxHashMap; -use rustc_span::{SpanDecoder, SpanEncoder}; - -use crate::{Interner, PredicateKind}; - -/// The shorthand encoding uses an enum's variant index `usize` -/// and is offset by this value so it never matches a real variant. -/// This offset is also chosen so that the first byte is never < 0x80. -pub const SHORTHAND_OFFSET: usize = 0x80; - -/// Trait for decoding to a reference. -/// -/// This is a separate trait from `Decodable` so that we can implement it for -/// upstream types, such as `FxHashSet`. -/// -/// The `TyDecodable` derive macro will use this trait for fields that are -/// references (and don't use a type alias to hide that). -/// -/// `Decodable` can still be implemented in cases where `Decodable` is required -/// by a trait bound. -pub trait RefDecodable<'tcx, D: TyDecoder> { - fn decode(d: &mut D) -> &'tcx Self; -} - -pub trait TyEncoder: SpanEncoder { - type I: Interner; - const CLEAR_CROSS_CRATE: bool; - - fn position(&self) -> usize; - - fn type_shorthands(&mut self) -> &mut FxHashMap<<Self::I as Interner>::Ty, usize>; - - fn predicate_shorthands(&mut self) -> &mut FxHashMap<PredicateKind<Self::I>, usize>; - - fn encode_alloc_id(&mut self, alloc_id: &<Self::I as Interner>::AllocId); -} - -pub trait TyDecoder: SpanDecoder { - type I: Interner; - const CLEAR_CROSS_CRATE: bool; - - fn interner(&self) -> Self::I; - - fn cached_ty_for_shorthand<F>( - &mut self, - shorthand: usize, - or_insert_with: F, - ) -> <Self::I as Interner>::Ty - where - F: FnOnce(&mut Self) -> <Self::I as Interner>::Ty; - - fn with_position<F, R>(&mut self, pos: usize, f: F) -> R - where - F: FnOnce(&mut Self) -> R; - - fn positioned_at_shorthand(&self) -> bool { - (self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0 - } - - fn decode_alloc_id(&mut self) -> <Self::I as Interner>::AllocId; -} diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index aafc0907ae1..70a8509b513 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -4,14 +4,17 @@ use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; #[cfg(feature = "nightly")] -use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use crate::{self as ty, DebruijnIndex, Interner}; /// Represents a constant in Rust. #[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub enum ConstKind<I: Interner> { /// A const generic parameter. Param(I::ParamConst), @@ -62,7 +65,10 @@ impl<I: Interner> fmt::Debug for ConstKind<I> { /// An unevaluated (potentially generic) constant used in the type-system. #[derive_where(Clone, Copy, Debug, Hash, PartialEq, Eq; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub struct UnevaluatedConst<I: Interner> { pub def: I::DefId, pub args: I::GenericArgs, @@ -86,7 +92,7 @@ rustc_index::newtype_index! { /// An inference variable for a const, for use in const generics. #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))] +#[cfg_attr(feature = "nightly", derive(Encodable_NoContext, Decodable_NoContext))] pub enum InferConst { /// Infer the value of the const. Var(ConstVid), diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs index 9955e92b55a..11ec1f0a9fb 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -9,7 +9,7 @@ use rustc_data_structures::fingerprint::Fingerprint; #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; #[cfg(feature = "nightly")] -use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use crate::inherent::*; use crate::visit::TypeVisitableExt as _; @@ -17,7 +17,10 @@ use crate::{self as ty, Interner}; /// See `simplify_type`. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub enum SimplifiedType<DefId> { Bool, Char, diff --git a/compiler/rustc_type_ir/src/generic_arg.rs b/compiler/rustc_type_ir/src/generic_arg.rs index 008268c3bff..c18cade0e39 100644 --- a/compiler/rustc_type_ir/src/generic_arg.rs +++ b/compiler/rustc_type_ir/src/generic_arg.rs @@ -1,11 +1,14 @@ use derive_where::derive_where; #[cfg(feature = "nightly")] -use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use crate::Interner; #[derive_where(Clone, Copy, PartialEq, Eq, Debug; I: Interner)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub enum GenericArgKind<I: Interner> { Lifetime(I::Region), Type(I::Ty), @@ -13,7 +16,10 @@ pub enum GenericArgKind<I: Interner> { } #[derive_where(Clone, Copy, PartialEq, Eq, Debug; I: Interner)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub enum TermKind<I: Interner> { Ty(I::Ty), Const(I::Const), diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index d5edc9610a4..26c49510696 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -1,6 +1,6 @@ use derive_where::derive_where; #[cfg(feature = "nightly")] -use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use crate::fold::TypeFoldable; @@ -20,7 +20,10 @@ use crate::{self as ty, Interner}; /// t-types for help. #[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub enum TypingMode<I: Interner> { /// When checking whether impls overlap, we check whether any obligations /// are guaranteed to never hold when unifying the impls. This requires us diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index e2dfd9173fa..62912189509 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -17,15 +17,10 @@ use std::hash::Hash; use rustc_macros::{Decodable, Encodable, HashStable_NoContext}; // These modules are `pub` since they are not glob-imported. -#[macro_use] -pub mod visit; -#[cfg(feature = "nightly")] -pub mod codec; pub mod data_structures; pub mod elaborate; pub mod error; pub mod fast_reject; -pub mod fold; #[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_inherent")] pub mod inherent; pub mod ir_print; @@ -43,6 +38,7 @@ mod binder; mod canonical; mod const_kind; mod flags; +mod fold; mod generic_arg; mod infer_ctxt; mod interner; @@ -53,6 +49,7 @@ mod region_kind; mod ty_info; mod ty_kind; mod upcast; +mod visit; pub use AliasTyKind::*; pub use DynKind::*; @@ -62,10 +59,9 @@ pub use TyKind::*; pub use Variance::*; pub use binder::*; pub use canonical::*; -#[cfg(feature = "nightly")] -pub use codec::*; pub use const_kind::*; pub use flags::*; +pub use fold::*; pub use generic_arg::*; pub use infer_ctxt::*; pub use interner::*; @@ -77,6 +73,7 @@ pub use rustc_ast_ir::{Movability, Mutability, Pinnedness}; pub use ty_info::*; pub use ty_kind::*; pub use upcast::*; +pub use visit::*; rustc_index::newtype_index! { /// A [De Bruijn index][dbi] is a standard means of representing diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs index fab1a11304d..c8c293121ca 100644 --- a/compiler/rustc_type_ir/src/macros.rs +++ b/compiler/rustc_type_ir/src/macros.rs @@ -1,10 +1,11 @@ /// Used for types that are `Copy` and which **do not care arena /// allocated data** (i.e., don't need to be folded). +#[macro_export] macro_rules! TrivialTypeTraversalImpls { ($($ty:ty,)+) => { $( - impl<I: $crate::Interner> $crate::fold::TypeFoldable<I> for $ty { - fn try_fold_with<F: $crate::fold::FallibleTypeFolder<I>>( + impl<I: $crate::Interner> $crate::TypeFoldable<I> for $ty { + fn try_fold_with<F: $crate::FallibleTypeFolder<I>>( self, _: &mut F, ) -> ::std::result::Result<Self, F::Error> { @@ -12,7 +13,7 @@ macro_rules! TrivialTypeTraversalImpls { } #[inline] - fn fold_with<F: $crate::fold::TypeFolder<I>>( + fn fold_with<F: $crate::TypeFolder<I>>( self, _: &mut F, ) -> Self { @@ -20,14 +21,14 @@ macro_rules! TrivialTypeTraversalImpls { } } - impl<I: $crate::Interner> $crate::visit::TypeVisitable<I> for $ty { + impl<I: $crate::Interner> $crate::TypeVisitable<I> for $ty { #[inline] - fn visit_with<F: $crate::visit::TypeVisitor<I>>( + fn visit_with<F: $crate::TypeVisitor<I>>( &self, _: &mut F) -> F::Result { - <F::Result as rustc_ast_ir::visit::VisitorResult>::output() + <F::Result as $crate::VisitorResult>::output() } } )+ diff --git a/compiler/rustc_type_ir/src/opaque_ty.rs b/compiler/rustc_type_ir/src/opaque_ty.rs index 6d61a52723a..416d355fd03 100644 --- a/compiler/rustc_type_ir/src/opaque_ty.rs +++ b/compiler/rustc_type_ir/src/opaque_ty.rs @@ -1,6 +1,6 @@ use derive_where::derive_where; #[cfg(feature = "nightly")] -use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use crate::inherent::*; @@ -8,7 +8,10 @@ use crate::{self as ty, Interner}; #[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub struct OpaqueTypeKey<I: Interner> { pub def_id: I::LocalDefId, pub args: I::GenericArgs, diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 46385ca3a6f..22d0fa23d0c 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -3,7 +3,9 @@ use std::hash::Hash; use derive_where::derive_where; #[cfg(feature = "nightly")] -use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_macros::{ + Decodable, Decodable_NoContext, Encodable, Encodable_NoContext, HashStable_NoContext, +}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use crate::inherent::*; @@ -20,7 +22,10 @@ use crate::{self as ty, Interner}; #[derive_where(Eq; I: Interner, A: Eq)] #[derive_where(Debug; I: Interner, A: fmt::Debug)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub struct OutlivesPredicate<I: Interner, A>(pub A, pub I::Region); // FIXME: We manually derive `Lift` because the `derive(Lift_Generic)` doesn't @@ -50,7 +55,10 @@ where /// that case the `Self` parameter is absent from the generic parameters. #[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub struct TraitRef<I: Interner> { pub def_id: I::DefId, pub args: I::GenericArgs, @@ -122,7 +130,10 @@ impl<I: Interner> ty::Binder<I, TraitRef<I>> { #[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub struct TraitPredicate<I: Interner> { pub trait_ref: TraitRef<I>, @@ -177,7 +188,10 @@ impl<I: Interner> fmt::Debug for TraitPredicate<I> { } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub enum ImplPolarity { /// `impl Trait for Type` Positive, @@ -215,7 +229,10 @@ impl ImplPolarity { /// Distinguished from [`ImplPolarity`] since we never compute goals with /// "reservation" level. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub enum PredicatePolarity { /// `Type: Trait` Positive, @@ -244,7 +261,10 @@ impl fmt::Display for PredicatePolarity { #[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub enum ExistentialPredicate<I: Interner> { /// E.g., `Iterator`. Trait(ExistentialTraitRef<I>), @@ -289,7 +309,10 @@ impl<I: Interner> ty::Binder<I, ExistentialPredicate<I>> { /// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above). #[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub struct ExistentialTraitRef<I: Interner> { pub def_id: I::DefId, pub args: I::GenericArgs, @@ -353,7 +376,10 @@ impl<I: Interner> ty::Binder<I, ExistentialTraitRef<I>> { /// A `ProjectionPredicate` for an `ExistentialTraitRef`. #[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub struct ExistentialProjection<I: Interner> { pub def_id: I::DefId, pub args: I::GenericArgs, @@ -485,7 +511,10 @@ impl From<ty::AliasTyKind> for AliasTermKind { /// * For an opaque type, there is no explicit syntax. #[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub struct AliasTerm<I: Interner> { /// The parameters of the associated or opaque item. /// @@ -656,7 +685,10 @@ impl<I: Interner> From<ty::UnevaluatedConst<I>> for AliasTerm<I> { /// instances to normalize the LHS. #[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub struct ProjectionPredicate<I: Interner> { pub projection_term: AliasTerm<I>, pub term: I::Term, @@ -711,7 +743,10 @@ impl<I: Interner> fmt::Debug for ProjectionPredicate<I> { /// be an unconstrained inference variable which is used as the output. #[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub struct NormalizesTo<I: Interner> { pub alias: AliasTerm<I>, pub term: I::Term, @@ -743,7 +778,10 @@ impl<I: Interner> fmt::Debug for NormalizesTo<I> { #[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub struct HostEffectPredicate<I: Interner> { pub trait_ref: ty::TraitRef<I>, pub constness: BoundConstness, @@ -784,7 +822,10 @@ impl<I: Interner> ty::Binder<I, HostEffectPredicate<I>> { /// presenting user diagnostics. #[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub struct SubtypePredicate<I: Interner> { pub a_is_expected: bool, pub a: I::Ty, @@ -794,14 +835,20 @@ pub struct SubtypePredicate<I: Interner> { /// Encodes that we have to coerce *from* the `a` type to the `b` type. #[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub struct CoercePredicate<I: Interner> { pub a: I::Ty, pub b: I::Ty, } #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub enum BoundConstness { /// `Type: const Trait` /// diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index 21f4456abd1..847dff156fe 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -2,7 +2,7 @@ use std::fmt; use derive_where::derive_where; #[cfg(feature = "nightly")] -use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use crate::{self as ty, Interner}; @@ -11,7 +11,10 @@ use crate::{self as ty, Interner}; /// by implied bounds. #[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub enum ClauseKind<I: Interner> { /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` @@ -47,7 +50,10 @@ pub enum ClauseKind<I: Interner> { #[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub enum PredicateKind<I: Interner> { /// Prove a clause Clause(ClauseKind<I>), @@ -97,7 +103,10 @@ pub enum PredicateKind<I: Interner> { } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] -#[cfg_attr(feature = "nightly", derive(HashStable_NoContext, Encodable, Decodable))] +#[cfg_attr( + feature = "nightly", + derive(HashStable_NoContext, Encodable_NoContext, Decodable_NoContext) +)] pub enum AliasRelationDirection { Equate, Subtype, diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index e0b39737007..eae3213ead0 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -4,7 +4,7 @@ use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; #[cfg(feature = "nightly")] -use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use self::RegionKind::*; use crate::{DebruijnIndex, Interner}; @@ -126,7 +126,7 @@ rustc_index::newtype_index! { /// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/ /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html #[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))] +#[cfg_attr(feature = "nightly", derive(Encodable_NoContext, Decodable_NoContext))] pub enum RegionKind<I: Interner> { /// A region parameter; for example `'a` in `impl<'a> Trait for &'a ()`. /// diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index 9ae83928057..1acd5d5c2af 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -21,7 +21,7 @@ use std::marker::PhantomData; use derive_where::derive_where; use rustc_index::{Idx, IndexVec}; #[cfg(feature = "nightly")] -use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use tracing::debug; use crate::data_structures::HashMap; @@ -113,7 +113,10 @@ pub trait Delegate { /// result. In the case we return an initial provisional result depending /// on the kind of cycle. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub enum PathKind { /// A path consisting of only inductive/unproductive steps. Their initial /// provisional result is `Err(NoSolution)`. We currently treat them as diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index de2e0f2c0ec..3aec4804b27 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -5,7 +5,7 @@ use std::hash::Hash; use derive_where::derive_where; #[cfg(feature = "nightly")] -use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use crate::search_graph::PathKind; @@ -38,7 +38,10 @@ pub struct NoSolution; #[derive_where(Eq; I: Interner, P: Eq)] #[derive_where(Debug; I: Interner, P: fmt::Debug)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub struct Goal<I: Interner, P> { pub param_env: I::ParamEnv, pub predicate: P, @@ -98,7 +101,10 @@ pub enum GoalSource { #[derive_where(Eq; I: Interner, Goal<I, P>: Eq)] #[derive_where(Debug; I: Interner, Goal<I, P>: fmt::Debug)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub struct QueryInput<I: Interner, P> { pub goal: Goal<I, P>, pub predefined_opaques_in_body: I::PredefinedOpaques, @@ -107,7 +113,10 @@ pub struct QueryInput<I: Interner, P> { /// Opaques that are defined in the inference context before a query is called. #[derive_where(Clone, Hash, PartialEq, Eq, Debug, Default; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub struct PredefinedOpaquesData<I: Interner> { pub opaque_types: Vec<(ty::OpaqueTypeKey<I>, I::Ty)>, } @@ -178,7 +187,10 @@ pub enum CandidateSource<I: Interner> { } #[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)] -#[cfg_attr(feature = "nightly", derive(HashStable_NoContext, TyEncodable, TyDecodable))] +#[cfg_attr( + feature = "nightly", + derive(HashStable_NoContext, Encodable_NoContext, Decodable_NoContext) +)] pub enum BuiltinImplSource { /// A built-in impl that is considered trivial, without any nested requirements. They /// are preferred over where-clauses, and we want to track them explicitly. diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 83631f7fe34..9bea4482b55 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -8,7 +8,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; #[cfg(feature = "nightly")] use rustc_data_structures::unify::{NoError, UnifyKey, UnifyValue}; #[cfg(feature = "nightly")] -use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use self::TyKind::*; @@ -22,7 +22,10 @@ mod closure; /// Specifies how a trait object is represented. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub enum DynKind { /// An unsized `dyn Trait` object Dyn, @@ -36,7 +39,10 @@ pub enum DynKind { } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub enum AliasTyKind { /// A projection `<Type as Trait>::AssocType`. /// Can get normalized away if monomorphic enough. @@ -69,7 +75,10 @@ impl AliasTyKind { /// converted to this representation using `<dyn HirTyLowerer>::lower_ty`. #[cfg_attr(feature = "nightly", rustc_diagnostic_item = "IrTyKind")] #[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub enum TyKind<I: Interner> { /// The primitive boolean type. Written as `bool`. Bool, @@ -341,7 +350,10 @@ impl<I: Interner> fmt::Debug for TyKind<I> { /// * For an opaque type, there is no explicit syntax. #[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] -#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext) +)] pub struct AliasTy<I: Interner> { /// The parameters of the associated or opaque type. /// @@ -464,7 +476,10 @@ impl<I: Interner> AliasTy<I> { } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub enum IntTy { Isize, I8, @@ -522,7 +537,10 @@ impl IntTy { } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)] -#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub enum UintTy { Usize, U8, @@ -580,7 +598,10 @@ impl UintTy { } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] pub enum FloatTy { F16, F32, @@ -680,7 +701,7 @@ rustc_index::newtype_index! { /// type variable for the element type since we won't know until it's /// used what the element type is supposed to be. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[cfg_attr(feature = "nightly", derive(Encodable, Decodable))] +#[cfg_attr(feature = "nightly", derive(Encodable_NoContext, Decodable_NoContext))] pub enum InferTy { /// A type variable. TyVar(TyVid), @@ -860,7 +881,10 @@ impl fmt::Debug for InferTy { } #[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic)] pub struct TypeAndMut<I: Interner> { pub ty: I::Ty, @@ -868,7 +892,10 @@ pub struct TypeAndMut<I: Interner> { } #[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] pub struct FnSig<I: Interner> { pub inputs_and_output: I::Tys, @@ -1010,7 +1037,8 @@ impl<I: Interner> Deref for UnsafeBinderInner<I> { } #[cfg(feature = "nightly")] -impl<I: Interner, E: crate::TyEncoder<I = I>> rustc_serialize::Encodable<E> for UnsafeBinderInner<I> +impl<I: Interner, E: rustc_serialize::Encoder> rustc_serialize::Encodable<E> + for UnsafeBinderInner<I> where I::Ty: rustc_serialize::Encodable<E>, I::BoundVarKinds: rustc_serialize::Encodable<E>, @@ -1022,7 +1050,8 @@ where } #[cfg(feature = "nightly")] -impl<I: Interner, D: crate::TyDecoder<I = I>> rustc_serialize::Decodable<D> for UnsafeBinderInner<I> +impl<I: Interner, D: rustc_serialize::Decoder> rustc_serialize::Decodable<D> + for UnsafeBinderInner<I> where I::Ty: TypeVisitable<I> + rustc_serialize::Decodable<D>, I::BoundVarKinds: rustc_serialize::Decodable<D>, @@ -1038,7 +1067,10 @@ where // This is just a `FnSig` without the `FnHeader` fields. #[derive_where(Clone, Copy, Debug, PartialEq, Eq, Hash; I: Interner)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] pub struct FnSigTys<I: Interner> { pub inputs_and_output: I::Tys, @@ -1087,7 +1119,10 @@ impl<I: Interner> ty::Binder<I, FnSigTys<I>> { } #[derive_where(Clone, Copy, Debug, PartialEq, Eq, Hash; I: Interner)] -#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[cfg_attr( + feature = "nightly", + derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) +)] #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] pub struct FnHeader<I: Interner> { pub c_variadic: bool, diff --git a/compiler/rustc_type_ir_macros/src/lib.rs b/compiler/rustc_type_ir_macros/src/lib.rs index 640299c2167..8eefecdc980 100644 --- a/compiler/rustc_type_ir_macros/src/lib.rs +++ b/compiler/rustc_type_ir_macros/src/lib.rs @@ -45,12 +45,12 @@ fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Tok s.add_bounds(synstructure::AddBounds::Fields); let body_visit = s.each(|bind| { quote! { - match ::rustc_type_ir::visit::VisitorResult::branch( - ::rustc_type_ir::visit::TypeVisitable::visit_with(#bind, __visitor) + match ::rustc_type_ir::VisitorResult::branch( + ::rustc_type_ir::TypeVisitable::visit_with(#bind, __visitor) ) { ::core::ops::ControlFlow::Continue(()) => {}, ::core::ops::ControlFlow::Break(r) => { - return ::rustc_type_ir::visit::VisitorResult::from_residual(r); + return ::rustc_type_ir::VisitorResult::from_residual(r); }, } } @@ -58,14 +58,14 @@ fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Tok s.bind_with(|_| synstructure::BindStyle::Move); s.bound_impl( - quote!(::rustc_type_ir::visit::TypeVisitable<I>), + quote!(::rustc_type_ir::TypeVisitable<I>), quote! { - fn visit_with<__V: ::rustc_type_ir::visit::TypeVisitor<I>>( + fn visit_with<__V: ::rustc_type_ir::TypeVisitor<I>>( &self, __visitor: &mut __V ) -> __V::Result { match *self { #body_visit } - <__V::Result as ::rustc_type_ir::visit::VisitorResult>::output() + <__V::Result as ::rustc_type_ir::VisitorResult>::output() } }, ) @@ -93,7 +93,7 @@ fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Toke bind.to_token_stream() } else { quote! { - ::rustc_type_ir::fold::TypeFoldable::try_fold_with(#bind, __folder)? + ::rustc_type_ir::TypeFoldable::try_fold_with(#bind, __folder)? } } }) @@ -105,9 +105,9 @@ fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::Toke s.filter(|bi| !has_ignore_attr(&bi.ast().attrs, "type_foldable", "identity")); s.add_bounds(synstructure::AddBounds::Fields); s.bound_impl( - quote!(::rustc_type_ir::fold::TypeFoldable<I>), + quote!(::rustc_type_ir::TypeFoldable<I>), quote! { - fn try_fold_with<__F: ::rustc_type_ir::fold::FallibleTypeFolder<I>>( + fn try_fold_with<__F: ::rustc_type_ir::FallibleTypeFolder<I>>( self, __folder: &mut __F ) -> Result<Self, __F::Error> { diff --git a/compiler/stable_mir/src/mir.rs b/compiler/stable_mir/src/mir.rs index 82555461d64..413b5152bb3 100644 --- a/compiler/stable_mir/src/mir.rs +++ b/compiler/stable_mir/src/mir.rs @@ -5,4 +5,4 @@ pub mod pretty; pub mod visit; pub use body::*; -pub use visit::MirVisitor; +pub use visit::{MirVisitor, MutMirVisitor}; diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index f8b46f50a52..b1bf7bce828 100644 --- a/compiler/stable_mir/src/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -77,6 +77,22 @@ impl Body { &self.locals[self.arg_count + 1..] } + /// Returns a mutable reference to the local that holds this function's return value. + pub(crate) fn ret_local_mut(&mut self) -> &mut LocalDecl { + &mut self.locals[RETURN_LOCAL] + } + + /// Returns a mutable slice of locals corresponding to this function's arguments. + pub(crate) fn arg_locals_mut(&mut self) -> &mut [LocalDecl] { + &mut self.locals[1..][..self.arg_count] + } + + /// Returns a mutable slice of inner locals for this function. + /// Inner locals are those that are neither the return local nor the argument locals. + pub(crate) fn inner_locals_mut(&mut self) -> &mut [LocalDecl] { + &mut self.locals[self.arg_count + 1..] + } + /// Convenience function to get all the locals in this function. /// /// Locals are typically accessed via the more specific methods `ret_local`, diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs index d985a98fcbf..09447e70dfb 100644 --- a/compiler/stable_mir/src/mir/visit.rs +++ b/compiler/stable_mir/src/mir/visit.rs @@ -39,406 +39,486 @@ use crate::mir::*; use crate::ty::{GenericArgs, MirConst, Region, Ty, TyConst}; use crate::{Error, Opaque, Span}; -pub trait MirVisitor { - fn visit_body(&mut self, body: &Body) { - self.super_body(body) - } - - fn visit_basic_block(&mut self, bb: &BasicBlock) { - self.super_basic_block(bb) - } - - fn visit_ret_decl(&mut self, local: Local, decl: &LocalDecl) { - self.super_ret_decl(local, decl) - } - - fn visit_arg_decl(&mut self, local: Local, decl: &LocalDecl) { - self.super_arg_decl(local, decl) - } - - fn visit_local_decl(&mut self, local: Local, decl: &LocalDecl) { - self.super_local_decl(local, decl) - } - - fn visit_statement(&mut self, stmt: &Statement, location: Location) { - self.super_statement(stmt, location) - } - - fn visit_terminator(&mut self, term: &Terminator, location: Location) { - self.super_terminator(term, location) - } - - fn visit_span(&mut self, span: &Span) { - self.super_span(span) - } +macro_rules! make_mir_visitor { + ($visitor_trait_name:ident, $($mutability:ident)?) => { + pub trait $visitor_trait_name { + fn visit_body(&mut self, body: &$($mutability)? Body) { + self.super_body(body) + } - fn visit_place(&mut self, place: &Place, ptx: PlaceContext, location: Location) { - self.super_place(place, ptx, location) - } + fn visit_basic_block(&mut self, bb: &$($mutability)? BasicBlock) { + self.super_basic_block(bb) + } - fn visit_projection_elem( - &mut self, - place_ref: PlaceRef<'_>, - elem: &ProjectionElem, - ptx: PlaceContext, - location: Location, - ) { - let _ = place_ref; - self.super_projection_elem(elem, ptx, location); - } + fn visit_ret_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) { + self.super_ret_decl(local, decl) + } - fn visit_local(&mut self, local: &Local, ptx: PlaceContext, location: Location) { - let _ = (local, ptx, location); - } + fn visit_arg_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) { + self.super_arg_decl(local, decl) + } - fn visit_rvalue(&mut self, rvalue: &Rvalue, location: Location) { - self.super_rvalue(rvalue, location) - } + fn visit_local_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) { + self.super_local_decl(local, decl) + } - fn visit_operand(&mut self, operand: &Operand, location: Location) { - self.super_operand(operand, location) - } + fn visit_statement(&mut self, stmt: &$($mutability)? Statement, location: Location) { + self.super_statement(stmt, location) + } - fn visit_user_type_projection(&mut self, projection: &UserTypeProjection) { - self.super_user_type_projection(projection) - } + fn visit_terminator(&mut self, term: &$($mutability)? Terminator, location: Location) { + self.super_terminator(term, location) + } - fn visit_ty(&mut self, ty: &Ty, location: Location) { - let _ = location; - self.super_ty(ty) - } + fn visit_span(&mut self, span: &$($mutability)? Span) { + self.super_span(span) + } - fn visit_const_operand(&mut self, constant: &ConstOperand, location: Location) { - self.super_const_operand(constant, location) - } + fn visit_place(&mut self, place: &$($mutability)? Place, ptx: PlaceContext, location: Location) { + self.super_place(place, ptx, location) + } - fn visit_mir_const(&mut self, constant: &MirConst, location: Location) { - self.super_mir_const(constant, location) - } + visit_place_fns!($($mutability)?); - fn visit_ty_const(&mut self, constant: &TyConst, location: Location) { - let _ = location; - self.super_ty_const(constant) - } + fn visit_local(&mut self, local: &$($mutability)? Local, ptx: PlaceContext, location: Location) { + let _ = (local, ptx, location); + } - fn visit_region(&mut self, region: &Region, location: Location) { - let _ = location; - self.super_region(region) - } + fn visit_rvalue(&mut self, rvalue: &$($mutability)? Rvalue, location: Location) { + self.super_rvalue(rvalue, location) + } - fn visit_args(&mut self, args: &GenericArgs, location: Location) { - let _ = location; - self.super_args(args) - } + fn visit_operand(&mut self, operand: &$($mutability)? Operand, location: Location) { + self.super_operand(operand, location) + } - fn visit_assert_msg(&mut self, msg: &AssertMessage, location: Location) { - self.super_assert_msg(msg, location) - } + fn visit_user_type_projection(&mut self, projection: &$($mutability)? UserTypeProjection) { + self.super_user_type_projection(projection) + } - fn visit_var_debug_info(&mut self, var_debug_info: &VarDebugInfo) { - self.super_var_debug_info(var_debug_info); - } + fn visit_ty(&mut self, ty: &$($mutability)? Ty, location: Location) { + let _ = location; + self.super_ty(ty) + } - fn super_body(&mut self, body: &Body) { - let Body { blocks, locals: _, arg_count, var_debug_info, spread_arg: _, span } = body; + fn visit_const_operand(&mut self, constant: &$($mutability)? ConstOperand, location: Location) { + self.super_const_operand(constant, location) + } - for bb in blocks { - self.visit_basic_block(bb); - } + fn visit_mir_const(&mut self, constant: &$($mutability)? MirConst, location: Location) { + self.super_mir_const(constant, location) + } - self.visit_ret_decl(RETURN_LOCAL, body.ret_local()); + fn visit_ty_const(&mut self, constant: &$($mutability)? TyConst, location: Location) { + let _ = location; + self.super_ty_const(constant) + } - for (idx, arg) in body.arg_locals().iter().enumerate() { - self.visit_arg_decl(idx + 1, arg) - } + fn visit_region(&mut self, region: &$($mutability)? Region, location: Location) { + let _ = location; + self.super_region(region) + } - let local_start = arg_count + 1; - for (idx, arg) in body.inner_locals().iter().enumerate() { - self.visit_local_decl(idx + local_start, arg) - } + fn visit_args(&mut self, args: &$($mutability)? GenericArgs, location: Location) { + let _ = location; + self.super_args(args) + } - for info in var_debug_info.iter() { - self.visit_var_debug_info(info); - } + fn visit_assert_msg(&mut self, msg: &$($mutability)? AssertMessage, location: Location) { + self.super_assert_msg(msg, location) + } - self.visit_span(span) - } + fn visit_var_debug_info(&mut self, var_debug_info: &$($mutability)? VarDebugInfo) { + self.super_var_debug_info(var_debug_info); + } - fn super_basic_block(&mut self, bb: &BasicBlock) { - let BasicBlock { statements, terminator } = bb; - for stmt in statements { - self.visit_statement(stmt, Location(stmt.span)); - } - self.visit_terminator(terminator, Location(terminator.span)); - } + fn super_body(&mut self, body: &$($mutability)? Body) { + super_body!(self, body, $($mutability)?); + } - fn super_local_decl(&mut self, local: Local, decl: &LocalDecl) { - let _ = local; - let LocalDecl { ty, span, .. } = decl; - self.visit_ty(ty, Location(*span)); - } + fn super_basic_block(&mut self, bb: &$($mutability)? BasicBlock) { + let BasicBlock { statements, terminator } = bb; + for stmt in statements { + self.visit_statement(stmt, Location(stmt.span)); + } + self.visit_terminator(terminator, Location(terminator.span)); + } - fn super_ret_decl(&mut self, local: Local, decl: &LocalDecl) { - self.super_local_decl(local, decl) - } + fn super_local_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) { + let _ = local; + let LocalDecl { ty, span, .. } = decl; + self.visit_ty(ty, Location(*span)); + } - fn super_arg_decl(&mut self, local: Local, decl: &LocalDecl) { - self.super_local_decl(local, decl) - } + fn super_ret_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) { + self.super_local_decl(local, decl) + } - fn super_statement(&mut self, stmt: &Statement, location: Location) { - let Statement { kind, span } = stmt; - self.visit_span(span); - match kind { - StatementKind::Assign(place, rvalue) => { - self.visit_place(place, PlaceContext::MUTATING, location); - self.visit_rvalue(rvalue, location); - } - StatementKind::FakeRead(_, place) | StatementKind::PlaceMention(place) => { - self.visit_place(place, PlaceContext::NON_MUTATING, location); - } - StatementKind::SetDiscriminant { place, .. } - | StatementKind::Deinit(place) - | StatementKind::Retag(_, place) => { - self.visit_place(place, PlaceContext::MUTATING, location); - } - StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { - self.visit_local(local, PlaceContext::NON_USE, location); - } - StatementKind::AscribeUserType { place, projections, variance: _ } => { - self.visit_place(place, PlaceContext::NON_USE, location); - self.visit_user_type_projection(projections); - } - StatementKind::Coverage(coverage) => visit_opaque(coverage), - StatementKind::Intrinsic(intrisic) => match intrisic { - NonDivergingIntrinsic::Assume(operand) => { - self.visit_operand(operand, location); - } - NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { - src, - dst, - count, - }) => { - self.visit_operand(src, location); - self.visit_operand(dst, location); - self.visit_operand(count, location); - } - }, - StatementKind::ConstEvalCounter | StatementKind::Nop => {} - } - } + fn super_arg_decl(&mut self, local: Local, decl: &$($mutability)? LocalDecl) { + self.super_local_decl(local, decl) + } - fn super_terminator(&mut self, term: &Terminator, location: Location) { - let Terminator { kind, span } = term; - self.visit_span(span); - match kind { - TerminatorKind::Goto { .. } - | TerminatorKind::Resume - | TerminatorKind::Abort - | TerminatorKind::Unreachable => {} - TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => { - self.visit_operand(cond, location); - self.visit_assert_msg(msg, location); - } - TerminatorKind::Drop { place, target: _, unwind: _ } => { - self.visit_place(place, PlaceContext::MUTATING, location); - } - TerminatorKind::Call { func, args, destination, target: _, unwind: _ } => { - self.visit_operand(func, location); - for arg in args { - self.visit_operand(arg, location); + fn super_statement(&mut self, stmt: &$($mutability)? Statement, location: Location) { + let Statement { kind, span } = stmt; + self.visit_span(span); + match kind { + StatementKind::Assign(place, rvalue) => { + self.visit_place(place, PlaceContext::MUTATING, location); + self.visit_rvalue(rvalue, location); + } + StatementKind::FakeRead(_, place) | StatementKind::PlaceMention(place) => { + self.visit_place(place, PlaceContext::NON_MUTATING, location); + } + StatementKind::SetDiscriminant { place, .. } + | StatementKind::Deinit(place) + | StatementKind::Retag(_, place) => { + self.visit_place(place, PlaceContext::MUTATING, location); + } + StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { + self.visit_local(local, PlaceContext::NON_USE, location); + } + StatementKind::AscribeUserType { place, projections, variance: _ } => { + self.visit_place(place, PlaceContext::NON_USE, location); + self.visit_user_type_projection(projections); + } + StatementKind::Coverage(coverage) => visit_opaque(coverage), + StatementKind::Intrinsic(intrisic) => match intrisic { + NonDivergingIntrinsic::Assume(operand) => { + self.visit_operand(operand, location); + } + NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { + src, + dst, + count, + }) => { + self.visit_operand(src, location); + self.visit_operand(dst, location); + self.visit_operand(count, location); + } + }, + StatementKind::ConstEvalCounter | StatementKind::Nop => {} } - self.visit_place(destination, PlaceContext::MUTATING, location); } - TerminatorKind::InlineAsm { operands, .. } => { - for op in operands { - let InlineAsmOperand { in_value, out_place, raw_rpr: _ } = op; - if let Some(input) = in_value { - self.visit_operand(input, location); + + fn super_terminator(&mut self, term: &$($mutability)? Terminator, location: Location) { + let Terminator { kind, span } = term; + self.visit_span(span); + match kind { + TerminatorKind::Goto { .. } + | TerminatorKind::Resume + | TerminatorKind::Abort + | TerminatorKind::Unreachable => {} + TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => { + self.visit_operand(cond, location); + self.visit_assert_msg(msg, location); + } + TerminatorKind::Drop { place, target: _, unwind: _ } => { + self.visit_place(place, PlaceContext::MUTATING, location); + } + TerminatorKind::Call { func, args, destination, target: _, unwind: _ } => { + self.visit_operand(func, location); + for arg in args { + self.visit_operand(arg, location); + } + self.visit_place(destination, PlaceContext::MUTATING, location); + } + TerminatorKind::InlineAsm { operands, .. } => { + for op in operands { + let InlineAsmOperand { in_value, out_place, raw_rpr: _ } = op; + if let Some(input) = in_value { + self.visit_operand(input, location); + } + if let Some(output) = out_place { + self.visit_place(output, PlaceContext::MUTATING, location); + } + } } - if let Some(output) = out_place { - self.visit_place(output, PlaceContext::MUTATING, location); + TerminatorKind::Return => { + let $($mutability)? local = RETURN_LOCAL; + self.visit_local(&$($mutability)? local, PlaceContext::NON_MUTATING, location); + } + TerminatorKind::SwitchInt { discr, targets: _ } => { + self.visit_operand(discr, location); } } } - TerminatorKind::Return => { - let local = RETURN_LOCAL; - self.visit_local(&local, PlaceContext::NON_MUTATING, location); - } - TerminatorKind::SwitchInt { discr, targets: _ } => { - self.visit_operand(discr, location); - } - } - } - fn super_span(&mut self, span: &Span) { - let _ = span; - } - - fn super_place(&mut self, place: &Place, ptx: PlaceContext, location: Location) { - let _ = location; - let _ = ptx; - self.visit_local(&place.local, ptx, location); + fn super_span(&mut self, span: &$($mutability)? Span) { + let _ = span; + } - for (idx, elem) in place.projection.iter().enumerate() { - let place_ref = PlaceRef { local: place.local, projection: &place.projection[..idx] }; - self.visit_projection_elem(place_ref, elem, ptx, location); - } - } + fn super_rvalue(&mut self, rvalue: &$($mutability)? Rvalue, location: Location) { + match rvalue { + Rvalue::AddressOf(mutability, place) => { + let pcx = PlaceContext { is_mut: *mutability == RawPtrKind::Mut }; + self.visit_place(place, pcx, location); + } + Rvalue::Aggregate(_, operands) => { + for op in operands { + self.visit_operand(op, location); + } + } + Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => { + self.visit_operand(lhs, location); + self.visit_operand(rhs, location); + } + Rvalue::Cast(_, op, ty) => { + self.visit_operand(op, location); + self.visit_ty(ty, location); + } + Rvalue::CopyForDeref(place) | Rvalue::Discriminant(place) | Rvalue::Len(place) => { + self.visit_place(place, PlaceContext::NON_MUTATING, location); + } + Rvalue::Ref(region, kind, place) => { + self.visit_region(region, location); + let pcx = PlaceContext { is_mut: matches!(kind, BorrowKind::Mut { .. }) }; + self.visit_place(place, pcx, location); + } + Rvalue::Repeat(op, constant) => { + self.visit_operand(op, location); + self.visit_ty_const(constant, location); + } + Rvalue::ShallowInitBox(op, ty) => { + self.visit_ty(ty, location); + self.visit_operand(op, location) + } + Rvalue::ThreadLocalRef(_) => {} + Rvalue::NullaryOp(_, ty) => { + self.visit_ty(ty, location); + } + Rvalue::UnaryOp(_, op) | Rvalue::Use(op) => { + self.visit_operand(op, location); + } + } + } - fn super_projection_elem( - &mut self, - elem: &ProjectionElem, - ptx: PlaceContext, - location: Location, - ) { - match elem { - ProjectionElem::Downcast(_idx) => {} - ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ } - | ProjectionElem::Deref - | ProjectionElem::Subslice { from: _, to: _, from_end: _ } => {} - ProjectionElem::Field(_idx, ty) => self.visit_ty(ty, location), - ProjectionElem::Index(local) => self.visit_local(local, ptx, location), - ProjectionElem::OpaqueCast(ty) | ProjectionElem::Subtype(ty) => { - self.visit_ty(ty, location) + fn super_operand(&mut self, operand: &$($mutability)? Operand, location: Location) { + match operand { + Operand::Copy(place) | Operand::Move(place) => { + self.visit_place(place, PlaceContext::NON_MUTATING, location) + } + Operand::Constant(constant) => { + self.visit_const_operand(constant, location); + } + } } - } - } - fn super_rvalue(&mut self, rvalue: &Rvalue, location: Location) { - match rvalue { - Rvalue::AddressOf(mutability, place) => { - let pcx = PlaceContext { is_mut: *mutability == RawPtrKind::Mut }; - self.visit_place(place, pcx, location); + fn super_user_type_projection(&mut self, projection: &$($mutability)? UserTypeProjection) { + // This is a no-op on mir::Visitor. + let _ = projection; } - Rvalue::Aggregate(_, operands) => { - for op in operands { - self.visit_operand(op, location); - } + + fn super_ty(&mut self, ty: &$($mutability)? Ty) { + let _ = ty; } - Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => { - self.visit_operand(lhs, location); - self.visit_operand(rhs, location); + + fn super_const_operand(&mut self, constant: &$($mutability)? ConstOperand, location: Location) { + let ConstOperand { span, user_ty: _, const_ } = constant; + self.visit_span(span); + self.visit_mir_const(const_, location); } - Rvalue::Cast(_, op, ty) => { - self.visit_operand(op, location); + + fn super_mir_const(&mut self, constant: &$($mutability)? MirConst, location: Location) { + let MirConst { kind: _, ty, id: _ } = constant; self.visit_ty(ty, location); } - Rvalue::CopyForDeref(place) | Rvalue::Discriminant(place) | Rvalue::Len(place) => { - self.visit_place(place, PlaceContext::NON_MUTATING, location); - } - Rvalue::Ref(region, kind, place) => { - self.visit_region(region, location); - let pcx = PlaceContext { is_mut: matches!(kind, BorrowKind::Mut { .. }) }; - self.visit_place(place, pcx, location); + + fn super_ty_const(&mut self, constant: &$($mutability)? TyConst) { + let _ = constant; } - Rvalue::Repeat(op, constant) => { - self.visit_operand(op, location); - self.visit_ty_const(constant, location); + + fn super_region(&mut self, region: &$($mutability)? Region) { + let _ = region; } - Rvalue::ShallowInitBox(op, ty) => { - self.visit_ty(ty, location); - self.visit_operand(op, location) + + fn super_args(&mut self, args: &$($mutability)? GenericArgs) { + let _ = args; } - Rvalue::ThreadLocalRef(_) => {} - Rvalue::NullaryOp(_, ty) => { - self.visit_ty(ty, location); + + fn super_var_debug_info(&mut self, var_debug_info: &$($mutability)? VarDebugInfo) { + let VarDebugInfo { source_info, composite, value, name: _, argument_index: _ } = + var_debug_info; + self.visit_span(&$($mutability)? source_info.span); + let location = Location(source_info.span); + if let Some(composite) = composite { + self.visit_ty(&$($mutability)? composite.ty, location); + } + match value { + VarDebugInfoContents::Place(place) => { + self.visit_place(place, PlaceContext::NON_USE, location); + } + VarDebugInfoContents::Const(constant) => { + self.visit_mir_const(&$($mutability)? constant.const_, location); + } + } } - Rvalue::UnaryOp(_, op) | Rvalue::Use(op) => { - self.visit_operand(op, location); + + fn super_assert_msg(&mut self, msg: &$($mutability)? AssertMessage, location: Location) { + match msg { + AssertMessage::BoundsCheck { len, index } => { + self.visit_operand(len, location); + self.visit_operand(index, location); + } + AssertMessage::Overflow(_, left, right) => { + self.visit_operand(left, location); + self.visit_operand(right, location); + } + AssertMessage::OverflowNeg(op) + | AssertMessage::DivisionByZero(op) + | AssertMessage::RemainderByZero(op) => { + self.visit_operand(op, location); + } + AssertMessage::ResumedAfterReturn(_) + | AssertMessage::ResumedAfterPanic(_) + | AssertMessage::NullPointerDereference => { + //nothing to visit + } + AssertMessage::MisalignedPointerDereference { required, found } => { + self.visit_operand(required, location); + self.visit_operand(found, location); + } + } } } - } + }; +} - fn super_operand(&mut self, operand: &Operand, location: Location) { - match operand { - Operand::Copy(place) | Operand::Move(place) => { - self.visit_place(place, PlaceContext::NON_MUTATING, location) - } - Operand::Constant(constant) => { - self.visit_const_operand(constant, location); - } +macro_rules! super_body { + ($self:ident, $body:ident, mut) => { + for bb in $body.blocks.iter_mut() { + $self.visit_basic_block(bb); } - } - fn super_user_type_projection(&mut self, projection: &UserTypeProjection) { - // This is a no-op on mir::Visitor. - let _ = projection; - } + $self.visit_ret_decl(RETURN_LOCAL, $body.ret_local_mut()); - fn super_ty(&mut self, ty: &Ty) { - let _ = ty; - } + for (idx, arg) in $body.arg_locals_mut().iter_mut().enumerate() { + $self.visit_arg_decl(idx + 1, arg) + } - fn super_const_operand(&mut self, constant: &ConstOperand, location: Location) { - let ConstOperand { span, user_ty: _, const_ } = constant; - self.visit_span(span); - self.visit_mir_const(const_, location); - } + let local_start = $body.arg_count + 1; + for (idx, arg) in $body.inner_locals_mut().iter_mut().enumerate() { + $self.visit_local_decl(idx + local_start, arg) + } - fn super_mir_const(&mut self, constant: &MirConst, location: Location) { - let MirConst { kind: _, ty, id: _ } = constant; - self.visit_ty(ty, location); - } + for info in $body.var_debug_info.iter_mut() { + $self.visit_var_debug_info(info); + } - fn super_ty_const(&mut self, constant: &TyConst) { - let _ = constant; - } + $self.visit_span(&mut $body.span) + }; - fn super_region(&mut self, region: &Region) { - let _ = region; - } + ($self:ident, $body:ident, ) => { + let Body { blocks, locals: _, arg_count, var_debug_info, spread_arg: _, span } = $body; - fn super_args(&mut self, args: &GenericArgs) { - let _ = args; - } + for bb in blocks { + $self.visit_basic_block(bb); + } - fn super_var_debug_info(&mut self, var_debug_info: &VarDebugInfo) { - let VarDebugInfo { source_info, composite, value, name: _, argument_index: _ } = - var_debug_info; - self.visit_span(&source_info.span); - let location = Location(source_info.span); - if let Some(composite) = composite { - self.visit_ty(&composite.ty, location); + $self.visit_ret_decl(RETURN_LOCAL, $body.ret_local()); + + for (idx, arg) in $body.arg_locals().iter().enumerate() { + $self.visit_arg_decl(idx + 1, arg) } - match value { - VarDebugInfoContents::Place(place) => { - self.visit_place(place, PlaceContext::NON_USE, location); - } - VarDebugInfoContents::Const(constant) => { - self.visit_mir_const(&constant.const_, location); - } + + let local_start = arg_count + 1; + for (idx, arg) in $body.inner_locals().iter().enumerate() { + $self.visit_local_decl(idx + local_start, arg) } - } - fn super_assert_msg(&mut self, msg: &AssertMessage, location: Location) { - match msg { - AssertMessage::BoundsCheck { len, index } => { - self.visit_operand(len, location); - self.visit_operand(index, location); - } - AssertMessage::Overflow(_, left, right) => { - self.visit_operand(left, location); - self.visit_operand(right, location); + for info in var_debug_info.iter() { + $self.visit_var_debug_info(info); + } + + $self.visit_span(span) + }; +} + +macro_rules! visit_place_fns { + (mut) => { + fn super_place(&mut self, place: &mut Place, ptx: PlaceContext, location: Location) { + self.visit_local(&mut place.local, ptx, location); + + for elem in place.projection.iter_mut() { + self.visit_projection_elem(elem, ptx, location); } - AssertMessage::OverflowNeg(op) - | AssertMessage::DivisionByZero(op) - | AssertMessage::RemainderByZero(op) => { - self.visit_operand(op, location); + } + + // We don't have to replicate the `process_projection()` like we did in + // `rustc_middle::mir::visit.rs` here because the `projection` field in `Place` + // of Stable-MIR is not an immutable borrow, unlike in `Place` of MIR. + fn visit_projection_elem( + &mut self, + elem: &mut ProjectionElem, + ptx: PlaceContext, + location: Location, + ) { + self.super_projection_elem(elem, ptx, location) + } + + fn super_projection_elem( + &mut self, + elem: &mut ProjectionElem, + ptx: PlaceContext, + location: Location, + ) { + match elem { + ProjectionElem::Deref => {} + ProjectionElem::Field(_idx, ty) => self.visit_ty(ty, location), + ProjectionElem::Index(local) => self.visit_local(local, ptx, location), + ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ } => {} + ProjectionElem::Subslice { from: _, to: _, from_end: _ } => {} + ProjectionElem::Downcast(_idx) => {} + ProjectionElem::OpaqueCast(ty) => self.visit_ty(ty, location), + ProjectionElem::Subtype(ty) => self.visit_ty(ty, location), } - AssertMessage::ResumedAfterReturn(_) - | AssertMessage::ResumedAfterPanic(_) - | AssertMessage::NullPointerDereference => { - //nothing to visit + } + }; + + () => { + fn super_place(&mut self, place: &Place, ptx: PlaceContext, location: Location) { + self.visit_local(&place.local, ptx, location); + + for (idx, elem) in place.projection.iter().enumerate() { + let place_ref = + PlaceRef { local: place.local, projection: &place.projection[..idx] }; + self.visit_projection_elem(place_ref, elem, ptx, location); } - AssertMessage::MisalignedPointerDereference { required, found } => { - self.visit_operand(required, location); - self.visit_operand(found, location); + } + + fn visit_projection_elem<'a>( + &mut self, + place_ref: PlaceRef<'a>, + elem: &ProjectionElem, + ptx: PlaceContext, + location: Location, + ) { + let _ = place_ref; + self.super_projection_elem(elem, ptx, location); + } + + fn super_projection_elem( + &mut self, + elem: &ProjectionElem, + ptx: PlaceContext, + location: Location, + ) { + match elem { + ProjectionElem::Deref => {} + ProjectionElem::Field(_idx, ty) => self.visit_ty(ty, location), + ProjectionElem::Index(local) => self.visit_local(local, ptx, location), + ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ } => {} + ProjectionElem::Subslice { from: _, to: _, from_end: _ } => {} + ProjectionElem::Downcast(_idx) => {} + ProjectionElem::OpaqueCast(ty) => self.visit_ty(ty, location), + ProjectionElem::Subtype(ty) => self.visit_ty(ty, location), } } - } + }; } +make_mir_visitor!(MirVisitor,); +make_mir_visitor!(MutMirVisitor, mut); + /// This function is a no-op that gets used to ensure this visitor is kept up-to-date. /// /// The idea is that whenever we replace an Opaque type by a real type, the compiler will fail diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 2f752f6eb39..1e03a191276 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -10,25 +10,28 @@ use core::ptr::{self, NonNull}; unsafe extern "Rust" { // These are the magic symbols to call the global allocator. rustc generates - // them to call `__rg_alloc` etc. if there is a `#[global_allocator]` attribute + // them to call the global allocator if there is a `#[global_allocator]` attribute // (the code expanding that attribute macro generates those functions), or to call // the default implementations in std (`__rdl_alloc` etc. in `library/std/src/alloc.rs`) // otherwise. - // The rustc fork of LLVM 14 and earlier also special-cases these function names to be able to optimize them - // like `malloc`, `realloc`, and `free`, respectively. #[rustc_allocator] #[rustc_nounwind] + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] fn __rust_alloc(size: usize, align: usize) -> *mut u8; #[rustc_deallocator] #[rustc_nounwind] + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); #[rustc_reallocator] #[rustc_nounwind] + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] fn __rust_realloc(ptr: *mut u8, old_size: usize, align: usize, new_size: usize) -> *mut u8; #[rustc_allocator_zeroed] #[rustc_nounwind] + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8; + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] static __rust_no_alloc_shim_is_unstable: u8; } @@ -357,6 +360,7 @@ unsafe extern "Rust" { // This is the magic symbol to call the global alloc error handler. rustc generates // it to call `__rg_oom` if there is a `#[alloc_error_handler]`, or to call the // default implementations below (`__rdl_oom`) otherwise. + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] fn __rust_alloc_error_handler(size: usize, align: usize) -> !; } @@ -423,6 +427,7 @@ pub mod __alloc_error_handler { unsafe extern "Rust" { // This symbol is emitted by rustc next to __rust_alloc_error_handler. // Its value depends on the -Zoom={panic,abort} compiler option. + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] static __rust_alloc_error_handler_should_panic: u8; } diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index fc1cee28d03..619d9f258e3 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1327,11 +1327,14 @@ impl<T: ?Sized> Rc<T> { /// /// # Safety /// - /// The pointer must have been obtained through `Rc::into_raw`, the - /// associated `Rc` instance must be valid (i.e. the strong count must be at + /// The pointer must have been obtained through `Rc::into_raw` and must satisfy the + /// same layout requirements specified in [`Rc::from_raw_in`][from_raw_in]. + /// The associated `Rc` instance must be valid (i.e. the strong count must be at /// least 1) for the duration of this method, and `ptr` must point to a block of memory /// allocated by the global allocator. /// + /// [from_raw_in]: Rc::from_raw_in + /// /// # Examples /// /// ``` @@ -1360,12 +1363,15 @@ impl<T: ?Sized> Rc<T> { /// /// # Safety /// - /// The pointer must have been obtained through `Rc::into_raw`, the - /// associated `Rc` instance must be valid (i.e. the strong count must be at + /// The pointer must have been obtained through `Rc::into_raw`and must satisfy the + /// same layout requirements specified in [`Rc::from_raw_in`][from_raw_in]. + /// The associated `Rc` instance must be valid (i.e. the strong count must be at /// least 1) when invoking this method, and `ptr` must point to a block of memory /// allocated by the global allocator. This method can be used to release the final `Rc` and /// backing storage, but **should not** be called after the final `Rc` has been released. /// + /// [from_raw_in]: Rc::from_raw_in + /// /// # Examples /// /// ``` @@ -1623,10 +1629,13 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> { /// /// # Safety /// - /// The pointer must have been obtained through `Rc::into_raw`, the - /// associated `Rc` instance must be valid (i.e. the strong count must be at + /// The pointer must have been obtained through `Rc::into_raw` and must satisfy the + /// same layout requirements specified in [`Rc::from_raw_in`][from_raw_in]. + /// The associated `Rc` instance must be valid (i.e. the strong count must be at /// least 1) for the duration of this method, and `ptr` must point to a block of memory - /// allocated by `alloc` + /// allocated by `alloc`. + /// + /// [from_raw_in]: Rc::from_raw_in /// /// # Examples /// @@ -1665,11 +1674,14 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> { /// /// # Safety /// - /// The pointer must have been obtained through `Rc::into_raw`, the - /// associated `Rc` instance must be valid (i.e. the strong count must be at + /// The pointer must have been obtained through `Rc::into_raw`and must satisfy the + /// same layout requirements specified in [`Rc::from_raw_in`][from_raw_in]. + /// The associated `Rc` instance must be valid (i.e. the strong count must be at /// least 1) when invoking this method, and `ptr` must point to a block of memory - /// allocated by `alloc`. This method can be used to release the final `Rc` and backing storage, - /// but **should not** be called after the final `Rc` has been released. + /// allocated by `alloc`. This method can be used to release the final `Rc` and + /// backing storage, but **should not** be called after the final `Rc` has been released. + /// + /// [from_raw_in]: Rc::from_raw_in /// /// # Examples /// diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 4999319f618..c62f8e5b70f 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -84,9 +84,29 @@ macro_rules! acquire { /// /// Shared references in Rust disallow mutation by default, and `Arc` is no /// exception: you cannot generally obtain a mutable reference to something -/// inside an `Arc`. If you need to mutate through an `Arc`, use -/// [`Mutex`][mutex], [`RwLock`][rwlock], or one of the [`Atomic`][atomic] -/// types. +/// inside an `Arc`. If you do need to mutate through an `Arc`, you have several options: +/// +/// 1. Use interior mutability with synchronization primitives like [`Mutex`][mutex], +/// [`RwLock`][rwlock], or one of the [`Atomic`][atomic] types. +/// +/// 2. Use clone-on-write semantics with [`Arc::make_mut`] which provides efficient mutation +/// without requiring interior mutability. This approach clones the data only when +/// needed (when there are multiple references) and can be more efficient when mutations +/// are infrequent. +/// +/// 3. Use [`Arc::get_mut`] when you know your `Arc` is not shared (has a reference count of 1), +/// which provides direct mutable access to the inner value without any cloning. +/// +/// ``` +/// use std::sync::Arc; +/// +/// let mut data = Arc::new(vec![1, 2, 3]); +/// +/// // This will clone the vector only if there are other references to it +/// Arc::make_mut(&mut data).push(4); +/// +/// assert_eq!(*data, vec![1, 2, 3, 4]); +/// ``` /// /// **Note**: This type is only available on platforms that support atomic /// loads and stores of pointers, which includes all platforms that support @@ -1453,11 +1473,14 @@ impl<T: ?Sized> Arc<T> { /// /// # Safety /// - /// The pointer must have been obtained through `Arc::into_raw`, and the - /// associated `Arc` instance must be valid (i.e. the strong count must be at + /// The pointer must have been obtained through `Arc::into_raw` and must satisfy the + /// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in]. + /// The associated `Arc` instance must be valid (i.e. the strong count must be at /// least 1) for the duration of this method, and `ptr` must point to a block of memory /// allocated by the global allocator. /// + /// [from_raw_in]: Arc::from_raw_in + /// /// # Examples /// /// ``` @@ -1488,13 +1511,16 @@ impl<T: ?Sized> Arc<T> { /// /// # Safety /// - /// The pointer must have been obtained through `Arc::into_raw`, and the - /// associated `Arc` instance must be valid (i.e. the strong count must be at + /// The pointer must have been obtained through `Arc::into_raw` and must satisfy the + /// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in]. + /// The associated `Arc` instance must be valid (i.e. the strong count must be at /// least 1) when invoking this method, and `ptr` must point to a block of memory /// allocated by the global allocator. This method can be used to release the final /// `Arc` and backing storage, but **should not** be called after the final `Arc` has been /// released. /// + /// [from_raw_in]: Arc::from_raw_in + /// /// # Examples /// /// ``` @@ -1806,11 +1832,14 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> { /// /// # Safety /// - /// The pointer must have been obtained through `Arc::into_raw`, and the - /// associated `Arc` instance must be valid (i.e. the strong count must be at - /// least 1) for the duration of this method,, and `ptr` must point to a block of memory + /// The pointer must have been obtained through `Arc::into_raw` and must satisfy the + /// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in]. + /// The associated `Arc` instance must be valid (i.e. the strong count must be at + /// least 1) for the duration of this method, and `ptr` must point to a block of memory /// allocated by `alloc`. /// + /// [from_raw_in]: Arc::from_raw_in + /// /// # Examples /// /// ``` @@ -1850,13 +1879,16 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> { /// /// # Safety /// - /// The pointer must have been obtained through `Arc::into_raw`, the - /// associated `Arc` instance must be valid (i.e. the strong count must be at + /// The pointer must have been obtained through `Arc::into_raw` and must satisfy the + /// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in]. + /// The associated `Arc` instance must be valid (i.e. the strong count must be at /// least 1) when invoking this method, and `ptr` must point to a block of memory /// allocated by `alloc`. This method can be used to release the final /// `Arc` and backing storage, but **should not** be called after the final `Arc` has been /// released. /// + /// [from_raw_in]: Arc::from_raw_in + /// /// # Examples /// /// ``` diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index da9a77154f9..3782f9e9519 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1252,6 +1252,19 @@ impl<T, A: Allocator> Vec<T, A> { /// vec.push(42); /// assert!(vec.capacity() >= 10); /// ``` + /// + /// A vector with zero-sized elements will always have a capacity of usize::MAX: + /// + /// ``` + /// #[derive(Clone)] + /// struct ZeroSized; + /// + /// fn main() { + /// assert_eq!(std::mem::size_of::<ZeroSized>(), 0); + /// let v = vec![ZeroSized; 0]; + /// assert_eq!(v.capacity(), usize::MAX); + /// } + /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_vec_string_slice", since = "CURRENT_RUSTC_VERSION")] diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 9ed2c8e9f3a..10f2a11d558 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -109,7 +109,7 @@ use crate::{fmt, hash, intrinsics}; // unsafe traits and unsafe methods (i.e., `type_id` would still be safe to call, // but we would likely want to indicate as such in documentation). #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "Any")] +#[rustc_diagnostic_item = "Any"] pub trait Any: 'static { /// Gets the `TypeId` of `self`. /// diff --git a/library/core/src/array/ascii.rs b/library/core/src/array/ascii.rs index e2faef855bc..792a57e3fa2 100644 --- a/library/core/src/array/ascii.rs +++ b/library/core/src/array/ascii.rs @@ -1,6 +1,5 @@ use crate::ascii; -#[cfg(not(test))] impl<const N: usize> [u8; N] { /// Converts this array of bytes into an array of ASCII characters, /// or returns `None` if any of the characters is non-ASCII. diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs index 3c589ca5dfa..d525ab425e6 100644 --- a/library/core/src/bool.rs +++ b/library/core/src/bool.rs @@ -56,7 +56,7 @@ impl bool { /// ``` #[doc(alias = "then_with")] #[stable(feature = "lazy_bool_to_option", since = "1.50.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "bool_then")] + #[rustc_diagnostic_item = "bool_then"] #[inline] pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> { if self { Some(f()) } else { None } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index cbf00106c51..1a320b316a4 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -304,7 +304,7 @@ pub use once::OnceCell; /// ``` /// /// See the [module-level documentation](self) for more. -#[cfg_attr(not(test), rustc_diagnostic_item = "Cell")] +#[rustc_diagnostic_item = "Cell"] #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] #[rustc_pub_transparent] @@ -725,7 +725,7 @@ impl<T, const N: usize> Cell<[T; N]> { /// A mutable memory location with dynamically checked borrow rules /// /// See the [module-level documentation](self) for more. -#[cfg_attr(not(test), rustc_diagnostic_item = "RefCell")] +#[rustc_diagnostic_item = "RefCell"] #[stable(feature = "rust1", since = "1.0.0")] pub struct RefCell<T: ?Sized> { borrow: Cell<BorrowFlag>, diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index bb71af339b8..fa584953bed 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1178,7 +1178,7 @@ impl char { #[must_use] #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[rustc_const_stable(feature = "const_char_is_ascii", since = "1.32.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "char_is_ascii")] + #[rustc_diagnostic_item = "char_is_ascii"] #[inline] pub const fn is_ascii(&self) -> bool { *self as u32 <= 0x7F diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index c777dd995a6..e0ac0bfc528 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -262,34 +262,150 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> { _field: crate::marker::PhantomData<T>, } -/// A generalization of [`Clone`] to dynamically-sized types stored in arbitrary containers. +/// A generalization of [`Clone`] to [dynamically-sized types][DST] stored in arbitrary containers. /// -/// This trait is implemented for all types implementing [`Clone`], and also [slices](slice) of all -/// such types. You may also implement this trait to enable cloning trait objects and custom DSTs -/// (structures containing dynamically-sized fields). +/// This trait is implemented for all types implementing [`Clone`], [slices](slice) of all +/// such types, and other dynamically-sized types in the standard library. +/// You may also implement this trait to enable cloning custom DSTs +/// (structures containing dynamically-sized fields), or use it as a supertrait to enable +/// cloning a [trait object]. +/// +/// This trait is normally used via operations on container types which support DSTs, +/// so you should not typically need to call `.clone_to_uninit()` explicitly except when +/// implementing such a container or otherwise performing explicit management of an allocation, +/// or when implementing `CloneToUninit` itself. /// /// # Safety /// -/// Implementations must ensure that when `.clone_to_uninit(dst)` returns normally rather than -/// panicking, it always leaves `*dst` initialized as a valid value of type `Self`. +/// Implementations must ensure that when `.clone_to_uninit(dest)` returns normally rather than +/// panicking, it always leaves `*dest` initialized as a valid value of type `Self`. +/// +/// # Examples +/// +// FIXME(#126799): when `Box::clone` allows use of `CloneToUninit`, rewrite these examples with it +// since `Rc` is a distraction. +/// +/// If you are defining a trait, you can add `CloneToUninit` as a supertrait to enable cloning of +/// `dyn` values of your trait: +/// +/// ``` +/// #![feature(clone_to_uninit)] +/// use std::rc::Rc; +/// +/// trait Foo: std::fmt::Debug + std::clone::CloneToUninit { +/// fn modify(&mut self); +/// fn value(&self) -> i32; +/// } +/// +/// impl Foo for i32 { +/// fn modify(&mut self) { +/// *self *= 10; +/// } +/// fn value(&self) -> i32 { +/// *self +/// } +/// } +/// +/// let first: Rc<dyn Foo> = Rc::new(1234); +/// +/// let mut second = first.clone(); +/// Rc::make_mut(&mut second).modify(); // make_mut() will call clone_to_uninit() +/// +/// assert_eq!(first.value(), 1234); +/// assert_eq!(second.value(), 12340); +/// ``` +/// +/// The following is an example of implementing `CloneToUninit` for a custom DST. +/// (It is essentially a limited form of what `derive(CloneToUninit)` would do, +/// if such a derive macro existed.) /// -/// # See also +/// ``` +/// #![feature(clone_to_uninit)] +/// use std::clone::CloneToUninit; +/// use std::mem::offset_of; +/// use std::rc::Rc; +/// +/// #[derive(PartialEq)] +/// struct MyDst<T: ?Sized> { +/// label: String, +/// contents: T, +/// } /// -/// * [`Clone::clone_from`] is a safe function which may be used instead when `Self` is a [`Sized`] +/// unsafe impl<T: ?Sized + CloneToUninit> CloneToUninit for MyDst<T> { +/// unsafe fn clone_to_uninit(&self, dest: *mut u8) { +/// // The offset of `self.contents` is dynamic because it depends on the alignment of T +/// // which can be dynamic (if `T = dyn SomeTrait`). Therefore, we have to obtain it +/// // dynamically by examining `self`, rather than using `offset_of!`. +/// // +/// // SAFETY: `self` by definition points somewhere before `&self.contents` in the same +/// // allocation. +/// let offset_of_contents = unsafe { +/// (&raw const self.contents).byte_offset_from_unsigned(self) +/// }; +/// +/// // Clone the *sized* fields of `self` (just one, in this example). +/// // (By cloning this first and storing it temporarily in a local variable, we avoid +/// // leaking it in case of any panic, using the ordinary automatic cleanup of local +/// // variables. Such a leak would be sound, but undesirable.) +/// let label = self.label.clone(); +/// +/// // SAFETY: The caller must provide a `dest` such that these field offsets are valid +/// // to write to. +/// unsafe { +/// // Clone the unsized field directly from `self` to `dest`. +/// self.contents.clone_to_uninit(dest.add(offset_of_contents)); +/// +/// // Now write all the sized fields. +/// // +/// // Note that we only do this once all of the clone() and clone_to_uninit() calls +/// // have completed, and therefore we know that there are no more possible panics; +/// // this ensures no memory leaks in case of panic. +/// dest.add(offset_of!(Self, label)).cast::<String>().write(label); +/// } +/// // All fields of the struct have been initialized; therefore, the struct is initialized, +/// // and we have satisfied our `unsafe impl CloneToUninit` obligations. +/// } +/// } +/// +/// fn main() { +/// // Construct MyDst<[u8; 4]>, then coerce to MyDst<[u8]>. +/// let first: Rc<MyDst<[u8]>> = Rc::new(MyDst { +/// label: String::from("hello"), +/// contents: [1, 2, 3, 4], +/// }); +/// +/// let mut second = first.clone(); +/// // make_mut() will call clone_to_uninit(). +/// for elem in Rc::make_mut(&mut second).contents.iter_mut() { +/// *elem *= 10; +/// } +/// +/// assert_eq!(first.contents, [1, 2, 3, 4]); +/// assert_eq!(second.contents, [10, 20, 30, 40]); +/// assert_eq!(second.label, "hello"); +/// } +/// ``` +/// +/// # See Also +/// +/// * [`Clone::clone_from`] is a safe function which may be used instead when [`Self: Sized`](Sized) /// and the destination is already initialized; it may be able to reuse allocations owned by -/// the destination. +/// the destination, whereas `clone_to_uninit` cannot, since its destination is assumed to be +/// uninitialized. /// * [`ToOwned`], which allocates a new destination container. /// /// [`ToOwned`]: ../../std/borrow/trait.ToOwned.html +/// [DST]: https://doc.rust-lang.org/reference/dynamically-sized-types.html +/// [trait object]: https://doc.rust-lang.org/reference/types/trait-object.html #[unstable(feature = "clone_to_uninit", issue = "126799")] pub unsafe trait CloneToUninit { - /// Performs copy-assignment from `self` to `dst`. + /// Performs copy-assignment from `self` to `dest`. /// - /// This is analogous to `std::ptr::write(dst.cast(), self.clone())`, - /// except that `self` may be a dynamically-sized type ([`!Sized`](Sized)). + /// This is analogous to `std::ptr::write(dest.cast(), self.clone())`, + /// except that `Self` may be a dynamically-sized type ([`!Sized`](Sized)). /// - /// Before this function is called, `dst` may point to uninitialized memory. - /// After this function is called, `dst` will point to initialized memory; it will be + /// Before this function is called, `dest` may point to uninitialized memory. + /// After this function is called, `dest` will point to initialized memory; it will be /// sound to create a `&Self` reference from the pointer with the [pointer metadata] /// from `self`. /// @@ -297,8 +413,8 @@ pub unsafe trait CloneToUninit { /// /// Behavior is undefined if any of the following conditions are violated: /// - /// * `dst` must be [valid] for writes for `size_of_val(self)` bytes. - /// * `dst` must be properly aligned to `align_of_val(self)`. + /// * `dest` must be [valid] for writes for `size_of_val(self)` bytes. + /// * `dest` must be properly aligned to `align_of_val(self)`. /// /// [valid]: crate::ptr#safety /// [pointer metadata]: crate::ptr::metadata() @@ -307,27 +423,26 @@ pub unsafe trait CloneToUninit { /// /// This function may panic. (For example, it might panic if memory allocation for a clone /// of a value owned by `self` fails.) - /// If the call panics, then `*dst` should be treated as uninitialized memory; it must not be + /// If the call panics, then `*dest` should be treated as uninitialized memory; it must not be /// read or dropped, because even if it was previously valid, it may have been partially /// overwritten. /// - /// The caller may also need to take care to deallocate the allocation pointed to by `dst`, - /// if applicable, to avoid a memory leak, and may need to take other precautions to ensure - /// soundness in the presence of unwinding. + /// The caller may wish to to take care to deallocate the allocation pointed to by `dest`, + /// if applicable, to avoid a memory leak (but this is not a requirement). /// /// Implementors should avoid leaking values by, upon unwinding, dropping all component values /// that might have already been created. (For example, if a `[Foo]` of length 3 is being /// cloned, and the second of the three calls to `Foo::clone()` unwinds, then the first `Foo` /// cloned should be dropped.) - unsafe fn clone_to_uninit(&self, dst: *mut u8); + unsafe fn clone_to_uninit(&self, dest: *mut u8); } #[unstable(feature = "clone_to_uninit", issue = "126799")] unsafe impl<T: Clone> CloneToUninit for T { #[inline] - unsafe fn clone_to_uninit(&self, dst: *mut u8) { + unsafe fn clone_to_uninit(&self, dest: *mut u8) { // SAFETY: we're calling a specialization with the same contract - unsafe { <T as self::uninit::CopySpec>::clone_one(self, dst.cast::<T>()) } + unsafe { <T as self::uninit::CopySpec>::clone_one(self, dest.cast::<T>()) } } } @@ -335,10 +450,10 @@ unsafe impl<T: Clone> CloneToUninit for T { unsafe impl<T: Clone> CloneToUninit for [T] { #[inline] #[cfg_attr(debug_assertions, track_caller)] - unsafe fn clone_to_uninit(&self, dst: *mut u8) { - let dst: *mut [T] = dst.with_metadata_of(self); + unsafe fn clone_to_uninit(&self, dest: *mut u8) { + let dest: *mut [T] = dest.with_metadata_of(self); // SAFETY: we're calling a specialization with the same contract - unsafe { <T as self::uninit::CopySpec>::clone_slice(self, dst) } + unsafe { <T as self::uninit::CopySpec>::clone_slice(self, dest) } } } @@ -346,21 +461,21 @@ unsafe impl<T: Clone> CloneToUninit for [T] { unsafe impl CloneToUninit for str { #[inline] #[cfg_attr(debug_assertions, track_caller)] - unsafe fn clone_to_uninit(&self, dst: *mut u8) { + unsafe fn clone_to_uninit(&self, dest: *mut u8) { // SAFETY: str is just a [u8] with UTF-8 invariant - unsafe { self.as_bytes().clone_to_uninit(dst) } + unsafe { self.as_bytes().clone_to_uninit(dest) } } } #[unstable(feature = "clone_to_uninit", issue = "126799")] unsafe impl CloneToUninit for crate::ffi::CStr { #[cfg_attr(debug_assertions, track_caller)] - unsafe fn clone_to_uninit(&self, dst: *mut u8) { + unsafe fn clone_to_uninit(&self, dest: *mut u8) { // SAFETY: For now, CStr is just a #[repr(trasnsparent)] [c_char] with some invariants. // And we can cast [c_char] to [u8] on all supported platforms (see: to_bytes_with_nul). // The pointer metadata properly preserves the length (so NUL is also copied). // See: `cstr_metadata_is_length_with_nul` in tests. - unsafe { self.to_bytes_with_nul().clone_to_uninit(dst) } + unsafe { self.to_bytes_with_nul().clone_to_uninit(dest) } } } diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index b29251b4b43..25bd17d5802 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -1481,7 +1481,7 @@ pub macro PartialOrd($item:item) { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "cmp_min")] +#[rustc_diagnostic_item = "cmp_min"] pub fn min<T: Ord>(v1: T, v2: T) -> T { v1.min(v2) } @@ -1573,7 +1573,7 @@ pub fn min_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T { #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "cmp_max")] +#[rustc_diagnostic_item = "cmp_max"] pub fn max<T: Ord>(v1: T, v2: T) -> T { v1.max(v2) } diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 43fd54f881d..e1b10e1074d 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -214,7 +214,7 @@ pub const fn identity<T>(x: T) -> T { /// is_hello(s); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "AsRef")] +#[rustc_diagnostic_item = "AsRef"] pub trait AsRef<T: ?Sized> { /// Converts this type into a shared reference of the (usually inferred) input type. #[stable(feature = "rust1", since = "1.0.0")] @@ -365,7 +365,7 @@ pub trait AsRef<T: ?Sized> { /// Note, however, that APIs don't need to be generic. In many cases taking a `&mut [u8]` or /// `&mut Vec<u8>`, for example, is the better choice (callers need to pass the correct type then). #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "AsMut")] +#[rustc_diagnostic_item = "AsMut"] pub trait AsMut<T: ?Sized> { /// Converts this type into a mutable reference of the (usually inferred) input type. #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 0246d0627ca..d5cb10a5d1c 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -147,22 +147,42 @@ impl_from!(i16 => isize, #[stable(feature = "lossless_iusize_conv", since = "1.2 // https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-951.pdf // Note: integers can only be represented with full precision in a float if -// they fit in the significand, which is 24 bits in f32 and 53 bits in f64. +// they fit in the significand, which is: +// * 11 bits in f16 +// * 24 bits in f32 +// * 53 bits in f64 +// * 113 bits in f128 // Lossy float conversions are not implemented at this time. +// FIXME(f16_f128): The `f16`/`f128` impls `#[stable]` attributes should be changed to reference +// `f16`/`f128` when they are stabilised (trait impls have to have a `#[stable]` attribute, but none +// of the `f16`/`f128` impls can be used on stable as the `f16` and `f128` types are unstable). // signed integer -> float +impl_from!(i8 => f16, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(i8 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(i8 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(i8 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(i16 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(i16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(i16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(i32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(i32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +// FIXME(f16_f128): This impl would allow using `f128` on stable before it is stabilised. +// impl_from!(i64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); // unsigned integer -> float +impl_from!(u8 => f16, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(u8 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(u8 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(u8 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(u16 => f16, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(u16 => f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(u16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(u16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); impl_from!(u32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +impl_from!(u32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); +// FIXME(f16_f128): This impl would allow using `f128` on stable before it is stabilised. +// impl_from!(u64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); // float -> float // FIXME(f16_f128): adding additional `From<{float}>` impls to `f32` breaks inference. See @@ -174,7 +194,12 @@ impl_from!(f32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0 impl_from!(f64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]); macro_rules! impl_float_from_bool { - ($float:ty) => { + ( + $float:ty $(; + doctest_prefix: $(#[doc = $doctest_prefix:literal])* + doctest_suffix: $(#[doc = $doctest_suffix:literal])* + )? + ) => { #[stable(feature = "float_from_bool", since = "1.68.0")] impl From<bool> for $float { #[doc = concat!("Converts a [`bool`] to [`", stringify!($float),"`] losslessly.")] @@ -182,12 +207,14 @@ macro_rules! impl_float_from_bool { /// /// # Examples /// ``` + $($(#[doc = $doctest_prefix])*)? #[doc = concat!("let x: ", stringify!($float)," = false.into();")] /// assert_eq!(x, 0.0); /// assert!(x.is_sign_positive()); /// #[doc = concat!("let y: ", stringify!($float)," = true.into();")] /// assert_eq!(y, 1.0); + $($(#[doc = $doctest_suffix])*)? /// ``` #[inline] fn from(small: bool) -> Self { @@ -198,8 +225,27 @@ macro_rules! impl_float_from_bool { } // boolean -> float +impl_float_from_bool!( + f16; + doctest_prefix: + // rustdoc doesn't remove the conventional space after the `///` + ///#![feature(f16)] + ///# #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + doctest_suffix: + ///# } +); impl_float_from_bool!(f32); impl_float_from_bool!(f64); +impl_float_from_bool!( + f128; + doctest_prefix: + ///#![feature(f128)] + ///# #[cfg(all(target_arch = "x86_64", target_os = "linux"))] { + /// + doctest_suffix: + ///# } +); // no possible bounds violation macro_rules! impl_try_from_unbounded { diff --git a/library/core/src/default.rs b/library/core/src/default.rs index 4c30290ff26..044997a81a9 100644 --- a/library/core/src/default.rs +++ b/library/core/src/default.rs @@ -101,7 +101,7 @@ use crate::ascii::Char as AsciiChar; /// bar: f32, /// } /// ``` -#[cfg_attr(not(test), rustc_diagnostic_item = "Default")] +#[rustc_diagnostic_item = "Default"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_trivial_field_reads] pub trait Default: Sized { diff --git a/library/core/src/error.rs b/library/core/src/error.rs index 94847685ec9..bfa392003b9 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -47,7 +47,7 @@ use crate::fmt::{self, Debug, Display, Formatter}; /// impl Error for ReadConfigError {} /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "Error")] +#[rustc_diagnostic_item = "Error"] #[rustc_has_incoherent_inherent_impls] #[allow(multiple_supertrait_upcastable)] pub trait Error: Debug + Display { diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs index 4a43c12be9a..870ad9df4fd 100644 --- a/library/core/src/fmt/float.rs +++ b/library/core/src/fmt/float.rs @@ -86,7 +86,7 @@ where true => flt2dec::Sign::MinusPlus, }; - if let Some(precision) = fmt.options.precision { + if let Some(precision) = fmt.options.get_precision() { float_to_decimal_common_exact(fmt, num, sign, precision) } else { let min_precision = 0; @@ -162,7 +162,7 @@ where true => flt2dec::Sign::MinusPlus, }; - if let Some(precision) = fmt.options.precision { + if let Some(precision) = fmt.options.get_precision() { // 1 integral digit + `precision` fractional digits = `precision + 1` total digits float_to_exponential_common_exact(fmt, num, sign, precision + 1, upper) } else { @@ -180,7 +180,7 @@ where true => flt2dec::Sign::MinusPlus, }; - if let Some(precision) = fmt.options.precision { + if let Some(precision) = fmt.options.get_precision() { // this behavior of {:.PREC?} predates exponential formatting for {:?} float_to_decimal_common_exact(fmt, num, sign, precision) } else { diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index e0dc632df70..30fd2d7815f 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -18,7 +18,7 @@ mod num; mod rt; #[stable(feature = "fmt_flags_align", since = "1.28.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "Alignment")] +#[rustc_diagnostic_item = "Alignment"] /// Possible alignments returned by `Formatter::align` #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Alignment { @@ -33,19 +33,6 @@ pub enum Alignment { Center, } -#[doc(hidden)] -#[unstable(feature = "fmt_internals", reason = "internal to standard library", issue = "none")] -impl From<rt::Alignment> for Option<Alignment> { - fn from(value: rt::Alignment) -> Self { - match value { - rt::Alignment::Left => Some(Alignment::Left), - rt::Alignment::Right => Some(Alignment::Right), - rt::Alignment::Center => Some(Alignment::Center), - rt::Alignment::Unknown => None, - } - } -} - #[stable(feature = "debug_builders", since = "1.2.0")] pub use self::builders::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple}; #[unstable(feature = "debug_closure_helpers", issue = "117729")] @@ -291,11 +278,52 @@ pub enum DebugAsHex { #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[unstable(feature = "formatting_options", issue = "118117")] pub struct FormattingOptions { + /// Flags, with the following bit fields: + /// + /// ```text + /// 31 30 29 28 27 26 25 24 23 22 21 20 0 + /// ┌───┬───────┬───┬───┬───┬───┬───┬───┬───┬───┬──────────────────────────────────┐ + /// │ 1 │ align │ p │ w │ X?│ x?│'0'│ # │ - │ + │ fill │ + /// └───┴───────┴───┴───┴───┴───┴───┴───┴───┴───┴──────────────────────────────────┘ + /// │ │ │ │ └─┬───────────────────┘ └─┬──────────────────────────────┘ + /// │ │ │ │ │ └─ The fill character (21 bits char). + /// │ │ │ │ └─ The debug upper/lower hex, zero pad, alternate, and plus/minus flags. + /// │ │ │ └─ Whether a width is set. (The value is stored separately.) + /// │ │ └─ Whether a precision is set. (The value is stored separately.) + /// │ ├─ 0: Align left. (<) + /// │ ├─ 1: Align right. (>) + /// │ ├─ 2: Align center. (^) + /// │ └─ 3: Alignment not set. (default) + /// └─ Always set. + /// This makes it possible to distinguish formatting flags from + /// a &str size when stored in (the upper bits of) the same field. + /// (fmt::Arguments will make use of this property in the future.) + /// ``` + // Note: This could use a special niche type with range 0x8000_0000..=0xfdd0ffff. + // It's unclear if that's useful, though. flags: u32, - fill: char, - align: Option<Alignment>, - width: Option<u16>, - precision: Option<u16>, + /// Width if width flag (bit 27) above is set. Otherwise, always 0. + width: u16, + /// Precision if precision flag (bit 28) above is set. Otherwise, always 0. + precision: u16, +} + +// This needs to match with compiler/rustc_ast_lowering/src/format.rs. +mod flags { + pub(super) const SIGN_PLUS_FLAG: u32 = 1 << 21; + pub(super) const SIGN_MINUS_FLAG: u32 = 1 << 22; + pub(super) const ALTERNATE_FLAG: u32 = 1 << 23; + pub(super) const SIGN_AWARE_ZERO_PAD_FLAG: u32 = 1 << 24; + pub(super) const DEBUG_LOWER_HEX_FLAG: u32 = 1 << 25; + pub(super) const DEBUG_UPPER_HEX_FLAG: u32 = 1 << 26; + pub(super) const WIDTH_FLAG: u32 = 1 << 27; + pub(super) const PRECISION_FLAG: u32 = 1 << 28; + pub(super) const ALIGN_BITS: u32 = 0b11 << 29; + pub(super) const ALIGN_LEFT: u32 = 0 << 29; + pub(super) const ALIGN_RIGHT: u32 = 1 << 29; + pub(super) const ALIGN_CENTER: u32 = 2 << 29; + pub(super) const ALIGN_UNKNOWN: u32 = 3 << 29; + pub(super) const ALWAYS_SET: u32 = 1 << 31; } impl FormattingOptions { @@ -311,7 +339,11 @@ impl FormattingOptions { /// - no [`DebugAsHex`] output mode. #[unstable(feature = "formatting_options", issue = "118117")] pub const fn new() -> Self { - Self { flags: 0, fill: ' ', align: None, width: None, precision: None } + Self { + flags: ' ' as u32 | flags::ALIGN_UNKNOWN | flags::ALWAYS_SET, + width: 0, + precision: 0, + } } /// Sets or removes the sign (the `+` or the `-` flag). @@ -324,13 +356,12 @@ impl FormattingOptions { /// - `-`: Currently not used #[unstable(feature = "formatting_options", issue = "118117")] pub fn sign(&mut self, sign: Option<Sign>) -> &mut Self { - self.flags = - self.flags & !(1 << rt::Flag::SignMinus as u32 | 1 << rt::Flag::SignPlus as u32); - match sign { - None => {} - Some(Sign::Plus) => self.flags |= 1 << rt::Flag::SignPlus as u32, - Some(Sign::Minus) => self.flags |= 1 << rt::Flag::SignMinus as u32, - } + let sign = match sign { + None => 0, + Some(Sign::Plus) => flags::SIGN_PLUS_FLAG, + Some(Sign::Minus) => flags::SIGN_MINUS_FLAG, + }; + self.flags = self.flags & !(flags::SIGN_PLUS_FLAG | flags::SIGN_MINUS_FLAG) | sign; self } /// Sets or unsets the `0` flag. @@ -339,9 +370,9 @@ impl FormattingOptions { #[unstable(feature = "formatting_options", issue = "118117")] pub fn sign_aware_zero_pad(&mut self, sign_aware_zero_pad: bool) -> &mut Self { if sign_aware_zero_pad { - self.flags |= 1 << rt::Flag::SignAwareZeroPad as u32 + self.flags |= flags::SIGN_AWARE_ZERO_PAD_FLAG; } else { - self.flags &= !(1 << rt::Flag::SignAwareZeroPad as u32) + self.flags &= !flags::SIGN_AWARE_ZERO_PAD_FLAG; } self } @@ -356,9 +387,9 @@ impl FormattingOptions { #[unstable(feature = "formatting_options", issue = "118117")] pub fn alternate(&mut self, alternate: bool) -> &mut Self { if alternate { - self.flags |= 1 << rt::Flag::Alternate as u32 + self.flags |= flags::ALTERNATE_FLAG; } else { - self.flags &= !(1 << rt::Flag::Alternate as u32) + self.flags &= !flags::ALTERNATE_FLAG; } self } @@ -370,7 +401,7 @@ impl FormattingOptions { /// printed around it. #[unstable(feature = "formatting_options", issue = "118117")] pub fn fill(&mut self, fill: char) -> &mut Self { - self.fill = fill; + self.flags = self.flags & (u32::MAX << 21) | fill as u32; self } /// Sets or removes the alignment. @@ -379,7 +410,13 @@ impl FormattingOptions { /// positioned if it is smaller than the width of the formatter. #[unstable(feature = "formatting_options", issue = "118117")] pub fn align(&mut self, align: Option<Alignment>) -> &mut Self { - self.align = align; + let align: u32 = match align { + Some(Alignment::Left) => flags::ALIGN_LEFT, + Some(Alignment::Right) => flags::ALIGN_RIGHT, + Some(Alignment::Center) => flags::ALIGN_CENTER, + None => flags::ALIGN_UNKNOWN, + }; + self.flags = self.flags & !flags::ALIGN_BITS | align; self } /// Sets or removes the width. @@ -390,7 +427,13 @@ impl FormattingOptions { /// will be used to take up the required space. #[unstable(feature = "formatting_options", issue = "118117")] pub fn width(&mut self, width: Option<u16>) -> &mut Self { - self.width = width; + if let Some(width) = width { + self.flags |= flags::WIDTH_FLAG; + self.width = width; + } else { + self.flags &= !flags::WIDTH_FLAG; + self.width = 0; + } self } /// Sets or removes the precision. @@ -404,77 +447,85 @@ impl FormattingOptions { /// decimal point should be printed. #[unstable(feature = "formatting_options", issue = "118117")] pub fn precision(&mut self, precision: Option<u16>) -> &mut Self { - self.precision = precision; + if let Some(precision) = precision { + self.flags |= flags::PRECISION_FLAG; + self.precision = precision; + } else { + self.flags &= !flags::PRECISION_FLAG; + self.precision = 0; + } self } /// Specifies whether the [`Debug`] trait should use lower-/upper-case /// hexadecimal or normal integers #[unstable(feature = "formatting_options", issue = "118117")] pub fn debug_as_hex(&mut self, debug_as_hex: Option<DebugAsHex>) -> &mut Self { - self.flags = self.flags - & !(1 << rt::Flag::DebugUpperHex as u32 | 1 << rt::Flag::DebugLowerHex as u32); - match debug_as_hex { - None => {} - Some(DebugAsHex::Upper) => self.flags |= 1 << rt::Flag::DebugUpperHex as u32, - Some(DebugAsHex::Lower) => self.flags |= 1 << rt::Flag::DebugLowerHex as u32, - } + let debug_as_hex = match debug_as_hex { + None => 0, + Some(DebugAsHex::Lower) => flags::DEBUG_LOWER_HEX_FLAG, + Some(DebugAsHex::Upper) => flags::DEBUG_UPPER_HEX_FLAG, + }; + self.flags = self.flags & !(flags::DEBUG_LOWER_HEX_FLAG | flags::DEBUG_UPPER_HEX_FLAG) + | debug_as_hex; self } /// Returns the current sign (the `+` or the `-` flag). #[unstable(feature = "formatting_options", issue = "118117")] pub const fn get_sign(&self) -> Option<Sign> { - const SIGN_PLUS_BITFIELD: u32 = 1 << rt::Flag::SignPlus as u32; - const SIGN_MINUS_BITFIELD: u32 = 1 << rt::Flag::SignMinus as u32; - match self.flags & ((1 << rt::Flag::SignPlus as u32) | (1 << rt::Flag::SignMinus as u32)) { - SIGN_PLUS_BITFIELD => Some(Sign::Plus), - SIGN_MINUS_BITFIELD => Some(Sign::Minus), - 0 => None, - _ => panic!("Invalid sign bits set in flags"), + if self.flags & flags::SIGN_PLUS_FLAG != 0 { + Some(Sign::Plus) + } else if self.flags & flags::SIGN_MINUS_FLAG != 0 { + Some(Sign::Minus) + } else { + None } } /// Returns the current `0` flag. #[unstable(feature = "formatting_options", issue = "118117")] pub const fn get_sign_aware_zero_pad(&self) -> bool { - self.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0 + self.flags & flags::SIGN_AWARE_ZERO_PAD_FLAG != 0 } /// Returns the current `#` flag. #[unstable(feature = "formatting_options", issue = "118117")] pub const fn get_alternate(&self) -> bool { - self.flags & (1 << rt::Flag::Alternate as u32) != 0 + self.flags & flags::ALTERNATE_FLAG != 0 } /// Returns the current fill character. #[unstable(feature = "formatting_options", issue = "118117")] pub const fn get_fill(&self) -> char { - self.fill + // SAFETY: We only ever put a valid `char` in the lower 21 bits of the flags field. + unsafe { char::from_u32_unchecked(self.flags & 0x1FFFFF) } } /// Returns the current alignment. #[unstable(feature = "formatting_options", issue = "118117")] pub const fn get_align(&self) -> Option<Alignment> { - self.align + match self.flags & flags::ALIGN_BITS { + flags::ALIGN_LEFT => Some(Alignment::Left), + flags::ALIGN_RIGHT => Some(Alignment::Right), + flags::ALIGN_CENTER => Some(Alignment::Center), + _ => None, + } } /// Returns the current width. #[unstable(feature = "formatting_options", issue = "118117")] pub const fn get_width(&self) -> Option<u16> { - self.width + if self.flags & flags::WIDTH_FLAG != 0 { Some(self.width) } else { None } } /// Returns the current precision. #[unstable(feature = "formatting_options", issue = "118117")] pub const fn get_precision(&self) -> Option<u16> { - self.precision + if self.flags & flags::PRECISION_FLAG != 0 { Some(self.precision) } else { None } } /// Returns the current precision. #[unstable(feature = "formatting_options", issue = "118117")] pub const fn get_debug_as_hex(&self) -> Option<DebugAsHex> { - const DEBUG_UPPER_BITFIELD: u32 = 1 << rt::Flag::DebugUpperHex as u32; - const DEBUG_LOWER_BITFIELD: u32 = 1 << rt::Flag::DebugLowerHex as u32; - match self.flags - & ((1 << rt::Flag::DebugUpperHex as u32) | (1 << rt::Flag::DebugLowerHex as u32)) - { - DEBUG_UPPER_BITFIELD => Some(DebugAsHex::Upper), - DEBUG_LOWER_BITFIELD => Some(DebugAsHex::Lower), - 0 => None, - _ => panic!("Invalid hex debug bits set in flags"), + if self.flags & flags::DEBUG_LOWER_HEX_FLAG != 0 { + Some(DebugAsHex::Lower) + } else if self.flags & flags::DEBUG_UPPER_HEX_FLAG != 0 { + Some(DebugAsHex::Upper) + } else { + None } } @@ -485,27 +536,6 @@ impl FormattingOptions { pub fn create_formatter<'a>(self, write: &'a mut (dyn Write + 'a)) -> Formatter<'a> { Formatter { options: self, buf: write } } - - #[doc(hidden)] - #[unstable( - feature = "fmt_internals", - reason = "internal routines only exposed for testing", - issue = "none" - )] - /// Flags for formatting - pub fn flags(&mut self, flags: u32) { - self.flags = flags - } - #[doc(hidden)] - #[unstable( - feature = "fmt_internals", - reason = "internal routines only exposed for testing", - issue = "none" - )] - /// Flags for formatting - pub fn get_flags(&self) -> u32 { - self.flags - } } #[unstable(feature = "formatting_options", issue = "118117")] @@ -710,9 +740,10 @@ impl<'a> Arguments<'a> { } /// Same as [`Arguments::as_str`], but will only return `Some(s)` if it can be determined at compile time. + #[unstable(feature = "fmt_internals", reason = "internal to standard library", issue = "none")] #[must_use] #[inline] - fn as_statically_known_str(&self) -> Option<&'static str> { + pub fn as_statically_known_str(&self) -> Option<&'static str> { let s = self.as_str(); if core::intrinsics::is_val_statically_known(s.is_some()) { s } else { None } } @@ -1478,15 +1509,25 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { } unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argument<'_>]) -> Result { - fmt.options.fill = arg.fill; - fmt.options.align = arg.align.into(); - fmt.options.flags = arg.flags; - // SAFETY: arg and args come from the same Arguments, - // which guarantees the indexes are always within bounds. - unsafe { - fmt.options.width = getcount(args, &arg.width); - fmt.options.precision = getcount(args, &arg.precision); - } + let (width, precision) = + // SAFETY: arg and args come from the same Arguments, + // which guarantees the indexes are always within bounds. + unsafe { (getcount(args, &arg.width), getcount(args, &arg.precision)) }; + + #[cfg(bootstrap)] + let options = + *FormattingOptions { flags: flags::ALWAYS_SET | arg.flags << 21, width: 0, precision: 0 } + .align(match arg.align { + rt::Alignment::Left => Some(Alignment::Left), + rt::Alignment::Right => Some(Alignment::Right), + rt::Alignment::Center => Some(Alignment::Center), + rt::Alignment::Unknown => None, + }) + .fill(arg.fill) + .width(width) + .precision(precision); + #[cfg(not(bootstrap))] + let options = FormattingOptions { flags: arg.flags, width, precision }; // Extract the correct argument debug_assert!(arg.position < args.len()); @@ -1494,17 +1535,18 @@ unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argume // which guarantees its index is always within bounds. let value = unsafe { args.get_unchecked(arg.position) }; + // Set all the formatting options. + fmt.options = options; + // Then actually do some printing // SAFETY: this is a placeholder argument. unsafe { value.fmt(fmt) } } +#[cfg(bootstrap)] unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<u16> { match *cnt { - #[cfg(bootstrap)] rt::Count::Is(n) => Some(n as u16), - #[cfg(not(bootstrap))] - rt::Count::Is(n) => Some(n), rt::Count::Implied => None, rt::Count::Param(i) => { debug_assert!(i < args.len()); @@ -1515,6 +1557,20 @@ unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<u16> { } } +#[cfg(not(bootstrap))] +unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> u16 { + match *cnt { + rt::Count::Is(n) => n, + rt::Count::Implied => 0, + rt::Count::Param(i) => { + debug_assert!(i < args.len()); + // SAFETY: cnt and args come from the same Arguments, + // which guarantees this index is always within bounds. + unsafe { args.get_unchecked(i).as_u16().unwrap_unchecked() } + } + } +} + /// Padding after the end of something. Returned by `Formatter::padding`. #[must_use = "don't forget to write the post padding"] pub(crate) struct PostPadding { @@ -1628,40 +1684,28 @@ impl<'a> Formatter<'a> { } // The `width` field is more of a `min-width` parameter at this point. - match self.options.width { - // If there's no minimum length requirements then we can just - // write the bytes. - None => { - write_prefix(self, sign, prefix)?; - self.buf.write_str(buf) - } - // Check if we're over the minimum width, if so then we can also - // just write the bytes. - Some(min) if width >= usize::from(min) => { - write_prefix(self, sign, prefix)?; - self.buf.write_str(buf) - } + let min = self.options.width; + if width >= usize::from(min) { + // We're over the minimum width, so then we can just write the bytes. + write_prefix(self, sign, prefix)?; + self.buf.write_str(buf) + } else if self.sign_aware_zero_pad() { // The sign and prefix goes before the padding if the fill character // is zero - Some(min) if self.sign_aware_zero_pad() => { - let old_fill = crate::mem::replace(&mut self.options.fill, '0'); - let old_align = - crate::mem::replace(&mut self.options.align, Some(Alignment::Right)); - write_prefix(self, sign, prefix)?; - let post_padding = self.padding(min - width as u16, Alignment::Right)?; - self.buf.write_str(buf)?; - post_padding.write(self)?; - self.options.fill = old_fill; - self.options.align = old_align; - Ok(()) - } + let old_options = self.options; + self.options.fill('0').align(Some(Alignment::Right)); + write_prefix(self, sign, prefix)?; + let post_padding = self.padding(min - width as u16, Alignment::Right)?; + self.buf.write_str(buf)?; + post_padding.write(self)?; + self.options = old_options; + Ok(()) + } else { // Otherwise, the sign and prefix goes after the padding - Some(min) => { - let post_padding = self.padding(min - width as u16, Alignment::Right)?; - write_prefix(self, sign, prefix)?; - self.buf.write_str(buf)?; - post_padding.write(self) - } + let post_padding = self.padding(min - width as u16, Alignment::Right)?; + write_prefix(self, sign, prefix)?; + self.buf.write_str(buf)?; + post_padding.write(self) } } @@ -1697,13 +1741,13 @@ impl<'a> Formatter<'a> { #[stable(feature = "rust1", since = "1.0.0")] pub fn pad(&mut self, s: &str) -> Result { // Make sure there's a fast path up front. - if self.options.width.is_none() && self.options.precision.is_none() { + if self.options.flags & (flags::WIDTH_FLAG | flags::PRECISION_FLAG) == 0 { return self.buf.write_str(s); } // The `precision` field can be interpreted as a maximum width for the // string being formatted. - let (s, char_count) = if let Some(max_char_count) = self.options.precision { + let (s, char_count) = if let Some(max_char_count) = self.options.get_precision() { let mut iter = s.char_indices(); let remaining = match iter.advance_by(usize::from(max_char_count)) { Ok(()) => 0, @@ -1719,12 +1763,11 @@ impl<'a> Formatter<'a> { }; // The `width` field is more of a minimum width parameter at this point. - if let Some(width) = self.options.width - && char_count < usize::from(width) - { + if char_count < usize::from(self.options.width) { // If we're under the minimum width, then fill up the minimum width // with the specified string + some alignment. - let post_padding = self.padding(width - char_count as u16, Alignment::Left)?; + let post_padding = + self.padding(self.options.width - char_count as u16, Alignment::Left)?; self.buf.write_str(s)?; post_padding.write(self) } else { @@ -1743,19 +1786,20 @@ impl<'a> Formatter<'a> { padding: u16, default: Alignment, ) -> result::Result<PostPadding, Error> { - let align = self.align().unwrap_or(default); + let align = self.options.get_align().unwrap_or(default); + let fill = self.options.get_fill(); - let (pre_pad, post_pad) = match align { - Alignment::Left => (0, padding), - Alignment::Right => (padding, 0), - Alignment::Center => (padding / 2, (padding + 1) / 2), + let padding_left = match align { + Alignment::Left => 0, + Alignment::Right => padding, + Alignment::Center => padding / 2, }; - for _ in 0..pre_pad { - self.buf.write_char(self.options.fill)?; + for _ in 0..padding_left { + self.buf.write_char(fill)?; } - Ok(PostPadding::new(self.options.fill, post_pad)) + Ok(PostPadding::new(fill, padding - padding_left)) } /// Takes the formatted parts and applies the padding. @@ -1767,12 +1811,16 @@ impl<'a> Formatter<'a> { /// /// Any `numfmt::Part::Copy` parts in `formatted` must contain valid UTF-8. unsafe fn pad_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result { - if let Some(mut width) = self.options.width { + if self.options.width == 0 { + // this is the common case and we take a shortcut + // SAFETY: Per the precondition. + unsafe { self.write_formatted_parts(formatted) } + } else { // for the sign-aware zero padding, we render the sign first and // behave as if we had no sign from the beginning. let mut formatted = formatted.clone(); - let old_fill = self.options.fill; - let old_align = self.options.align; + let mut width = self.options.width; + let old_options = self.options; if self.sign_aware_zero_pad() { // a sign always goes first let sign = formatted.sign; @@ -1781,8 +1829,7 @@ impl<'a> Formatter<'a> { // remove the sign from the formatted parts formatted.sign = ""; width = width.saturating_sub(sign.len() as u16); - self.options.fill = '0'; - self.options.align = Some(Alignment::Right); + self.options.fill('0').align(Some(Alignment::Right)); } // remaining parts go through the ordinary padding process. @@ -1799,13 +1846,8 @@ impl<'a> Formatter<'a> { } post_padding.write(self) }; - self.options.fill = old_fill; - self.options.align = old_align; + self.options = old_options; ret - } else { - // this is the common case and we take a shortcut - // SAFETY: Per the precondition. - unsafe { self.write_formatted_parts(formatted) } } } @@ -1926,7 +1968,9 @@ impl<'a> Formatter<'a> { or `sign_aware_zero_pad` methods instead" )] pub fn flags(&self) -> u32 { - self.options.flags + // Extract the debug upper/lower hex, zero pad, alternate, and plus/minus flags + // to stay compatible with older versions of Rust. + self.options.flags >> 21 & 0x3F } /// Returns the character used as 'fill' whenever there is alignment. @@ -1959,7 +2003,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn fill(&self) -> char { - self.options.fill + self.options.get_fill() } /// Returns a flag indicating what form of alignment was requested. @@ -1994,7 +2038,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags_align", since = "1.28.0")] pub fn align(&self) -> Option<Alignment> { - self.options.align + self.options.get_align() } /// Returns the optionally specified integer width that the output should be. @@ -2024,7 +2068,11 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn width(&self) -> Option<usize> { - self.options.width.map(|x| x as usize) + if self.options.flags & flags::WIDTH_FLAG == 0 { + None + } else { + Some(self.options.width as usize) + } } /// Returns the optionally specified precision for numeric types. @@ -2055,7 +2103,11 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn precision(&self) -> Option<usize> { - self.options.precision.map(|x| x as usize) + if self.options.flags & flags::PRECISION_FLAG == 0 { + None + } else { + Some(self.options.precision as usize) + } } /// Determines if the `+` flag was specified. @@ -2087,7 +2139,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn sign_plus(&self) -> bool { - self.options.flags & (1 << rt::Flag::SignPlus as u32) != 0 + self.options.flags & flags::SIGN_PLUS_FLAG != 0 } /// Determines if the `-` flag was specified. @@ -2116,7 +2168,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn sign_minus(&self) -> bool { - self.options.flags & (1 << rt::Flag::SignMinus as u32) != 0 + self.options.flags & flags::SIGN_MINUS_FLAG != 0 } /// Determines if the `#` flag was specified. @@ -2144,7 +2196,7 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn alternate(&self) -> bool { - self.options.flags & (1 << rt::Flag::Alternate as u32) != 0 + self.options.flags & flags::ALTERNATE_FLAG != 0 } /// Determines if the `0` flag was specified. @@ -2170,17 +2222,16 @@ impl<'a> Formatter<'a> { #[must_use] #[stable(feature = "fmt_flags", since = "1.5.0")] pub fn sign_aware_zero_pad(&self) -> bool { - self.options.flags & (1 << rt::Flag::SignAwareZeroPad as u32) != 0 + self.options.flags & flags::SIGN_AWARE_ZERO_PAD_FLAG != 0 } // FIXME: Decide what public API we want for these two flags. // https://github.com/rust-lang/rust/issues/48584 fn debug_lower_hex(&self) -> bool { - self.options.flags & (1 << rt::Flag::DebugLowerHex as u32) != 0 + self.options.flags & flags::DEBUG_LOWER_HEX_FLAG != 0 } - fn debug_upper_hex(&self) -> bool { - self.options.flags & (1 << rt::Flag::DebugUpperHex as u32) != 0 + self.options.flags & flags::DEBUG_UPPER_HEX_FLAG != 0 } /// Creates a [`DebugStruct`] builder designed to assist with creation of @@ -2760,7 +2811,7 @@ impl Debug for char { #[stable(feature = "rust1", since = "1.0.0")] impl Display for char { fn fmt(&self, f: &mut Formatter<'_>) -> Result { - if f.options.width.is_none() && f.options.precision.is_none() { + if f.options.flags & (flags::WIDTH_FLAG | flags::PRECISION_FLAG) == 0 { f.write_char(*self) } else { f.pad(self.encode_utf8(&mut [0; MAX_LEN_UTF8])) @@ -2771,7 +2822,14 @@ impl Display for char { #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> Pointer for *const T { fn fmt(&self, f: &mut Formatter<'_>) -> Result { - pointer_fmt_inner(self.expose_provenance(), f) + if <<T as core::ptr::Pointee>::Metadata as core::unit::IsUnit>::is_unit() { + pointer_fmt_inner(self.expose_provenance(), f) + } else { + f.debug_struct("Pointer") + .field_with("addr", |f| pointer_fmt_inner(self.expose_provenance(), f)) + .field("metadata", &core::ptr::metadata(*self)) + .finish() + } } } @@ -2784,26 +2842,24 @@ impl<T: ?Sized> Pointer for *const T { /// /// [problematic]: https://github.com/rust-lang/rust/issues/95489 pub(crate) fn pointer_fmt_inner(ptr_addr: usize, f: &mut Formatter<'_>) -> Result { - let old_width = f.options.width; - let old_flags = f.options.flags; + let old_options = f.options; // The alternate flag is already treated by LowerHex as being special- // it denotes whether to prefix with 0x. We use it to work out whether // or not to zero extend, and then unconditionally set it to get the // prefix. - if f.alternate() { - f.options.flags |= 1 << (rt::Flag::SignAwareZeroPad as u32); + if f.options.get_alternate() { + f.options.sign_aware_zero_pad(true); - if f.options.width.is_none() { - f.options.width = Some((usize::BITS / 4) as u16 + 2); + if f.options.get_width().is_none() { + f.options.width(Some((usize::BITS / 4) as u16 + 2)); } } - f.options.flags |= 1 << (rt::Flag::Alternate as u32); + f.options.alternate(true); let ret = LowerHex::fmt(&ptr_addr, f); - f.options.width = old_width; - f.options.flags = old_flags; + f.options = old_options; ret } diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs index 080fc6ddfc9..d27f7e6e0d8 100644 --- a/library/core/src/fmt/rt.rs +++ b/library/core/src/fmt/rt.rs @@ -11,7 +11,9 @@ use crate::ptr::NonNull; #[derive(Copy, Clone)] pub struct Placeholder { pub position: usize, + #[cfg(bootstrap)] pub fill: char, + #[cfg(bootstrap)] pub align: Alignment, pub flags: u32, pub precision: Count, @@ -19,6 +21,7 @@ pub struct Placeholder { } impl Placeholder { + #[cfg(bootstrap)] #[inline] pub const fn new( position: usize, @@ -30,8 +33,15 @@ impl Placeholder { ) -> Self { Self { position, fill, align, flags, precision, width } } + + #[cfg(not(bootstrap))] + #[inline] + pub const fn new(position: usize, flags: u32, precision: Count, width: Count) -> Self { + Self { position, flags, precision, width } + } } +#[cfg(bootstrap)] #[lang = "format_alignment"] #[derive(Copy, Clone, PartialEq, Eq)] pub enum Alignment { @@ -58,17 +68,6 @@ pub enum Count { Implied, } -// This needs to match the order of flags in compiler/rustc_ast_lowering/src/format.rs. -#[derive(Copy, Clone)] -pub(super) enum Flag { - SignPlus, - SignMinus, - Alternate, - SignAwareZeroPad, - DebugLowerHex, - DebugUpperHex, -} - #[derive(Copy, Clone)] enum ArgumentType<'a> { Placeholder { diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 48b265fabc7..81e59a1f349 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -1774,10 +1774,14 @@ pub fn ptr_mask<T>(ptr: *const T, mask: usize) -> *const T; /// a size of `count` * `size_of::<T>()` and an alignment of /// `min_align_of::<T>()` /// -/// The volatile parameter is set to `true`, so it will not be optimized out -/// unless size is equal to zero. -/// /// This intrinsic does not have a stable counterpart. +/// # Safety +/// +/// The safety requirements are consistent with [`copy_nonoverlapping`] +/// while the read and write behaviors are volatile, +/// which means it will not be optimized out unless `_count` or `size_of::<T>()` is equal to zero. +/// +/// [`copy_nonoverlapping`]: ptr::copy_nonoverlapping #[rustc_intrinsic] #[rustc_nounwind] pub unsafe fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: usize); @@ -1796,10 +1800,13 @@ pub unsafe fn volatile_copy_memory<T>(dst: *mut T, src: *const T, count: usize); /// size of `count * size_of::<T>()` and an alignment of /// `min_align_of::<T>()`. /// -/// The volatile parameter is set to `true`, so it will not be optimized out -/// unless size is equal to zero. -/// /// This intrinsic does not have a stable counterpart. +/// # Safety +/// +/// The safety requirements are consistent with [`write_bytes`] while the write behavior is volatile, +/// which means it will not be optimized out unless `_count` or `size_of::<T>()` is equal to zero. +/// +/// [`write_bytes`]: ptr::write_bytes #[rustc_intrinsic] #[rustc_nounwind] pub unsafe fn volatile_set_memory<T>(dst: *mut T, val: u8, count: usize); @@ -2995,6 +3002,7 @@ pub const fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discrimina /// Rust's "try catch" construct for unwinding. Invokes the function pointer `try_fn` with the /// data pointer `data`, and calls `catch_fn` if unwinding occurs while `try_fn` runs. +/// Returns `1` if unwinding occurred and `catch_fn` was called; returns `0` otherwise. /// /// `catch_fn` must not unwind. /// @@ -3341,8 +3349,18 @@ pub const fn is_val_statically_known<T: Copy>(_arg: T) -> bool { /// The stabilized form of this intrinsic is [`crate::mem::swap`]. /// /// # Safety +/// Behavior is undefined if any of the following conditions are violated: +/// +/// * Both `x` and `y` must be [valid] for both reads and writes. /// -/// `x` and `y` are readable and writable as `T`, and non-overlapping. +/// * Both `x` and `y` must be properly aligned. +/// +/// * The region of memory beginning at `x` must *not* overlap with the region of memory +/// beginning at `y`. +/// +/// * The memory pointed by `x` and `y` must both contain values of type `T`. +/// +/// [valid]: crate::ptr#safety #[rustc_nounwind] #[inline] #[rustc_intrinsic] @@ -3624,7 +3642,8 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(ptr: *const /// For regions of memory which might overlap, use [`copy`] instead. /// /// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but -/// with the argument order swapped. +/// with the source and destination arguments swapped, +/// and `count` counting the number of `T`s instead of bytes. /// /// The copy is "untyped" in the sense that data may be uninitialized or otherwise violate the /// requirements of `T`. The initialization state is preserved exactly. @@ -3744,8 +3763,10 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us /// If the source and destination will *never* overlap, /// [`copy_nonoverlapping`] can be used instead. /// -/// `copy` is semantically equivalent to C's [`memmove`], but with the argument -/// order swapped. Copying takes place as if the bytes were copied from `src` +/// `copy` is semantically equivalent to C's [`memmove`], but +/// with the source and destination arguments swapped, +/// and `count` counting the number of `T`s instead of bytes. +/// Copying takes place as if the bytes were copied from `src` /// to a temporary array and then copied from the array to `dst`. /// /// The copy is "untyped" in the sense that data may be uninitialized or otherwise violate the diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs index ac15e3767fc..f9c388e8564 100644 --- a/library/core/src/iter/adapters/enumerate.rs +++ b/library/core/src/iter/adapters/enumerate.rs @@ -14,7 +14,7 @@ use crate::ops::Try; #[derive(Clone, Debug)] #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "Enumerate")] +#[rustc_diagnostic_item = "Enumerate"] pub struct Enumerate<I> { iter: I, count: usize, diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs index 9b9353b800a..a820045521b 100644 --- a/library/core/src/iter/adapters/flatten.rs +++ b/library/core/src/iter/adapters/flatten.rs @@ -172,61 +172,6 @@ where } } -/// Marker trait for iterators/iterables which have a statically known upper -/// bound of the number of items they can produce. -/// -/// # Safety -/// -/// Implementations must not yield more elements than indicated by UPPER_BOUND if it is `Some`. -/// Used in specializations. Implementations must not be conditional on lifetimes or -/// user-implementable traits. -#[rustc_specialization_trait] -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe trait BoundedSize { - const UPPER_BOUND: Option<NonZero<usize>> = NonZero::new(1); -} - -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<T> BoundedSize for Option<T> {} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<T> BoundedSize for option::IntoIter<T> {} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<T, U> BoundedSize for Result<T, U> {} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<T> BoundedSize for result::IntoIter<T> {} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<T> BoundedSize for Once<T> {} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<T> BoundedSize for OnceWith<T> {} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<T, const N: usize> BoundedSize for [T; N] { - const UPPER_BOUND: Option<NonZero<usize>> = NonZero::new(N); -} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<T, const N: usize> BoundedSize for array::IntoIter<T, N> { - const UPPER_BOUND: Option<NonZero<usize>> = NonZero::new(N); -} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<I: BoundedSize, P> BoundedSize for Filter<I, P> { - const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND; -} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<I: BoundedSize, P> BoundedSize for FilterMap<I, P> { - const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND; -} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<I: BoundedSize, F> BoundedSize for Map<I, F> { - const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND; -} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<I: BoundedSize> BoundedSize for Copied<I> { - const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND; -} -#[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl<I: BoundedSize> BoundedSize for Cloned<I> { - const UPPER_BOUND: Option<NonZero<usize>> = I::UPPER_BOUND; -} - /// An iterator that flattens one level of nesting in an iterator of things /// that can be turned into iterators. /// diff --git a/library/core/src/iter/sources/repeat.rs b/library/core/src/iter/sources/repeat.rs index 243f938bce2..c4f5a483e5c 100644 --- a/library/core/src/iter/sources/repeat.rs +++ b/library/core/src/iter/sources/repeat.rs @@ -56,7 +56,7 @@ use crate::num::NonZero; /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "iter_repeat")] +#[rustc_diagnostic_item = "iter_repeat"] pub fn repeat<T: Clone>(elt: T) -> Repeat<T> { Repeat { element: elt } } diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs index cc089c617c0..ada37b9af4c 100644 --- a/library/core/src/iter/sources/repeat_n.rs +++ b/library/core/src/iter/sources/repeat_n.rs @@ -1,7 +1,8 @@ use crate::fmt; use crate::iter::{FusedIterator, TrustedLen, UncheckedIterator}; -use crate::mem::{self, MaybeUninit}; +use crate::mem::MaybeUninit; use crate::num::NonZero; +use crate::ops::{NeverShortCircuit, Try}; /// Creates a new iterator that repeats a single element a given number of times. /// @@ -95,10 +96,10 @@ impl<A> RepeatN<A> { fn take_element(&mut self) -> Option<A> { if self.count > 0 { self.count = 0; - let element = mem::replace(&mut self.element, MaybeUninit::uninit()); // SAFETY: We just set count to zero so it won't be dropped again, // and it used to be non-zero so it hasn't already been dropped. - unsafe { Some(element.assume_init()) } + let element = unsafe { self.element.assume_init_read() }; + Some(element) } else { None } @@ -169,6 +170,39 @@ impl<A: Clone> Iterator for RepeatN<A> { } } + fn try_fold<B, F, R>(&mut self, mut acc: B, mut f: F) -> R + where + F: FnMut(B, A) -> R, + R: Try<Output = B>, + { + if self.count > 0 { + while self.count > 1 { + self.count -= 1; + // SAFETY: the count was larger than 1, so the element is + // initialized and hasn't been dropped. + acc = f(acc, unsafe { self.element.assume_init_ref().clone() })?; + } + + // We could just set the count to zero directly, but doing it this + // way should make it easier for the optimizer to fold this tail + // into the loop when `clone()` is equivalent to copying. + self.count -= 1; + // SAFETY: we just set the count to zero from one, so the element + // is still initialized, has not been dropped yet and will not be + // accessed by future calls. + f(acc, unsafe { self.element.assume_init_read() }) + } else { + try { acc } + } + } + + fn fold<B, F>(mut self, init: B, f: F) -> B + where + F: FnMut(B, A) -> B, + { + self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0 + } + #[inline] fn last(mut self) -> Option<A> { self.take_element() @@ -203,6 +237,23 @@ impl<A: Clone> DoubleEndedIterator for RepeatN<A> { fn nth_back(&mut self, n: usize) -> Option<A> { self.nth(n) } + + #[inline] + fn try_rfold<B, F, R>(&mut self, init: B, f: F) -> R + where + F: FnMut(B, A) -> R, + R: Try<Output = B>, + { + self.try_fold(init, f) + } + + #[inline] + fn rfold<B, F>(self, init: B, f: F) -> B + where + F: FnMut(B, A) -> B, + { + self.fold(init, f) + } } #[stable(feature = "iter_repeat_n", since = "1.82.0")] @@ -220,7 +271,7 @@ impl<A: Clone> UncheckedIterator for RepeatN<A> { // SAFETY: the check above ensured that the count used to be non-zero, // so element hasn't been dropped yet, and we just lowered the count to // zero so it won't be dropped later, and thus it's okay to take it here. - unsafe { mem::replace(&mut self.element, MaybeUninit::uninit()).assume_init() } + unsafe { self.element.assume_init_read() } } else { // SAFETY: the count is non-zero, so it must have not been dropped yet. let element = unsafe { self.element.assume_init_ref() }; diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index 3b126785728..7dabaece955 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -37,7 +37,7 @@ use crate::ops::{ControlFlow, Try}; /// assert_eq!(None, iter.next_back()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "DoubleEndedIterator")] +#[rustc_diagnostic_item = "DoubleEndedIterator"] pub trait DoubleEndedIterator: Iterator { /// Removes and returns an element from the end of the iterator. /// diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 10ae43ac3fc..3bbb52fdbcb 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -862,7 +862,7 @@ pub trait Iterator { /// Note that `iter.filter(f).next()` is equivalent to `iter.find(f)`. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "iter_filter")] + #[rustc_diagnostic_item = "iter_filter"] fn filter<P>(self, predicate: P) -> Filter<Self, P> where Self: Sized, @@ -954,7 +954,7 @@ pub trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "enumerate_method")] + #[rustc_diagnostic_item = "enumerate_method"] fn enumerate(self) -> Enumerate<Self> where Self: Sized, @@ -1704,11 +1704,7 @@ pub trait Iterator { /// self.state = self.state + 1; /// /// // if it's even, Some(i32), else None - /// if val % 2 == 0 { - /// Some(val) - /// } else { - /// None - /// } + /// (val % 2 == 0).then_some(val) /// } /// } /// @@ -1972,11 +1968,20 @@ pub trait Iterator { #[inline] #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead"] - #[cfg_attr(not(test), rustc_diagnostic_item = "iterator_collect_fn")] + #[rustc_diagnostic_item = "iterator_collect_fn"] fn collect<B: FromIterator<Self::Item>>(self) -> B where Self: Sized, { + // This is too aggressive to turn on for everything all the time, but PR#137908 + // accidentally noticed that some rustc iterators had malformed `size_hint`s, + // so this will help catch such things in debug-assertions-std runners, + // even if users won't actually ever see it. + if cfg!(debug_assertions) { + let hint = self.size_hint(); + assert!(hint.1.is_none_or(|high| high >= hint.0), "Malformed size_hint {hint:?}"); + } + FromIterator::from_iter(self) } @@ -3367,7 +3372,7 @@ pub trait Iterator { /// assert_eq!(v_map, vec![1, 2, 3]); /// ``` #[stable(feature = "iter_copied", since = "1.36.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "iter_copied")] + #[rustc_diagnostic_item = "iter_copied"] fn copied<'a, T: 'a>(self) -> Copied<Self> where Self: Sized + Iterator<Item = &'a T>, @@ -3415,7 +3420,7 @@ pub trait Iterator { /// assert_eq!(&[vec![23]], &faster[..]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "iter_cloned")] + #[rustc_diagnostic_item = "iter_cloned"] fn cloned<'a, T: 'a>(self) -> Cloned<Self> where Self: Sized + Iterator<Item = &'a T>, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 6e058069756..e1ca69edcbb 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -43,18 +43,6 @@ //! which do not trigger a panic can be assured that this function is never //! called. The `lang` attribute is called `eh_personality`. -// Since core defines many fundamental lang items, all tests live in a -// separate crate, coretests (library/coretests), to avoid bizarre issues. -// -// Here we explicitly #[cfg]-out this whole crate when testing. If we don't do -// this, both the generated test artifact and the linked libtest (which -// transitively includes core) will both define the same set of lang items, -// and this will cause the E0152 "found duplicate lang item" error. See -// discussion in #50466 for details. -// -// This cfg won't affect doc tests. -#![cfg(not(test))] -// #![stable(feature = "core", since = "1.6.0")] #![doc( html_playground_url = "https://play.rust-lang.org/", @@ -64,7 +52,6 @@ )] #![doc(rust_logo)] #![doc(cfg_hide( - not(test), no_fp_fmt_parse, target_pointer_width = "16", target_pointer_width = "32", @@ -228,13 +215,9 @@ extern crate self as core; #[allow(unused)] use prelude::rust_2024::*; -#[cfg(not(test))] // See #65860 #[macro_use] mod macros; -// We don't export this through #[macro_export] for now, to avoid breakage. -// See https://github.com/rust-lang/rust/issues/82913 -#[cfg(not(test))] #[unstable(feature = "assert_matches", issue = "82775")] /// Unstable module containing the unstable `assert_matches` macro. pub mod assert_matches { diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index a527a2ea5aa..fa0d882181a 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -37,7 +37,7 @@ macro_rules! panic { /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "assert_eq_macro")] +#[rustc_diagnostic_item = "assert_eq_macro"] #[allow_internal_unstable(panic_internals)] macro_rules! assert_eq { ($left:expr, $right:expr $(,)?) => { @@ -93,7 +93,7 @@ macro_rules! assert_eq { /// ``` #[macro_export] #[stable(feature = "assert_ne", since = "1.13.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "assert_ne_macro")] +#[rustc_diagnostic_item = "assert_ne_macro"] #[allow_internal_unstable(panic_internals)] macro_rules! assert_ne { ($left:expr, $right:expr $(,)?) => { @@ -331,7 +331,7 @@ macro_rules! debug_assert { /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "debug_assert_eq_macro")] +#[rustc_diagnostic_item = "debug_assert_eq_macro"] macro_rules! debug_assert_eq { ($($arg:tt)*) => { if $crate::cfg!(debug_assertions) { @@ -361,7 +361,7 @@ macro_rules! debug_assert_eq { /// ``` #[macro_export] #[stable(feature = "assert_ne", since = "1.13.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "debug_assert_ne_macro")] +#[rustc_diagnostic_item = "debug_assert_ne_macro"] macro_rules! debug_assert_ne { ($($arg:tt)*) => { if $crate::cfg!(debug_assertions) { @@ -442,7 +442,7 @@ pub macro debug_assert_matches($($arg:tt)*) { /// ``` #[macro_export] #[stable(feature = "matches_macro", since = "1.42.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "matches_macro")] +#[rustc_diagnostic_item = "matches_macro"] macro_rules! matches { ($expression:expr, $pattern:pat $(if $guard:expr)? $(,)?) => { match $expression { @@ -617,7 +617,7 @@ macro_rules! r#try { /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "write_macro")] +#[rustc_diagnostic_item = "write_macro"] macro_rules! write { ($dst:expr, $($arg:tt)*) => { $dst.write_fmt($crate::format_args!($($arg)*)) @@ -651,7 +651,7 @@ macro_rules! write { /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "writeln_macro")] +#[rustc_diagnostic_item = "writeln_macro"] #[allow_internal_unstable(format_args_nl)] macro_rules! writeln { ($dst:expr $(,)?) => { @@ -718,7 +718,7 @@ macro_rules! writeln { #[rustc_builtin_macro(unreachable)] #[allow_internal_unstable(edition_panic)] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "unreachable_macro")] +#[rustc_diagnostic_item = "unreachable_macro"] macro_rules! unreachable { // Expands to either `$crate::panic::unreachable_2015` or `$crate::panic::unreachable_2021` // depending on the edition of the caller. @@ -803,7 +803,7 @@ macro_rules! unreachable { /// ``` #[macro_export] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "unimplemented_macro")] +#[rustc_diagnostic_item = "unimplemented_macro"] #[allow_internal_unstable(panic_internals)] macro_rules! unimplemented { () => { @@ -883,7 +883,7 @@ macro_rules! unimplemented { /// ``` #[macro_export] #[stable(feature = "todo_macro", since = "1.40.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "todo_macro")] +#[rustc_diagnostic_item = "todo_macro"] #[allow_internal_unstable(panic_internals)] macro_rules! todo { () => { @@ -995,7 +995,7 @@ pub(crate) mod builtin { /// and cannot be stored for later use. /// This is a known limitation, see [#92698](https://github.com/rust-lang/rust/issues/92698). #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "format_args_macro")] + #[rustc_diagnostic_item = "format_args_macro"] #[allow_internal_unsafe] #[allow_internal_unstable(fmt_internals)] #[rustc_builtin_macro] @@ -1342,7 +1342,7 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] #[macro_export] - #[cfg_attr(not(test), rustc_diagnostic_item = "include_str_macro")] + #[rustc_diagnostic_item = "include_str_macro"] macro_rules! include_str { ($file:expr $(,)?) => {{ /* compiler built-in */ }}; } @@ -1382,7 +1382,7 @@ pub(crate) mod builtin { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_builtin_macro] #[macro_export] - #[cfg_attr(not(test), rustc_diagnostic_item = "include_bytes_macro")] + #[rustc_diagnostic_item = "include_bytes_macro"] macro_rules! include_bytes { ($file:expr $(,)?) => {{ /* compiler built-in */ }}; } diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index a4ab4674f4a..68011310d2c 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -82,7 +82,7 @@ macro marker_impls { /// [arc]: ../../std/sync/struct.Arc.html /// [ub]: ../../reference/behavior-considered-undefined.html #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "Send")] +#[rustc_diagnostic_item = "Send"] #[diagnostic::on_unimplemented( message = "`{Self}` cannot be sent between threads safely", label = "`{Self}` cannot be sent between threads safely" @@ -545,7 +545,7 @@ pub trait BikeshedGuaranteedNoDrop {} /// [transmute]: crate::mem::transmute /// [nomicon-send-and-sync]: ../../nomicon/send-and-sync.html #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "Sync")] +#[rustc_diagnostic_item = "Sync"] #[lang = "sync"] #[rustc_on_unimplemented( on( @@ -1305,7 +1305,7 @@ pub trait FnPtr: Copy + Clone { /// ``` #[rustc_builtin_macro(CoercePointee, attributes(pointee))] #[allow_internal_unstable(dispatch_from_dyn, coerce_unsized, unsize, coerce_pointee_validated)] -#[cfg_attr(not(test), rustc_diagnostic_item = "CoercePointee")] +#[rustc_diagnostic_item = "CoercePointee"] #[unstable(feature = "derive_coerce_pointee", issue = "123430")] pub macro CoercePointee($item:item) { /* compiler built-in */ diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index ce84f105e5c..d0be82adb6b 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -1065,161 +1065,46 @@ impl<T> MaybeUninit<T> { this.write_clone_of_slice(src) } - /// Fills a slice with elements by cloning `value`, returning a mutable reference to the now - /// initialized contents of the slice. - /// Any previously initialized elements will not be dropped. - /// - /// This is similar to [`slice::fill`]. - /// - /// # Panics - /// - /// This function will panic if any call to `Clone` panics. - /// - /// If such a panic occurs, any elements previously initialized during this operation will be - /// dropped. - /// - /// # Examples - /// - /// ``` - /// #![feature(maybe_uninit_fill)] - /// use std::mem::MaybeUninit; - /// - /// let mut buf = [const { MaybeUninit::uninit() }; 10]; - /// let initialized = MaybeUninit::fill(&mut buf, 1); - /// assert_eq!(initialized, &mut [1; 10]); - /// ``` - #[doc(alias = "memset")] + /// Deprecated version of [`slice::write_filled`]. #[unstable(feature = "maybe_uninit_fill", issue = "117428")] - pub fn fill(this: &mut [MaybeUninit<T>], value: T) -> &mut [T] + #[deprecated( + note = "replaced by inherent write_filled method; will eventually be removed", + since = "1.83.0" + )] + pub fn fill<'a>(this: &'a mut [MaybeUninit<T>], value: T) -> &'a mut [T] where T: Clone, { - SpecFill::spec_fill(this, value); - // SAFETY: Valid elements have just been filled into `this` so it is initialized - unsafe { this.assume_init_mut() } + this.write_filled(value) } - /// Fills a slice with elements returned by calling a closure repeatedly. - /// - /// This method uses a closure to create new values. If you'd rather `Clone` a given value, use - /// [`MaybeUninit::fill`]. If you want to use the `Default` trait to generate values, you can - /// pass [`Default::default`] as the argument. - /// - /// # Panics - /// - /// This function will panic if any call to the provided closure panics. - /// - /// If such a panic occurs, any elements previously initialized during this operation will be - /// dropped. - /// - /// # Examples - /// - /// ``` - /// #![feature(maybe_uninit_fill)] - /// use std::mem::MaybeUninit; - /// - /// let mut buf = [const { MaybeUninit::<i32>::uninit() }; 10]; - /// let initialized = MaybeUninit::fill_with(&mut buf, Default::default); - /// assert_eq!(initialized, &mut [0; 10]); - /// ``` + /// Deprecated version of [`slice::write_with`]. #[unstable(feature = "maybe_uninit_fill", issue = "117428")] - pub fn fill_with<F>(this: &mut [MaybeUninit<T>], mut f: F) -> &mut [T] + #[deprecated( + note = "replaced by inherent write_with method; will eventually be removed", + since = "1.83.0" + )] + pub fn fill_with<'a, F>(this: &'a mut [MaybeUninit<T>], mut f: F) -> &'a mut [T] where F: FnMut() -> T, { - let mut guard = Guard { slice: this, initialized: 0 }; - - for element in guard.slice.iter_mut() { - element.write(f()); - guard.initialized += 1; - } - - super::forget(guard); - - // SAFETY: Valid elements have just been written into `this` so it is initialized - unsafe { this.assume_init_mut() } + this.write_with(|_| f()) } - /// Fills a slice with elements yielded by an iterator until either all elements have been - /// initialized or the iterator is empty. - /// - /// Returns two slices. The first slice contains the initialized portion of the original slice. - /// The second slice is the still-uninitialized remainder of the original slice. - /// - /// # Panics - /// - /// This function panics if the iterator's `next` function panics. - /// - /// If such a panic occurs, any elements previously initialized during this operation will be - /// dropped. - /// - /// # Examples - /// - /// Completely filling the slice: - /// - /// ``` - /// #![feature(maybe_uninit_fill)] - /// use std::mem::MaybeUninit; - /// - /// let mut buf = [const { MaybeUninit::uninit() }; 5]; - /// - /// let iter = [1, 2, 3].into_iter().cycle(); - /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter); - /// - /// assert_eq!(initialized, &mut [1, 2, 3, 1, 2]); - /// assert_eq!(remainder.len(), 0); - /// ``` - /// - /// Partially filling the slice: - /// - /// ``` - /// #![feature(maybe_uninit_fill)] - /// use std::mem::MaybeUninit; - /// - /// let mut buf = [const { MaybeUninit::uninit() }; 5]; - /// let iter = [1, 2]; - /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter); - /// - /// assert_eq!(initialized, &mut [1, 2]); - /// assert_eq!(remainder.len(), 3); - /// ``` - /// - /// Checking an iterator after filling a slice: - /// - /// ``` - /// #![feature(maybe_uninit_fill)] - /// use std::mem::MaybeUninit; - /// - /// let mut buf = [const { MaybeUninit::uninit() }; 3]; - /// let mut iter = [1, 2, 3, 4, 5].into_iter(); - /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter.by_ref()); - /// - /// assert_eq!(initialized, &mut [1, 2, 3]); - /// assert_eq!(remainder.len(), 0); - /// assert_eq!(iter.as_slice(), &[4, 5]); - /// ``` + /// Deprecated version of [`slice::write_iter`]. #[unstable(feature = "maybe_uninit_fill", issue = "117428")] - pub fn fill_from<I>(this: &mut [MaybeUninit<T>], it: I) -> (&mut [T], &mut [MaybeUninit<T>]) + #[deprecated( + note = "replaced by inherent write_iter method; will eventually be removed", + since = "1.83.0" + )] + pub fn fill_from<'a, I>( + this: &'a mut [MaybeUninit<T>], + it: I, + ) -> (&'a mut [T], &'a mut [MaybeUninit<T>]) where I: IntoIterator<Item = T>, { - let iter = it.into_iter(); - let mut guard = Guard { slice: this, initialized: 0 }; - - for (element, val) in guard.slice.iter_mut().zip(iter) { - element.write(val); - guard.initialized += 1; - } - - let initialized_len = guard.initialized; - super::forget(guard); - - // SAFETY: guard.initialized <= this.len() - let (initted, remainder) = unsafe { this.split_at_mut_unchecked(initialized_len) }; - - // SAFETY: Valid elements have just been written into `init`, so that portion - // of `this` is initialized. - (unsafe { initted.assume_init_mut() }, remainder) + this.write_iter(it) } /// Deprecated version of [`slice::as_bytes`]. @@ -1380,6 +1265,163 @@ impl<T> [MaybeUninit<T>] { unsafe { self.assume_init_mut() } } + /// Fills a slice with elements by cloning `value`, returning a mutable reference to the now + /// initialized contents of the slice. + /// Any previously initialized elements will not be dropped. + /// + /// This is similar to [`slice::fill`]. + /// + /// # Panics + /// + /// This function will panic if any call to `Clone` panics. + /// + /// If such a panic occurs, any elements previously initialized during this operation will be + /// dropped. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = [const { MaybeUninit::uninit() }; 10]; + /// let initialized = buf.write_filled(1); + /// assert_eq!(initialized, &mut [1; 10]); + /// ``` + #[doc(alias = "memset")] + #[unstable(feature = "maybe_uninit_fill", issue = "117428")] + pub fn write_filled(&mut self, value: T) -> &mut [T] + where + T: Clone, + { + SpecFill::spec_fill(self, value); + // SAFETY: Valid elements have just been filled into `self` so it is initialized + unsafe { self.assume_init_mut() } + } + + /// Fills a slice with elements returned by calling a closure for each index. + /// + /// This method uses a closure to create new values. If you'd rather `Clone` a given value, use + /// [`MaybeUninit::fill`]. If you want to use the `Default` trait to generate values, you can + /// pass [`|_| Default::default()`][Default::default] as the argument. + /// + /// # Panics + /// + /// This function will panic if any call to the provided closure panics. + /// + /// If such a panic occurs, any elements previously initialized during this operation will be + /// dropped. + /// + /// # Examples + /// + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = [const { MaybeUninit::<usize>::uninit() }; 5]; + /// let initialized = buf.write_with(|idx| idx + 1); + /// assert_eq!(initialized, &mut [1, 2, 3, 4, 5]); + /// ``` + #[unstable(feature = "maybe_uninit_fill", issue = "117428")] + pub fn write_with<F>(&mut self, mut f: F) -> &mut [T] + where + F: FnMut(usize) -> T, + { + let mut guard = Guard { slice: self, initialized: 0 }; + + for (idx, element) in guard.slice.iter_mut().enumerate() { + element.write(f(idx)); + guard.initialized += 1; + } + + super::forget(guard); + + // SAFETY: Valid elements have just been written into `this` so it is initialized + unsafe { self.assume_init_mut() } + } + + /// Fills a slice with elements yielded by an iterator until either all elements have been + /// initialized or the iterator is empty. + /// + /// Returns two slices. The first slice contains the initialized portion of the original slice. + /// The second slice is the still-uninitialized remainder of the original slice. + /// + /// # Panics + /// + /// This function panics if the iterator's `next` function panics. + /// + /// If such a panic occurs, any elements previously initialized during this operation will be + /// dropped. + /// + /// # Examples + /// + /// Completely filling the slice: + /// + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = [const { MaybeUninit::uninit() }; 5]; + /// + /// let iter = [1, 2, 3].into_iter().cycle(); + /// let (initialized, remainder) = buf.write_iter(iter); + /// + /// assert_eq!(initialized, &mut [1, 2, 3, 1, 2]); + /// assert_eq!(remainder.len(), 0); + /// ``` + /// + /// Partially filling the slice: + /// + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = [const { MaybeUninit::uninit() }; 5]; + /// let iter = [1, 2]; + /// let (initialized, remainder) = buf.write_iter(iter); + /// + /// assert_eq!(initialized, &mut [1, 2]); + /// assert_eq!(remainder.len(), 3); + /// ``` + /// + /// Checking an iterator after filling a slice: + /// + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = [const { MaybeUninit::uninit() }; 3]; + /// let mut iter = [1, 2, 3, 4, 5].into_iter(); + /// let (initialized, remainder) = buf.write_iter(iter.by_ref()); + /// + /// assert_eq!(initialized, &mut [1, 2, 3]); + /// assert_eq!(remainder.len(), 0); + /// assert_eq!(iter.as_slice(), &[4, 5]); + /// ``` + #[unstable(feature = "maybe_uninit_fill", issue = "117428")] + pub fn write_iter<I>(&mut self, it: I) -> (&mut [T], &mut [MaybeUninit<T>]) + where + I: IntoIterator<Item = T>, + { + let iter = it.into_iter(); + let mut guard = Guard { slice: self, initialized: 0 }; + + for (element, val) in guard.slice.iter_mut().zip(iter) { + element.write(val); + guard.initialized += 1; + } + + let initialized_len = guard.initialized; + super::forget(guard); + + // SAFETY: guard.initialized <= self.len() + let (initted, remainder) = unsafe { self.split_at_mut_unchecked(initialized_len) }; + + // SAFETY: Valid elements have just been written into `init`, so that portion + // of `this` is initialized. + (unsafe { initted.assume_init_mut() }, remainder) + } + /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes. /// /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 1494d7aca15..27387754633 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -140,7 +140,7 @@ pub use crate::intrinsics::transmute; #[inline] #[rustc_const_stable(feature = "const_forget", since = "1.46.0")] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "mem_forget")] +#[rustc_diagnostic_item = "mem_forget"] pub const fn forget<T>(t: T) { let _ = ManuallyDrop::new(t); } @@ -300,7 +300,7 @@ pub fn forget_unsized<T: ?Sized>(t: T) { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] #[rustc_const_stable(feature = "const_mem_size_of", since = "1.24.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of")] +#[rustc_diagnostic_item = "mem_size_of"] pub const fn size_of<T>() -> usize { intrinsics::size_of::<T>() } @@ -328,7 +328,7 @@ pub const fn size_of<T>() -> usize { #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_size_of_val", since = "1.85.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "mem_size_of_val")] +#[rustc_diagnostic_item = "mem_size_of_val"] pub const fn size_of_val<T: ?Sized>(val: &T) -> usize { // SAFETY: `val` is a reference, so it's a valid raw pointer unsafe { intrinsics::size_of_val(val) } @@ -846,7 +846,7 @@ pub fn take<T: Default>(dest: &mut T) -> T { #[stable(feature = "rust1", since = "1.0.0")] #[must_use = "if you don't need the old value, you can just assign the new value directly"] #[rustc_const_stable(feature = "const_replace", since = "1.83.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "mem_replace")] +#[rustc_diagnostic_item = "mem_replace"] pub const fn replace<T>(dest: &mut T, src: T) -> T { // It may be tempting to use `swap` to avoid `unsafe` here. Don't! // The compiler optimizes the implementation below to two `memcpy`s @@ -931,7 +931,7 @@ pub const fn replace<T>(dest: &mut T, src: T) -> T { /// [`RefCell`]: crate::cell::RefCell #[inline] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "mem_drop")] +#[rustc_diagnostic_item = "mem_drop"] pub fn drop<T>(_x: T) {} /// Bitwise-copies a value. @@ -1154,7 +1154,7 @@ impl<T> fmt::Debug for Discriminant<T> { /// ``` #[stable(feature = "discriminant_value", since = "1.21.0")] #[rustc_const_stable(feature = "const_discriminant", since = "1.75.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "mem_discriminant")] +#[rustc_diagnostic_item = "mem_discriminant"] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces pub const fn discriminant<T>(v: &T) -> Discriminant<T> { Discriminant(intrinsics::discriminant_value(v)) @@ -1254,42 +1254,56 @@ impl<T> SizedTypeProperties for T {} /// Expands to the offset in bytes of a field from the beginning of the given type. /// -/// Structs, enums, unions and tuples are supported. +/// The type may be a `struct`, `enum`, `union`, or tuple. /// -/// Nested field accesses may be used, but not array indexes. +/// The field may be a nested field (`field1.field2`), but not an array index. +/// The field must be visible to the call site. /// -/// If the nightly-only feature `offset_of_enum` is enabled, -/// variants may be traversed as if they were fields. -/// Variants themselves do not have an offset. +/// The offset is returned as a [`usize`]. /// -/// Visibility is respected - all types and fields must be visible to the call site: +/// # Offsets of, and in, dynamically sized types /// -/// ``` -/// mod nested { -/// #[repr(C)] -/// pub struct Struct { -/// private: u8, -/// } -/// } +/// The field’s type must be [`Sized`], but it may be located in a [dynamically sized] container. +/// If the field type is dynamically sized, then you cannot use `offset_of!` (since the field's +/// alignment, and therefore its offset, may also be dynamic) and must take the offset from an +/// actual pointer to the container instead. /// -/// // assert_eq!(mem::offset_of!(nested::Struct, private), 0); -/// // ^^^ error[E0616]: field `private` of struct `Struct` is private -/// ``` -/// -/// Only [`Sized`] fields are supported, but the container may be unsized: /// ``` /// # use core::mem; +/// # use core::fmt::Debug; /// #[repr(C)] -/// pub struct Struct { +/// pub struct Struct<T: ?Sized> { /// a: u8, -/// b: [u8], +/// b: T, /// } /// -/// assert_eq!(mem::offset_of!(Struct, a), 0); // OK -/// // assert_eq!(mem::offset_of!(Struct, b), 1); -/// // ^^^ error[E0277]: doesn't have a size known at compile-time +/// #[derive(Debug)] +/// #[repr(C, align(4))] +/// struct Align4(u32); +/// +/// assert_eq!(mem::offset_of!(Struct<dyn Debug>, a), 0); // OK — Sized field +/// assert_eq!(mem::offset_of!(Struct<Align4>, b), 4); // OK — not DST +/// +/// // assert_eq!(mem::offset_of!(Struct<dyn Debug>, b), 1); +/// // ^^^ error[E0277]: ... cannot be known at compilation time +/// +/// // To obtain the offset of a !Sized field, examine a concrete value +/// // instead of using offset_of!. +/// let value: Struct<Align4> = Struct { a: 1, b: Align4(2) }; +/// let ref_unsized: &Struct<dyn Debug> = &value; +/// let offset_of_b = unsafe { +/// (&raw const ref_unsized.b).byte_offset_from_unsigned(ref_unsized) +/// }; +/// assert_eq!(offset_of_b, 4); /// ``` /// +/// If you need to obtain the offset of a field of a `!Sized` type, then, since the offset may +/// depend on the particular value being stored (in particular, `dyn Trait` values have a +/// dynamically-determined alignment), you must retrieve the offset from a specific reference +/// or pointer, and so you cannot use `offset_of!` to work without one. +/// +/// # Layout is subject to change +/// /// Note that type layout is, in general, [subject to change and /// platform-specific](https://doc.rust-lang.org/reference/type-layout.html). If /// layout stability is required, consider using an [explicit `repr` attribute]. @@ -1325,11 +1339,16 @@ impl<T> SizedTypeProperties for T {} /// /// [explicit `repr` attribute]: https://doc.rust-lang.org/reference/type-layout.html#representations /// +/// # Unstable features +/// +/// The following unstable features expand the functionality of `offset_of!`: +/// +/// * [`offset_of_enum`] — allows `enum` variants to be traversed as if they were fields. +/// * [`offset_of_slice`] — allows getting the offset of a field of type `[T]`. +/// /// # Examples /// /// ``` -/// #![feature(offset_of_enum)] -/// /// use std::mem; /// #[repr(C)] /// struct FieldStruct { @@ -1351,18 +1370,11 @@ impl<T> SizedTypeProperties for T {} /// struct NestedB(u8); /// /// assert_eq!(mem::offset_of!(NestedA, b.0), 0); -/// -/// #[repr(u8)] -/// enum Enum { -/// A(u8, u16), -/// B { one: u8, two: u16 }, -/// } -/// -/// assert_eq!(mem::offset_of!(Enum, A.0), 1); -/// assert_eq!(mem::offset_of!(Enum, B.two), 2); -/// -/// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0); /// ``` +/// +/// [dynamically sized]: https://doc.rust-lang.org/reference/dynamically-sized-types.html +/// [`offset_of_enum`]: https://doc.rust-lang.org/nightly/unstable-book/language-features/offset-of-enum.html +/// [`offset_of_slice`]: https://doc.rust-lang.org/nightly/unstable-book/language-features/offset-of-slice.html #[stable(feature = "offset_of", since = "1.77.0")] #[allow_internal_unstable(builtin_syntax)] pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) { diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 8e4417ec461..7aa5ed60d04 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -25,7 +25,7 @@ use crate::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not}; /// assert_eq!(localhost_v4.is_ipv6(), false); /// assert_eq!(localhost_v4.is_ipv4(), true); /// ``` -#[cfg_attr(not(test), rustc_diagnostic_item = "IpAddr")] +#[rustc_diagnostic_item = "IpAddr"] #[stable(feature = "ip_addr", since = "1.7.0")] #[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] pub enum IpAddr { diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 5e45974b3d4..b17190971c3 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -12,11 +12,9 @@ #![unstable(feature = "f128", issue = "116909")] use crate::convert::FloatToInt; -#[cfg(not(test))] -use crate::intrinsics; -use crate::mem; use crate::num::FpCategory; use crate::panic::const_assert; +use crate::{intrinsics, mem}; /// Basic mathematical constants. #[unstable(feature = "f128", issue = "116909")] @@ -138,7 +136,6 @@ pub mod consts { pub const LN_10: f128 = 2.30258509299404568401799145468436420760110148862877297603333_f128; } -#[cfg(not(test))] impl f128 { // FIXME(f16_f128): almost all methods in this `impl` are missing examples and a const // implementation. Add these once we can run code on all platforms and have f16/f128 in CTFE. diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index e3176cd1688..d20677f43b4 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -12,11 +12,9 @@ #![unstable(feature = "f16", issue = "116909")] use crate::convert::FloatToInt; -#[cfg(not(test))] -use crate::intrinsics; -use crate::mem; use crate::num::FpCategory; use crate::panic::const_assert; +use crate::{intrinsics, mem}; /// Basic mathematical constants. #[unstable(feature = "f16", issue = "116909")] @@ -133,7 +131,6 @@ pub mod consts { pub const LN_10: f16 = 2.30258509299404568401799145468436421_f16; } -#[cfg(not(test))] impl f16 { // FIXME(f16_f128): almost all methods in this `impl` are missing examples and a const // implementation. Add these once we can run code on all platforms and have f16/f128 in CTFE. diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index de1557ccc90..79d864e1b19 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -12,11 +12,9 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::convert::FloatToInt; -#[cfg(not(test))] -use crate::intrinsics; -use crate::mem; use crate::num::FpCategory; use crate::panic::const_assert; +use crate::{intrinsics, mem}; /// The radix or base of the internal representation of `f32`. /// Use [`f32::RADIX`] instead. @@ -386,7 +384,6 @@ pub mod consts { pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32; } -#[cfg(not(test))] impl f32 { /// The radix or base of the internal representation of `f32`. #[stable(feature = "assoc_int_consts", since = "1.43.0")] @@ -416,7 +413,7 @@ impl f32 { /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon /// [`MANTISSA_DIGITS`]: f32::MANTISSA_DIGITS #[stable(feature = "assoc_int_consts", since = "1.43.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "f32_epsilon")] + #[rustc_diagnostic_item = "f32_epsilon"] pub const EPSILON: f32 = 1.19209290e-07_f32; /// Smallest finite `f32` value. diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 65b5f3b9af0..ca28b40bb3a 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -12,11 +12,9 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::convert::FloatToInt; -#[cfg(not(test))] -use crate::intrinsics; -use crate::mem; use crate::num::FpCategory; use crate::panic::const_assert; +use crate::{intrinsics, mem}; /// The radix or base of the internal representation of `f64`. /// Use [`f64::RADIX`] instead. @@ -386,7 +384,6 @@ pub mod consts { pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64; } -#[cfg(not(test))] impl f64 { /// The radix or base of the internal representation of `f64`. #[stable(feature = "assoc_int_consts", since = "1.43.0")] @@ -415,7 +412,7 @@ impl f64 { /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon /// [`MANTISSA_DIGITS`]: f64::MANTISSA_DIGITS #[stable(feature = "assoc_int_consts", since = "1.43.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "f64_epsilon")] + #[rustc_diagnostic_item = "f64_epsilon"] pub const EPSILON: f64 = 2.2204460492503131e-16_f64; /// Smallest finite `f64` value. diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 8993e14fcd3..ef7e6f9c2f4 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -79,7 +79,8 @@ use crate::{convert, ops}; /// [`Break`]: ControlFlow::Break /// [`Continue`]: ControlFlow::Continue #[stable(feature = "control_flow_enum_type", since = "1.55.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "ControlFlow")] +#[rustc_diagnostic_item = "ControlFlow"] +#[must_use] // ControlFlow should not implement PartialOrd or Ord, per RFC 3058: // https://rust-lang.github.io/rfcs/3058-try-trait-v2.html#traits-for-controlflow #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/library/core/src/option.rs b/library/core/src/option.rs index f668c6f0672..7ec0ac71271 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -924,7 +924,7 @@ impl<T> Option<T> { #[inline] #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "option_expect")] + #[rustc_diagnostic_item = "option_expect"] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn expect(self, msg: &str) -> T { @@ -969,7 +969,7 @@ impl<T> Option<T> { #[inline(always)] #[track_caller] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "option_unwrap")] + #[rustc_diagnostic_item = "option_unwrap"] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] #[rustc_const_stable(feature = "const_option", since = "1.83.0")] pub const fn unwrap(self) -> T { diff --git a/library/core/src/panic/unwind_safe.rs b/library/core/src/panic/unwind_safe.rs index 37859212c0e..a60f0799c0e 100644 --- a/library/core/src/panic/unwind_safe.rs +++ b/library/core/src/panic/unwind_safe.rs @@ -82,7 +82,7 @@ use crate::task::{Context, Poll}; /// [`AssertUnwindSafe`] wrapper struct can be used to force this trait to be /// implemented for any closed over variables passed to `catch_unwind`. #[stable(feature = "catch_unwind", since = "1.9.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "unwind_safe_trait")] +#[rustc_diagnostic_item = "unwind_safe_trait"] #[diagnostic::on_unimplemented( message = "the type `{Self}` may not be safely transferred across an unwind boundary", label = "`{Self}` may not be safely transferred across an unwind boundary" @@ -98,7 +98,7 @@ pub auto trait UnwindSafe {} /// This is a "helper marker trait" used to provide impl blocks for the /// [`UnwindSafe`] trait, for more information see that documentation. #[stable(feature = "catch_unwind", since = "1.9.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "ref_unwind_safe_trait")] +#[rustc_diagnostic_item = "ref_unwind_safe_trait"] #[diagnostic::on_unimplemented( message = "the type `{Self}` may contain interior mutability and a reference may not be safely \ transferrable across a catch_unwind boundary", diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 7fcd19f67ee..bc097bf198d 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1943,6 +1943,7 @@ unsafe impl<T: ?Sized> PinCoerceUnsized for *mut T {} #[stable(feature = "pin_macro", since = "1.68.0")] #[rustc_macro_transparency = "semitransparent"] #[allow_internal_unstable(unsafe_pin_internals)] +#[cfg_attr(not(bootstrap), rustc_macro_edition_2021)] pub macro pin($value:expr $(,)?) { // This is `Pin::new_unchecked(&mut { $value })`, so, for starters, let's // review such a hypothetical macro (that any user-code could define): diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs index 48707506389..9c5da306e27 100644 --- a/library/core/src/ptr/metadata.rs +++ b/library/core/src/ptr/metadata.rs @@ -61,6 +61,8 @@ pub trait Pointee { // NOTE: Keep trait bounds in `static_assert_expected_bounds_for_metadata` // in `library/core/src/ptr/metadata.rs` // in sync with those here: + // NOTE: The metadata of `dyn Trait + 'a` is `DynMetadata<dyn Trait + 'a>` + // so a `'static` bound must not be added. type Metadata: fmt::Debug + Copy + Send + Sync + Ord + Hash + Unpin + Freeze; } diff --git a/library/core/src/result.rs b/library/core/src/result.rs index ee98a47523f..48ab9267f21 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -654,7 +654,7 @@ impl<T, E> Result<T, E> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "result_ok_method")] + #[rustc_diagnostic_item = "result_ok_method"] pub fn ok(self) -> Option<T> { match self { Ok(x) => Some(x), diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs index 51b25fa40e3..91befdb8c78 100644 --- a/library/core/src/slice/ascii.rs +++ b/library/core/src/slice/ascii.rs @@ -7,7 +7,6 @@ use crate::fmt::{self, Write}; use crate::intrinsics::const_eval_select; use crate::{ascii, iter, ops}; -#[cfg(not(test))] impl [u8] { /// Checks if all bytes in this slice are within the ASCII range. #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 804bdfcbb4f..da85f42926e 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -282,4 +282,4 @@ macro_rules! impl_slice_contains { }; } -impl_slice_contains!(u16, u32, u64, i16, i32, i64, f32, f64, usize, isize); +impl_slice_contains!(u16, u32, u64, i16, i32, i64, f32, f64, usize, isize, char); diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 3570d8d0876..5bb7243c449 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -97,7 +97,6 @@ enum Direction { Back, } -#[cfg(not(test))] impl<T> [T] { /// Returns the number of elements in the slice. /// @@ -1045,7 +1044,7 @@ impl<T> [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - #[cfg_attr(not(test), rustc_diagnostic_item = "slice_iter")] + #[rustc_diagnostic_item = "slice_iter"] pub fn iter(&self) -> Iter<'_, T> { Iter::new(self) } @@ -4446,8 +4445,10 @@ impl<T> [T] { /// ``` #[inline] #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")] - pub fn split_off_first<'a>(self: &mut &'a Self) -> Option<&'a T> { - let (first, rem) = self.split_first()?; + #[rustc_const_unstable(feature = "const_split_off_first_last", issue = "138539")] + pub const fn split_off_first<'a>(self: &mut &'a Self) -> Option<&'a T> { + // FIXME(const-hack): Use `?` when available in const instead of `let-else`. + let Some((first, rem)) = self.split_first() else { return None }; *self = rem; Some(first) } @@ -4469,8 +4470,11 @@ impl<T> [T] { /// ``` #[inline] #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")] - pub fn split_off_first_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { - let (first, rem) = mem::take(self).split_first_mut()?; + #[rustc_const_unstable(feature = "const_split_off_first_last", issue = "138539")] + pub const fn split_off_first_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { + // FIXME(const-hack): Use `mem::take` and `?` when available in const. + // Original: `mem::take(self).split_first_mut()?` + let Some((first, rem)) = mem::replace(self, &mut []).split_first_mut() else { return None }; *self = rem; Some(first) } @@ -4491,8 +4495,10 @@ impl<T> [T] { /// ``` #[inline] #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")] - pub fn split_off_last<'a>(self: &mut &'a Self) -> Option<&'a T> { - let (last, rem) = self.split_last()?; + #[rustc_const_unstable(feature = "const_split_off_first_last", issue = "138539")] + pub const fn split_off_last<'a>(self: &mut &'a Self) -> Option<&'a T> { + // FIXME(const-hack): Use `?` when available in const instead of `let-else`. + let Some((last, rem)) = self.split_last() else { return None }; *self = rem; Some(last) } @@ -4514,8 +4520,11 @@ impl<T> [T] { /// ``` #[inline] #[stable(feature = "slice_take", since = "CURRENT_RUSTC_VERSION")] - pub fn split_off_last_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { - let (last, rem) = mem::take(self).split_last_mut()?; + #[rustc_const_unstable(feature = "const_split_off_first_last", issue = "138539")] + pub const fn split_off_last_mut<'a>(self: &mut &'a mut Self) -> Option<&'a mut T> { + // FIXME(const-hack): Use `mem::take` and `?` when available in const. + // Original: `mem::take(self).split_last_mut()?` + let Some((last, rem)) = mem::replace(self, &mut []).split_last_mut() else { return None }; *self = rem; Some(last) } @@ -4844,7 +4853,6 @@ impl<T, const N: usize> [[T; N]] { } } -#[cfg(not(test))] impl [f32] { /// Sorts the slice of floats. /// @@ -4873,7 +4881,6 @@ impl [f32] { } } -#[cfg(not(test))] impl [f64] { /// Sorts the slice of floats. /// diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 83ad10db2da..5cc08f8a71a 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -114,7 +114,6 @@ fn slice_error_fail_rt(s: &str, begin: usize, end: usize) -> ! { ); } -#[cfg(not(test))] impl str { /// Returns the length of `self`. /// @@ -134,7 +133,7 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_str_len", since = "1.39.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "str_len")] + #[rustc_diagnostic_item = "str_len"] #[must_use] #[inline] pub const fn len(&self) -> usize { @@ -1029,7 +1028,7 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - #[cfg_attr(not(test), rustc_diagnostic_item = "str_chars")] + #[rustc_diagnostic_item = "str_chars"] pub fn chars(&self) -> Chars<'_> { Chars { iter: self.as_bytes().iter() } } @@ -1160,7 +1159,7 @@ impl str { #[must_use = "this returns the split string as an iterator, \ without modifying the original"] #[stable(feature = "split_whitespace", since = "1.1.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "str_split_whitespace")] + #[rustc_diagnostic_item = "str_split_whitespace"] #[inline] pub fn split_whitespace(&self) -> SplitWhitespace<'_> { SplitWhitespace { inner: self.split(IsWhitespace).filter(IsNotEmpty) } @@ -1355,7 +1354,7 @@ impl str { /// assert!(bananas.starts_with(&['a', 'b', 'c', 'd'])); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "str_starts_with")] + #[rustc_diagnostic_item = "str_starts_with"] pub fn starts_with<P: Pattern>(&self, pat: P) -> bool { pat.is_prefix_of(self) } @@ -1380,7 +1379,7 @@ impl str { /// assert!(!bananas.ends_with("nana")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "str_ends_with")] + #[rustc_diagnostic_item = "str_ends_with"] pub fn ends_with<P: Pattern>(&self, pat: P) -> bool where for<'a> P::Searcher<'a>: ReverseSearcher<'a>, @@ -2114,7 +2113,7 @@ impl str { #[must_use = "this returns the trimmed string as a slice, \ without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "str_trim")] + #[rustc_diagnostic_item = "str_trim"] pub fn trim(&self) -> &str { self.trim_matches(|c: char| c.is_whitespace()) } @@ -2153,7 +2152,7 @@ impl str { #[must_use = "this returns the trimmed string as a new slice, \ without modifying the original"] #[stable(feature = "trim_direction", since = "1.30.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "str_trim_start")] + #[rustc_diagnostic_item = "str_trim_start"] pub fn trim_start(&self) -> &str { self.trim_start_matches(|c: char| c.is_whitespace()) } @@ -2192,7 +2191,7 @@ impl str { #[must_use = "this returns the trimmed string as a new slice, \ without modifying the original"] #[stable(feature = "trim_direction", since = "1.30.0")] - #[cfg_attr(not(test), rustc_diagnostic_item = "str_trim_end")] + #[rustc_diagnostic_item = "str_trim_end"] pub fn trim_end(&self) -> &str { self.trim_end_matches(|c: char| c.is_whitespace()) } diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs index 2d941adfd85..bcbbb11c83b 100644 --- a/library/core/src/str/pattern.rs +++ b/library/core/src/str/pattern.rs @@ -644,21 +644,21 @@ where impl<const N: usize> MultiCharEq for [char; N] { #[inline] fn matches(&mut self, c: char) -> bool { - self.iter().any(|&m| m == c) + self.contains(&c) } } impl<const N: usize> MultiCharEq for &[char; N] { #[inline] fn matches(&mut self, c: char) -> bool { - self.iter().any(|&m| m == c) + self.contains(&c) } } impl MultiCharEq for &[char] { #[inline] fn matches(&mut self, c: char) -> bool { - self.iter().any(|&m| m == c) + self.contains(&c) } } diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 54a65c8459e..9b1b13e7129 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -295,7 +295,7 @@ unsafe impl Sync for AtomicBool {} /// loads and stores of pointers. Its size depends on the target pointer's size. #[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "AtomicPtr")] +#[rustc_diagnostic_item = "AtomicPtr"] #[cfg_attr(target_pointer_width = "16", repr(C, align(2)))] #[cfg_attr(target_pointer_width = "32", repr(C, align(4)))] #[cfg_attr(target_pointer_width = "64", repr(C, align(8)))] @@ -469,6 +469,7 @@ impl AtomicBool { /// /// [valid]: crate::ptr#safety /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses + #[inline] #[stable(feature = "atomic_from_ptr", since = "1.75.0")] #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")] pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool { @@ -1389,6 +1390,7 @@ impl<T> AtomicPtr<T> { /// /// [valid]: crate::ptr#safety /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses + #[inline] #[stable(feature = "atomic_from_ptr", since = "1.75.0")] #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")] pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr<T> { @@ -2525,6 +2527,7 @@ macro_rules! atomic_int { /// /// [valid]: crate::ptr#safety /// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses + #[inline] #[stable(feature = "atomic_from_ptr", since = "1.75.0")] #[rustc_const_stable(feature = "const_atomic_from_ptr", since = "1.84.0")] pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type { @@ -3446,7 +3449,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), - cfg_attr(not(test), rustc_diagnostic_item = "AtomicI8"), + rustc_diagnostic_item = "AtomicI8", "i8", "", atomic_min, atomic_max, @@ -3465,7 +3468,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), - cfg_attr(not(test), rustc_diagnostic_item = "AtomicU8"), + rustc_diagnostic_item = "AtomicU8", "u8", "", atomic_umin, atomic_umax, @@ -3484,7 +3487,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), - cfg_attr(not(test), rustc_diagnostic_item = "AtomicI16"), + rustc_diagnostic_item = "AtomicI16", "i16", "", atomic_min, atomic_max, @@ -3503,7 +3506,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), - cfg_attr(not(test), rustc_diagnostic_item = "AtomicU16"), + rustc_diagnostic_item = "AtomicU16", "u16", "", atomic_umin, atomic_umax, @@ -3522,7 +3525,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), - cfg_attr(not(test), rustc_diagnostic_item = "AtomicI32"), + rustc_diagnostic_item = "AtomicI32", "i32", "", atomic_min, atomic_max, @@ -3541,7 +3544,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), - cfg_attr(not(test), rustc_diagnostic_item = "AtomicU32"), + rustc_diagnostic_item = "AtomicU32", "u32", "", atomic_umin, atomic_umax, @@ -3560,7 +3563,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), - cfg_attr(not(test), rustc_diagnostic_item = "AtomicI64"), + rustc_diagnostic_item = "AtomicI64", "i64", "", atomic_min, atomic_max, @@ -3579,7 +3582,7 @@ atomic_int! { stable(feature = "integer_atomics_stable", since = "1.34.0"), rustc_const_stable(feature = "const_integer_atomics", since = "1.34.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), - cfg_attr(not(test), rustc_diagnostic_item = "AtomicU64"), + rustc_diagnostic_item = "AtomicU64", "u64", "", atomic_umin, atomic_umax, @@ -3598,7 +3601,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "99069"), rustc_const_unstable(feature = "integer_atomics", issue = "99069"), rustc_const_unstable(feature = "integer_atomics", issue = "99069"), - cfg_attr(not(test), rustc_diagnostic_item = "AtomicI128"), + rustc_diagnostic_item = "AtomicI128", "i128", "#![feature(integer_atomics)]\n\n", atomic_min, atomic_max, @@ -3617,7 +3620,7 @@ atomic_int! { unstable(feature = "integer_atomics", issue = "99069"), rustc_const_unstable(feature = "integer_atomics", issue = "99069"), rustc_const_unstable(feature = "integer_atomics", issue = "99069"), - cfg_attr(not(test), rustc_diagnostic_item = "AtomicU128"), + rustc_diagnostic_item = "AtomicU128", "u128", "#![feature(integer_atomics)]\n\n", atomic_umin, atomic_umax, @@ -3640,7 +3643,7 @@ macro_rules! atomic_int_ptr_sized { stable(feature = "atomic_nand", since = "1.27.0"), rustc_const_stable(feature = "const_ptr_sized_atomics", since = "1.24.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), - cfg_attr(not(test), rustc_diagnostic_item = "AtomicIsize"), + rustc_diagnostic_item = "AtomicIsize", "isize", "", atomic_min, atomic_max, @@ -3659,7 +3662,7 @@ macro_rules! atomic_int_ptr_sized { stable(feature = "atomic_nand", since = "1.27.0"), rustc_const_stable(feature = "const_ptr_sized_atomics", since = "1.24.0"), rustc_const_stable(feature = "const_atomic_into_inner", since = "1.79.0"), - cfg_attr(not(test), rustc_diagnostic_item = "AtomicUsize"), + rustc_diagnostic_item = "AtomicUsize", "usize", "", atomic_umin, atomic_umax, diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 3f57b04753a..9b8fefe42af 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -402,7 +402,7 @@ impl<'a> ContextBuilder<'a> { /// [`Wake`]: ../../alloc/task/trait.Wake.html #[repr(transparent)] #[stable(feature = "futures_api", since = "1.36.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "Waker")] +#[rustc_diagnostic_item = "Waker"] pub struct Waker { waker: RawWaker, } diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 37b5c1076fa..18c03b4a6f8 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -77,7 +77,7 @@ const DAYS_PER_WEEK: u64 = 7; /// crate to do so. #[stable(feature = "duration", since = "1.3.0")] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] -#[cfg_attr(not(test), rustc_diagnostic_item = "Duration")] +#[rustc_diagnostic_item = "Duration"] pub struct Duration { secs: u64, nanos: Nanoseconds, // Always 0 <= nanos < NANOS_PER_SEC diff --git a/library/core/src/unit.rs b/library/core/src/unit.rs index d656005f3d4..d54816c444b 100644 --- a/library/core/src/unit.rs +++ b/library/core/src/unit.rs @@ -17,3 +17,19 @@ impl FromIterator<()> for () { iter.into_iter().for_each(|()| {}) } } + +pub(crate) trait IsUnit { + fn is_unit() -> bool; +} + +impl<T: ?Sized> IsUnit for T { + default fn is_unit() -> bool { + false + } +} + +impl IsUnit for () { + fn is_unit() -> bool { + true + } +} diff --git a/library/coretests/tests/fmt/mod.rs b/library/coretests/tests/fmt/mod.rs index 025c69c4f62..d9060fe903d 100644 --- a/library/coretests/tests/fmt/mod.rs +++ b/library/coretests/tests/fmt/mod.rs @@ -15,8 +15,31 @@ fn test_format_flags() { fn test_pointer_formats_data_pointer() { let b: &[u8] = b""; let s: &str = ""; - assert_eq!(format!("{s:p}"), format!("{:p}", s.as_ptr())); - assert_eq!(format!("{b:p}"), format!("{:p}", b.as_ptr())); + assert_eq!(format!("{s:p}"), format!("{:p}", s as *const _)); + assert_eq!(format!("{b:p}"), format!("{:p}", b as *const _)); +} + +#[test] +fn test_fmt_debug_of_raw_pointers() { + use core::fmt::Debug; + use core::ptr; + + fn check_fmt<T: Debug>(t: T, start: &str, contains: &str) { + let formatted = format!("{:?}", t); + assert!(formatted.starts_with(start), "{formatted:?} doesn't start with {start:?}"); + assert!(formatted.contains(contains), "{formatted:?} doesn't contain {contains:?}"); + } + + assert_eq!(format!("{:?}", ptr::without_provenance_mut::<i32>(0x100)), "0x100"); + assert_eq!(format!("{:?}", ptr::without_provenance::<i32>(0x100)), "0x100"); + + let slice = ptr::slice_from_raw_parts(ptr::without_provenance::<i32>(0x100), 3); + assert_eq!(format!("{:?}", slice as *mut [i32]), "Pointer { addr: 0x100, metadata: 3 }"); + assert_eq!(format!("{:?}", slice as *const [i32]), "Pointer { addr: 0x100, metadata: 3 }"); + + let vtable = &mut 500 as &mut dyn Debug; + check_fmt(vtable as *mut dyn Debug, "Pointer { addr: ", ", metadata: DynMetadata("); + check_fmt(vtable as *const dyn Debug, "Pointer { addr: ", ", metadata: DynMetadata("); } #[test] @@ -58,6 +81,7 @@ fn formatting_options_ctor() { } #[test] +#[allow(deprecated)] fn formatting_options_flags() { use core::fmt::*; for sign in [None, Some(Sign::Plus), Some(Sign::Minus)] { @@ -75,6 +99,25 @@ fn formatting_options_flags() { assert_eq!(formatting_options.get_alternate(), alternate); assert_eq!(formatting_options.get_sign_aware_zero_pad(), sign_aware_zero_pad); assert_eq!(formatting_options.get_debug_as_hex(), debug_as_hex); + + let mut output = String::new(); + let fmt = Formatter::new(&mut output, formatting_options); + assert_eq!(fmt.options(), formatting_options); + + assert_eq!(fmt.sign_minus(), sign == Some(Sign::Minus)); + assert_eq!(fmt.sign_plus(), sign == Some(Sign::Plus)); + assert_eq!(fmt.alternate(), alternate); + assert_eq!(fmt.sign_aware_zero_pad(), sign_aware_zero_pad); + + // The flags method is deprecated. + // This checks compatibility with older versions of Rust. + assert_eq!(fmt.flags() & 1 != 0, sign == Some(Sign::Plus)); + assert_eq!(fmt.flags() & 2 != 0, sign == Some(Sign::Minus)); + assert_eq!(fmt.flags() & 4 != 0, alternate); + assert_eq!(fmt.flags() & 8 != 0, sign_aware_zero_pad); + assert_eq!(fmt.flags() & 16 != 0, debug_as_hex == Some(DebugAsHex::Lower)); + assert_eq!(fmt.flags() & 32 != 0, debug_as_hex == Some(DebugAsHex::Upper)); + assert_eq!(fmt.flags() & 0xFFFF_FFC0, 0); } } } diff --git a/library/coretests/tests/mem.rs b/library/coretests/tests/mem.rs index 9cb94ca3b0f..9c15be4a8c4 100644 --- a/library/coretests/tests/mem.rs +++ b/library/coretests/tests/mem.rs @@ -1,5 +1,5 @@ use core::mem::*; -use core::ptr; +use core::{array, ptr}; #[cfg(panic = "unwind")] use std::rc::Rc; @@ -327,11 +327,11 @@ fn uninit_write_clone_of_slice_no_drop() { } #[test] -fn uninit_fill() { +fn uninit_write_filled() { let mut dst = [MaybeUninit::new(255); 64]; let expect = [0; 64]; - assert_eq!(MaybeUninit::fill(&mut dst, 0), &expect); + assert_eq!(dst.write_filled(0), &expect); } #[cfg(panic = "unwind")] @@ -352,7 +352,7 @@ impl Clone for CloneUntilPanic { #[test] #[cfg(panic = "unwind")] -fn uninit_fill_clone_panic_drop() { +fn uninit_write_filled_panic_drop() { use std::panic; let rc = Rc::new(()); @@ -361,7 +361,7 @@ fn uninit_fill_clone_panic_drop() { let src = CloneUntilPanic { limit: 3, rc: rc.clone() }; let err = panic::catch_unwind(panic::AssertUnwindSafe(|| { - MaybeUninit::fill(&mut dst, src); + dst.write_filled(src); })); match err { @@ -378,23 +378,23 @@ fn uninit_fill_clone_panic_drop() { #[test] #[cfg(panic = "unwind")] -fn uninit_fill_clone_no_drop_clones() { +fn uninit_write_filled_no_drop_clones() { let mut dst = [MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit()]; - MaybeUninit::fill(&mut dst, Bomb); + dst.write_filled(Bomb); } #[test] -fn uninit_fill_with() { - let mut dst = [MaybeUninit::new(255); 64]; - let expect = [0; 64]; +fn uninit_write_with() { + let mut dst = [MaybeUninit::new(255usize); 64]; + let expect = array::from_fn::<usize, 64, _>(|idx| idx); - assert_eq!(MaybeUninit::fill_with(&mut dst, || 0), &expect); + assert_eq!(dst.write_with(|idx| idx), &expect); } #[test] #[cfg(panic = "unwind")] -fn uninit_fill_with_mid_panic() { +fn uninit_write_with_mid_panic() { use std::panic; let rc = Rc::new(()); @@ -403,7 +403,7 @@ fn uninit_fill_with_mid_panic() { let src = CloneUntilPanic { limit: 3, rc: rc.clone() }; let err = panic::catch_unwind(panic::AssertUnwindSafe(|| { - MaybeUninit::fill_with(&mut dst, || src.clone()); + dst.write_with(|_| src.clone()); })); drop(src); @@ -423,58 +423,58 @@ fn uninit_fill_with_mid_panic() { #[test] #[cfg(panic = "unwind")] -fn uninit_fill_with_no_drop() { +fn uninit_write_with_no_drop() { let mut dst = [MaybeUninit::uninit()]; let src = Bomb; - MaybeUninit::fill_with(&mut dst, || src.clone()); + dst.write_with(|_| src.clone()); forget(src); } #[test] -fn uninit_fill_from() { +fn uninit_write_iter() { let mut dst = [MaybeUninit::new(255); 64]; let src = [0; 64]; - let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + let (initted, remainder) = dst.write_iter(src.into_iter()); assert_eq!(initted, &src); assert_eq!(remainder.len(), 0); } #[test] -fn uninit_fill_from_partial() { +fn uninit_write_iter_partial() { let mut dst = [MaybeUninit::new(255); 64]; let src = [0; 48]; - let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + let (initted, remainder) = dst.write_iter(src.into_iter()); assert_eq!(initted, &src); assert_eq!(remainder.len(), 16); } #[test] -fn uninit_over_fill() { +fn uninit_write_iter_overfill() { let mut dst = [MaybeUninit::new(255); 64]; let src = [0; 72]; - let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + let (initted, remainder) = dst.write_iter(src.into_iter()); assert_eq!(initted, &src[0..64]); assert_eq!(remainder.len(), 0); } #[test] -fn uninit_empty_fill() { +fn uninit_write_iter_empty() { let mut dst = [MaybeUninit::new(255); 64]; let src = [0; 0]; - let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + let (initted, remainder) = dst.write_iter(src.into_iter()); assert_eq!(initted, &src[0..0]); assert_eq!(remainder.len(), 64); } #[test] #[cfg(panic = "unwind")] -fn uninit_fill_from_mid_panic() { +fn uninit_write_iter_mid_panic() { use std::panic; struct IterUntilPanic { @@ -504,7 +504,7 @@ fn uninit_fill_from_mid_panic() { let src = IterUntilPanic { limit: 3, rc: rc.clone() }; let err = panic::catch_unwind(panic::AssertUnwindSafe(|| { - MaybeUninit::fill_from(&mut dst, src); + dst.write_iter(src); })); match err { @@ -522,11 +522,11 @@ fn uninit_fill_from_mid_panic() { #[test] #[cfg(panic = "unwind")] -fn uninit_fill_from_no_drop() { +fn uninit_write_iter_no_drop() { let mut dst = [MaybeUninit::uninit()]; let src = [Bomb]; - MaybeUninit::fill_from(&mut dst, src.iter()); + dst.write_iter(src.iter()); forget(src); } diff --git a/library/coretests/tests/pin.rs b/library/coretests/tests/pin.rs index b3fb06e710d..a866cf12a3b 100644 --- a/library/coretests/tests/pin.rs +++ b/library/coretests/tests/pin.rs @@ -34,6 +34,9 @@ fn pin_const() { } pin_mut_const(); + + // Check that we accept a Rust 2024 $expr. + std::pin::pin!(const { 1 }); } #[allow(unused)] @@ -81,3 +84,14 @@ mod pin_coerce_unsized { arg } } + +#[test] +#[cfg(not(bootstrap))] +fn temp_lifetime() { + // Check that temporary lifetimes work as in Rust 2021. + // Regression test for https://github.com/rust-lang/rust/issues/138596 + match std::pin::pin!(foo(&mut 0)) { + _ => {} + } + async fn foo(_: &mut usize) {} +} diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index a284633ea2f..e5c1d6bdb3b 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -79,9 +79,11 @@ cfg_if::cfg_if! { unsafe extern "C" { /// Handler in std called when a panic object is dropped outside of /// `catch_unwind`. + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] fn __rust_drop_panic() -> !; /// Handler in std called when a foreign exception is caught. + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] fn __rust_foreign_exception() -> !; } diff --git a/library/portable-simd/beginners-guide.md b/library/portable-simd/beginners-guide.md index 17ade06ae80..dc08d847ced 100644 --- a/library/portable-simd/beginners-guide.md +++ b/library/portable-simd/beginners-guide.md @@ -80,12 +80,12 @@ Most of the portable SIMD API is designed to allow the user to gloss over the de Fortunately, most SIMD types have a fairly predictable size. `i32x4` is bit-equivalent to `[i32; 4]` and so can be bitcast to it, e.g. using [`mem::transmute`], though the API usually offers a safe cast you can use instead. -However, this is not the same as alignment. Computer architectures generally prefer aligned accesses, especially when moving data between memory and vector registers, and while some support specialized operations that can bend the rules to help with this, unaligned access is still typically slow, or even undefined behavior. In addition, different architectures can require different alignments when interacting with their native SIMD types. For this reason, any `#[repr(simd)]` type has a non-portable alignment. If it is necessary to directly interact with the alignment of these types, it should be via [`mem::align_of`]. +However, this is not the same as alignment. Computer architectures generally prefer aligned accesses, especially when moving data between memory and vector registers, and while some support specialized operations that can bend the rules to help with this, unaligned access is still typically slow, or even undefined behavior. In addition, different architectures can require different alignments when interacting with their native SIMD types. For this reason, any `#[repr(simd)]` type has a non-portable alignment. If it is necessary to directly interact with the alignment of these types, it should be via [`align_of`]. When working with slices, data correctly aligned for SIMD can be acquired using the [`as_simd`] and [`as_simd_mut`] methods of the slice primitive. [`mem::transmute`]: https://doc.rust-lang.org/core/mem/fn.transmute.html -[`mem::align_of`]: https://doc.rust-lang.org/core/mem/fn.align_of.html +[`align_of`]: https://doc.rust-lang.org/core/mem/fn.align_of.html [`as_simd`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.as_simd [`as_simd_mut`]: https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.as_simd_mut diff --git a/library/portable-simd/crates/core_simd/Cargo.toml b/library/portable-simd/crates/core_simd/Cargo.toml index a7a6d43b11d..537ce459c07 100644 --- a/library/portable-simd/crates/core_simd/Cargo.toml +++ b/library/portable-simd/crates/core_simd/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "core_simd" version = "0.1.0" -edition = "2021" +edition = "2024" homepage = "https://github.com/rust-lang/portable-simd" repository = "https://github.com/rust-lang/portable-simd" keywords = ["core", "simd", "intrinsics"] diff --git a/library/portable-simd/crates/core_simd/src/lib.rs b/library/portable-simd/crates/core_simd/src/lib.rs index 7f57847c9c2..717b882b64b 100644 --- a/library/portable-simd/crates/core_simd/src/lib.rs +++ b/library/portable-simd/crates/core_simd/src/lib.rs @@ -35,7 +35,11 @@ feature(stdarch_x86_avx512) )] #![warn(missing_docs, clippy::missing_inline_in_public_items)] // basically all items, really -#![deny(unsafe_op_in_unsafe_fn, clippy::undocumented_unsafe_blocks)] +#![deny( + unsafe_op_in_unsafe_fn, + unreachable_pub, + clippy::undocumented_unsafe_blocks +)] #![doc(test(attr(deny(warnings))))] #![allow(internal_features)] #![unstable(feature = "portable_simd", issue = "86656")] diff --git a/library/portable-simd/crates/core_simd/src/masks/bitmask.rs b/library/portable-simd/crates/core_simd/src/masks/bitmask.rs index db4312d5bf8..8221d8f17e9 100644 --- a/library/portable-simd/crates/core_simd/src/masks/bitmask.rs +++ b/library/portable-simd/crates/core_simd/src/masks/bitmask.rs @@ -5,7 +5,7 @@ use core::marker::PhantomData; /// A mask where each lane is represented by a single bit. #[repr(transparent)] -pub struct Mask<T, const N: usize>( +pub(crate) struct Mask<T, const N: usize>( <LaneCount<N> as SupportedLaneCount>::BitMask, PhantomData<T>, ) @@ -78,7 +78,7 @@ where { #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub fn splat(value: bool) -> Self { + pub(crate) fn splat(value: bool) -> Self { let mut mask = <LaneCount<N> as SupportedLaneCount>::BitMask::default(); if value { mask.as_mut().fill(u8::MAX) @@ -93,12 +93,12 @@ where #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] - pub unsafe fn test_unchecked(&self, lane: usize) -> bool { + pub(crate) unsafe fn test_unchecked(&self, lane: usize) -> bool { (self.0.as_ref()[lane / 8] >> (lane % 8)) & 0x1 > 0 } #[inline] - pub unsafe fn set_unchecked(&mut self, lane: usize, value: bool) { + pub(crate) unsafe fn set_unchecked(&mut self, lane: usize, value: bool) { unsafe { self.0.as_mut()[lane / 8] ^= ((value ^ self.test_unchecked(lane)) as u8) << (lane % 8) } @@ -106,7 +106,7 @@ where #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - pub fn to_int(self) -> Simd<T, N> { + pub(crate) fn to_int(self) -> Simd<T, N> { unsafe { core::intrinsics::simd::simd_select_bitmask( self.0, @@ -118,19 +118,19 @@ where #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub unsafe fn from_int_unchecked(value: Simd<T, N>) -> Self { + pub(crate) unsafe fn from_int_unchecked(value: Simd<T, N>) -> Self { unsafe { Self(core::intrinsics::simd::simd_bitmask(value), PhantomData) } } #[inline] - pub fn to_bitmask_integer(self) -> u64 { + pub(crate) fn to_bitmask_integer(self) -> u64 { let mut bitmask = [0u8; 8]; bitmask[..self.0.as_ref().len()].copy_from_slice(self.0.as_ref()); u64::from_ne_bytes(bitmask) } #[inline] - pub fn from_bitmask_integer(bitmask: u64) -> Self { + pub(crate) fn from_bitmask_integer(bitmask: u64) -> Self { let mut bytes = <LaneCount<N> as SupportedLaneCount>::BitMask::default(); let len = bytes.as_mut().len(); bytes @@ -141,7 +141,7 @@ where #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub fn convert<U>(self) -> Mask<U, N> + pub(crate) fn convert<U>(self) -> Mask<U, N> where U: MaskElement, { @@ -151,13 +151,13 @@ where #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] - pub fn any(self) -> bool { + pub(crate) fn any(self) -> bool { self != Self::splat(false) } #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] - pub fn all(self) -> bool { + pub(crate) fn all(self) -> bool { self == Self::splat(true) } } diff --git a/library/portable-simd/crates/core_simd/src/masks/full_masks.rs b/library/portable-simd/crates/core_simd/src/masks/full_masks.rs index 387b508c4b4..4e98db4070a 100644 --- a/library/portable-simd/crates/core_simd/src/masks/full_masks.rs +++ b/library/portable-simd/crates/core_simd/src/masks/full_masks.rs @@ -3,7 +3,7 @@ use crate::simd::{LaneCount, MaskElement, Simd, SupportedLaneCount}; #[repr(transparent)] -pub struct Mask<T, const N: usize>(Simd<T, N>) +pub(crate) struct Mask<T, const N: usize>(Simd<T, N>) where T: MaskElement, LaneCount<N>: SupportedLaneCount; @@ -80,7 +80,7 @@ macro_rules! impl_reverse_bits { #[inline(always)] fn reverse_bits(self, n: usize) -> Self { let rev = <$int>::reverse_bits(self); - let bitsize = core::mem::size_of::<$int>() * 8; + let bitsize = size_of::<$int>() * 8; if n < bitsize { // Shift things back to the right rev >> (bitsize - n) @@ -102,36 +102,36 @@ where { #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub fn splat(value: bool) -> Self { + pub(crate) fn splat(value: bool) -> Self { Self(Simd::splat(if value { T::TRUE } else { T::FALSE })) } #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] - pub unsafe fn test_unchecked(&self, lane: usize) -> bool { + pub(crate) unsafe fn test_unchecked(&self, lane: usize) -> bool { T::eq(self.0[lane], T::TRUE) } #[inline] - pub unsafe fn set_unchecked(&mut self, lane: usize, value: bool) { + pub(crate) unsafe fn set_unchecked(&mut self, lane: usize, value: bool) { self.0[lane] = if value { T::TRUE } else { T::FALSE } } #[inline] #[must_use = "method returns a new vector and does not mutate the original value"] - pub fn to_int(self) -> Simd<T, N> { + pub(crate) fn to_int(self) -> Simd<T, N> { self.0 } #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub unsafe fn from_int_unchecked(value: Simd<T, N>) -> Self { + pub(crate) unsafe fn from_int_unchecked(value: Simd<T, N>) -> Self { Self(value) } #[inline] #[must_use = "method returns a new mask and does not mutate the original value"] - pub fn convert<U>(self) -> Mask<U, N> + pub(crate) fn convert<U>(self) -> Mask<U, N> where U: MaskElement, { @@ -220,14 +220,14 @@ where #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] - pub fn any(self) -> bool { + pub(crate) fn any(self) -> bool { // Safety: use `self` as an integer vector unsafe { core::intrinsics::simd::simd_reduce_any(self.to_int()) } } #[inline] #[must_use = "method returns a new bool and does not mutate the original value"] - pub fn all(self) -> bool { + pub(crate) fn all(self) -> bool { // Safety: use `self` as an integer vector unsafe { core::intrinsics::simd::simd_reduce_all(self.to_int()) } } diff --git a/library/portable-simd/crates/core_simd/src/ops.rs b/library/portable-simd/crates/core_simd/src/ops.rs index 4ac64a253a3..f36e8d01a73 100644 --- a/library/portable-simd/crates/core_simd/src/ops.rs +++ b/library/portable-simd/crates/core_simd/src/ops.rs @@ -1,4 +1,4 @@ -use crate::simd::{cmp::SimdPartialEq, LaneCount, Simd, SimdElement, SupportedLaneCount}; +use crate::simd::{LaneCount, Simd, SimdElement, SupportedLaneCount, cmp::SimdPartialEq}; use core::ops::{Add, Mul}; use core::ops::{BitAnd, BitOr, BitXor}; use core::ops::{Div, Rem, Sub}; diff --git a/library/portable-simd/crates/core_simd/src/simd/cmp/eq.rs b/library/portable-simd/crates/core_simd/src/simd/cmp/eq.rs index 93989ce91b8..2312ba401fa 100644 --- a/library/portable-simd/crates/core_simd/src/simd/cmp/eq.rs +++ b/library/portable-simd/crates/core_simd/src/simd/cmp/eq.rs @@ -1,6 +1,6 @@ use crate::simd::{ - ptr::{SimdConstPtr, SimdMutPtr}, LaneCount, Mask, Simd, SimdElement, SupportedLaneCount, + ptr::{SimdConstPtr, SimdMutPtr}, }; /// Parallel `PartialEq`. diff --git a/library/portable-simd/crates/core_simd/src/simd/cmp/ord.rs b/library/portable-simd/crates/core_simd/src/simd/cmp/ord.rs index 899f00a8316..e813e761303 100644 --- a/library/portable-simd/crates/core_simd/src/simd/cmp/ord.rs +++ b/library/portable-simd/crates/core_simd/src/simd/cmp/ord.rs @@ -1,7 +1,7 @@ use crate::simd::{ + LaneCount, Mask, Simd, SupportedLaneCount, cmp::SimdPartialEq, ptr::{SimdConstPtr, SimdMutPtr}, - LaneCount, Mask, Simd, SupportedLaneCount, }; /// Parallel `PartialOrd`. diff --git a/library/portable-simd/crates/core_simd/src/simd/num/float.rs b/library/portable-simd/crates/core_simd/src/simd/num/float.rs index db705dfe202..b5972c47373 100644 --- a/library/portable-simd/crates/core_simd/src/simd/num/float.rs +++ b/library/portable-simd/crates/core_simd/src/simd/num/float.rs @@ -1,7 +1,7 @@ use super::sealed::Sealed; use crate::simd::{ - cmp::{SimdPartialEq, SimdPartialOrd}, LaneCount, Mask, Simd, SimdCast, SimdElement, SupportedLaneCount, + cmp::{SimdPartialEq, SimdPartialOrd}, }; /// Operations on SIMD vectors of floats. @@ -263,7 +263,8 @@ macro_rules! impl_trait { unsafe { core::intrinsics::simd::simd_as(self) } } - // https://github.com/llvm/llvm-project/issues/94694 + // workaround for https://github.com/llvm/llvm-project/issues/94694 (fixed in LLVM 20) + // tracked in: https://github.com/rust-lang/rust/issues/135982 #[cfg(target_arch = "aarch64")] #[inline] fn cast<T: SimdCast>(self) -> Self::Cast<T> @@ -302,14 +303,14 @@ macro_rules! impl_trait { #[inline] fn to_bits(self) -> Simd<$bits_ty, N> { - assert_eq!(core::mem::size_of::<Self>(), core::mem::size_of::<Self::Bits>()); + assert_eq!(size_of::<Self>(), size_of::<Self::Bits>()); // Safety: transmuting between vector types is safe unsafe { core::mem::transmute_copy(&self) } } #[inline] fn from_bits(bits: Simd<$bits_ty, N>) -> Self { - assert_eq!(core::mem::size_of::<Self>(), core::mem::size_of::<Self::Bits>()); + assert_eq!(size_of::<Self>(), size_of::<Self::Bits>()); // Safety: transmuting between vector types is safe unsafe { core::mem::transmute_copy(&bits) } } diff --git a/library/portable-simd/crates/core_simd/src/simd/num/int.rs b/library/portable-simd/crates/core_simd/src/simd/num/int.rs index 3a51235ff95..d25050c3e4b 100644 --- a/library/portable-simd/crates/core_simd/src/simd/num/int.rs +++ b/library/portable-simd/crates/core_simd/src/simd/num/int.rs @@ -1,7 +1,7 @@ use super::sealed::Sealed; use crate::simd::{ - cmp::SimdOrd, cmp::SimdPartialOrd, num::SimdUint, LaneCount, Mask, Simd, SimdCast, SimdElement, - SupportedLaneCount, + LaneCount, Mask, Simd, SimdCast, SimdElement, SupportedLaneCount, cmp::SimdOrd, + cmp::SimdPartialOrd, num::SimdUint, }; /// Operations on SIMD vectors of signed integers. diff --git a/library/portable-simd/crates/core_simd/src/simd/num/uint.rs b/library/portable-simd/crates/core_simd/src/simd/num/uint.rs index 1ab2d8c7b73..45d978068b6 100644 --- a/library/portable-simd/crates/core_simd/src/simd/num/uint.rs +++ b/library/portable-simd/crates/core_simd/src/simd/num/uint.rs @@ -1,5 +1,5 @@ use super::sealed::Sealed; -use crate::simd::{cmp::SimdOrd, LaneCount, Simd, SimdCast, SimdElement, SupportedLaneCount}; +use crate::simd::{LaneCount, Simd, SimdCast, SimdElement, SupportedLaneCount, cmp::SimdOrd}; /// Operations on SIMD vectors of unsigned integers. pub trait SimdUint: Copy + Sealed { diff --git a/library/portable-simd/crates/core_simd/src/simd/prelude.rs b/library/portable-simd/crates/core_simd/src/simd/prelude.rs index 4b7c744c013..e5d7a2aeb73 100644 --- a/library/portable-simd/crates/core_simd/src/simd/prelude.rs +++ b/library/portable-simd/crates/core_simd/src/simd/prelude.rs @@ -7,10 +7,11 @@ #[doc(no_inline)] pub use super::{ + Mask, Simd, cmp::{SimdOrd, SimdPartialEq, SimdPartialOrd}, num::{SimdFloat, SimdInt, SimdUint}, ptr::{SimdConstPtr, SimdMutPtr}, - simd_swizzle, Mask, Simd, + simd_swizzle, }; #[rustfmt::skip] diff --git a/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs b/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs index 47383809ffb..36452e7ae92 100644 --- a/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs +++ b/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs @@ -1,5 +1,5 @@ use super::sealed::Sealed; -use crate::simd::{cmp::SimdPartialEq, num::SimdUint, LaneCount, Mask, Simd, SupportedLaneCount}; +use crate::simd::{LaneCount, Mask, Simd, SupportedLaneCount, cmp::SimdPartialEq, num::SimdUint}; /// Operations on SIMD vectors of constant pointers. pub trait SimdConstPtr: Copy + Sealed { diff --git a/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs b/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs index 3f20eef21a3..c644f390c20 100644 --- a/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs +++ b/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs @@ -1,5 +1,5 @@ use super::sealed::Sealed; -use crate::simd::{cmp::SimdPartialEq, num::SimdUint, LaneCount, Mask, Simd, SupportedLaneCount}; +use crate::simd::{LaneCount, Mask, Simd, SupportedLaneCount, cmp::SimdPartialEq, num::SimdUint}; /// Operations on SIMD vectors of mutable pointers. pub trait SimdMutPtr: Copy + Sealed { diff --git a/library/portable-simd/crates/core_simd/src/swizzle.rs b/library/portable-simd/crates/core_simd/src/swizzle.rs index 42425ef37e5..dbdd6ef40eb 100644 --- a/library/portable-simd/crates/core_simd/src/swizzle.rs +++ b/library/portable-simd/crates/core_simd/src/swizzle.rs @@ -214,6 +214,17 @@ where /// Rotates the vector such that the first `OFFSET` elements of the slice move to the end /// while the last `self.len() - OFFSET` elements move to the front. After calling `rotate_elements_left`, /// the element previously at index `OFFSET` will become the first element in the slice. + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd::Simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd::Simd; + /// let a = Simd::from_array([0, 1, 2, 3]); + /// let x = a.rotate_elements_left::<3>(); + /// assert_eq!(x.to_array(), [3, 0, 1, 2]); + /// + /// let y = a.rotate_elements_left::<7>(); + /// assert_eq!(y.to_array(), [3, 0, 1, 2]); + /// ``` #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn rotate_elements_left<const OFFSET: usize>(self) -> Self { @@ -238,6 +249,17 @@ where /// Rotates the vector such that the first `self.len() - OFFSET` elements of the vector move to /// the end while the last `OFFSET` elements move to the front. After calling `rotate_elements_right`, /// the element previously at index `self.len() - OFFSET` will become the first element in the slice. + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd::Simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd::Simd; + /// let a = Simd::from_array([0, 1, 2, 3]); + /// let x = a.rotate_elements_right::<3>(); + /// assert_eq!(x.to_array(), [1, 2, 3, 0]); + /// + /// let y = a.rotate_elements_right::<7>(); + /// assert_eq!(y.to_array(), [1, 2, 3, 0]); + /// ``` #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn rotate_elements_right<const OFFSET: usize>(self) -> Self { @@ -261,6 +283,17 @@ where /// Shifts the vector elements to the left by `OFFSET`, filling in with /// `padding` from the right. + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd::Simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd::Simd; + /// let a = Simd::from_array([0, 1, 2, 3]); + /// let x = a.shift_elements_left::<3>(255); + /// assert_eq!(x.to_array(), [3, 255, 255, 255]); + /// + /// let y = a.shift_elements_left::<7>(255); + /// assert_eq!(y.to_array(), [255, 255, 255, 255]); + /// ``` #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn shift_elements_left<const OFFSET: usize>(self, padding: T) -> Self { @@ -283,6 +316,17 @@ where /// Shifts the vector elements to the right by `OFFSET`, filling in with /// `padding` from the left. + /// ``` + /// # #![feature(portable_simd)] + /// # #[cfg(feature = "as_crate")] use core_simd::simd::Simd; + /// # #[cfg(not(feature = "as_crate"))] use core::simd::Simd; + /// let a = Simd::from_array([0, 1, 2, 3]); + /// let x = a.shift_elements_right::<3>(255); + /// assert_eq!(x.to_array(), [255, 255, 255, 0]); + /// + /// let y = a.shift_elements_right::<7>(255); + /// assert_eq!(y.to_array(), [255, 255, 255, 255]); + /// ``` #[inline] #[must_use = "method returns a new vector and does not mutate the original inputs"] pub fn shift_elements_right<const OFFSET: usize>(self, padding: T) -> Self { diff --git a/library/portable-simd/crates/core_simd/src/to_bytes.rs b/library/portable-simd/crates/core_simd/src/to_bytes.rs index 4833ea9e113..fee2cc06c5b 100644 --- a/library/portable-simd/crates/core_simd/src/to_bytes.rs +++ b/library/portable-simd/crates/core_simd/src/to_bytes.rs @@ -1,6 +1,6 @@ use crate::simd::{ - num::{SimdFloat, SimdInt, SimdUint}, LaneCount, Simd, SimdElement, SupportedLaneCount, + num::{SimdFloat, SimdInt, SimdUint}, }; mod sealed { diff --git a/library/portable-simd/crates/core_simd/src/vector.rs b/library/portable-simd/crates/core_simd/src/vector.rs index 9c4dd36c24f..d76a6cd52bf 100644 --- a/library/portable-simd/crates/core_simd/src/vector.rs +++ b/library/portable-simd/crates/core_simd/src/vector.rs @@ -1,8 +1,8 @@ use crate::simd::{ + LaneCount, Mask, MaskElement, SupportedLaneCount, Swizzle, cmp::SimdPartialOrd, num::SimdUint, ptr::{SimdConstPtr, SimdMutPtr}, - LaneCount, Mask, MaskElement, SupportedLaneCount, Swizzle, }; /// A SIMD vector with the shape of `[T; N]` but the operations of `T`. @@ -83,7 +83,7 @@ use crate::simd::{ /// converting `[T]` to `[Simd<T, N>]`, and allows soundly operating on an aligned SIMD body, /// but it may cost more time when handling the scalar head and tail. /// If these are not enough, it is most ideal to design data structures to be already aligned -/// to `mem::align_of::<Simd<T, N>>()` before using `unsafe` Rust to read or write. +/// to `align_of::<Simd<T, N>>()` before using `unsafe` Rust to read or write. /// Other ways to compensate for these facts, like materializing `Simd` to or from an array first, /// are handled by safe methods like [`Simd::from_array`] and [`Simd::from_slice`]. /// diff --git a/library/portable-simd/crates/core_simd/tests/layout.rs b/library/portable-simd/crates/core_simd/tests/layout.rs index 24114c2d261..3b4666249b0 100644 --- a/library/portable-simd/crates/core_simd/tests/layout.rs +++ b/library/portable-simd/crates/core_simd/tests/layout.rs @@ -7,8 +7,8 @@ macro_rules! layout_tests { test_helpers::test_lanes! { fn no_padding<const LANES: usize>() { assert_eq!( - core::mem::size_of::<core_simd::simd::Simd::<$ty, LANES>>(), - core::mem::size_of::<[$ty; LANES]>(), + size_of::<core_simd::simd::Simd::<$ty, LANES>>(), + size_of::<[$ty; LANES]>(), ); } } diff --git a/library/portable-simd/crates/core_simd/tests/pointers.rs b/library/portable-simd/crates/core_simd/tests/pointers.rs index d7db4e82b3c..6e74c2d18b1 100644 --- a/library/portable-simd/crates/core_simd/tests/pointers.rs +++ b/library/portable-simd/crates/core_simd/tests/pointers.rs @@ -1,8 +1,8 @@ #![feature(portable_simd)] use core_simd::simd::{ - ptr::{SimdConstPtr, SimdMutPtr}, Simd, + ptr::{SimdConstPtr, SimdMutPtr}, }; macro_rules! common_tests { diff --git a/library/portable-simd/crates/core_simd/tests/round.rs b/library/portable-simd/crates/core_simd/tests/round.rs index 847766ec41e..4c1ac3c36f8 100644 --- a/library/portable-simd/crates/core_simd/tests/round.rs +++ b/library/portable-simd/crates/core_simd/tests/round.rs @@ -58,7 +58,7 @@ macro_rules! float_rounding_test { // all of the mantissa digits set to 1, pushed up to the MSB. const ALL_MANTISSA_BITS: IntScalar = ((1 << <Scalar>::MANTISSA_DIGITS) - 1); const MAX_REPRESENTABLE_VALUE: Scalar = - (ALL_MANTISSA_BITS << (core::mem::size_of::<Scalar>() * 8 - <Scalar>::MANTISSA_DIGITS as usize - 1)) as Scalar; + (ALL_MANTISSA_BITS << (size_of::<Scalar>() * 8 - <Scalar>::MANTISSA_DIGITS as usize - 1)) as Scalar; let mut runner = test_helpers::make_runner(); runner.run( diff --git a/library/portable-simd/crates/test_helpers/src/subnormals.rs b/library/portable-simd/crates/test_helpers/src/subnormals.rs index ec0f1fb24b9..b5f19ba47b8 100644 --- a/library/portable-simd/crates/test_helpers/src/subnormals.rs +++ b/library/portable-simd/crates/test_helpers/src/subnormals.rs @@ -12,7 +12,7 @@ macro_rules! impl_float { $( impl FlushSubnormals for $ty { fn flush(self) -> Self { - let is_f32 = core::mem::size_of::<Self>() == 4; + let is_f32 = size_of::<Self>() == 4; let ppc_flush = is_f32 && cfg!(all( any(target_arch = "powerpc", all(target_arch = "powerpc64", target_endian = "big")), target_feature = "altivec", diff --git a/library/std/build.rs b/library/std/build.rs index a0cfbc4685e..d76d07a89f4 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -62,6 +62,7 @@ fn main() { || target_os == "zkvm" || target_os == "rtems" || target_os == "nuttx" + || target_os == "cygwin" // See src/bootstrap/src/core/build_steps/synthetic_targets.rs || env::var("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET").is_ok() diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index 99d105a2454..5d2a304b41c 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -348,6 +348,7 @@ fn default_alloc_error_hook(layout: Layout) { unsafe extern "Rust" { // This symbol is emitted by rustc next to __rust_alloc_error_handler. // Its value depends on the -Zoom={panic,abort} compiler option. + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] static __rust_alloc_error_handler_should_panic: u8; } diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 6961fa8ea94..05bd4345ea8 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -333,7 +333,7 @@ impl Error for VarError { /// /// Discussion of this unsafety on Unix may be found in: /// -/// - [Austin Group Bugzilla](https://austingroupbugs.net/view.php?id=188) +/// - [Austin Group Bugzilla (for POSIX)](https://austingroupbugs.net/view.php?id=188) /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2) /// /// To pass an environment variable to a child process, you can instead use [`Command::env`]. diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs index 974514c9c45..ede21969051 100644 --- a/library/std/src/f128.rs +++ b/library/std/src/f128.rs @@ -468,6 +468,8 @@ impl f128 { /// Returns the natural logarithm of the number. /// + /// This returns NaN when the number is negative, and negative infinity when number is zero. + /// /// # Unspecified precision /// /// The precision of this function is non-deterministic. This means it varies by platform, @@ -489,6 +491,16 @@ impl f128 { /// assert!(abs_difference <= f128::EPSILON); /// # } /// ``` + /// + /// Non-positive values: + /// ``` + /// #![feature(f128)] + /// # #[cfg(reliable_f128_math)] { + /// + /// assert_eq!(0_f128.ln(), f128::NEG_INFINITY); + /// assert!((-42_f128).ln().is_nan()); + /// # } + /// ``` #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f128", issue = "116909")] @@ -499,6 +511,8 @@ impl f128 { /// Returns the logarithm of the number with respect to an arbitrary base. /// + /// This returns NaN when the number is negative, and negative infinity when number is zero. + /// /// The result might not be correctly rounded owing to implementation details; /// `self.log2()` can produce more accurate results for base 2, and /// `self.log10()` can produce more accurate results for base 10. @@ -522,6 +536,16 @@ impl f128 { /// assert!(abs_difference <= f128::EPSILON); /// # } /// ``` + /// + /// Non-positive values: + /// ``` + /// #![feature(f128)] + /// # #[cfg(reliable_f128_math)] { + /// + /// assert_eq!(0_f128.log(10.0), f128::NEG_INFINITY); + /// assert!((-42_f128).log(10.0).is_nan()); + /// # } + /// ``` #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f128", issue = "116909")] @@ -532,6 +556,8 @@ impl f128 { /// Returns the base 2 logarithm of the number. /// + /// This returns NaN when the number is negative, and negative infinity when number is zero. + /// /// # Unspecified precision /// /// The precision of this function is non-deterministic. This means it varies by platform, @@ -551,6 +577,16 @@ impl f128 { /// assert!(abs_difference <= f128::EPSILON); /// # } /// ``` + /// + /// Non-positive values: + /// ``` + /// #![feature(f128)] + /// # #[cfg(reliable_f128_math)] { + /// + /// assert_eq!(0_f128.log2(), f128::NEG_INFINITY); + /// assert!((-42_f128).log2().is_nan()); + /// # } + /// ``` #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f128", issue = "116909")] @@ -561,6 +597,8 @@ impl f128 { /// Returns the base 10 logarithm of the number. /// + /// This returns NaN when the number is negative, and negative infinity when number is zero. + /// /// # Unspecified precision /// /// The precision of this function is non-deterministic. This means it varies by platform, @@ -580,6 +618,16 @@ impl f128 { /// assert!(abs_difference <= f128::EPSILON); /// # } /// ``` + /// + /// Non-positive values: + /// ``` + /// #![feature(f128)] + /// # #[cfg(reliable_f128_math)] { + /// + /// assert_eq!(0_f128.log10(), f128::NEG_INFINITY); + /// assert!((-42_f128).log10().is_nan()); + /// # } + /// ``` #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f128", issue = "116909")] @@ -966,6 +1014,8 @@ impl f128 { /// Returns `ln(1+n)` (natural logarithm) more accurately than if /// the operations were performed separately. /// + /// This returns NaN when `n < -1.0`, and negative infinity when `n == -1.0`. + /// /// # Unspecified precision /// /// The precision of this function is non-deterministic. This means it varies by platform, @@ -989,6 +1039,16 @@ impl f128 { /// assert!(abs_difference < 1e-10); /// # } /// ``` + /// + /// Out-of-range values: + /// ``` + /// #![feature(f128)] + /// # #[cfg(reliable_f128_math)] { + /// + /// assert_eq!((-1.0_f128).ln_1p(), f128::NEG_INFINITY); + /// assert!((-2.0_f128).ln_1p().is_nan()); + /// # } + /// ``` #[inline] #[doc(alias = "log1p")] #[must_use = "method returns a new number and does not mutate the original value"] diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs index c3b51bf31de..286993d736b 100644 --- a/library/std/src/f16.rs +++ b/library/std/src/f16.rs @@ -468,6 +468,8 @@ impl f16 { /// Returns the natural logarithm of the number. /// + /// This returns NaN when the number is negative, and negative infinity when number is zero. + /// /// # Unspecified precision /// /// The precision of this function is non-deterministic. This means it varies by platform, @@ -489,6 +491,16 @@ impl f16 { /// assert!(abs_difference <= f16::EPSILON); /// # } /// ``` + /// + /// Non-positive values: + /// ``` + /// #![feature(f16)] + /// # #[cfg(reliable_f16_math)] { + /// + /// assert_eq!(0_f16.ln(), f16::NEG_INFINITY); + /// assert!((-42_f16).ln().is_nan()); + /// # } + /// ``` #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f16", issue = "116909")] @@ -499,6 +511,8 @@ impl f16 { /// Returns the logarithm of the number with respect to an arbitrary base. /// + /// This returns NaN when the number is negative, and negative infinity when number is zero. + /// /// The result might not be correctly rounded owing to implementation details; /// `self.log2()` can produce more accurate results for base 2, and /// `self.log10()` can produce more accurate results for base 10. @@ -522,6 +536,16 @@ impl f16 { /// assert!(abs_difference <= f16::EPSILON); /// # } /// ``` + /// + /// Non-positive values: + /// ``` + /// #![feature(f16)] + /// # #[cfg(reliable_f16_math)] { + /// + /// assert_eq!(0_f16.log(10.0), f16::NEG_INFINITY); + /// assert!((-42_f16).log(10.0).is_nan()); + /// # } + /// ``` #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f16", issue = "116909")] @@ -532,6 +556,8 @@ impl f16 { /// Returns the base 2 logarithm of the number. /// + /// This returns NaN when the number is negative, and negative infinity when number is zero. + /// /// # Unspecified precision /// /// The precision of this function is non-deterministic. This means it varies by platform, @@ -551,6 +577,16 @@ impl f16 { /// assert!(abs_difference <= f16::EPSILON); /// # } /// ``` + /// + /// Non-positive values: + /// ``` + /// #![feature(f16)] + /// # #[cfg(reliable_f16_math)] { + /// + /// assert_eq!(0_f16.log2(), f16::NEG_INFINITY); + /// assert!((-42_f16).log2().is_nan()); + /// # } + /// ``` #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f16", issue = "116909")] @@ -561,6 +597,8 @@ impl f16 { /// Returns the base 10 logarithm of the number. /// + /// This returns NaN when the number is negative, and negative infinity when number is zero. + /// /// # Unspecified precision /// /// The precision of this function is non-deterministic. This means it varies by platform, @@ -580,6 +618,16 @@ impl f16 { /// assert!(abs_difference <= f16::EPSILON); /// # } /// ``` + /// + /// Non-positive values: + /// ``` + /// #![feature(f16)] + /// # #[cfg(reliable_f16_math)] { + /// + /// assert_eq!(0_f16.log10(), f16::NEG_INFINITY); + /// assert!((-42_f16).log10().is_nan()); + /// # } + /// ``` #[inline] #[rustc_allow_incoherent_impl] #[unstable(feature = "f16", issue = "116909")] @@ -964,6 +1012,8 @@ impl f16 { /// Returns `ln(1+n)` (natural logarithm) more accurately than if /// the operations were performed separately. /// + /// This returns NaN when `n < -1.0`, and negative infinity when `n == -1.0`. + /// /// # Unspecified precision /// /// The precision of this function is non-deterministic. This means it varies by platform, @@ -987,6 +1037,16 @@ impl f16 { /// assert!(abs_difference < 1e-4); /// # } /// ``` + /// + /// Out-of-range values: + /// ``` + /// #![feature(f16)] + /// # #[cfg(reliable_f16_math)] { + /// + /// assert_eq!((-1.0_f16).ln_1p(), f16::NEG_INFINITY); + /// assert!((-2.0_f16).ln_1p().is_nan()); + /// # } + /// ``` #[inline] #[doc(alias = "log1p")] #[rustc_allow_incoherent_impl] diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs index 19fb24c8ee2..980e7f7793a 100644 --- a/library/std/src/f32.rs +++ b/library/std/src/f32.rs @@ -424,6 +424,8 @@ impl f32 { /// Returns the natural logarithm of the number. /// + /// This returns NaN when the number is negative, and negative infinity when number is zero. + /// /// # Unspecified precision /// /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and @@ -441,6 +443,12 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + /// + /// Non-positive values: + /// ``` + /// assert_eq!(0_f32.ln(), f32::NEG_INFINITY); + /// assert!((-42_f32).ln().is_nan()); + /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -451,6 +459,8 @@ impl f32 { /// Returns the logarithm of the number with respect to an arbitrary base. /// + /// This returns NaN when the number is negative, and negative infinity when number is zero. + /// /// The result might not be correctly rounded owing to implementation details; /// `self.log2()` can produce more accurate results for base 2, and /// `self.log10()` can produce more accurate results for base 10. @@ -470,6 +480,12 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + /// + /// Non-positive values: + /// ``` + /// assert_eq!(0_f32.log(10.0), f32::NEG_INFINITY); + /// assert!((-42_f32).log(10.0).is_nan()); + /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -480,6 +496,8 @@ impl f32 { /// Returns the base 2 logarithm of the number. /// + /// This returns NaN when the number is negative, and negative infinity when number is zero. + /// /// # Unspecified precision /// /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and @@ -495,6 +513,12 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + /// + /// Non-positive values: + /// ``` + /// assert_eq!(0_f32.log2(), f32::NEG_INFINITY); + /// assert!((-42_f32).log2().is_nan()); + /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -505,6 +529,8 @@ impl f32 { /// Returns the base 10 logarithm of the number. /// + /// This returns NaN when the number is negative, and negative infinity when number is zero. + /// /// # Unspecified precision /// /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and @@ -520,6 +546,12 @@ impl f32 { /// /// assert!(abs_difference <= f32::EPSILON); /// ``` + /// + /// Non-positive values: + /// ``` + /// assert_eq!(0_f32.log10(), f32::NEG_INFINITY); + /// assert!((-42_f32).log10().is_nan()); + /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -893,6 +925,8 @@ impl f32 { /// Returns `ln(1+n)` (natural logarithm) more accurately than if /// the operations were performed separately. /// + /// This returns NaN when `n < -1.0`, and negative infinity when `n == -1.0`. + /// /// # Unspecified precision /// /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and @@ -911,6 +945,12 @@ impl f32 { /// /// assert!(abs_difference < 1e-10); /// ``` + /// + /// Out-of-range values: + /// ``` + /// assert_eq!((-1.0_f32).ln_1p(), f32::NEG_INFINITY); + /// assert!((-2.0_f32).ln_1p().is_nan()); + /// ``` #[doc(alias = "log1p")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs index f1c3cb56127..2aaab3ffc83 100644 --- a/library/std/src/f64.rs +++ b/library/std/src/f64.rs @@ -424,6 +424,8 @@ impl f64 { /// Returns the natural logarithm of the number. /// + /// This returns NaN when the number is negative, and negative infinity when number is zero. + /// /// # Unspecified precision /// /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and @@ -441,6 +443,12 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + /// + /// Non-positive values: + /// ``` + /// assert_eq!(0_f64.ln(), f64::NEG_INFINITY); + /// assert!((-42_f64).ln().is_nan()); + /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -451,6 +459,8 @@ impl f64 { /// Returns the logarithm of the number with respect to an arbitrary base. /// + /// This returns NaN when the number is negative, and negative infinity when number is zero. + /// /// The result might not be correctly rounded owing to implementation details; /// `self.log2()` can produce more accurate results for base 2, and /// `self.log10()` can produce more accurate results for base 10. @@ -470,6 +480,12 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + /// + /// Non-positive values: + /// ``` + /// assert_eq!(0_f64.log(10.0), f64::NEG_INFINITY); + /// assert!((-42_f64).log(10.0).is_nan()); + /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -480,6 +496,8 @@ impl f64 { /// Returns the base 2 logarithm of the number. /// + /// This returns NaN when the number is negative, and negative infinity when number is zero. + /// /// # Unspecified precision /// /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and @@ -495,6 +513,12 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + /// + /// Non-positive values: + /// ``` + /// assert_eq!(0_f64.log2(), f64::NEG_INFINITY); + /// assert!((-42_f64).log2().is_nan()); + /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -505,6 +529,8 @@ impl f64 { /// Returns the base 10 logarithm of the number. /// + /// This returns NaN when the number is negative, and negative infinity when number is zero. + /// /// # Unspecified precision /// /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and @@ -520,6 +546,12 @@ impl f64 { /// /// assert!(abs_difference < 1e-10); /// ``` + /// + /// Non-positive values: + /// ``` + /// assert_eq!(0_f64.log10(), f64::NEG_INFINITY); + /// assert!((-42_f64).log10().is_nan()); + /// ``` #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] #[stable(feature = "rust1", since = "1.0.0")] @@ -893,6 +925,8 @@ impl f64 { /// Returns `ln(1+n)` (natural logarithm) more accurately than if /// the operations were performed separately. /// + /// This returns NaN when `n < -1.0`, and negative infinity when `n == -1.0`. + /// /// # Unspecified precision /// /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and @@ -911,6 +945,12 @@ impl f64 { /// /// assert!(abs_difference < 1e-20); /// ``` + /// + /// Out-of-range values: + /// ``` + /// assert_eq!((-1.0_f64).ln_1p(), f64::NEG_INFINITY); + /// assert!((-2.0_f64).ln_1p().is_nan()); + /// ``` #[doc(alias = "log1p")] #[rustc_allow_incoherent_impl] #[must_use = "method returns a new number and does not mutate the original value"] diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index f9a360585e8..fa98db69306 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -665,6 +665,7 @@ impl File { /// # Examples /// /// ```no_run + /// #![feature(file_lock)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { @@ -673,7 +674,7 @@ impl File { /// Ok(()) /// } /// ``` - #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] + #[unstable(feature = "file_lock", issue = "130994")] pub fn lock(&self) -> io::Result<()> { self.inner.lock() } @@ -717,6 +718,7 @@ impl File { /// # Examples /// /// ```no_run + /// #![feature(file_lock)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { @@ -725,7 +727,7 @@ impl File { /// Ok(()) /// } /// ``` - #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] + #[unstable(feature = "file_lock", issue = "130994")] pub fn lock_shared(&self) -> io::Result<()> { self.inner.lock_shared() } @@ -774,6 +776,7 @@ impl File { /// # Examples /// /// ```no_run + /// #![feature(file_lock)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { @@ -782,7 +785,7 @@ impl File { /// Ok(()) /// } /// ``` - #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] + #[unstable(feature = "file_lock", issue = "130994")] pub fn try_lock(&self) -> io::Result<bool> { self.inner.try_lock() } @@ -830,6 +833,7 @@ impl File { /// # Examples /// /// ```no_run + /// #![feature(file_lock)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { @@ -838,7 +842,7 @@ impl File { /// Ok(()) /// } /// ``` - #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] + #[unstable(feature = "file_lock", issue = "130994")] pub fn try_lock_shared(&self) -> io::Result<bool> { self.inner.try_lock_shared() } @@ -866,6 +870,7 @@ impl File { /// # Examples /// /// ```no_run + /// #![feature(file_lock)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { @@ -875,7 +880,7 @@ impl File { /// Ok(()) /// } /// ``` - #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] + #[unstable(feature = "file_lock", issue = "130994")] pub fn unlock(&self) -> io::Result<()> { self.inner.unlock() } @@ -1343,6 +1348,9 @@ impl Seek for Arc<File> { fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { (&**self).seek(pos) } + fn stream_position(&mut self) -> io::Result<u64> { + (&**self).stream_position() + } } impl OpenOptions { diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index 697fb5974a3..40441dc057d 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -109,9 +109,13 @@ impl<R: Read + ?Sized> BufReader<R> { /// /// `n` must be less than or equal to `capacity`. /// - /// the returned slice may be less than `n` bytes long if + /// The returned slice may be less than `n` bytes long if /// end of file is reached. /// + /// After calling this method, you may call [`consume`](BufRead::consume) + /// with a value less than or equal to `n` to advance over some or all of + /// the returned bytes. + /// /// ## Examples /// /// ```rust diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 7f610bc88bf..6579b6887aa 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -310,7 +310,7 @@ pub use self::error::RawOsError; pub use self::error::SimpleMessage; #[unstable(feature = "io_const_error", issue = "133448")] pub use self::error::const_error; -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] pub use self::pipe::{PipeReader, PipeWriter, pipe}; #[stable(feature = "is_terminal", since = "1.70.0")] pub use self::stdio::IsTerminal; @@ -612,6 +612,47 @@ pub(crate) fn default_read_buf_exact<R: Read + ?Sized>( Ok(()) } +pub(crate) fn default_write_fmt<W: Write + ?Sized>( + this: &mut W, + args: fmt::Arguments<'_>, +) -> Result<()> { + // Create a shim which translates a `Write` to a `fmt::Write` and saves off + // I/O errors, instead of discarding them. + struct Adapter<'a, T: ?Sized + 'a> { + inner: &'a mut T, + error: Result<()>, + } + + impl<T: Write + ?Sized> fmt::Write for Adapter<'_, T> { + fn write_str(&mut self, s: &str) -> fmt::Result { + match self.inner.write_all(s.as_bytes()) { + Ok(()) => Ok(()), + Err(e) => { + self.error = Err(e); + Err(fmt::Error) + } + } + } + } + + let mut output = Adapter { inner: this, error: Ok(()) }; + match fmt::write(&mut output, args) { + Ok(()) => Ok(()), + Err(..) => { + // Check whether the error came from the underlying `Write`. + if output.error.is_err() { + output.error + } else { + // This shouldn't happen: the underlying stream did not error, + // but somehow the formatter still errored? + panic!( + "a formatting trait implementation returned an error when the underlying stream did not" + ); + } + } + } +} + /// The `Read` trait allows for reading bytes from a source. /// /// Implementors of the `Read` trait are called 'readers'. @@ -1866,41 +1907,11 @@ pub trait Write { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> { - // Create a shim which translates a Write to a fmt::Write and saves - // off I/O errors. instead of discarding them - struct Adapter<'a, T: ?Sized + 'a> { - inner: &'a mut T, - error: Result<()>, - } - - impl<T: Write + ?Sized> fmt::Write for Adapter<'_, T> { - fn write_str(&mut self, s: &str) -> fmt::Result { - match self.inner.write_all(s.as_bytes()) { - Ok(()) => Ok(()), - Err(e) => { - self.error = Err(e); - Err(fmt::Error) - } - } - } - } - - let mut output = Adapter { inner: self, error: Ok(()) }; - match fmt::write(&mut output, fmt) { - Ok(()) => Ok(()), - Err(..) => { - // check if the error came from the underlying `Write` or not - if output.error.is_err() { - output.error - } else { - // This shouldn't happen: the underlying stream did not error, but somehow - // the formatter still errored? - panic!( - "a formatting trait implementation returned an error when the underlying stream did not" - ); - } - } + fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<()> { + if let Some(s) = args.as_statically_known_str() { + self.write_all(s.as_bytes()) + } else { + default_write_fmt(self, args) } } @@ -2251,24 +2262,18 @@ fn skip_until<R: BufRead + ?Sized>(r: &mut R, delim: u8) -> Result<usize> { #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "IoBufRead")] pub trait BufRead: Read { - /// Returns the contents of the internal buffer, filling it with more data - /// from the inner reader if it is empty. + /// Returns the contents of the internal buffer, filling it with more data, via `Read` methods, if empty. /// - /// This function is a lower-level call. It needs to be paired with the - /// [`consume`] method to function properly. When calling this - /// method, none of the contents will be "read" in the sense that later - /// calling `read` may return the same contents. As such, [`consume`] must - /// be called with the number of bytes that are consumed from this buffer to - /// ensure that the bytes are never returned twice. + /// This is a lower-level method and is meant to be used together with [`consume`], + /// which can be used to mark bytes that should not be returned by subsequent calls to `read`. /// /// [`consume`]: BufRead::consume /// - /// An empty buffer returned indicates that the stream has reached EOF. + /// Returns an empty buffer when the stream has reached EOF. /// /// # Errors /// - /// This function will return an I/O error if the underlying reader was - /// read, but returned an error. + /// This function will return an I/O error if a `Read` method was called, but returned an error. /// /// # Examples /// @@ -2286,7 +2291,7 @@ pub trait BufRead: Read { /// // work with buffer /// println!("{buffer:?}"); /// - /// // ensure the bytes we worked with aren't returned again later + /// // mark the bytes we worked with as read /// let length = buffer.len(); /// stdin.consume(length); /// # std::io::Result::Ok(()) @@ -2294,18 +2299,13 @@ pub trait BufRead: Read { #[stable(feature = "rust1", since = "1.0.0")] fn fill_buf(&mut self) -> Result<&[u8]>; - /// Tells this buffer that `amt` bytes have been consumed from the buffer, - /// so they should no longer be returned in calls to `read`. + /// Marks the given `amount` of additional bytes from the internal buffer as having been read. + /// Subsequent calls to `read` only return bytes that have not been marked as read. /// - /// This function is a lower-level call. It needs to be paired with the - /// [`fill_buf`] method to function properly. This function does - /// not perform any I/O, it simply informs this object that some amount of - /// its buffer, returned from [`fill_buf`], has been consumed and should - /// no longer be returned. As such, this function may do odd things if - /// [`fill_buf`] isn't called before calling it. + /// This is a lower-level method and is meant to be used together with [`fill_buf`], + /// which can be used to fill the internal buffer via `Read` methods. /// - /// The `amt` must be `<=` the number of bytes in the buffer returned by - /// [`fill_buf`]. + /// It is a logic error if `amount` exceeds the number of unread bytes in the internal buffer, which is returned by [`fill_buf`]. /// /// # Examples /// @@ -2314,9 +2314,9 @@ pub trait BufRead: Read { /// /// [`fill_buf`]: BufRead::fill_buf #[stable(feature = "rust1", since = "1.0.0")] - fn consume(&mut self, amt: usize); + fn consume(&mut self, amount: usize); - /// Checks if the underlying `Read` has any data left to be read. + /// Checks if there is any data left to be `read`. /// /// This function may fill the buffer to check for data, /// so this functions returns `Result<bool>`, not `bool`. @@ -2325,6 +2325,10 @@ pub trait BufRead: Read { /// returned slice is empty (which means that there is no data left, /// since EOF is reached). /// + /// # Errors + /// + /// This function will return an I/O error if a `Read` method was called, but returned an error. + /// /// Examples /// /// ``` diff --git a/library/std/src/io/pipe.rs b/library/std/src/io/pipe.rs index 266c7bc9638..cfed9b05cc0 100644 --- a/library/std/src/io/pipe.rs +++ b/library/std/src/io/pipe.rs @@ -1,5 +1,6 @@ use crate::io; use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner}; +use crate::sys_common::{FromInner, IntoInner}; /// Create an anonymous pipe. /// @@ -40,7 +41,6 @@ use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner}; /// # Examples /// /// ```no_run -/// #![feature(anonymous_pipe)] /// # #[cfg(miri)] fn main() {} /// # #[cfg(not(miri))] /// # fn main() -> std::io::Result<()> { @@ -67,29 +67,52 @@ use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner}; /// ``` /// [changes]: io#platform-specific-behavior /// [man page]: https://man7.org/linux/man-pages/man7/pipe.7.html -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] #[inline] pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> { pipe_inner().map(|(reader, writer)| (PipeReader(reader), PipeWriter(writer))) } /// Read end of an anonymous pipe. -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] #[derive(Debug)] pub struct PipeReader(pub(crate) AnonPipe); /// Write end of an anonymous pipe. -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] #[derive(Debug)] pub struct PipeWriter(pub(crate) AnonPipe); +impl FromInner<AnonPipe> for PipeReader { + fn from_inner(inner: AnonPipe) -> Self { + Self(inner) + } +} + +impl IntoInner<AnonPipe> for PipeReader { + fn into_inner(self) -> AnonPipe { + self.0 + } +} + +impl FromInner<AnonPipe> for PipeWriter { + fn from_inner(inner: AnonPipe) -> Self { + Self(inner) + } +} + +impl IntoInner<AnonPipe> for PipeWriter { + fn into_inner(self) -> AnonPipe { + self.0 + } +} + impl PipeReader { /// Create a new [`PipeReader`] instance that shares the same underlying file description. /// /// # Examples /// /// ```no_run - /// #![feature(anonymous_pipe)] /// # #[cfg(miri)] fn main() {} /// # #[cfg(not(miri))] /// # fn main() -> std::io::Result<()> { @@ -137,7 +160,7 @@ impl PipeReader { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "anonymous_pipe", issue = "127154")] + #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] pub fn try_clone(&self) -> io::Result<Self> { self.0.try_clone().map(Self) } @@ -149,7 +172,6 @@ impl PipeWriter { /// # Examples /// /// ```no_run - /// #![feature(anonymous_pipe)] /// # #[cfg(miri)] fn main() {} /// # #[cfg(not(miri))] /// # fn main() -> std::io::Result<()> { @@ -177,13 +199,13 @@ impl PipeWriter { /// # Ok(()) /// # } /// ``` - #[unstable(feature = "anonymous_pipe", issue = "127154")] + #[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] pub fn try_clone(&self) -> io::Result<Self> { self.0.try_clone().map(Self) } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl io::Read for &PipeReader { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) @@ -203,7 +225,7 @@ impl io::Read for &PipeReader { } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl io::Read for PipeReader { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) @@ -223,7 +245,7 @@ impl io::Read for PipeReader { } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl io::Write for &PipeWriter { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) @@ -241,7 +263,7 @@ impl io::Write for &PipeWriter { } } -#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] impl io::Write for PipeWriter { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index ce46241f8e8..8fc16331339 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -97,15 +97,15 @@ const fn stderr_raw() -> StderrRaw { impl Read for StdinRaw { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - handle_ebadf(self.0.read(buf), 0) + handle_ebadf(self.0.read(buf), || Ok(0)) } fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> { - handle_ebadf(self.0.read_buf(buf), ()) + handle_ebadf(self.0.read_buf(buf), || Ok(())) } fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { - handle_ebadf(self.0.read_vectored(bufs), 0) + handle_ebadf(self.0.read_vectored(bufs), || Ok(0)) } #[inline] @@ -113,23 +113,37 @@ impl Read for StdinRaw { self.0.is_read_vectored() } + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + if buf.is_empty() { + return Ok(()); + } + handle_ebadf(self.0.read_exact(buf), || Err(io::Error::READ_EXACT_EOF)) + } + + fn read_buf_exact(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> { + if buf.capacity() == 0 { + return Ok(()); + } + handle_ebadf(self.0.read_buf_exact(buf), || Err(io::Error::READ_EXACT_EOF)) + } + fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { - handle_ebadf(self.0.read_to_end(buf), 0) + handle_ebadf(self.0.read_to_end(buf), || Ok(0)) } fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> { - handle_ebadf(self.0.read_to_string(buf), 0) + handle_ebadf(self.0.read_to_string(buf), || Ok(0)) } } impl Write for StdoutRaw { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - handle_ebadf(self.0.write(buf), buf.len()) + handle_ebadf(self.0.write(buf), || Ok(buf.len())) } fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { - let total = || bufs.iter().map(|b| b.len()).sum(); - handle_ebadf_lazy(self.0.write_vectored(bufs), total) + let total = || Ok(bufs.iter().map(|b| b.len()).sum()); + handle_ebadf(self.0.write_vectored(bufs), total) } #[inline] @@ -138,30 +152,30 @@ impl Write for StdoutRaw { } fn flush(&mut self) -> io::Result<()> { - handle_ebadf(self.0.flush(), ()) + handle_ebadf(self.0.flush(), || Ok(())) } fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - handle_ebadf(self.0.write_all(buf), ()) + handle_ebadf(self.0.write_all(buf), || Ok(())) } fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> { - handle_ebadf(self.0.write_all_vectored(bufs), ()) + handle_ebadf(self.0.write_all_vectored(bufs), || Ok(())) } fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> { - handle_ebadf(self.0.write_fmt(fmt), ()) + handle_ebadf(self.0.write_fmt(fmt), || Ok(())) } } impl Write for StderrRaw { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - handle_ebadf(self.0.write(buf), buf.len()) + handle_ebadf(self.0.write(buf), || Ok(buf.len())) } fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { - let total = || bufs.iter().map(|b| b.len()).sum(); - handle_ebadf_lazy(self.0.write_vectored(bufs), total) + let total = || Ok(bufs.iter().map(|b| b.len()).sum()); + handle_ebadf(self.0.write_vectored(bufs), total) } #[inline] @@ -170,32 +184,25 @@ impl Write for StderrRaw { } fn flush(&mut self) -> io::Result<()> { - handle_ebadf(self.0.flush(), ()) + handle_ebadf(self.0.flush(), || Ok(())) } fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { - handle_ebadf(self.0.write_all(buf), ()) + handle_ebadf(self.0.write_all(buf), || Ok(())) } fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> { - handle_ebadf(self.0.write_all_vectored(bufs), ()) + handle_ebadf(self.0.write_all_vectored(bufs), || Ok(())) } fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> { - handle_ebadf(self.0.write_fmt(fmt), ()) - } -} - -fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> { - match r { - Err(ref e) if stdio::is_ebadf(e) => Ok(default), - r => r, + handle_ebadf(self.0.write_fmt(fmt), || Ok(())) } } -fn handle_ebadf_lazy<T>(r: io::Result<T>, default: impl FnOnce() -> T) -> io::Result<T> { +fn handle_ebadf<T>(r: io::Result<T>, default: impl FnOnce() -> io::Result<T>) -> io::Result<T> { match r { - Err(ref e) if stdio::is_ebadf(e) => Ok(default()), + Err(ref e) if stdio::is_ebadf(e) => default(), r => r, } } diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs index cb3f864fd4e..0410df3ef1a 100644 --- a/library/std/src/io/util.rs +++ b/library/std/src/io/util.rs @@ -7,7 +7,6 @@ use crate::fmt; use crate::io::{ self, BorrowedCursor, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, SizeHint, Write, }; -use crate::mem::MaybeUninit; /// `Empty` ignores any data written via [`Write`], and will always be empty /// (returning zero bytes) when read via [`Read`]. @@ -68,6 +67,38 @@ impl Read for Empty { fn read_buf(&mut self, _cursor: BorrowedCursor<'_>) -> io::Result<()> { Ok(()) } + + #[inline] + fn read_vectored(&mut self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { + Ok(0) + } + + #[inline] + fn is_read_vectored(&self) -> bool { + // Do not force `Chain<Empty, T>` or `Chain<T, Empty>` to use vectored + // reads, unless the other reader is vectored. + false + } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + if !buf.is_empty() { Err(io::Error::READ_EXACT_EOF) } else { Ok(()) } + } + + #[inline] + fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { + if cursor.capacity() != 0 { Err(io::Error::READ_EXACT_EOF) } else { Ok(()) } + } + + #[inline] + fn read_to_end(&mut self, _buf: &mut Vec<u8>) -> io::Result<usize> { + Ok(0) + } + + #[inline] + fn read_to_string(&mut self, _buf: &mut String) -> io::Result<usize> { + Ok(0) + } } #[stable(feature = "rust1", since = "1.0.0")] impl BufRead for Empty { @@ -75,20 +106,44 @@ impl BufRead for Empty { fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(&[]) } + #[inline] fn consume(&mut self, _n: usize) {} + + #[inline] + fn has_data_left(&mut self) -> io::Result<bool> { + Ok(false) + } + + #[inline] + fn read_until(&mut self, _byte: u8, _buf: &mut Vec<u8>) -> io::Result<usize> { + Ok(0) + } + + #[inline] + fn skip_until(&mut self, _byte: u8) -> io::Result<usize> { + Ok(0) + } + + #[inline] + fn read_line(&mut self, _buf: &mut String) -> io::Result<usize> { + Ok(0) + } } #[stable(feature = "empty_seek", since = "1.51.0")] impl Seek for Empty { + #[inline] fn seek(&mut self, _pos: SeekFrom) -> io::Result<u64> { Ok(0) } + #[inline] fn stream_len(&mut self) -> io::Result<u64> { Ok(0) } + #[inline] fn stream_position(&mut self) -> io::Result<u64> { Ok(0) } @@ -120,6 +175,21 @@ impl Write for Empty { } #[inline] + fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> { + Ok(()) + } + + #[inline] + fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> { + Ok(()) + } + + #[inline] + fn write_fmt(&mut self, _args: fmt::Arguments<'_>) -> io::Result<()> { + Ok(()) + } + + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } @@ -144,6 +214,21 @@ impl Write for &Empty { } #[inline] + fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> { + Ok(()) + } + + #[inline] + fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> { + Ok(()) + } + + #[inline] + fn write_fmt(&mut self, _args: fmt::Arguments<'_>) -> io::Result<()> { + Ok(()) + } + + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } @@ -196,7 +281,7 @@ impl Read for Repeat { #[inline] fn read_buf(&mut self, mut buf: BorrowedCursor<'_>) -> io::Result<()> { // SAFETY: No uninit bytes are being written. - MaybeUninit::fill(unsafe { buf.as_mut() }, self.byte); + unsafe { buf.as_mut() }.write_filled(self.byte); // SAFETY: the entire unfilled portion of buf has been initialized. unsafe { buf.advance_unchecked(buf.capacity()) }; Ok(()) @@ -303,6 +388,21 @@ impl Write for Sink { } #[inline] + fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> { + Ok(()) + } + + #[inline] + fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> { + Ok(()) + } + + #[inline] + fn write_fmt(&mut self, _args: fmt::Arguments<'_>) -> io::Result<()> { + Ok(()) + } + + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } @@ -327,6 +427,21 @@ impl Write for &Sink { } #[inline] + fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> { + Ok(()) + } + + #[inline] + fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> { + Ok(()) + } + + #[inline] + fn write_fmt(&mut self, _args: fmt::Arguments<'_>) -> io::Result<()> { + Ok(()) + } + + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } diff --git a/library/std/src/io/util/tests.rs b/library/std/src/io/util/tests.rs index 0599a881af1..d0f106d7af4 100644 --- a/library/std/src/io/util/tests.rs +++ b/library/std/src/io/util/tests.rs @@ -1,14 +1,51 @@ +use crate::fmt; use crate::io::prelude::*; -use crate::io::{BorrowedBuf, Empty, Repeat, SeekFrom, Sink, empty, repeat, sink}; +use crate::io::{ + BorrowedBuf, Empty, ErrorKind, IoSlice, IoSliceMut, Repeat, SeekFrom, Sink, empty, repeat, sink, +}; use crate::mem::MaybeUninit; +struct ErrorDisplay; + +impl fmt::Display for ErrorDisplay { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + Err(fmt::Error) + } +} + +struct PanicDisplay; + +impl fmt::Display for PanicDisplay { + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { + panic!() + } +} + +#[track_caller] +fn test_sinking<W: Write>(mut w: W) { + assert_eq!(w.write(&[]).unwrap(), 0); + assert_eq!(w.write(&[0]).unwrap(), 1); + assert_eq!(w.write(&[0; 1024]).unwrap(), 1024); + w.write_all(&[]).unwrap(); + w.write_all(&[0]).unwrap(); + w.write_all(&[0; 1024]).unwrap(); + let mut bufs = + [IoSlice::new(&[]), IoSlice::new(&[0]), IoSlice::new(&[0; 1024]), IoSlice::new(&[])]; + assert!(w.is_write_vectored()); + assert_eq!(w.write_vectored(&[]).unwrap(), 0); + assert_eq!(w.write_vectored(&bufs).unwrap(), 1025); + w.write_all_vectored(&mut []).unwrap(); + w.write_all_vectored(&mut bufs).unwrap(); + assert!(w.flush().is_ok()); + assert_eq!(w.by_ref().write(&[0; 1024]).unwrap(), 1024); + // Ignores fmt arguments + w.write_fmt(format_args!("{}", ErrorDisplay)).unwrap(); + w.write_fmt(format_args!("{}", PanicDisplay)).unwrap(); +} + #[test] fn sink_sinks() { - let mut s = sink(); - assert_eq!(s.write(&[]).unwrap(), 0); - assert_eq!(s.write(&[0]).unwrap(), 1); - assert_eq!(s.write(&[0; 1024]).unwrap(), 1024); - assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024); + test_sinking(sink()); } #[test] @@ -19,6 +56,21 @@ fn empty_reads() { assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0); assert_eq!(Read::by_ref(&mut e).read(&mut [0; 1024]).unwrap(), 0); + e.read_exact(&mut []).unwrap(); + assert_eq!(e.read_exact(&mut [0]).unwrap_err().kind(), ErrorKind::UnexpectedEof); + assert_eq!(e.read_exact(&mut [0; 1024]).unwrap_err().kind(), ErrorKind::UnexpectedEof); + + assert!(!e.is_read_vectored()); + assert_eq!(e.read_vectored(&mut []).unwrap(), 0); + let (mut buf1, mut buf1024) = ([0], [0; 1024]); + let bufs = &mut [ + IoSliceMut::new(&mut []), + IoSliceMut::new(&mut buf1), + IoSliceMut::new(&mut buf1024), + IoSliceMut::new(&mut []), + ]; + assert_eq!(e.read_vectored(bufs).unwrap(), 0); + let buf: &mut [MaybeUninit<_>] = &mut []; let mut buf: BorrowedBuf<'_> = buf.into(); e.read_buf(buf.unfilled()).unwrap(); @@ -42,6 +94,47 @@ fn empty_reads() { Read::by_ref(&mut e).read_buf(buf.unfilled()).unwrap(); assert_eq!(buf.len(), 0); assert_eq!(buf.init_len(), 0); + + let buf: &mut [MaybeUninit<_>] = &mut []; + let mut buf: BorrowedBuf<'_> = buf.into(); + e.read_buf_exact(buf.unfilled()).unwrap(); + assert_eq!(buf.len(), 0); + assert_eq!(buf.init_len(), 0); + + let buf: &mut [_] = &mut [MaybeUninit::uninit()]; + let mut buf: BorrowedBuf<'_> = buf.into(); + assert_eq!(e.read_buf_exact(buf.unfilled()).unwrap_err().kind(), ErrorKind::UnexpectedEof); + assert_eq!(buf.len(), 0); + assert_eq!(buf.init_len(), 0); + + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1024]; + let mut buf: BorrowedBuf<'_> = buf.into(); + assert_eq!(e.read_buf_exact(buf.unfilled()).unwrap_err().kind(), ErrorKind::UnexpectedEof); + assert_eq!(buf.len(), 0); + assert_eq!(buf.init_len(), 0); + + let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1024]; + let mut buf: BorrowedBuf<'_> = buf.into(); + assert_eq!( + Read::by_ref(&mut e).read_buf_exact(buf.unfilled()).unwrap_err().kind(), + ErrorKind::UnexpectedEof, + ); + assert_eq!(buf.len(), 0); + assert_eq!(buf.init_len(), 0); + + let mut buf = Vec::new(); + assert_eq!(e.read_to_end(&mut buf).unwrap(), 0); + assert_eq!(buf, vec![]); + let mut buf = vec![1, 2, 3]; + assert_eq!(e.read_to_end(&mut buf).unwrap(), 0); + assert_eq!(buf, vec![1, 2, 3]); + + let mut buf = String::new(); + assert_eq!(e.read_to_string(&mut buf).unwrap(), 0); + assert_eq!(buf, ""); + let mut buf = "hello".to_owned(); + assert_eq!(e.read_to_string(&mut buf).unwrap(), 0); + assert_eq!(buf, "hello"); } #[test] @@ -66,11 +159,7 @@ fn empty_seeks() { #[test] fn empty_sinks() { - let mut e = empty(); - assert_eq!(e.write(&[]).unwrap(), 0); - assert_eq!(e.write(&[0]).unwrap(), 1); - assert_eq!(e.write(&[0; 1024]).unwrap(), 1024); - assert_eq!(Write::by_ref(&mut e).write(&[0; 1024]).unwrap(), 1024); + test_sinking(empty()); } #[test] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 938b8c6e4f4..ad005833ad5 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -174,7 +174,9 @@ //! //! - after-main use of thread-locals, which also affects additional features: //! - [`thread::current()`] -//! - before-main stdio file descriptors are not guaranteed to be open on unix platforms +//! - under UNIX, before main, file descriptors 0, 1, and 2 may be unchanged +//! (they are guaranteed to be open during main, +//! and are opened to /dev/null O_RDWR if they weren't open on program start) //! //! //! [I/O]: io @@ -666,6 +668,8 @@ pub mod arch { pub use std_detect::is_loongarch_feature_detected; #[unstable(feature = "is_riscv_feature_detected", issue = "111192")] pub use std_detect::is_riscv_feature_detected; + #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] + pub use std_detect::is_s390x_feature_detected; #[stable(feature = "simd_x86", since = "1.27.0")] pub use std_detect::is_x86_feature_detected; #[unstable(feature = "stdarch_mips_feature_detection", issue = "111188")] diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs index e0f9f0bb5ce..f008d42804c 100644 --- a/library/std/src/macros.rs +++ b/library/std/src/macros.rs @@ -41,7 +41,7 @@ macro_rules! panic { /// Use `print!` only for the primary output of your program. Use /// [`eprint!`] instead to print error and progress messages. /// -/// See [the formatting documentation in `std::fmt`](../std/fmt/index.html) +/// See the formatting documentation in [`std::fmt`](crate::fmt) /// for details of the macro argument syntax. /// /// [flush]: crate::io::Write::flush @@ -106,7 +106,7 @@ macro_rules! print { /// Use `println!` only for the primary output of your program. Use /// [`eprintln!`] instead to print error and progress messages. /// -/// See [the formatting documentation in `std::fmt`](../std/fmt/index.html) +/// See the formatting documentation in [`std::fmt`](crate::fmt) /// for details of the macro argument syntax. /// /// [`std::fmt`]: crate::fmt @@ -156,7 +156,7 @@ macro_rules! println { /// [`io::stderr`]: crate::io::stderr /// [`io::stdout`]: crate::io::stdout /// -/// See [the formatting documentation in `std::fmt`](../std/fmt/index.html) +/// See the formatting documentation in [`std::fmt`](crate::fmt) /// for details of the macro argument syntax. /// /// # Panics @@ -190,7 +190,7 @@ macro_rules! eprint { /// Use `eprintln!` only for error and progress messages. Use `println!` /// instead for the primary output of your program. /// -/// See [the formatting documentation in `std::fmt`](../std/fmt/index.html) +/// See the formatting documentation in [`std::fmt`](crate::fmt) /// for details of the macro argument syntax. /// /// [`io::stderr`]: crate::io::stderr diff --git a/library/std/src/os/cygwin/fs.rs b/library/std/src/os/cygwin/fs.rs new file mode 100644 index 00000000000..5533264fd51 --- /dev/null +++ b/library/std/src/os/cygwin/fs.rs @@ -0,0 +1,102 @@ +#![stable(feature = "metadata_ext", since = "1.1.0")] +use crate::fs::Metadata; +use crate::sys_common::AsInner; +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: crate::fs::Metadata +#[stable(feature = "metadata_ext", since = "1.1.0")] +pub trait MetadataExt { + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_dev(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ino(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mode(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_nlink(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_uid(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_gid(&self) -> u32; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_rdev(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_size(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime_nsec(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blksize(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blocks(&self) -> u64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_birthtime(&self) -> i64; + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_birthtime_nsec(&self) -> i64; +} +#[stable(feature = "metadata_ext", since = "1.1.0")] +impl MetadataExt for Metadata { + fn st_dev(&self) -> u64 { + self.as_inner().as_inner().st_dev as u64 + } + fn st_ino(&self) -> u64 { + self.as_inner().as_inner().st_ino as u64 + } + fn st_mode(&self) -> u32 { + self.as_inner().as_inner().st_mode as u32 + } + fn st_nlink(&self) -> u64 { + self.as_inner().as_inner().st_nlink as u64 + } + fn st_uid(&self) -> u32 { + self.as_inner().as_inner().st_uid as u32 + } + fn st_gid(&self) -> u32 { + self.as_inner().as_inner().st_gid as u32 + } + fn st_rdev(&self) -> u64 { + self.as_inner().as_inner().st_rdev as u64 + } + fn st_size(&self) -> u64 { + self.as_inner().as_inner().st_size as u64 + } + fn st_atime(&self) -> i64 { + self.as_inner().as_inner().st_atime as i64 + } + fn st_atime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_atime_nsec as i64 + } + fn st_mtime(&self) -> i64 { + self.as_inner().as_inner().st_mtime as i64 + } + fn st_mtime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_mtime_nsec as i64 + } + fn st_ctime(&self) -> i64 { + self.as_inner().as_inner().st_ctime as i64 + } + fn st_ctime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_ctime_nsec as i64 + } + fn st_blksize(&self) -> u64 { + self.as_inner().as_inner().st_blksize as u64 + } + fn st_blocks(&self) -> u64 { + self.as_inner().as_inner().st_blocks as u64 + } + fn st_birthtime(&self) -> i64 { + self.as_inner().as_inner().st_birthtime as i64 + } + fn st_birthtime_nsec(&self) -> i64 { + self.as_inner().as_inner().st_birthtime_nsec as i64 + } +} diff --git a/library/std/src/os/cygwin/mod.rs b/library/std/src/os/cygwin/mod.rs new file mode 100644 index 00000000000..7f6d6a645c8 --- /dev/null +++ b/library/std/src/os/cygwin/mod.rs @@ -0,0 +1,4 @@ +//! Cygwin-specific definitions +#![stable(feature = "raw_ext", since = "1.1.0")] +pub mod fs; +pub(crate) mod raw; diff --git a/library/std/src/os/cygwin/raw.rs b/library/std/src/os/cygwin/raw.rs new file mode 100644 index 00000000000..2bae1477fcf --- /dev/null +++ b/library/std/src/os/cygwin/raw.rs @@ -0,0 +1,4 @@ +//! Cygwin-specific raw type definitions. + +#[stable(feature = "raw_ext", since = "1.1.0")] +pub use libc::{blkcnt_t, blksize_t, dev_t, ino_t, mode_t, nlink_t, off_t, pthread_t, time_t}; diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 701cf823357..2dcbfc96618 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -15,8 +15,9 @@ use crate::mem::ManuallyDrop; target_os = "trusty" )))] use crate::sys::cvt; +use crate::sys_common::FromInner; #[cfg(not(target_os = "trusty"))] -use crate::sys_common::{AsInner, FromInner, IntoInner}; +use crate::sys_common::{AsInner, IntoInner}; use crate::{fmt, io}; type ValidRawFd = core::num::niche_types::NotAllOnes<RawFd>; @@ -504,3 +505,45 @@ impl<'a> AsFd for io::StderrLock<'a> { unsafe { BorrowedFd::borrow_raw(2) } } } + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl AsFd for io::PipeReader { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From<io::PipeReader> for OwnedFd { + fn from(pipe: io::PipeReader) -> Self { + pipe.0.into_inner() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl AsFd for io::PipeWriter { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0.as_fd() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From<io::PipeWriter> for OwnedFd { + fn from(pipe: io::PipeWriter) -> Self { + pipe.0.into_inner() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From<OwnedFd> for io::PipeReader { + fn from(owned_fd: OwnedFd) -> Self { + Self(FromInner::from_inner(owned_fd)) + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From<OwnedFd> for io::PipeWriter { + fn from(owned_fd: OwnedFd) -> Self { + Self(FromInner::from_inner(owned_fd)) + } +} diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs index 083ac6e3fe6..596b21a5204 100644 --- a/library/std/src/os/fd/raw.rs +++ b/library/std/src/os/fd/raw.rs @@ -18,6 +18,7 @@ use crate::os::unix::io::AsFd; use crate::os::unix::io::OwnedFd; #[cfg(target_os = "wasi")] use crate::os::wasi::io::OwnedFd; +use crate::sys_common::FromInner; #[cfg(not(target_os = "trusty"))] use crate::sys_common::{AsInner, IntoInner}; @@ -284,3 +285,45 @@ impl<T: AsRawFd> AsRawFd for Box<T> { (**self).as_raw_fd() } } + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl AsRawFd for io::PipeReader { + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl FromRawFd for io::PipeReader { + unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { + Self::from_inner(unsafe { FromRawFd::from_raw_fd(raw_fd) }) + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl IntoRawFd for io::PipeReader { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw_fd() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl AsRawFd for io::PipeWriter { + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl FromRawFd for io::PipeWriter { + unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { + Self::from_inner(unsafe { FromRawFd::from_raw_fd(raw_fd) }) + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl IntoRawFd for io::PipeWriter { + fn into_raw_fd(self) -> RawFd { + self.0.into_raw_fd() + } +} diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index 58cbecd30e5..ab7734a7952 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -125,6 +125,8 @@ pub mod windows; pub mod aix; #[cfg(target_os = "android")] pub mod android; +#[cfg(target_os = "cygwin")] +pub mod cygwin; #[cfg(target_os = "dragonfly")] pub mod dragonfly; #[cfg(target_os = "emscripten")] diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs index 2f9dffe8c65..5802b653965 100644 --- a/library/std/src/os/unix/mod.rs +++ b/library/std/src/os/unix/mod.rs @@ -41,6 +41,8 @@ mod platform { pub use crate::os::aix::*; #[cfg(target_os = "android")] pub use crate::os::android::*; + #[cfg(target_os = "cygwin")] + pub use crate::os::cygwin::*; #[cfg(target_vendor = "apple")] pub use crate::os::darwin::*; #[cfg(target_os = "dragonfly")] diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index 82446ea107f..7735637c840 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -9,6 +9,7 @@ target_os = "illumos", target_os = "haiku", target_os = "nto", + target_os = "cygwin" ))] use libc::MSG_NOSIGNAL; @@ -37,6 +38,7 @@ use crate::{fmt, io}; target_os = "illumos", target_os = "haiku", target_os = "nto", + target_os = "cygwin" )))] const MSG_NOSIGNAL: core::ffi::c_int = 0x0; diff --git a/library/std/src/os/unix/net/mod.rs b/library/std/src/os/unix/net/mod.rs index 3e45e3533ed..6cd62303a53 100644 --- a/library/std/src/os/unix/net/mod.rs +++ b/library/std/src/os/unix/net/mod.rs @@ -21,6 +21,7 @@ mod tests; target_os = "openbsd", target_os = "nto", target_vendor = "apple", + target_os = "cygwin" ))] mod ucred; @@ -44,6 +45,7 @@ pub use self::stream::*; target_os = "openbsd", target_os = "nto", target_vendor = "apple", + target_os = "cygwin", ))] #[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")] pub use self::ucred::*; diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index cb210b41eae..1cab04a454d 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -10,6 +10,7 @@ use super::{SocketAncillary, recv_vectored_with_ancillary_from, send_vectored_wi target_os = "openbsd", target_os = "nto", target_vendor = "apple", + target_os = "cygwin" ))] use super::{UCred, peer_cred}; use crate::fmt; @@ -231,6 +232,7 @@ impl UnixStream { target_os = "openbsd", target_os = "nto", target_vendor = "apple", + target_os = "cygwin" ))] pub fn peer_cred(&self) -> io::Result<UCred> { peer_cred(self) diff --git a/library/std/src/os/unix/net/ucred.rs b/library/std/src/os/unix/net/ucred.rs index 2dd7d409e48..36fb9c46b4a 100644 --- a/library/std/src/os/unix/net/ucred.rs +++ b/library/std/src/os/unix/net/ucred.rs @@ -33,10 +33,10 @@ pub(super) use self::impl_apple::peer_cred; target_os = "nto" ))] pub(super) use self::impl_bsd::peer_cred; -#[cfg(any(target_os = "android", target_os = "linux"))] +#[cfg(any(target_os = "android", target_os = "linux", target_os = "cygwin"))] pub(super) use self::impl_linux::peer_cred; -#[cfg(any(target_os = "linux", target_os = "android"))] +#[cfg(any(target_os = "linux", target_os = "android", target_os = "cygwin"))] mod impl_linux { use libc::{SO_PEERCRED, SOL_SOCKET, c_void, getsockopt, socklen_t, ucred}; diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index 76f5f549dd2..7f21929b85f 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -660,3 +660,45 @@ impl<T> From<crate::thread::JoinHandle<T>> for OwnedHandle { join_handle.into_inner().into_handle().into_inner() } } + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl AsHandle for io::PipeReader { + fn as_handle(&self) -> BorrowedHandle<'_> { + self.0.as_handle() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From<io::PipeReader> for OwnedHandle { + fn from(pipe: io::PipeReader) -> Self { + pipe.into_inner().into_inner() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl AsHandle for io::PipeWriter { + fn as_handle(&self) -> BorrowedHandle<'_> { + self.0.as_handle() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From<io::PipeWriter> for OwnedHandle { + fn from(pipe: io::PipeWriter) -> Self { + pipe.into_inner().into_inner() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From<OwnedHandle> for io::PipeReader { + fn from(owned_handle: OwnedHandle) -> Self { + Self::from_inner(FromInner::from_inner(owned_handle)) + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From<OwnedHandle> for io::PipeWriter { + fn from(owned_handle: OwnedHandle) -> Self { + Self::from_inner(FromInner::from_inner(owned_handle)) + } +} diff --git a/library/std/src/os/windows/io/raw.rs b/library/std/src/os/windows/io/raw.rs index c0517fab950..bc3e55c8629 100644 --- a/library/std/src/os/windows/io/raw.rs +++ b/library/std/src/os/windows/io/raw.rs @@ -310,3 +310,45 @@ impl IntoRawSocket for net::UdpSocket { self.into_inner().into_socket().into_inner().into_raw_socket() } } + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl AsRawHandle for io::PipeReader { + fn as_raw_handle(&self) -> RawHandle { + self.0.as_raw_handle() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl FromRawHandle for io::PipeReader { + unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { + unsafe { Self::from_inner(FromRawHandle::from_raw_handle(raw_handle)) } + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl IntoRawHandle for io::PipeReader { + fn into_raw_handle(self) -> RawHandle { + self.0.into_raw_handle() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl AsRawHandle for io::PipeWriter { + fn as_raw_handle(&self) -> RawHandle { + self.0.as_raw_handle() + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl FromRawHandle for io::PipeWriter { + unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { + unsafe { Self::from_inner(FromRawHandle::from_raw_handle(raw_handle)) } + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl IntoRawHandle for io::PipeWriter { + fn into_raw_handle(self) -> RawHandle { + self.0.into_raw_handle() + } +} diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index b47b41d4bc5..b35549c92ad 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -55,12 +55,14 @@ pub static EMPTY_PANIC: fn(&'static str) -> ! = // hook up these functions, but it is not this day! #[allow(improper_ctypes)] unsafe extern "C" { + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static); } unsafe extern "Rust" { /// `PanicPayload` lazily performs allocation only when needed (this avoids /// allocations when using the "abort" panic runtime). + #[cfg_attr(not(bootstrap), rustc_std_internal_symbol)] fn __rust_start_panic(payload: &mut dyn PanicPayload) -> u32; } diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 37762c65f65..f81ce8e1a1a 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1659,6 +1659,20 @@ impl From<io::Stderr> for Stdio { } } +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From<io::PipeWriter> for Stdio { + fn from(pipe: io::PipeWriter) -> Self { + Stdio::from_inner(pipe.into_inner().into()) + } +} + +#[stable(feature = "anonymous_pipe", since = "CURRENT_RUSTC_VERSION")] +impl From<io::PipeReader> for Stdio { + fn from(pipe: io::PipeReader) -> Self { + Stdio::from_inner(pipe.into_inner().into()) + } +} + /// Describes the result of a process after it has terminated. /// /// This `struct` is used to represent the exit status or other termination of a child process. @@ -2004,9 +2018,9 @@ impl ExitCode { /// /// Note that this has the same caveats as [`process::exit()`][exit], namely that this function /// terminates the process immediately, so no destructors on the current stack or any other - /// thread's stack will be run. If a clean shutdown is needed, it is recommended to simply - /// return this ExitCode from the `main` function, as demonstrated in the [type - /// documentation](#examples). + /// thread's stack will be run. Also see those docs for some important notes on interop with C + /// code. If a clean shutdown is needed, it is recommended to simply return this ExitCode from + /// the `main` function, as demonstrated in the [type documentation](#examples). /// /// # Differences from `process::exit()` /// @@ -2312,6 +2326,33 @@ impl Child { /// /// process::exit(0x0100); /// ``` +/// +/// ### Safe interop with C code +/// +/// On Unix, this function is currently implemented using the `exit` C function [`exit`][C-exit]. As +/// of C23, the C standard does not permit multiple threads to call `exit` concurrently. Rust +/// mitigates this with a lock, but if C code calls `exit`, that can still cause undefined behavior. +/// Note that returning from `main` is equivalent to calling `exit`. +/// +/// Therefore, it is undefined behavior to have two concurrent threads perform the following +/// without synchronization: +/// - One thread calls Rust's `exit` function or returns from Rust's `main` function +/// - Another thread calls the C function `exit` or `quick_exit`, or returns from C's `main` function +/// +/// Note that if a binary contains multiple copies of the Rust runtime (e.g., when combining +/// multiple `cdylib` or `staticlib`), they each have their own separate lock, so from the +/// perspective of code running in one of the Rust runtimes, the "outside" Rust code is basically C +/// code, and concurrent `exit` again causes undefined behavior. +/// +/// Individual C implementations might provide more guarantees than the standard and permit concurrent +/// calls to `exit`; consult the documentation of your C implementation for details. +/// +/// For some of the on-going discussion to make `exit` thread-safe in C, see: +/// - [Rust issue #126600](https://github.com/rust-lang/rust/issues/126600) +/// - [Austin Group Bugzilla (for POSIX)](https://austingroupbugs.net/view.php?id=1845) +/// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=31997) +/// +/// [C-exit]: https://en.cppreference.com/w/c/program/exit #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "process_exit")] pub fn exit(code: i32) -> ! { diff --git a/library/std/src/random.rs b/library/std/src/random.rs index 45f51dd37b0..e7d4ab81df0 100644 --- a/library/std/src/random.rs +++ b/library/std/src/random.rs @@ -37,7 +37,7 @@ use crate::sys::random as sys; /// Solaris | [`arc4random_buf`](https://docs.oracle.com/cd/E88353_01/html/E37843/arc4random-3c.html) /// Vita | `arc4random_buf` /// Hermit | `read_entropy` -/// Horizon | `getrandom` shim +/// Horizon, Cygwin | `getrandom` /// AIX, Hurd, L4Re, QNX | `/dev/urandom` /// Redox | `/scheme/rand` /// RTEMS | [`arc4random_buf`](https://docs.rtems.org/branches/master/bsp-howto/getentropy.html) diff --git a/library/std/src/sys/anonymous_pipe/unix.rs b/library/std/src/sys/anonymous_pipe/unix.rs index 9e398765634..dfe10f7fafe 100644 --- a/library/std/src/sys/anonymous_pipe/unix.rs +++ b/library/std/src/sys/anonymous_pipe/unix.rs @@ -1,9 +1,7 @@ -use crate::io::{self, PipeReader, PipeWriter}; -use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; -use crate::process::Stdio; +use crate::io; use crate::sys::fd::FileDesc; use crate::sys::pipe::anon_pipe; -use crate::sys_common::{FromInner, IntoInner}; +use crate::sys_common::IntoInner; pub type AnonPipe = FileDesc; @@ -11,91 +9,3 @@ pub type AnonPipe = FileDesc; pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> { anon_pipe().map(|(rx, wx)| (rx.into_inner(), wx.into_inner())) } - -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl AsFd for PipeReader { - fn as_fd(&self) -> BorrowedFd<'_> { - self.0.as_fd() - } -} -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl AsRawFd for PipeReader { - fn as_raw_fd(&self) -> RawFd { - self.0.as_raw_fd() - } -} -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl From<PipeReader> for OwnedFd { - fn from(pipe: PipeReader) -> Self { - FileDesc::into_inner(pipe.0) - } -} -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl FromRawFd for PipeReader { - unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { - unsafe { Self(FileDesc::from_raw_fd(raw_fd)) } - } -} -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl IntoRawFd for PipeReader { - fn into_raw_fd(self) -> RawFd { - self.0.into_raw_fd() - } -} -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl From<PipeReader> for Stdio { - fn from(pipe: PipeReader) -> Self { - Self::from(OwnedFd::from(pipe)) - } -} - -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl AsFd for PipeWriter { - fn as_fd(&self) -> BorrowedFd<'_> { - self.0.as_fd() - } -} -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl AsRawFd for PipeWriter { - fn as_raw_fd(&self) -> RawFd { - self.0.as_raw_fd() - } -} -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl From<PipeWriter> for OwnedFd { - fn from(pipe: PipeWriter) -> Self { - FileDesc::into_inner(pipe.0) - } -} -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl FromRawFd for PipeWriter { - unsafe fn from_raw_fd(raw_fd: RawFd) -> Self { - unsafe { Self(FileDesc::from_raw_fd(raw_fd)) } - } -} -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl IntoRawFd for PipeWriter { - fn into_raw_fd(self) -> RawFd { - self.0.into_raw_fd() - } -} -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl From<PipeWriter> for Stdio { - fn from(pipe: PipeWriter) -> Self { - Self::from(OwnedFd::from(pipe)) - } -} - -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl From<OwnedFd> for PipeReader { - fn from(owned_fd: OwnedFd) -> Self { - Self(FileDesc::from_inner(owned_fd)) - } -} - -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl From<OwnedFd> for PipeWriter { - fn from(owned_fd: OwnedFd) -> Self { - Self(FileDesc::from_inner(owned_fd)) - } -} diff --git a/library/std/src/sys/anonymous_pipe/unsupported.rs b/library/std/src/sys/anonymous_pipe/unsupported.rs index 4e79ac9c21a..a0805ba9540 100644 --- a/library/std/src/sys/anonymous_pipe/unsupported.rs +++ b/library/std/src/sys/anonymous_pipe/unsupported.rs @@ -1,22 +1,7 @@ -use crate::io::{self, PipeReader, PipeWriter}; -use crate::process::Stdio; +use crate::io; pub use crate::sys::pipe::AnonPipe; #[inline] pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> { Err(io::Error::UNSUPPORTED_PLATFORM) } - -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl From<PipeReader> for Stdio { - fn from(pipe: PipeReader) -> Self { - pipe.0.diverge() - } -} - -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl From<PipeWriter> for Stdio { - fn from(pipe: PipeWriter) -> Self { - pipe.0.diverge() - } -} diff --git a/library/std/src/sys/anonymous_pipe/windows.rs b/library/std/src/sys/anonymous_pipe/windows.rs index eb7fa8ec1c9..bdda7ffc5d2 100644 --- a/library/std/src/sys/anonymous_pipe/windows.rs +++ b/library/std/src/sys/anonymous_pipe/windows.rs @@ -1,12 +1,7 @@ -use crate::io::{self, PipeReader, PipeWriter}; -use crate::os::windows::io::{ - AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle, RawHandle, -}; -use crate::process::Stdio; -use crate::ptr; +use crate::os::windows::io::FromRawHandle; use crate::sys::c; use crate::sys::handle::Handle; -use crate::sys_common::{FromInner, IntoInner}; +use crate::{io, ptr}; pub type AnonPipe = Handle; @@ -22,95 +17,3 @@ pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> { unsafe { Ok((Handle::from_raw_handle(read_pipe), Handle::from_raw_handle(write_pipe))) } } } - -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl AsHandle for PipeReader { - fn as_handle(&self) -> BorrowedHandle<'_> { - self.0.as_handle() - } -} -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl AsRawHandle for PipeReader { - fn as_raw_handle(&self) -> RawHandle { - self.0.as_raw_handle() - } -} - -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl FromRawHandle for PipeReader { - unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { - unsafe { Self(Handle::from_raw_handle(raw_handle)) } - } -} -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl IntoRawHandle for PipeReader { - fn into_raw_handle(self) -> RawHandle { - self.0.into_raw_handle() - } -} - -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl From<PipeReader> for OwnedHandle { - fn from(pipe: PipeReader) -> Self { - Handle::into_inner(pipe.0) - } -} -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl From<PipeReader> for Stdio { - fn from(pipe: PipeReader) -> Self { - Self::from(OwnedHandle::from(pipe)) - } -} - -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl AsHandle for PipeWriter { - fn as_handle(&self) -> BorrowedHandle<'_> { - self.0.as_handle() - } -} -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl AsRawHandle for PipeWriter { - fn as_raw_handle(&self) -> RawHandle { - self.0.as_raw_handle() - } -} - -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl FromRawHandle for PipeWriter { - unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self { - unsafe { Self(Handle::from_raw_handle(raw_handle)) } - } -} -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl IntoRawHandle for PipeWriter { - fn into_raw_handle(self) -> RawHandle { - self.0.into_raw_handle() - } -} - -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl From<PipeWriter> for OwnedHandle { - fn from(pipe: PipeWriter) -> Self { - Handle::into_inner(pipe.0) - } -} -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl From<PipeWriter> for Stdio { - fn from(pipe: PipeWriter) -> Self { - Self::from(OwnedHandle::from(pipe)) - } -} - -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl From<OwnedHandle> for PipeReader { - fn from(owned_handle: OwnedHandle) -> Self { - Self(Handle::from_inner(owned_handle)) - } -} - -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl From<OwnedHandle> for PipeWriter { - fn from(owned_handle: OwnedHandle) -> Self { - Self(Handle::from_inner(owned_handle)) - } -} diff --git a/library/std/src/sys/fs/hermit.rs b/library/std/src/sys/fs/hermit.rs index 1191e335daa..f83a2f90ed2 100644 --- a/library/std/src/sys/fs/hermit.rs +++ b/library/std/src/sys/fs/hermit.rs @@ -396,7 +396,7 @@ impl File { } pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> { - crate::io::default_read_buf(|buf| self.read(buf), cursor) + self.0.read_buf(cursor) } pub fn write(&self, buf: &[u8]) -> io::Result<usize> { diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs index 56aed7dfd8e..defc1681d38 100644 --- a/library/std/src/sys/fs/uefi.rs +++ b/library/std/src/sys/fs/uefi.rs @@ -286,8 +286,13 @@ pub fn remove_dir_all(_path: &Path) -> io::Result<()> { unsupported() } -pub fn exists(_path: &Path) -> io::Result<bool> { - unsupported() +pub fn exists(path: &Path) -> io::Result<bool> { + let f = uefi_fs::File::from_path(path, r_efi::protocols::file::MODE_READ, 0); + match f { + Ok(_) => Ok(true), + Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(false), + Err(e) => Err(e), + } } pub fn readlink(_p: &Path) -> io::Result<PathBuf> { @@ -317,3 +322,134 @@ pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> { pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> { unsupported() } + +mod uefi_fs { + use r_efi::protocols::{device_path, file, simple_file_system}; + + use crate::boxed::Box; + use crate::io; + use crate::path::Path; + use crate::ptr::NonNull; + use crate::sys::helpers; + + pub(crate) struct File(NonNull<file::Protocol>); + + impl File { + pub(crate) fn from_path(path: &Path, open_mode: u64, attr: u64) -> io::Result<Self> { + let absolute = crate::path::absolute(path)?; + + let p = helpers::OwnedDevicePath::from_text(absolute.as_os_str())?; + let (vol, mut path_remaining) = Self::open_volume_from_device_path(p.borrow())?; + + vol.open(&mut path_remaining, open_mode, attr) + } + + /// Open Filesystem volume given a devicepath to the volume, or a file/directory in the + /// volume. The path provided should be absolute UEFI device path, without any UEFI shell + /// mappings. + /// + /// Returns + /// 1. The volume as a UEFI File + /// 2. Path relative to the volume. + /// + /// For example, given "PciRoot(0x0)/Pci(0x1,0x1)/Ata(Secondary,Slave,0x0)/\abc\run.efi", + /// this will open the volume "PciRoot(0x0)/Pci(0x1,0x1)/Ata(Secondary,Slave,0x0)" + /// and return the remaining file path "\abc\run.efi". + fn open_volume_from_device_path( + path: helpers::BorrowedDevicePath<'_>, + ) -> io::Result<(Self, Box<[u16]>)> { + let handles = match helpers::locate_handles(simple_file_system::PROTOCOL_GUID) { + Ok(x) => x, + Err(e) => return Err(e), + }; + for handle in handles { + let volume_device_path: NonNull<device_path::Protocol> = + match helpers::open_protocol(handle, device_path::PROTOCOL_GUID) { + Ok(x) => x, + Err(_) => continue, + }; + let volume_device_path = helpers::BorrowedDevicePath::new(volume_device_path); + + if let Some(left_path) = path_best_match(&volume_device_path, &path) { + return Ok((Self::open_volume(handle)?, left_path)); + } + } + + Err(io::const_error!(io::ErrorKind::NotFound, "Volume Not Found")) + } + + // Open volume on device_handle using SIMPLE_FILE_SYSTEM_PROTOCOL + fn open_volume(device_handle: NonNull<crate::ffi::c_void>) -> io::Result<Self> { + let simple_file_system_protocol = helpers::open_protocol::<simple_file_system::Protocol>( + device_handle, + simple_file_system::PROTOCOL_GUID, + )?; + + let mut file_protocol = crate::ptr::null_mut(); + let r = unsafe { + ((*simple_file_system_protocol.as_ptr()).open_volume)( + simple_file_system_protocol.as_ptr(), + &mut file_protocol, + ) + }; + if r.is_error() { + return Err(io::Error::from_raw_os_error(r.as_usize())); + } + + // Since no error was returned, file protocol should be non-NULL. + let p = NonNull::new(file_protocol).unwrap(); + Ok(Self(p)) + } + + fn open(&self, path: &mut [u16], open_mode: u64, attr: u64) -> io::Result<Self> { + let file_ptr = self.0.as_ptr(); + let mut file_opened = crate::ptr::null_mut(); + + let r = unsafe { + ((*file_ptr).open)(file_ptr, &mut file_opened, path.as_mut_ptr(), open_mode, attr) + }; + + if r.is_error() { + return Err(io::Error::from_raw_os_error(r.as_usize())); + } + + // Since no error was returned, file protocol should be non-NULL. + let p = NonNull::new(file_opened).unwrap(); + Ok(File(p)) + } + } + + impl Drop for File { + fn drop(&mut self) { + let file_ptr = self.0.as_ptr(); + let _ = unsafe { ((*self.0.as_ptr()).close)(file_ptr) }; + } + } + + /// A helper to check that target path is a descendent of source. It is expected to be used with + /// absolute UEFI device paths without any UEFI shell mappings. + /// + /// Returns the path relative to source + /// + /// For example, given "PciRoot(0x0)/Pci(0x1,0x1)/Ata(Secondary,Slave,0x0)/" and + /// "PciRoot(0x0)/Pci(0x1,0x1)/Ata(Secondary,Slave,0x0)/\abc\run.efi", this will return + /// "\abc\run.efi" + fn path_best_match( + source: &helpers::BorrowedDevicePath<'_>, + target: &helpers::BorrowedDevicePath<'_>, + ) -> Option<Box<[u16]>> { + let mut source_iter = source.iter().take_while(|x| !x.is_end_instance()); + let mut target_iter = target.iter().take_while(|x| !x.is_end_instance()); + + loop { + match (source_iter.next(), target_iter.next()) { + (Some(x), Some(y)) if x == y => continue, + (None, Some(y)) => { + let p = y.to_path().to_text().ok()?; + return helpers::os_string_to_raw(&p); + } + _ => return None, + } + } + } +} diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index d944bc9c9a2..7c3ed8029f7 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -543,7 +543,12 @@ impl FileAttr { SystemTime::new(self.stat.st_atim.tv_sec as i64, self.stat.st_atim.tv_nsec as i64) } - #[cfg(any(target_os = "freebsd", target_os = "openbsd", target_vendor = "apple"))] + #[cfg(any( + target_os = "freebsd", + target_os = "openbsd", + target_vendor = "apple", + target_os = "cygwin", + ))] pub fn created(&self) -> io::Result<SystemTime> { SystemTime::new(self.stat.st_birthtime as i64, self.stat.st_birthtime_nsec as i64) } @@ -553,6 +558,7 @@ impl FileAttr { target_os = "openbsd", target_os = "vita", target_vendor = "apple", + target_os = "cygwin", )))] pub fn created(&self) -> io::Result<SystemTime> { cfg_has_statx! { @@ -960,6 +966,7 @@ impl DirEntry { #[cfg(any( target_os = "linux", + target_os = "cygwin", target_os = "emscripten", target_os = "android", target_os = "solaris", @@ -1220,6 +1227,7 @@ impl File { target_os = "freebsd", target_os = "fuchsia", target_os = "linux", + target_os = "cygwin", target_os = "android", target_os = "netbsd", target_os = "openbsd", @@ -1234,6 +1242,7 @@ impl File { target_os = "fuchsia", target_os = "freebsd", target_os = "linux", + target_os = "cygwin", target_os = "netbsd", target_os = "openbsd", target_os = "nto", diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index 09677b9d642..f0cfb9b2773 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -17,6 +17,7 @@ pub mod io; pub mod net; pub mod os_str; pub mod path; +pub mod process; pub mod random; pub mod stdio; pub mod sync; diff --git a/library/std/src/sys/net/connection/socket.rs b/library/std/src/sys/net/connection/socket.rs index e154cf039ca..7301bde6881 100644 --- a/library/std/src/sys/net/connection/socket.rs +++ b/library/std/src/sys/net/connection/socket.rs @@ -59,7 +59,8 @@ cfg_if::cfg_if! { target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "solaris", target_os = "illumos", - target_os = "haiku", target_os = "nto"))] { + target_os = "haiku", target_os = "nto", + target_os = "cygwin"))] { use libc::MSG_NOSIGNAL; } else { const MSG_NOSIGNAL: c_int = 0x0; diff --git a/library/std/src/sys/net/connection/socket/unix.rs b/library/std/src/sys/net/connection/socket/unix.rs index e633cf772c5..bbe1e038dcc 100644 --- a/library/std/src/sys/net/connection/socket/unix.rs +++ b/library/std/src/sys/net/connection/socket/unix.rs @@ -81,6 +81,7 @@ impl Socket { target_os = "linux", target_os = "netbsd", target_os = "openbsd", + target_os = "cygwin", target_os = "nto", target_os = "solaris", ))] { @@ -128,6 +129,7 @@ impl Socket { target_os = "hurd", target_os = "netbsd", target_os = "openbsd", + target_os = "cygwin", target_os = "nto", ))] { // Like above, set cloexec atomically @@ -257,6 +259,7 @@ impl Socket { target_os = "hurd", target_os = "netbsd", target_os = "openbsd", + target_os = "cygwin", ))] { unsafe { let fd = cvt_r(|| libc::accept4(self.as_raw_fd(), storage, len, libc::SOCK_CLOEXEC))?; @@ -421,6 +424,7 @@ impl Socket { Ok(()) } + #[cfg(not(target_os = "cygwin"))] pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> { let linger = libc::linger { l_onoff: linger.is_some() as libc::c_int, @@ -430,6 +434,16 @@ impl Socket { setsockopt(self, libc::SOL_SOCKET, SO_LINGER, linger) } + #[cfg(target_os = "cygwin")] + pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> { + let linger = libc::linger { + l_onoff: linger.is_some() as libc::c_ushort, + l_linger: linger.unwrap_or_default().as_secs() as libc::c_ushort, + }; + + setsockopt(self, libc::SOL_SOCKET, SO_LINGER, linger) + } + pub fn linger(&self) -> io::Result<Option<Duration>> { let val: libc::linger = getsockopt(self, libc::SOL_SOCKET, SO_LINGER)?; diff --git a/library/std/src/sys/pal/hermit/fd.rs b/library/std/src/sys/pal/hermit/fd.rs index 3d6b99cd77b..edd984d920a 100644 --- a/library/std/src/sys/pal/hermit/fd.rs +++ b/library/std/src/sys/pal/hermit/fd.rs @@ -2,7 +2,7 @@ use super::hermit_abi; use crate::cmp; -use crate::io::{self, IoSlice, IoSliceMut, Read, SeekFrom}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, SeekFrom}; use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; use crate::sys::{cvt, unsupported}; use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -23,6 +23,21 @@ impl FileDesc { Ok(result as usize) } + pub fn read_buf(&self, mut buf: BorrowedCursor<'_>) -> io::Result<()> { + // SAFETY: The `read` syscall does not read from the buffer, so it is + // safe to use `&mut [MaybeUninit<u8>]`. + let result = cvt(unsafe { + hermit_abi::read( + self.fd.as_raw_fd(), + buf.as_mut().as_mut_ptr() as *mut u8, + buf.capacity(), + ) + })?; + // SAFETY: Exactly `result` bytes have been filled. + unsafe { buf.advance_unchecked(result as usize) }; + Ok(()) + } + pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { let ret = cvt(unsafe { hermit_abi::readv( diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index 608245bd430..67eab96fa40 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -25,8 +25,6 @@ pub mod futex; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; pub mod thread; pub mod time; diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs index bb419c2530e..fe43cfd2caf 100644 --- a/library/std/src/sys/pal/sgx/mod.rs +++ b/library/std/src/sys/pal/sgx/mod.rs @@ -16,8 +16,6 @@ mod libunwind_integration; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; pub mod thread; pub mod thread_parking; pub mod time; diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs index e4a61fdcfe3..22052a168fd 100644 --- a/library/std/src/sys/pal/solid/mod.rs +++ b/library/std/src/sys/pal/solid/mod.rs @@ -25,8 +25,6 @@ pub(crate) mod error; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; pub use self::itron::{thread, thread_parking}; pub mod time; diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index 41b25121592..c1921a2f40d 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -14,8 +14,6 @@ pub mod env; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; pub mod thread; #[allow(non_upper_case_globals)] #[path = "../unix/time.rs"] diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs index 60c33c637d7..309022bcccf 100644 --- a/library/std/src/sys/pal/uefi/helpers.rs +++ b/library/std/src/sys/pal/uefi/helpers.rs @@ -120,39 +120,6 @@ pub(crate) fn open_protocol<T>( } } -pub(crate) fn create_event( - signal: u32, - tpl: efi::Tpl, - handler: Option<efi::EventNotify>, - context: *mut crate::ffi::c_void, -) -> io::Result<NonNull<crate::ffi::c_void>> { - let boot_services: NonNull<efi::BootServices> = - boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast(); - let mut event: r_efi::efi::Event = crate::ptr::null_mut(); - let r = unsafe { - let create_event = (*boot_services.as_ptr()).create_event; - (create_event)(signal, tpl, handler, context, &mut event) - }; - if r.is_error() { - Err(crate::io::Error::from_raw_os_error(r.as_usize())) - } else { - NonNull::new(event).ok_or(const_error!(io::ErrorKind::Other, "null protocol")) - } -} - -/// # SAFETY -/// - The supplied event must be valid -pub(crate) unsafe fn close_event(evt: NonNull<crate::ffi::c_void>) -> io::Result<()> { - let boot_services: NonNull<efi::BootServices> = - boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast(); - let r = unsafe { - let close_event = (*boot_services.as_ptr()).close_event; - (close_event)(evt.as_ptr()) - }; - - if r.is_error() { Err(crate::io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) } -} - /// Gets the Protocol for current system handle. /// /// Note: Some protocols need to be manually freed. It is the caller's responsibility to do so. @@ -374,7 +341,6 @@ impl<'a> BorrowedDevicePath<'a> { device_path_to_text(self.protocol) } - #[expect(dead_code)] pub(crate) const fn iter(&'a self) -> DevicePathIterator<'a> { DevicePathIterator::new(DevicePathNode::new(self.protocol)) } @@ -452,7 +418,6 @@ impl<'a> DevicePathNode<'a> { && self.sub_type() == r_efi::protocols::device_path::End::SUBTYPE_ENTIRE } - #[expect(dead_code)] pub(crate) const fn is_end_instance(&self) -> bool { self.node_type() == r_efi::protocols::device_path::TYPE_END && self.sub_type() == r_efi::protocols::device_path::End::SUBTYPE_INSTANCE @@ -468,7 +433,6 @@ impl<'a> DevicePathNode<'a> { Self::new(node) } - #[expect(dead_code)] pub(crate) fn to_path(&'a self) -> BorrowedDevicePath<'a> { BorrowedDevicePath::new(self.protocol) } @@ -738,3 +702,56 @@ impl Drop for ServiceProtocol { } } } + +#[repr(transparent)] +pub(crate) struct OwnedEvent(NonNull<crate::ffi::c_void>); + +impl OwnedEvent { + pub(crate) fn new( + signal: u32, + tpl: efi::Tpl, + handler: Option<efi::EventNotify>, + context: Option<NonNull<crate::ffi::c_void>>, + ) -> io::Result<Self> { + let boot_services: NonNull<efi::BootServices> = + boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast(); + let mut event: r_efi::efi::Event = crate::ptr::null_mut(); + let context = context.map(NonNull::as_ptr).unwrap_or(crate::ptr::null_mut()); + + let r = unsafe { + let create_event = (*boot_services.as_ptr()).create_event; + (create_event)(signal, tpl, handler, context, &mut event) + }; + + if r.is_error() { + Err(crate::io::Error::from_raw_os_error(r.as_usize())) + } else { + NonNull::new(event) + .ok_or(const_error!(io::ErrorKind::Other, "failed to create event")) + .map(Self) + } + } + + pub(crate) fn into_raw(self) -> *mut crate::ffi::c_void { + let r = self.0.as_ptr(); + crate::mem::forget(self); + r + } + + /// SAFETY: Assumes that ptr is a non-null valid UEFI event + pub(crate) unsafe fn from_raw(ptr: *mut crate::ffi::c_void) -> Self { + Self(unsafe { NonNull::new_unchecked(ptr) }) + } +} + +impl Drop for OwnedEvent { + fn drop(&mut self) { + if let Some(boot_services) = boot_services() { + let bt: NonNull<r_efi::efi::BootServices> = boot_services.cast(); + unsafe { + let close_event = (*bt.as_ptr()).close_event; + (close_event)(self.0.as_ptr()) + }; + } + } +} diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index 714dc392688..9760a23084a 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -19,7 +19,6 @@ pub mod helpers; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -pub mod process; pub mod thread; pub mod time; @@ -47,17 +46,17 @@ pub(crate) unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) { unsafe { uefi::env::init_globals(image_handle, system_table) }; // Register exit boot services handler - match helpers::create_event( + match helpers::OwnedEvent::new( r_efi::efi::EVT_SIGNAL_EXIT_BOOT_SERVICES, r_efi::efi::TPL_NOTIFY, Some(exit_boot_service_handler), - crate::ptr::null_mut(), + None, ) { Ok(x) => { if EXIT_BOOT_SERVICE_EVENT .compare_exchange( crate::ptr::null_mut(), - x.as_ptr(), + x.into_raw(), Ordering::Release, Ordering::Acquire, ) @@ -77,7 +76,7 @@ pub unsafe fn cleanup() { if let Some(exit_boot_service_event) = NonNull::new(EXIT_BOOT_SERVICE_EVENT.swap(crate::ptr::null_mut(), Ordering::Acquire)) { - let _ = unsafe { helpers::close_event(exit_boot_service_event) }; + let _ = unsafe { helpers::OwnedEvent::from_raw(exit_boot_service_event.as_ptr()) }; } } @@ -143,7 +142,7 @@ pub fn abort_internal() -> ! { if let Some(exit_boot_service_event) = NonNull::new(EXIT_BOOT_SERVICE_EVENT.load(Ordering::Acquire)) { - let _ = unsafe { helpers::close_event(exit_boot_service_event) }; + let _ = unsafe { helpers::OwnedEvent::from_raw(exit_boot_service_event.as_ptr()) }; } if let (Some(boot_services), Some(handle)) = diff --git a/library/std/src/sys/pal/unix/args.rs b/library/std/src/sys/pal/unix/args.rs index 1c87a79803c..0bb7b64007a 100644 --- a/library/std/src/sys/pal/unix/args.rs +++ b/library/std/src/sys/pal/unix/args.rs @@ -100,6 +100,7 @@ impl DoubleEndedIterator for Args { target_os = "dragonfly", target_os = "netbsd", target_os = "openbsd", + target_os = "cygwin", target_os = "solaris", target_os = "illumos", target_os = "emscripten", diff --git a/library/std/src/sys/pal/unix/env.rs b/library/std/src/sys/pal/unix/env.rs index 2aee0b5d460..c6609298f4b 100644 --- a/library/std/src/sys/pal/unix/env.rs +++ b/library/std/src/sys/pal/unix/env.rs @@ -108,6 +108,17 @@ pub mod os { pub const EXE_EXTENSION: &str = ""; } +#[cfg(target_os = "cygwin")] +pub mod os { + pub const FAMILY: &str = "unix"; + pub const OS: &str = "cygwin"; + pub const DLL_PREFIX: &str = ""; + pub const DLL_SUFFIX: &str = ".dll"; + pub const DLL_EXTENSION: &str = "dll"; + pub const EXE_SUFFIX: &str = ".exe"; + pub const EXE_EXTENSION: &str = "exe"; +} + #[cfg(target_os = "android")] pub mod os { pub const FAMILY: &str = "unix"; diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs index a08c7ccec2d..f03c440e30e 100644 --- a/library/std/src/sys/pal/unix/fd.rs +++ b/library/std/src/sys/pal/unix/fd.rs @@ -47,6 +47,7 @@ const READ_LIMIT: usize = if cfg!(target_vendor = "apple") { target_os = "netbsd", target_os = "openbsd", target_vendor = "apple", + target_os = "cygwin", ))] const fn max_iov() -> usize { libc::IOV_MAX as usize @@ -74,6 +75,7 @@ const fn max_iov() -> usize { target_os = "horizon", target_os = "vita", target_vendor = "apple", + target_os = "cygwin", )))] const fn max_iov() -> usize { 16 // The minimum value required by POSIX. @@ -503,6 +505,7 @@ impl FileDesc { target_os = "fuchsia", target_os = "l4re", target_os = "linux", + target_os = "cygwin", target_os = "haiku", target_os = "redox", target_os = "vxworks", @@ -525,6 +528,7 @@ impl FileDesc { target_os = "fuchsia", target_os = "l4re", target_os = "linux", + target_os = "cygwin", target_os = "haiku", target_os = "redox", target_os = "vxworks", diff --git a/library/std/src/sys/pal/unix/process/zircon.rs b/library/std/src/sys/pal/unix/fuchsia.rs index 7932bd26d76..7932bd26d76 100644 --- a/library/std/src/sys/pal/unix/process/zircon.rs +++ b/library/std/src/sys/pal/unix/fuchsia.rs diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 419abe732ac..413fda1d8d8 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -9,6 +9,8 @@ pub mod weak; pub mod args; pub mod env; pub mod fd; +#[cfg(target_os = "fuchsia")] +pub mod fuchsia; pub mod futex; #[cfg(any(target_os = "linux", target_os = "android"))] pub mod kernel_copy; @@ -16,7 +18,6 @@ pub mod kernel_copy; pub mod linux; pub mod os; pub mod pipe; -pub mod process; pub mod stack_overflow; pub mod sync; pub mod thread; @@ -380,7 +381,7 @@ cfg_if::cfg_if! { #[link(name = "pthread")] #[link(name = "rt")] unsafe extern "C" {} - } else if #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))] { + } else if #[cfg(any(target_os = "dragonfly", target_os = "openbsd", target_os = "cygwin"))] { #[link(name = "pthread")] unsafe extern "C" {} } else if #[cfg(target_os = "solaris")] { @@ -419,7 +420,7 @@ cfg_if::cfg_if! { } #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nuttx"))] -mod unsupported { +pub mod unsupported { use crate::io; pub fn unsupported<T>() -> io::Result<T> { diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 91f55fcd32b..30282fbf655 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -46,6 +46,7 @@ unsafe extern "C" { any( target_os = "netbsd", target_os = "openbsd", + target_os = "cygwin", target_os = "android", target_os = "redox", target_os = "nuttx", @@ -118,7 +119,12 @@ pub fn error_string(errno: i32) -> String { unsafe extern "C" { #[cfg_attr( all( - any(target_os = "linux", target_os = "hurd", target_env = "newlib"), + any( + target_os = "linux", + target_os = "hurd", + target_env = "newlib", + target_os = "cygwin" + ), not(target_env = "ohos") ), link_name = "__xpg_strerror_r" @@ -395,6 +401,7 @@ pub fn current_exe() -> io::Result<PathBuf> { #[cfg(any( target_os = "linux", + target_os = "cygwin", target_os = "hurd", target_os = "android", target_os = "nuttx", diff --git a/library/std/src/sys/pal/unix/pipe.rs b/library/std/src/sys/pal/unix/pipe.rs index 4a992e32a91..55510153dc8 100644 --- a/library/std/src/sys/pal/unix/pipe.rs +++ b/library/std/src/sys/pal/unix/pipe.rs @@ -27,6 +27,7 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> { target_os = "linux", target_os = "netbsd", target_os = "openbsd", + target_os = "cygwin", target_os = "redox" ))] { unsafe { diff --git a/library/std/src/sys/pal/unix/process/mod.rs b/library/std/src/sys/pal/unix/process/mod.rs deleted file mode 100644 index 2751d51c44d..00000000000 --- a/library/std/src/sys/pal/unix/process/mod.rs +++ /dev/null @@ -1,27 +0,0 @@ -pub use self::process_common::{Command, CommandArgs, ExitCode, Stdio, StdioPipes}; -pub use self::process_inner::{ExitStatus, ExitStatusError, Process}; -pub use crate::ffi::OsString as EnvKey; - -#[cfg_attr(any(target_os = "espidf", target_os = "horizon", target_os = "nuttx"), allow(unused))] -mod process_common; - -#[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nuttx"))] -mod process_unsupported; - -cfg_if::cfg_if! { - if #[cfg(target_os = "fuchsia")] { - #[path = "process_fuchsia.rs"] - mod process_inner; - mod zircon; - } else if #[cfg(target_os = "vxworks")] { - #[path = "process_vxworks.rs"] - mod process_inner; - } else if #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nuttx"))] { - mod process_inner { - pub use super::process_unsupported::*; - } - } else { - #[path = "process_unix.rs"] - mod process_inner; - } -} diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index 0ecccdc8812..4bd0cedd44c 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -585,6 +585,7 @@ mod imp { target_os = "openbsd", target_os = "solaris", target_os = "illumos", + target_os = "cygwin", )))] mod imp { pub unsafe fn init() {} @@ -597,3 +598,89 @@ mod imp { pub unsafe fn drop_handler(_data: *mut libc::c_void) {} } + +#[cfg(target_os = "cygwin")] +mod imp { + mod c { + pub type PVECTORED_EXCEPTION_HANDLER = + Option<unsafe extern "system" fn(exceptioninfo: *mut EXCEPTION_POINTERS) -> i32>; + pub type NTSTATUS = i32; + pub type BOOL = i32; + + unsafe extern "system" { + pub fn AddVectoredExceptionHandler( + first: u32, + handler: PVECTORED_EXCEPTION_HANDLER, + ) -> *mut core::ffi::c_void; + pub fn SetThreadStackGuarantee(stacksizeinbytes: *mut u32) -> BOOL; + } + + pub const EXCEPTION_STACK_OVERFLOW: NTSTATUS = 0xC00000FD_u32 as _; + pub const EXCEPTION_CONTINUE_SEARCH: i32 = 1i32; + + #[repr(C)] + #[derive(Clone, Copy)] + pub struct EXCEPTION_POINTERS { + pub ExceptionRecord: *mut EXCEPTION_RECORD, + // We don't need this field here + // pub Context: *mut CONTEXT, + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct EXCEPTION_RECORD { + pub ExceptionCode: NTSTATUS, + pub ExceptionFlags: u32, + pub ExceptionRecord: *mut EXCEPTION_RECORD, + pub ExceptionAddress: *mut core::ffi::c_void, + pub NumberParameters: u32, + pub ExceptionInformation: [usize; 15], + } + } + + /// Reserve stack space for use in stack overflow exceptions. + fn reserve_stack() { + let result = unsafe { c::SetThreadStackGuarantee(&mut 0x5000) }; + // Reserving stack space is not critical so we allow it to fail in the released build of libstd. + // We still use debug assert here so that CI will test that we haven't made a mistake calling the function. + debug_assert_ne!(result, 0, "failed to reserve stack space for exception handling"); + } + + unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> i32 { + // SAFETY: It's up to the caller (which in this case is the OS) to ensure that `ExceptionInfo` is valid. + unsafe { + let rec = &(*(*ExceptionInfo).ExceptionRecord); + let code = rec.ExceptionCode; + + if code == c::EXCEPTION_STACK_OVERFLOW { + crate::thread::with_current_name(|name| { + let name = name.unwrap_or("<unknown>"); + rtprintpanic!("\nthread '{name}' has overflowed its stack\n"); + }); + } + c::EXCEPTION_CONTINUE_SEARCH + } + } + + pub unsafe fn init() { + // SAFETY: `vectored_handler` has the correct ABI and is safe to call during exception handling. + unsafe { + let result = c::AddVectoredExceptionHandler(0, Some(vectored_handler)); + // Similar to the above, adding the stack overflow handler is allowed to fail + // but a debug assert is used so CI will still test that it normally works. + debug_assert!(!result.is_null(), "failed to install exception handler"); + } + // Set the thread stack guarantee for the main thread. + reserve_stack(); + } + + pub unsafe fn cleanup() {} + + pub unsafe fn make_handler(main_thread: bool) -> super::Handler { + if !main_thread { + reserve_stack(); + } + super::Handler::null() + } + + pub unsafe fn drop_handler(_data: *mut libc::c_void) {} +} diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index abe8d3fbf68..bb34c2fabe5 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -137,13 +137,14 @@ impl Thread { target_os = "linux", target_os = "freebsd", target_os = "dragonfly", - target_os = "nuttx" + target_os = "nuttx", + target_os = "cygwin" ))] pub fn set_name(name: &CStr) { unsafe { cfg_if::cfg_if! { - if #[cfg(target_os = "linux")] { - // Linux limits the allowed length of the name. + if #[cfg(any(target_os = "linux", target_os = "cygwin"))] { + // Linux and Cygwin limits the allowed length of the name. const TASK_COMM_LEN: usize = 16; let name = truncate_cstr::<{ TASK_COMM_LEN }>(name); } else { @@ -345,6 +346,7 @@ impl Drop for Thread { target_os = "solaris", target_os = "illumos", target_os = "vxworks", + target_os = "cygwin", target_vendor = "apple", ))] fn truncate_cstr<const MAX_WITH_NUL: usize>(cstr: &CStr) -> [libc::c_char; MAX_WITH_NUL] { @@ -365,6 +367,7 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> { target_os = "linux", target_os = "aix", target_vendor = "apple", + target_os = "cygwin", ))] { #[allow(unused_assignments)] #[allow(unused_mut)] diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs index bcea699f3b2..38838b915b5 100644 --- a/library/std/src/sys/pal/unsupported/mod.rs +++ b/library/std/src/sys/pal/unsupported/mod.rs @@ -4,7 +4,6 @@ pub mod args; pub mod env; pub mod os; pub mod pipe; -pub mod process; pub mod thread; pub mod time; diff --git a/library/std/src/sys/pal/unsupported/pipe.rs b/library/std/src/sys/pal/unsupported/pipe.rs index 6799d21a1ff..988e551de52 100644 --- a/library/std/src/sys/pal/unsupported/pipe.rs +++ b/library/std/src/sys/pal/unsupported/pipe.rs @@ -1,5 +1,6 @@ use crate::fmt; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; +use crate::sys_common::{FromInner, IntoInner}; pub struct AnonPipe(!); @@ -54,3 +55,53 @@ impl AnonPipe { pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> { match p1.0 {} } + +impl FromInner<!> for AnonPipe { + fn from_inner(inner: !) -> Self { + inner + } +} + +impl IntoInner<!> for AnonPipe { + fn into_inner(self) -> ! { + self.0 + } +} + +#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))] +mod unix_traits { + use super::AnonPipe; + use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; + use crate::sys_common::FromInner; + + impl AsRawFd for AnonPipe { + #[inline] + fn as_raw_fd(&self) -> RawFd { + self.0 + } + } + + impl AsFd for AnonPipe { + fn as_fd(&self) -> BorrowedFd<'_> { + self.0 + } + } + + impl IntoRawFd for AnonPipe { + fn into_raw_fd(self) -> RawFd { + self.0 + } + } + + impl FromRawFd for AnonPipe { + unsafe fn from_raw_fd(_: RawFd) -> Self { + panic!("creating pipe on this platform is unsupported!") + } + } + + impl FromInner<OwnedFd> for AnonPipe { + fn from_inner(_: OwnedFd) -> Self { + panic!("creating pipe on this platform is unsupported!") + } + } +} diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index c89832857dd..cdd613f76b6 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -23,8 +23,6 @@ pub mod futex; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; pub mod thread; pub mod time; diff --git a/library/std/src/sys/pal/wasip2/mod.rs b/library/std/src/sys/pal/wasip2/mod.rs index 3008ba88753..6ac28f1bf4f 100644 --- a/library/std/src/sys/pal/wasip2/mod.rs +++ b/library/std/src/sys/pal/wasip2/mod.rs @@ -20,8 +20,6 @@ pub mod futex; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; #[path = "../wasi/thread.rs"] pub mod thread; #[path = "../wasi/time.rs"] diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs index 175fe75357f..8d39b70d039 100644 --- a/library/std/src/sys/pal/wasm/mod.rs +++ b/library/std/src/sys/pal/wasm/mod.rs @@ -23,8 +23,6 @@ pub mod env; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; #[path = "../unsupported/time.rs"] pub mod time; diff --git a/library/std/src/sys/pal/windows/args.rs b/library/std/src/sys/pal/windows/args.rs index 3447a0157e4..d973743639a 100644 --- a/library/std/src/sys/pal/windows/args.rs +++ b/library/std/src/sys/pal/windows/args.rs @@ -6,13 +6,13 @@ #[cfg(test)] mod tests; +use super::ensure_no_nuls; use super::os::current_exe; use crate::ffi::{OsStr, OsString}; use crate::num::NonZero; use crate::os::windows::prelude::*; use crate::path::{Path, PathBuf}; use crate::sys::path::get_long_path; -use crate::sys::process::ensure_no_nuls; use crate::sys::{c, to_u16s}; use crate::sys_common::AsInner; use crate::sys_common::wstr::WStrUnits; diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 6eb68f3a3bc..bdf0cc2c59c 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -22,7 +22,6 @@ pub mod futex; pub mod handle; pub mod os; pub mod pipe; -pub mod process; pub mod thread; pub mod time; cfg_if::cfg_if! { @@ -287,6 +286,14 @@ pub fn truncate_utf16_at_nul(v: &[u16]) -> &[u16] { } } +pub fn ensure_no_nuls<T: AsRef<OsStr>>(s: T) -> crate::io::Result<T> { + if s.as_ref().encode_wide().any(|b| b == 0) { + Err(crate::io::const_error!(ErrorKind::InvalidInput, "nul byte found in provided data")) + } else { + Ok(s) + } +} + pub trait IsZero { fn is_zero(&self) -> bool; } diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs index 7d823012ad1..58926e2beb1 100644 --- a/library/std/src/sys/pal/xous/mod.rs +++ b/library/std/src/sys/pal/xous/mod.rs @@ -6,8 +6,6 @@ pub mod env; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; pub mod thread; pub mod time; diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs index 499e2787201..4659dad16e8 100644 --- a/library/std/src/sys/pal/zkvm/mod.rs +++ b/library/std/src/sys/pal/zkvm/mod.rs @@ -17,8 +17,6 @@ pub mod env; pub mod os; #[path = "../unsupported/pipe.rs"] pub mod pipe; -#[path = "../unsupported/process.rs"] -pub mod process; #[path = "../unsupported/thread.rs"] pub mod thread; #[path = "../unsupported/time.rs"] diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs index cd2c7899f4b..b012e47f9aa 100644 --- a/library/std/src/sys/personality/gcc.rs +++ b/library/std/src/sys/personality/gcc.rs @@ -220,7 +220,7 @@ cfg_if::cfg_if! { Ok(action) => action, Err(_) => return uw::_URC_FATAL_PHASE1_ERROR, }; - if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 { + if actions & uw::_UA_SEARCH_PHASE != 0 { match eh_action { EHAction::None | EHAction::Cleanup(_) => uw::_URC_CONTINUE_UNWIND, EHAction::Catch(_) | EHAction::Filter(_) => uw::_URC_HANDLER_FOUND, @@ -230,7 +230,7 @@ cfg_if::cfg_if! { match eh_action { EHAction::None => uw::_URC_CONTINUE_UNWIND, // Forced unwinding hits a terminate action. - EHAction::Filter(_) if actions as i32 & uw::_UA_FORCE_UNWIND as i32 != 0 => uw::_URC_CONTINUE_UNWIND, + EHAction::Filter(_) if actions & uw::_UA_FORCE_UNWIND != 0 => uw::_URC_CONTINUE_UNWIND, EHAction::Cleanup(lpad) | EHAction::Catch(lpad) | EHAction::Filter(lpad) => { uw::_Unwind_SetGR( context, @@ -248,7 +248,10 @@ cfg_if::cfg_if! { } cfg_if::cfg_if! { - if #[cfg(all(windows, any(target_arch = "aarch64", target_arch = "x86_64"), target_env = "gnu"))] { + if #[cfg(any( + all(windows, any(target_arch = "aarch64", target_arch = "x86_64"), target_env = "gnu"), + target_os = "cygwin", + ))] { /// personality fn called by [Windows Structured Exception Handling][windows-eh] /// /// On x86_64 and AArch64 MinGW targets, the unwinding mechanism is SEH, diff --git a/library/std/src/sys/process/mod.rs b/library/std/src/sys/process/mod.rs new file mode 100644 index 00000000000..92cfac7f47c --- /dev/null +++ b/library/std/src/sys/process/mod.rs @@ -0,0 +1,19 @@ +cfg_if::cfg_if! { + if #[cfg(target_family = "unix")] { + mod unix; + use unix as imp; + } else if #[cfg(target_os = "windows")] { + mod windows; + use windows as imp; + } else if #[cfg(target_os = "uefi")] { + mod uefi; + use uefi as imp; + } else { + mod unsupported; + use unsupported as imp; + } +} + +pub use imp::{ + Command, CommandArgs, EnvKey, ExitCode, ExitStatus, ExitStatusError, Process, Stdio, StdioPipes, +}; diff --git a/library/std/src/sys/pal/uefi/process.rs b/library/std/src/sys/process/uefi.rs index 1203d51e531..b46418ae9bb 100644 --- a/library/std/src/sys/pal/uefi/process.rs +++ b/library/std/src/sys/process/uefi.rs @@ -1,12 +1,13 @@ use r_efi::protocols::simple_text_output; -use super::helpers; use crate::collections::BTreeMap; pub use crate::ffi::OsString as EnvKey; use crate::ffi::{OsStr, OsString}; use crate::num::{NonZero, NonZeroI32}; use crate::path::Path; use crate::sys::fs::File; +use crate::sys::pal::helpers; +use crate::sys::pal::os::error_string; use crate::sys::pipe::AnonPipe; use crate::sys::unsupported; use crate::sys_common::process::{CommandEnv, CommandEnvs}; @@ -225,7 +226,7 @@ impl ExitStatus { impl fmt::Display for ExitStatus { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let err_str = super::os::error_string(self.0.as_usize()); + let err_str = error_string(self.0.as_usize()); write!(f, "{}", err_str) } } @@ -241,7 +242,7 @@ pub struct ExitStatusError(r_efi::efi::Status); impl fmt::Debug for ExitStatusError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let err_str = super::os::error_string(self.0.as_usize()); + let err_str = error_string(self.0.as_usize()); write!(f, "{}", err_str) } } @@ -335,7 +336,6 @@ impl<'a> fmt::Debug for CommandArgs<'a> { mod uefi_command_internal { use r_efi::protocols::{loaded_image, simple_text_output}; - use super::super::helpers; use crate::ffi::{OsStr, OsString}; use crate::io::{self, const_error}; use crate::mem::MaybeUninit; @@ -343,7 +343,7 @@ mod uefi_command_internal { use crate::os::uefi::ffi::{OsStrExt, OsStringExt}; use crate::ptr::NonNull; use crate::slice; - use crate::sys::pal::uefi::helpers::OwnedTable; + use crate::sys::pal::helpers::{self, OwnedTable}; use crate::sys_common::wstr::WStrUnits; pub struct Image { diff --git a/library/std/src/sys/pal/unix/process/process_common.rs b/library/std/src/sys/process/unix/common.rs index dd41921f263..8bc17f31491 100644 --- a/library/std/src/sys/pal/unix/process/process_common.rs +++ b/library/std/src/sys/process/unix/common.rs @@ -54,7 +54,7 @@ cfg_if::cfg_if! { let bit = (signum - 1) as usize; if set.is_null() || bit >= (8 * size_of::<sigset_t>()) { - crate::sys::pal::unix::os::set_errno(libc::EINVAL); + crate::sys::pal::os::set_errno(libc::EINVAL); return -1; } let raw = slice::from_raw_parts_mut( @@ -489,6 +489,12 @@ impl From<AnonPipe> for Stdio { } } +impl From<FileDesc> for Stdio { + fn from(fd: FileDesc) -> Stdio { + Stdio::Fd(fd) + } +} + impl From<File> for Stdio { fn from(file: File) -> Stdio { Stdio::Fd(file.into_inner()) diff --git a/library/std/src/sys/pal/unix/process/process_common/tests.rs b/library/std/src/sys/process/unix/common/tests.rs index e5c8dd6e341..e5c8dd6e341 100644 --- a/library/std/src/sys/pal/unix/process/process_common/tests.rs +++ b/library/std/src/sys/process/unix/common/tests.rs diff --git a/library/std/src/sys/pal/unix/process/process_fuchsia.rs b/library/std/src/sys/process/unix/fuchsia.rs index 05c9ace470e..0de32ecffd4 100644 --- a/library/std/src/sys/pal/unix/process/process_fuchsia.rs +++ b/library/std/src/sys/process/unix/fuchsia.rs @@ -1,8 +1,8 @@ use libc::{c_int, size_t}; +use super::common::*; use crate::num::NonZero; -use crate::sys::process::process_common::*; -use crate::sys::process::zircon::{Handle, zx_handle_t}; +use crate::sys::pal::fuchsia::*; use crate::{fmt, io, mem, ptr}; //////////////////////////////////////////////////////////////////////////////// @@ -58,8 +58,6 @@ impl Command { stdio: ChildPipes, maybe_envp: Option<&CStringArray>, ) -> io::Result<zx_handle_t> { - use crate::sys::process::zircon::*; - let envp = match maybe_envp { // None means to clone the current environment, which is done in the // flags below. @@ -152,8 +150,6 @@ impl Process { } pub fn kill(&mut self) -> io::Result<()> { - use crate::sys::process::zircon::*; - unsafe { zx_cvt(zx_task_kill(self.handle.raw()))?; } @@ -162,8 +158,6 @@ impl Process { } pub fn wait(&mut self) -> io::Result<ExitStatus> { - use crate::sys::process::zircon::*; - let mut proc_info: zx_info_process_t = Default::default(); let mut actual: size_t = 0; let mut avail: size_t = 0; @@ -194,8 +188,6 @@ impl Process { } pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> { - use crate::sys::process::zircon::*; - let mut proc_info: zx_info_process_t = Default::default(); let mut actual: size_t = 0; let mut avail: size_t = 0; @@ -251,7 +243,7 @@ impl ExitStatus { None } - // FIXME: The actually-Unix implementation in process_unix.rs uses WSTOPSIG, WCOREDUMP et al. + // FIXME: The actually-Unix implementation in unix.rs uses WSTOPSIG, WCOREDUMP et al. // I infer from the implementation of `success`, `code` and `signal` above that these are not // available on Fuchsia. // diff --git a/library/std/src/sys/process/unix/mod.rs b/library/std/src/sys/process/unix/mod.rs new file mode 100644 index 00000000000..2e8b38f7de1 --- /dev/null +++ b/library/std/src/sys/process/unix/mod.rs @@ -0,0 +1,23 @@ +#[cfg_attr(any(target_os = "espidf", target_os = "horizon", target_os = "nuttx"), allow(unused))] +mod common; + +cfg_if::cfg_if! { + if #[cfg(target_os = "fuchsia")] { + mod fuchsia; + use fuchsia as imp; + } else if #[cfg(target_os = "vxworks")] { + mod vxworks; + use vxworks as imp; + } else if #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita", target_os = "nuttx"))] { + mod unsupported; + use unsupported as imp; + } else { + mod unix; + use unix as imp; + } +} + +pub use imp::{ExitStatus, ExitStatusError, Process}; + +pub use self::common::{Command, CommandArgs, ExitCode, Stdio, StdioPipes}; +pub use crate::ffi::OsString as EnvKey; diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/process/unix/unix.rs index be9a7e91990..42542f81b65 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/process/unix/unix.rs @@ -10,12 +10,12 @@ use libc::{c_int, pid_t}; )))] use libc::{gid_t, uid_t}; +use super::common::*; use crate::io::{self, Error, ErrorKind}; use crate::num::NonZero; use crate::sys::cvt; #[cfg(target_os = "linux")] -use crate::sys::pal::unix::linux::pidfd::PidFd; -use crate::sys::process::process_common::*; +use crate::sys::pal::linux::pidfd::PidFd; use crate::{fmt, mem, sys}; cfg_if::cfg_if! { @@ -1051,7 +1051,7 @@ impl ExitStatus { // true on all actual versions of Unix, is widely assumed, and is specified in SuS // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not // true for a platform pretending to be Unix, the tests (our doctests, and also - // process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. + // unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. match NonZero::try_from(self.0) { /* was nonzero */ Ok(failure) => Err(ExitStatusError(failure)), /* was zero, couldn't convert */ Err(_) => Ok(()), @@ -1157,7 +1157,7 @@ fn signal_string(signal: i32) -> &'static str { ) ))] libc::SIGSTKFLT => " (SIGSTKFLT)", - #[cfg(any(target_os = "linux", target_os = "nto"))] + #[cfg(any(target_os = "linux", target_os = "nto", target_os = "cygwin"))] libc::SIGPWR => " (SIGPWR)", #[cfg(any( target_os = "freebsd", @@ -1166,6 +1166,7 @@ fn signal_string(signal: i32) -> &'static str { target_os = "dragonfly", target_os = "nto", target_vendor = "apple", + target_os = "cygwin", ))] libc::SIGEMT => " (SIGEMT)", #[cfg(any( @@ -1231,10 +1232,9 @@ impl ExitStatusError { #[cfg(target_os = "linux")] mod linux_child_ext { - + use crate::io::ErrorKind; use crate::os::linux::process as os; - use crate::sys::pal::unix::ErrorKind; - use crate::sys::pal::unix::linux::pidfd as imp; + use crate::sys::pal::linux::pidfd as imp; use crate::sys_common::FromInner; use crate::{io, mem}; @@ -1260,10 +1260,9 @@ mod linux_child_ext { } #[cfg(test)] -#[path = "process_unix/tests.rs"] mod tests; -// See [`process_unsupported_wait_status::compare_with_linux`]; +// See [`unsupported_wait_status::compare_with_linux`]; #[cfg(all(test, target_os = "linux"))] -#[path = "process_unsupported/wait_status.rs"] -mod process_unsupported_wait_status; +#[path = "unsupported/wait_status.rs"] +mod unsupported_wait_status; diff --git a/library/std/src/sys/pal/unix/process/process_unix/tests.rs b/library/std/src/sys/process/unix/unix/tests.rs index f4d6ac6b4e3..f4d6ac6b4e3 100644 --- a/library/std/src/sys/pal/unix/process/process_unix/tests.rs +++ b/library/std/src/sys/process/unix/unix/tests.rs diff --git a/library/std/src/sys/pal/unix/process/process_unsupported.rs b/library/std/src/sys/process/unix/unsupported.rs index c58548835ff..78d270923cf 100644 --- a/library/std/src/sys/pal/unix/process/process_unsupported.rs +++ b/library/std/src/sys/process/unix/unsupported.rs @@ -1,9 +1,9 @@ use libc::{c_int, pid_t}; +use super::common::*; use crate::io; use crate::num::NonZero; -use crate::sys::pal::unix::unsupported::*; -use crate::sys::process::process_common::*; +use crate::sys::pal::unsupported::*; //////////////////////////////////////////////////////////////////////////////// // Command diff --git a/library/std/src/sys/pal/unix/process/process_unsupported/wait_status.rs b/library/std/src/sys/process/unix/unsupported/wait_status.rs index f04036bde49..f348d557e4b 100644 --- a/library/std/src/sys/pal/unix/process/process_unsupported/wait_status.rs +++ b/library/std/src/sys/process/unix/unsupported/wait_status.rs @@ -7,7 +7,7 @@ use crate::ffi::c_int; use crate::fmt; use crate::num::NonZero; -/// Emulated wait status for use by `process_unsupported.rs` +/// Emulated wait status for use by `unsupported.rs` /// /// Uses the "traditional unix" encoding. For use on platfors which are `#[cfg(unix)]` /// but do not actually support subprocesses at all. @@ -48,7 +48,7 @@ impl ExitStatus { // true on all actual versions of Unix, is widely assumed, and is specified in SuS // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not // true for a platform pretending to be Unix, the tests (our doctests, and also - // process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. + // unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. match NonZero::try_from(self.wait_status) { /* was nonzero */ Ok(failure) => Err(ExitStatusError(failure)), /* was zero, couldn't convert */ Err(_) => Ok(()), @@ -79,5 +79,6 @@ impl ExitStatus { } #[cfg(test)] -#[path = "wait_status/tests.rs"] // needed because of strange layout of process_unsupported +#[path = "wait_status/tests.rs"] +// needed because this module is also imported through #[path] for testing purposes mod tests; diff --git a/library/std/src/sys/pal/unix/process/process_unsupported/wait_status/tests.rs b/library/std/src/sys/process/unix/unsupported/wait_status/tests.rs index 5132eab10a1..0d9232fac5e 100644 --- a/library/std/src/sys/pal/unix/process/process_unsupported/wait_status/tests.rs +++ b/library/std/src/sys/process/unix/unsupported/wait_status/tests.rs @@ -1,4 +1,4 @@ -// Note that tests in this file are run on Linux as well as on platforms using process_unsupported +// Note that tests in this file are run on Linux as well as on platforms using unsupported // Test that our emulation exactly matches Linux // diff --git a/library/std/src/sys/pal/unix/process/process_vxworks.rs b/library/std/src/sys/process/unix/vxworks.rs index e2c1b6a0326..5f1727789a1 100644 --- a/library/std/src/sys/pal/unix/process/process_vxworks.rs +++ b/library/std/src/sys/process/unix/vxworks.rs @@ -1,11 +1,11 @@ #![forbid(unsafe_op_in_unsafe_fn)] use libc::{self, RTP_ID, c_char, c_int}; +use super::common::*; use crate::io::{self, ErrorKind}; use crate::num::NonZero; use crate::sys::cvt; -use crate::sys::pal::unix::thread; -use crate::sys::process::process_common::*; +use crate::sys::pal::thread; use crate::{fmt, sys}; //////////////////////////////////////////////////////////////////////////////// @@ -200,7 +200,7 @@ impl ExitStatus { // true on all actual versions of Unix, is widely assumed, and is specified in SuS // https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html. If it is not // true for a platform pretending to be Unix, the tests (our doctests, and also - // process_unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. + // unix/tests.rs) will spot it. `ExitStatusError::code` assumes this too. match NonZero::try_from(self.0) { Ok(failure) => Err(ExitStatusError(failure)), Err(_) => Ok(()), diff --git a/library/std/src/sys/pal/unsupported/process.rs b/library/std/src/sys/process/unsupported.rs index fee81744f09..fee81744f09 100644 --- a/library/std/src/sys/pal/unsupported/process.rs +++ b/library/std/src/sys/process/unsupported.rs diff --git a/library/std/src/sys/pal/windows/process.rs b/library/std/src/sys/process/windows.rs index c57ff355d12..06c15e08f3f 100644 --- a/library/std/src/sys/pal/windows/process.rs +++ b/library/std/src/sys/process/windows.rs @@ -5,11 +5,10 @@ mod tests; use core::ffi::c_void; -use super::api::{self, WinError}; use crate::collections::BTreeMap; use crate::env::consts::{EXE_EXTENSION, EXE_SUFFIX}; use crate::ffi::{OsStr, OsString}; -use crate::io::{self, Error, ErrorKind}; +use crate::io::{self, Error}; use crate::num::NonZero; use crate::os::windows::ffi::{OsStrExt, OsStringExt}; use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle}; @@ -20,6 +19,8 @@ use crate::sys::args::{self, Arg}; use crate::sys::c::{self, EXIT_FAILURE, EXIT_SUCCESS}; use crate::sys::fs::{File, OpenOptions}; use crate::sys::handle::Handle; +use crate::sys::pal::api::{self, WinError}; +use crate::sys::pal::{ensure_no_nuls, fill_utf16_buf}; use crate::sys::pipe::{self, AnonPipe}; use crate::sys::{cvt, path, stdio}; use crate::sys_common::IntoInner; @@ -142,14 +143,6 @@ impl AsRef<OsStr> for EnvKey { } } -pub(crate) fn ensure_no_nuls<T: AsRef<OsStr>>(s: T) -> io::Result<T> { - if s.as_ref().encode_wide().any(|b| b == 0) { - Err(io::const_error!(ErrorKind::InvalidInput, "nul byte found in provided data")) - } else { - Ok(s) - } -} - pub struct Command { program: OsString, args: Vec<Arg>, @@ -279,7 +272,7 @@ impl Command { let is_batch_file = if path::is_verbatim(&program) { has_bat_extension(&program[..program.len() - 1]) } else { - super::fill_utf16_buf( + fill_utf16_buf( |buffer, size| unsafe { // resolve the path so we can test the final file name. c::GetFullPathNameW(program.as_ptr(), size, buffer, ptr::null_mut()) @@ -521,7 +514,7 @@ where // 3 & 4. System paths // SAFETY: This uses `fill_utf16_buf` to safely call the OS functions. unsafe { - if let Ok(Some(path)) = super::fill_utf16_buf( + if let Ok(Some(path)) = fill_utf16_buf( |buf, size| c::GetSystemDirectoryW(buf, size), |buf| exists(PathBuf::from(OsString::from_wide(buf))), ) { @@ -529,7 +522,7 @@ where } #[cfg(not(target_vendor = "uwp"))] { - if let Ok(Some(path)) = super::fill_utf16_buf( + if let Ok(Some(path)) = fill_utf16_buf( |buf, size| c::GetWindowsDirectoryW(buf, size), |buf| exists(PathBuf::from(OsString::from_wide(buf))), ) { @@ -621,6 +614,12 @@ impl From<AnonPipe> for Stdio { } } +impl From<Handle> for Stdio { + fn from(pipe: Handle) -> Stdio { + Stdio::Handle(pipe) + } +} + impl From<File> for Stdio { fn from(file: File) -> Stdio { Stdio::Handle(file.into_inner()) @@ -845,10 +844,8 @@ fn make_command_line(argv0: &OsStr, args: &[Arg], force_quotes: bool) -> io::Res // Get `cmd.exe` for use with bat scripts, encoded as a UTF-16 string. fn command_prompt() -> io::Result<Vec<u16>> { - let mut system: Vec<u16> = super::fill_utf16_buf( - |buf, size| unsafe { c::GetSystemDirectoryW(buf, size) }, - |buf| buf.into(), - )?; + let mut system: Vec<u16> = + fill_utf16_buf(|buf, size| unsafe { c::GetSystemDirectoryW(buf, size) }, |buf| buf.into())?; system.extend("\\cmd.exe".encode_utf16().chain([0])); Ok(system) } diff --git a/library/std/src/sys/pal/windows/process/tests.rs b/library/std/src/sys/process/windows/tests.rs index 1377e12162f..1377e12162f 100644 --- a/library/std/src/sys/pal/windows/process/tests.rs +++ b/library/std/src/sys/process/windows/tests.rs diff --git a/library/std/src/sys/random/horizon.rs b/library/std/src/sys/random/getrandom.rs index 0be2eae20a7..0be2eae20a7 100644 --- a/library/std/src/sys/random/horizon.rs +++ b/library/std/src/sys/random/getrandom.rs diff --git a/library/std/src/sys/random/mod.rs b/library/std/src/sys/random/mod.rs index 870039602bc..013e886a99b 100644 --- a/library/std/src/sys/random/mod.rs +++ b/library/std/src/sys/random/mod.rs @@ -35,10 +35,10 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "hermit")] { mod hermit; pub use hermit::fill_bytes; - } else if #[cfg(target_os = "horizon")] { - // FIXME: add arc4random_buf to shim-3ds - mod horizon; - pub use horizon::fill_bytes; + } else if #[cfg(any(target_os = "horizon", target_os = "cygwin"))] { + // FIXME(horizon): add arc4random_buf to shim-3ds + mod getrandom; + pub use getrandom::fill_bytes; } else if #[cfg(any( target_os = "aix", target_os = "hurd", diff --git a/library/std/src/sys/random/trusty.rs b/library/std/src/sys/random/trusty.rs index da6ca3eea24..e4db24695f8 100644 --- a/library/std/src/sys/random/trusty.rs +++ b/library/std/src/sys/random/trusty.rs @@ -1,4 +1,4 @@ -extern "C" { +unsafe extern "C" { fn trusty_rng_secure_rand(randomBuffer: *mut core::ffi::c_void, randomBufferLen: libc::size_t); } diff --git a/library/std/src/sys/stdio/sgx.rs b/library/std/src/sys/stdio/sgx.rs index 1894c098d18..2cf47f49192 100644 --- a/library/std/src/sys/stdio/sgx.rs +++ b/library/std/src/sys/stdio/sgx.rs @@ -3,9 +3,9 @@ use fortanix_sgx_abi as abi; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::sys::fd::FileDesc; -pub struct Stdin(()); -pub struct Stdout(()); -pub struct Stderr(()); +pub struct Stdin; +pub struct Stdout; +pub struct Stderr; fn with_std_fd<F: FnOnce(&FileDesc) -> R, R>(fd: abi::Fd, f: F) -> R { let fd = FileDesc::new(fd); @@ -16,7 +16,7 @@ fn with_std_fd<F: FnOnce(&FileDesc) -> R, R>(fd: abi::Fd, f: F) -> R { impl Stdin { pub const fn new() -> Stdin { - Stdin(()) + Stdin } } @@ -41,7 +41,7 @@ impl io::Read for Stdin { impl Stdout { pub const fn new() -> Stdout { - Stdout(()) + Stdout } } @@ -66,7 +66,7 @@ impl io::Write for Stdout { impl Stderr { pub const fn new() -> Stderr { - Stderr(()) + Stderr } } diff --git a/library/std/src/sys/stdio/solid.rs b/library/std/src/sys/stdio/solid.rs index a2ff4bb212f..55daf0b54b9 100644 --- a/library/std/src/sys/stdio/solid.rs +++ b/library/std/src/sys/stdio/solid.rs @@ -1,22 +1,13 @@ +#[expect(dead_code)] +#[path = "unsupported.rs"] +mod unsupported_stdio; + use crate::io; use crate::sys::pal::abi; -pub struct Stdin; +pub type Stdin = unsupported_stdio::Stdin; pub struct Stdout; -pub struct Stderr; -struct PanicOutput; - -impl Stdin { - pub const fn new() -> Stdin { - Stdin - } -} - -impl io::Read for Stdin { - fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { - Ok(0) - } -} +pub type Stderr = Stdout; impl Stdout { pub const fn new() -> Stdout { @@ -35,46 +26,12 @@ impl io::Write for Stdout { } } -impl Stderr { - pub const fn new() -> Stderr { - Stderr - } -} - -impl io::Write for Stderr { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - unsafe { abi::SOLID_LOG_write(buf.as_ptr(), buf.len()) }; - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -impl PanicOutput { - pub const fn new() -> PanicOutput { - PanicOutput - } -} - -impl io::Write for PanicOutput { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - unsafe { abi::SOLID_LOG_write(buf.as_ptr(), buf.len()) }; - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -pub const STDIN_BUF_SIZE: usize = 0; +pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE; pub fn is_ebadf(_err: &io::Error) -> bool { true } pub fn panic_output() -> Option<impl io::Write> { - Some(PanicOutput::new()) + Some(Stderr::new()) } diff --git a/library/std/src/sys/stdio/teeos.rs b/library/std/src/sys/stdio/teeos.rs index 67e251812da..27b3292bf8f 100644 --- a/library/std/src/sys/stdio/teeos.rs +++ b/library/std/src/sys/stdio/teeos.rs @@ -1,12 +1,16 @@ #![deny(unsafe_op_in_unsafe_fn)] +#[expect(dead_code)] +#[path = "unsupported.rs"] +mod unsupported_stdio; + use core::arch::asm; use crate::io; -pub struct Stdin; +pub type Stdin = unsupported_stdio::Stdin; pub struct Stdout; -pub struct Stderr; +pub type Stderr = Stdout; const KCALL_DEBUG_CMD_PUT_BYTES: i64 = 2; @@ -25,27 +29,6 @@ unsafe fn debug_call(cap_ref: u64, call_no: i64, arg1: u64, arg2: u64) -> i32 { ret as i32 } -fn print_buf(s: &[u8]) -> io::Result<usize> { - // Corresponds to `HM_DEBUG_PUT_BYTES_LIMIT`. - const MAX_LEN: usize = 512; - let len = if s.len() > MAX_LEN { MAX_LEN } else { s.len() }; - let result = unsafe { debug_call(0, KCALL_DEBUG_CMD_PUT_BYTES, s.as_ptr() as u64, len as u64) }; - - if result == 0 { Ok(len) } else { Err(io::Error::from(io::ErrorKind::InvalidInput)) } -} - -impl Stdin { - pub const fn new() -> Stdin { - Stdin - } -} - -impl io::Read for Stdin { - fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { - Ok(0) - } -} - impl Stdout { pub const fn new() -> Stdout { Stdout @@ -54,23 +37,13 @@ impl Stdout { impl io::Write for Stdout { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - print_buf(buf) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} + // Corresponds to `HM_DEBUG_PUT_BYTES_LIMIT`. + const MAX_LEN: usize = 512; + let len = buf.len().min(MAX_LEN); + let result = + unsafe { debug_call(0, KCALL_DEBUG_CMD_PUT_BYTES, buf.as_ptr() as u64, len as u64) }; -impl Stderr { - pub const fn new() -> Stderr { - Stderr - } -} - -impl io::Write for Stderr { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - print_buf(buf) + if result == 0 { Ok(len) } else { Err(io::Error::from(io::ErrorKind::InvalidInput)) } } fn flush(&mut self) -> io::Result<()> { @@ -78,7 +51,7 @@ impl io::Write for Stderr { } } -pub const STDIN_BUF_SIZE: usize = 0; +pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE; pub fn is_ebadf(err: &io::Error) -> bool { err.raw_os_error() == Some(libc::EBADF as i32) diff --git a/library/std/src/sys/stdio/unix.rs b/library/std/src/sys/stdio/unix.rs index 8d133857c59..8535e3539e9 100644 --- a/library/std/src/sys/stdio/unix.rs +++ b/library/std/src/sys/stdio/unix.rs @@ -3,9 +3,7 @@ use hermit_abi::{EBADF, STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO}; #[cfg(target_family = "unix")] use libc::{EBADF, STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO}; -#[cfg(target_family = "unix")] -use crate::io::BorrowedCursor; -use crate::io::{self, IoSlice, IoSliceMut}; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; use crate::mem::ManuallyDrop; #[cfg(target_os = "hermit")] use crate::os::hermit::io::FromRawFd; @@ -13,13 +11,13 @@ use crate::os::hermit::io::FromRawFd; use crate::os::unix::io::FromRawFd; use crate::sys::fd::FileDesc; -pub struct Stdin(()); -pub struct Stdout(()); -pub struct Stderr(()); +pub struct Stdin; +pub struct Stdout; +pub struct Stderr; impl Stdin { pub const fn new() -> Stdin { - Stdin(()) + Stdin } } @@ -28,7 +26,6 @@ impl io::Read for Stdin { unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(STDIN_FILENO)).read(buf) } } - #[cfg(not(target_os = "hermit"))] fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> { unsafe { ManuallyDrop::new(FileDesc::from_raw_fd(STDIN_FILENO)).read_buf(buf) } } @@ -45,7 +42,7 @@ impl io::Read for Stdin { impl Stdout { pub const fn new() -> Stdout { - Stdout(()) + Stdout } } @@ -71,7 +68,7 @@ impl io::Write for Stdout { impl Stderr { pub const fn new() -> Stderr { - Stderr(()) + Stderr } } diff --git a/library/std/src/sys/stdio/unsupported.rs b/library/std/src/sys/stdio/unsupported.rs index b5e3f5be988..177264f5c10 100644 --- a/library/std/src/sys/stdio/unsupported.rs +++ b/library/std/src/sys/stdio/unsupported.rs @@ -1,8 +1,8 @@ -use crate::io; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; pub struct Stdin; pub struct Stdout; -pub struct Stderr; +pub type Stderr = Stdout; impl Stdin { pub const fn new() -> Stdin { @@ -11,9 +11,47 @@ impl Stdin { } impl io::Read for Stdin { + #[inline] fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { Ok(0) } + + #[inline] + fn read_buf(&mut self, _cursor: BorrowedCursor<'_>) -> io::Result<()> { + Ok(()) + } + + #[inline] + fn read_vectored(&mut self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { + Ok(0) + } + + #[inline] + fn is_read_vectored(&self) -> bool { + // Do not force `Chain<Empty, T>` or `Chain<T, Empty>` to use vectored + // reads, unless the other reader is vectored. + false + } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + if !buf.is_empty() { Err(io::Error::READ_EXACT_EOF) } else { Ok(()) } + } + + #[inline] + fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { + if cursor.capacity() != 0 { Err(io::Error::READ_EXACT_EOF) } else { Ok(()) } + } + + #[inline] + fn read_to_end(&mut self, _buf: &mut Vec<u8>) -> io::Result<usize> { + Ok(0) + } + + #[inline] + fn read_to_string(&mut self, _buf: &mut String) -> io::Result<usize> { + Ok(0) + } } impl Stdout { @@ -23,26 +61,35 @@ impl Stdout { } impl io::Write for Stdout { + #[inline] fn write(&mut self, buf: &[u8]) -> io::Result<usize> { Ok(buf.len()) } - fn flush(&mut self) -> io::Result<()> { - Ok(()) + #[inline] + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { + let total_len = bufs.iter().map(|b| b.len()).sum(); + Ok(total_len) } -} -impl Stderr { - pub const fn new() -> Stderr { - Stderr + #[inline] + fn is_write_vectored(&self) -> bool { + true } -} -impl io::Write for Stderr { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - Ok(buf.len()) + #[inline] + fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> { + Ok(()) } + #[inline] + fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> { + Ok(()) + } + + // Keep the default write_fmt so the `fmt::Arguments` are still evaluated. + + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } diff --git a/library/std/src/sys/stdio/xous.rs b/library/std/src/sys/stdio/xous.rs index 71736145221..a92167642b7 100644 --- a/library/std/src/sys/stdio/xous.rs +++ b/library/std/src/sys/stdio/xous.rs @@ -1,27 +1,18 @@ -use crate::io; - -pub struct Stdin; -pub struct Stdout {} -pub struct Stderr; +#[expect(dead_code)] +#[path = "unsupported.rs"] +mod unsupported_stdio; +use crate::io; use crate::os::xous::ffi::{Connection, lend, try_lend, try_scalar}; use crate::os::xous::services::{LogLend, LogScalar, log_server, try_connect}; -impl Stdin { - pub const fn new() -> Stdin { - Stdin - } -} - -impl io::Read for Stdin { - fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> { - Ok(0) - } -} +pub type Stdin = unsupported_stdio::Stdin; +pub struct Stdout; +pub struct Stderr; impl Stdout { pub const fn new() -> Stdout { - Stdout {} + Stdout } } @@ -73,7 +64,7 @@ impl io::Write for Stderr { } } -pub const STDIN_BUF_SIZE: usize = 0; +pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE; pub fn is_ebadf(_err: &io::Error) -> bool { true diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs index 06c347af181..59ec48a57d1 100644 --- a/library/std/src/thread/tests.rs +++ b/library/std/src/thread/tests.rs @@ -108,6 +108,7 @@ fn test_is_finished() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_join_panic() { match thread::spawn(move || panic!()).join() { result::Result::Err(_) => (), @@ -210,6 +211,7 @@ fn test_simple_newsched_spawn() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_try_panic_message_string_literal() { match thread::spawn(move || { panic!("static string"); @@ -226,6 +228,7 @@ fn test_try_panic_message_string_literal() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_try_panic_any_message_owned_str() { match thread::spawn(move || { panic_any("owned string".to_string()); @@ -242,6 +245,7 @@ fn test_try_panic_any_message_owned_str() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_try_panic_any_message_any() { match thread::spawn(move || { panic_any(Box::new(413u16) as Box<dyn Any + Send>); @@ -260,6 +264,7 @@ fn test_try_panic_any_message_any() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_try_panic_any_message_unit_struct() { struct Juju; diff --git a/library/std/tests/floats/f128.rs b/library/std/tests/floats/f128.rs index d0e8b157e6b..b4a6c672bf0 100644 --- a/library/std/tests/floats/f128.rs +++ b/library/std/tests/floats/f128.rs @@ -983,3 +983,34 @@ fn test_total_cmp() { assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f128::INFINITY)); assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan())); } + +#[test] +fn test_from() { + assert_eq!(f128::from(false), 0.0); + assert_eq!(f128::from(true), 1.0); + assert_eq!(f128::from(u8::MIN), 0.0); + assert_eq!(f128::from(42_u8), 42.0); + assert_eq!(f128::from(u8::MAX), 255.0); + assert_eq!(f128::from(i8::MIN), -128.0); + assert_eq!(f128::from(42_i8), 42.0); + assert_eq!(f128::from(i8::MAX), 127.0); + assert_eq!(f128::from(u16::MIN), 0.0); + assert_eq!(f128::from(42_u16), 42.0); + assert_eq!(f128::from(u16::MAX), 65535.0); + assert_eq!(f128::from(i16::MIN), -32768.0); + assert_eq!(f128::from(42_i16), 42.0); + assert_eq!(f128::from(i16::MAX), 32767.0); + assert_eq!(f128::from(u32::MIN), 0.0); + assert_eq!(f128::from(42_u32), 42.0); + assert_eq!(f128::from(u32::MAX), 4294967295.0); + assert_eq!(f128::from(i32::MIN), -2147483648.0); + assert_eq!(f128::from(42_i32), 42.0); + assert_eq!(f128::from(i32::MAX), 2147483647.0); + // FIXME(f16_f128): Uncomment these tests once the From<{u64,i64}> impls are added. + // assert_eq!(f128::from(u64::MIN), 0.0); + // assert_eq!(f128::from(42_u64), 42.0); + // assert_eq!(f128::from(u64::MAX), 18446744073709551615.0); + // assert_eq!(f128::from(i64::MIN), -9223372036854775808.0); + // assert_eq!(f128::from(42_i64), 42.0); + // assert_eq!(f128::from(i64::MAX), 9223372036854775807.0); +} diff --git a/library/std/tests/floats/f16.rs b/library/std/tests/floats/f16.rs index 19389a9178e..ca0b8efbe83 100644 --- a/library/std/tests/floats/f16.rs +++ b/library/std/tests/floats/f16.rs @@ -953,3 +953,15 @@ fn test_total_cmp() { assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::INFINITY)); assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan())); } + +#[test] +fn test_from() { + assert_eq!(f16::from(false), 0.0); + assert_eq!(f16::from(true), 1.0); + assert_eq!(f16::from(u8::MIN), 0.0); + assert_eq!(f16::from(42_u8), 42.0); + assert_eq!(f16::from(u8::MAX), 255.0); + assert_eq!(f16::from(i8::MIN), -128.0); + assert_eq!(f16::from(42_i8), 42.0); + assert_eq!(f16::from(i8::MAX), 127.0); +} diff --git a/library/std/tests/pipe_subprocess.rs b/library/std/tests/pipe_subprocess.rs index 00d99a578d5..c51a4459e71 100644 --- a/library/std/tests/pipe_subprocess.rs +++ b/library/std/tests/pipe_subprocess.rs @@ -1,5 +1,3 @@ -#![feature(anonymous_pipe)] - fn main() { #[cfg(all(not(miri), any(unix, windows), not(target_os = "emscripten")))] { diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index dd14c0266aa..e59ae2f3d7f 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -9,6 +9,10 @@ feature(stdarch_aarch64_feature_detection) )] #![cfg_attr( + all(target_arch = "s390x", target_os = "linux"), + feature(stdarch_s390x_feature_detection) +)] +#![cfg_attr( all(target_arch = "powerpc", target_os = "linux"), feature(stdarch_powerpc_feature_detection) )] @@ -133,6 +137,32 @@ fn powerpc64_linux() { } #[test] +#[cfg(all(target_arch = "s390x", target_os = "linux"))] +fn s390x_linux() { + use std::arch::is_s390x_feature_detected; + // tidy-alphabetical-start + println!("deflate-conversion: {}", is_s390x_feature_detected!("deflate-conversion")); + println!("enhanced-sort: {}", is_s390x_feature_detected!("enhanced-sort")); + println!("guarded-storage: {}", is_s390x_feature_detected!("guarded-storage")); + println!("high-word: {}", is_s390x_feature_detected!("high-word")); + println!("nnp-assist: {}", is_s390x_feature_detected!("nnp-assist")); + println!("transactional-execution: {}", is_s390x_feature_detected!("transactional-execution")); + println!("vector-enhancements-1: {}", is_s390x_feature_detected!("vector-enhancements-1")); + println!("vector-enhancements-2: {}", is_s390x_feature_detected!("vector-enhancements-2")); + println!( + "vector-packed-decimal-enhancement-2: {}", + is_s390x_feature_detected!("vector-packed-decimal-enhancement-2") + ); + println!( + "vector-packed-decimal-enhancement: {}", + is_s390x_feature_detected!("vector-packed-decimal-enhancement") + ); + println!("vector-packed-decimal: {}", is_s390x_feature_detected!("vector-packed-decimal")); + println!("vector: {}", is_s390x_feature_detected!("vector")); + // tidy-alphabetical-end +} + +#[test] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] fn x86_all() { use std::arch::is_x86_feature_detected; diff --git a/library/std/tests/sync/mutex.rs b/library/std/tests/sync/mutex.rs index 74c62720107..88fb448d1eb 100644 --- a/library/std/tests/sync/mutex.rs +++ b/library/std/tests/sync/mutex.rs @@ -118,6 +118,7 @@ fn test_into_inner_drop() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_into_inner_poison() { let m = new_poisoned_mutex(NonCopy(10)); @@ -135,6 +136,7 @@ fn test_get_cloned() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_get_cloned_poison() { let m = new_poisoned_mutex(Cloneable(10)); @@ -152,6 +154,7 @@ fn test_get_mut() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_get_mut_poison() { let mut m = new_poisoned_mutex(NonCopy(10)); @@ -179,6 +182,7 @@ fn test_set() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_set_poison() { fn inner<T>(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T) where @@ -217,6 +221,7 @@ fn test_replace() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_replace_poison() { fn inner<T>(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T) where @@ -261,6 +266,7 @@ fn test_mutex_arc_condvar() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_arc_condvar_poison() { let packet = Packet(Arc::new((Mutex::new(1), Condvar::new()))); let packet2 = Packet(packet.0.clone()); @@ -290,6 +296,7 @@ fn test_arc_condvar_poison() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_mutex_arc_poison() { let arc = Arc::new(Mutex::new(1)); assert!(!arc.is_poisoned()); @@ -304,6 +311,7 @@ fn test_mutex_arc_poison() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_mutex_arc_poison_mapped() { let arc = Arc::new(Mutex::new(1)); assert!(!arc.is_poisoned()); @@ -335,6 +343,7 @@ fn test_mutex_arc_nested() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_mutex_arc_access_in_unwind() { let arc = Arc::new(Mutex::new(1)); let arc2 = arc.clone(); @@ -381,6 +390,7 @@ fn test_mapping_mapped_guard() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn panic_while_mapping_unlocked_poison() { let lock = Mutex::new(()); diff --git a/library/std/tests/sync/once.rs b/library/std/tests/sync/once.rs index a3ffc73fe06..1b43831df3a 100644 --- a/library/std/tests/sync/once.rs +++ b/library/std/tests/sync/once.rs @@ -52,6 +52,7 @@ fn stampede_once() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn poison_bad() { static O: Once = Once::new(); @@ -80,6 +81,7 @@ fn poison_bad() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn wait_for_force_to_finish() { static O: Once = Once::new(); @@ -137,6 +139,7 @@ fn wait() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn wait_on_poisoned() { let once = Once::new(); @@ -145,6 +148,7 @@ fn wait_on_poisoned() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn wait_force_on_poisoned() { let once = Once::new(); diff --git a/library/std/tests/sync/once_lock.rs b/library/std/tests/sync/once_lock.rs index ac9aaa8892e..922fd7da3d4 100644 --- a/library/std/tests/sync/once_lock.rs +++ b/library/std/tests/sync/once_lock.rs @@ -77,8 +77,10 @@ fn get_or_try_init() { let cell: OnceLock<String> = OnceLock::new(); assert!(cell.get().is_none()); - let res = panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() })); - assert!(res.is_err()); + if cfg!(panic = "unwind") { + let res = panic::catch_unwind(|| cell.get_or_try_init(|| -> Result<_, ()> { panic!() })); + assert!(res.is_err()); + } assert!(cell.get().is_none()); assert_eq!(cell.get_or_try_init(|| Err(())), Err(())); diff --git a/library/std/tests/sync/rwlock.rs b/library/std/tests/sync/rwlock.rs index 49f260648c6..d2c784aefcf 100644 --- a/library/std/tests/sync/rwlock.rs +++ b/library/std/tests/sync/rwlock.rs @@ -73,6 +73,7 @@ fn frob() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_rw_arc_poison_wr() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); @@ -85,6 +86,7 @@ fn test_rw_arc_poison_wr() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_rw_arc_poison_mapped_w_r() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); @@ -98,6 +100,7 @@ fn test_rw_arc_poison_mapped_w_r() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_rw_arc_poison_ww() { let arc = Arc::new(RwLock::new(1)); assert!(!arc.is_poisoned()); @@ -112,6 +115,7 @@ fn test_rw_arc_poison_ww() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_rw_arc_poison_mapped_w_w() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); @@ -126,6 +130,7 @@ fn test_rw_arc_poison_mapped_w_w() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_rw_arc_no_poison_rr() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); @@ -139,6 +144,7 @@ fn test_rw_arc_no_poison_rr() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_rw_arc_no_poison_mapped_r_r() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); @@ -153,6 +159,7 @@ fn test_rw_arc_no_poison_mapped_r_r() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_rw_arc_no_poison_rw() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); @@ -166,6 +173,7 @@ fn test_rw_arc_no_poison_rw() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_rw_arc_no_poison_mapped_r_w() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); @@ -218,6 +226,7 @@ fn test_rw_arc() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_rw_arc_access_in_unwind() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); @@ -316,6 +325,7 @@ fn test_into_inner_drop() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_into_inner_poison() { let m = new_poisoned_rwlock(NonCopy(10)); @@ -333,6 +343,7 @@ fn test_get_cloned() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_get_cloned_poison() { let m = new_poisoned_rwlock(Cloneable(10)); @@ -350,6 +361,7 @@ fn test_get_mut() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_get_mut_poison() { let mut m = new_poisoned_rwlock(NonCopy(10)); @@ -377,6 +389,7 @@ fn test_set() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_set_poison() { fn inner<T>(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T) where @@ -415,6 +428,7 @@ fn test_replace() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_replace_poison() { fn inner<T>(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T) where @@ -482,6 +496,7 @@ fn test_mapping_mapped_guard() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn panic_while_mapping_read_unlocked_no_poison() { let lock = RwLock::new(()); @@ -551,6 +566,7 @@ fn panic_while_mapping_read_unlocked_no_poison() { } #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn panic_while_mapping_write_unlocked_poison() { let lock = RwLock::new(()); diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index ced8e82b8eb..12582569a57 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -27,10 +27,10 @@ pub type _Unwind_Trace_Fn = #[cfg(target_arch = "x86")] pub const unwinder_private_data_size: usize = 5; -#[cfg(all(target_arch = "x86_64", not(target_os = "windows")))] +#[cfg(all(target_arch = "x86_64", not(any(target_os = "windows", target_os = "cygwin"))))] pub const unwinder_private_data_size: usize = 2; -#[cfg(all(target_arch = "x86_64", target_os = "windows"))] +#[cfg(all(target_arch = "x86_64", any(target_os = "windows", target_os = "cygwin")))] pub const unwinder_private_data_size: usize = 6; #[cfg(all(target_arch = "arm", not(target_vendor = "apple")))] @@ -128,16 +128,13 @@ if #[cfg(any(target_vendor = "apple", target_os = "netbsd", not(target_arch = "a // // 32-bit ARM on iOS/tvOS/watchOS use either DWARF/Compact unwinding or // "setjmp-longjmp" / SjLj unwinding. - #[repr(C)] - #[derive(Copy, Clone, PartialEq)] - pub enum _Unwind_Action { - _UA_SEARCH_PHASE = 1, - _UA_CLEANUP_PHASE = 2, - _UA_HANDLER_FRAME = 4, - _UA_FORCE_UNWIND = 8, - _UA_END_OF_STACK = 16, - } - pub use _Unwind_Action::*; + pub type _Unwind_Action = c_int; + + pub const _UA_SEARCH_PHASE: c_int = 1; + pub const _UA_CLEANUP_PHASE: c_int = 2; + pub const _UA_HANDLER_FRAME: c_int = 4; + pub const _UA_FORCE_UNWIND: c_int = 8; + pub const _UA_END_OF_STACK: c_int = 16; #[cfg_attr( all(feature = "llvm-libunwind", any(target_os = "fuchsia", target_os = "linux", target_os = "xous")), @@ -292,7 +289,10 @@ if #[cfg(all(target_vendor = "apple", not(target_os = "watchos"), target_arch = } // cfg_if! cfg_if::cfg_if! { -if #[cfg(all(windows, any(target_arch = "aarch64", target_arch = "x86_64"), target_env = "gnu"))] { +if #[cfg(any( + all(windows, any(target_arch = "aarch64", target_arch = "x86_64"), target_env = "gnu"), + target_os = "cygwin", + ))] { // We declare these as opaque types. This is fine since you just need to // pass them to _GCC_specific_handler and forget about them. pub enum EXCEPTION_RECORD {} diff --git a/library/unwind/src/unwinding.rs b/library/unwind/src/unwinding.rs index fa8a8c38583..36120bc868e 100644 --- a/library/unwind/src/unwinding.rs +++ b/library/unwind/src/unwinding.rs @@ -2,16 +2,13 @@ use core::ffi::{c_int, c_void}; -#[repr(C)] -#[derive(Copy, Clone, PartialEq)] -pub enum _Unwind_Action { - _UA_SEARCH_PHASE = 1, - _UA_CLEANUP_PHASE = 2, - _UA_HANDLER_FRAME = 4, - _UA_FORCE_UNWIND = 8, - _UA_END_OF_STACK = 16, -} -pub use _Unwind_Action::*; +pub type _Unwind_Action = c_int; + +pub const _UA_SEARCH_PHASE: c_int = 1; +pub const _UA_CLEANUP_PHASE: c_int = 2; +pub const _UA_HANDLER_FRAME: c_int = 4; +pub const _UA_FORCE_UNWIND: c_int = 8; +pub const _UA_END_OF_STACK: c_int = 16; #[repr(C)] #[derive(Debug, Copy, Clone, PartialEq)] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 2ea2596088f..d3e2b9e05e9 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -28,11 +28,6 @@ name = "rustdoc" path = "src/bin/rustdoc.rs" test = false -[[bin]] -name = "sccache-plus-cl" -path = "src/bin/sccache-plus-cl.rs" -test = false - [dependencies] # Most of the time updating these dependencies requires modifications to the # bootstrap codebase(e.g., https://github.com/rust-lang/rust/issues/124565); diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index f036603ee70..f9d7c811f60 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -163,7 +163,7 @@ compiler, which will then build the bootstrap binary written in Rust. Because there are two separate codebases behind `x.py`, they need to be kept in sync. In particular, both `bootstrap.py` and the bootstrap binary -parse `config.toml` and read the same command line arguments. `bootstrap.py` +parse `bootstrap.toml` and read the same command line arguments. `bootstrap.py` keeps these in sync by setting various environment variables, and the programs sometimes have to add arguments that are explicitly ignored, to be read by the other. diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 01a9792f1b3..68400ba0ea0 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -726,7 +726,7 @@ class RustBuild(object): def should_fix_bins_and_dylibs(self): """Whether or not `fix_bin_or_dylib` needs to be run; can only be True - on NixOS or if config.toml has `build.patch-binaries-for-nix` set. + on NixOS or if bootstrap.toml has `build.patch-binaries-for-nix` set. """ if self._should_fix_bins_and_dylibs is not None: return self._should_fix_bins_and_dylibs @@ -775,7 +775,7 @@ class RustBuild(object): "The IN_NIX_SHELL environment variable is `{}`;".format( in_nix_shell ), - "you may need to set `patch-binaries-for-nix=true` in config.toml", + "you may need to set `patch-binaries-for-nix=true` in bootstrap.toml", ) return is_nixos @@ -884,7 +884,7 @@ class RustBuild(object): return os.path.join(self.build_dir, self.build, subdir) def get_toml(self, key, section=None): - """Returns the value of the given key in config.toml, otherwise returns None + """Returns the value of the given key in bootstrap.toml, otherwise returns None >>> rb = RustBuild() >>> rb.config_toml = 'key1 = "value1"\\nkey2 = "value2"' @@ -1250,17 +1250,23 @@ def bootstrap(args): "unless you put them in place manually." ) - # Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`, - # then `config.toml` in the root directory. + # Read from `--config` first, followed by `RUST_BOOTSTRAP_CONFIG`. + # If neither is set, check `./bootstrap.toml`, then `bootstrap.toml` in the root directory. + # If those are unavailable, fall back to `./config.toml`, then `config.toml` for + # backward compatibility. toml_path = args.config or os.getenv("RUST_BOOTSTRAP_CONFIG") using_default_path = toml_path is None if using_default_path: - toml_path = "config.toml" + toml_path = "bootstrap.toml" if not os.path.exists(toml_path): - toml_path = os.path.join(rust_root, toml_path) + toml_path = os.path.join(rust_root, "bootstrap.toml") + if not os.path.exists(toml_path): + toml_path = "config.toml" + if not os.path.exists(toml_path): + toml_path = os.path.join(rust_root, "config.toml") # Give a hard error if `--config` or `RUST_BOOTSTRAP_CONFIG` are set to a missing path, - # but not if `config.toml` hasn't been created. + # but not if `bootstrap.toml` hasn't been created. if not using_default_path or os.path.exists(toml_path): with open(toml_path) as config: config_toml = config.read() @@ -1278,7 +1284,9 @@ def bootstrap(args): # profiles to be renamed while maintaining back compatibility # Keep in sync with `profile_aliases` in config.rs profile_aliases = {"user": "dist"} - include_file = "config.{}.toml".format(profile_aliases.get(profile) or profile) + include_file = "bootstrap.{}.toml".format( + profile_aliases.get(profile) or profile + ) include_dir = os.path.join(rust_root, "src", "bootstrap", "defaults") include_path = os.path.join(include_dir, include_file) diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py index 7494536539d..9e12982a43d 100644 --- a/src/bootstrap/bootstrap_test.py +++ b/src/bootstrap/bootstrap_test.py @@ -156,7 +156,7 @@ class ParseArgsInConfigure(unittest.TestCase): class GenerateAndParseConfig(unittest.TestCase): - """Test that we can serialize and deserialize a config.toml file""" + """Test that we can serialize and deserialize a bootstrap.toml file""" def test_no_args(self): build = serialize_and_parse([]) @@ -206,11 +206,11 @@ class BuildBootstrap(unittest.TestCase): # problem in most cases, but there is a scenario where it would cause # the test to fail. # - # When a custom local Cargo is configured in config.toml (with the + # When a custom local Cargo is configured in bootstrap.toml (with the # build.cargo setting), no Cargo is downloaded to any location known by # bootstrap, and bootstrap relies on that setting to find it. # - # In this test though we are not using the config.toml of the caller: + # In this test though we are not using the bootstrap.toml of the caller: # we are generating a blank one instead. If we don't set build.cargo in # it, the test will have no way to find Cargo, failing the test. cargo_bin = os.environ.get("BOOTSTRAP_TEST_CARGO_BIN") diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 77151edd240..f6afe096724 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -367,8 +367,8 @@ if "--help" in sys.argv or "-h" in sys.argv: print("\t\t" + option.desc) print("") print("This configure script is a thin configuration shim over the true") - print("configuration system, `config.toml`. You can explore the comments") - print("in `config.example.toml` next to this configure script to see") + print("configuration system, `bootstrap.toml`. You can explore the comments") + print("in `bootstrap.example.toml` next to this configure script to see") print("more information about what each option is. Additionally you can") print("pass `--set` as an argument to set arbitrary key/value pairs") print("in the TOML configuration if desired") @@ -567,8 +567,8 @@ def apply_args(known_args, option_checking, config): raise RuntimeError("unhandled option {}".format(option.name)) -# "Parse" the `config.example.toml` file into the various sections, and we'll -# use this as a template of a `config.toml` to write out which preserves +# "Parse" the `bootstrap.example.toml` file into the various sections, and we'll +# use this as a template of a `bootstrap.toml` to write out which preserves # all the various comments and whatnot. # # Note that the `target` section is handled separately as we'll duplicate it @@ -581,7 +581,7 @@ def parse_example_config(known_args, config): targets = {} top_level_keys = [] - with open(rust_dir + "/config.example.toml") as example_config: + with open(rust_dir + "/bootstrap.example.toml") as example_config: example_lines = example_config.read().split("\n") for line in example_lines: if cur_section is None: @@ -755,8 +755,8 @@ def quit_if_file_exists(file): if __name__ == "__main__": - # If 'config.toml' already exists, exit the script at this point - quit_if_file_exists("config.toml") + # If 'bootstrap.toml' already exists, exit the script at this point + quit_if_file_exists("bootstrap.toml") if "GITHUB_ACTIONS" in os.environ: print("::group::Configure the build") @@ -766,11 +766,11 @@ if __name__ == "__main__": p("") section_order, sections, targets = parse_args(sys.argv[1:]) - # Now that we've built up our `config.toml`, write it all out in the same + # Now that we've built up our `bootstrap.toml`, write it all out in the same # order that we read it in. p("") - p("writing `config.toml` in current directory") - with bootstrap.output("config.toml") as f: + p("writing `bootstrap.toml` in current directory") + with bootstrap.output("bootstrap.toml") as f: write_config_toml(f, section_order, targets, sections) with bootstrap.output("Makefile") as f: diff --git a/src/bootstrap/defaults/config.compiler.toml b/src/bootstrap/defaults/bootstrap.compiler.toml index 269b90106e3..269b90106e3 100644 --- a/src/bootstrap/defaults/config.compiler.toml +++ b/src/bootstrap/defaults/bootstrap.compiler.toml diff --git a/src/bootstrap/defaults/config.dist.toml b/src/bootstrap/defaults/bootstrap.dist.toml index 7b381b416ca..7b381b416ca 100644 --- a/src/bootstrap/defaults/config.dist.toml +++ b/src/bootstrap/defaults/bootstrap.dist.toml diff --git a/src/bootstrap/defaults/config.library.toml b/src/bootstrap/defaults/bootstrap.library.toml index b43796d6f20..b43796d6f20 100644 --- a/src/bootstrap/defaults/config.library.toml +++ b/src/bootstrap/defaults/bootstrap.library.toml diff --git a/src/bootstrap/defaults/config.tools.toml b/src/bootstrap/defaults/bootstrap.tools.toml index 57c2706f60a..57c2706f60a 100644 --- a/src/bootstrap/defaults/config.tools.toml +++ b/src/bootstrap/defaults/bootstrap.tools.toml diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index 6f6aaa878ef..443131dc7f3 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -14,7 +14,6 @@ use bootstrap::{ Build, CONFIG_CHANGE_HISTORY, Config, Flags, Subcommand, debug, find_recent_config_change_ids, human_readable_changes, t, }; -use build_helper::ci::CiEnv; #[cfg(feature = "tracing")] use tracing::instrument; @@ -70,21 +69,23 @@ fn main() { } // check_version warnings are not printed during setup, or during CI - let changelog_suggestion = - if matches!(config.cmd, Subcommand::Setup { .. }) || CiEnv::is_ci() || config.dry_run() { - None - } else { - check_version(&config) - }; + let changelog_suggestion = if matches!(config.cmd, Subcommand::Setup { .. }) + || config.is_running_on_ci + || config.dry_run() + { + None + } else { + check_version(&config) + }; - // NOTE: Since `./configure` generates a `config.toml`, distro maintainers will see the + // NOTE: Since `./configure` generates a `bootstrap.toml`, distro maintainers will see the // changelog warning, not the `x.py setup` message. let suggest_setup = config.config.is_none() && !matches!(config.cmd, Subcommand::Setup { .. }); if suggest_setup { - println!("WARNING: you have not made a `config.toml`"); + println!("WARNING: you have not made a `bootstrap.toml`"); println!( - "HELP: consider running `./x.py setup` or copying `config.example.toml` by running \ - `cp config.example.toml config.toml`" + "HELP: consider running `./x.py setup` or copying `bootstrap.example.toml` by running \ + `cp bootstrap.example.toml bootstrap.toml`" ); } else if let Some(suggestion) = &changelog_suggestion { println!("{suggestion}"); @@ -98,10 +99,10 @@ fn main() { Build::new(config).build(); if suggest_setup { - println!("WARNING: you have not made a `config.toml`"); + println!("WARNING: you have not made a `bootstrap.toml`"); println!( - "HELP: consider running `./x.py setup` or copying `config.example.toml` by running \ - `cp config.example.toml config.toml`" + "HELP: consider running `./x.py setup` or copying `bootstrap.example.toml` by running \ + `cp bootstrap.example.toml bootstrap.toml`" ); } else if let Some(suggestion) = &changelog_suggestion { println!("{suggestion}"); @@ -160,7 +161,7 @@ fn check_version(config: &Config) -> Option<String> { } // Always try to use `change-id` from .last-warned-change-id first. If it doesn't exist, - // then use the one from the config.toml. This way we never show the same warnings + // then use the one from the bootstrap.toml. This way we never show the same warnings // more than once. if let Ok(t) = fs::read_to_string(&warned_id_path) { let last_warned_id = usize::from_str(&t) @@ -185,16 +186,18 @@ fn check_version(config: &Config) -> Option<String> { msg.push_str("NOTE: to silence this warning, "); msg.push_str(&format!( - "update `config.toml` to use `change-id = {latest_change_id}` instead" + "update `bootstrap.toml` to use `change-id = {latest_change_id}` instead" )); if io::stdout().is_terminal() { t!(fs::write(warned_id_path, latest_change_id.to_string())); } } else { - msg.push_str("WARNING: The `change-id` is missing in the `config.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n"); + msg.push_str("WARNING: The `change-id` is missing in the `bootstrap.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n"); msg.push_str("NOTE: to silence this warning, "); - msg.push_str(&format!("add `change-id = {latest_change_id}` at the top of `config.toml`")); + msg.push_str(&format!( + "add `change-id = {latest_change_id}` at the top of `bootstrap.toml`" + )); }; Some(msg) diff --git a/src/bootstrap/src/bin/sccache-plus-cl.rs b/src/bootstrap/src/bin/sccache-plus-cl.rs deleted file mode 100644 index c161d69d5f7..00000000000 --- a/src/bootstrap/src/bin/sccache-plus-cl.rs +++ /dev/null @@ -1,43 +0,0 @@ -use std::env; -use std::process::{self, Command}; - -fn main() { - let target = env::var("SCCACHE_TARGET").unwrap(); - // Locate the actual compiler that we're invoking - - // SAFETY: we're in main, there are no other threads - unsafe { - env::set_var("CC", env::var_os("SCCACHE_CC").unwrap()); - env::set_var("CXX", env::var_os("SCCACHE_CXX").unwrap()); - } - - let mut cfg = cc::Build::new(); - cfg.cargo_metadata(false) - .out_dir("/") - .target(&target) - .host(&target) - .opt_level(0) - .warnings(false) - .debug(false); - let compiler = cfg.get_compiler(); - - // Invoke sccache with said compiler - let sccache_path = env::var_os("SCCACHE_PATH").unwrap(); - let mut cmd = Command::new(sccache_path); - cmd.arg(compiler.path()); - for (k, v) in compiler.env() { - cmd.env(k, v); - } - for arg in env::args().skip(1) { - cmd.arg(arg); - } - - if let Ok(s) = env::var("SCCACHE_EXTRA_ARGS") { - for s in s.split_whitespace() { - cmd.arg(s); - } - } - - let status = cmd.status().expect("failed to spawn"); - process::exit(status.code().unwrap_or(2)) -} diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 7c83c53d2c2..846b4de8142 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -425,7 +425,7 @@ fn copy_self_contained_objects( } else if target.contains("-wasi") { let srcdir = builder.wasi_libdir(target).unwrap_or_else(|| { panic!( - "Target {:?} does not have a \"wasi-root\" key in Config.toml \ + "Target {:?} does not have a \"wasi-root\" key in bootstrap.toml \ or `$WASI_SDK_PATH` set", target.triple ) @@ -1294,7 +1294,7 @@ pub fn rustc_cargo_env( .env("CFG_VERSION", builder.rust_version()); // Some tools like Cargo detect their own git information in build scripts. When omit-git-hash - // is enabled in config.toml, we pass this environment variable to tell build scripts to avoid + // is enabled in bootstrap.toml, we pass this environment variable to tell build scripts to avoid // detecting git information on their own. if builder.config.omit_git_hash { cargo.env("CFG_OMIT_GIT_HASH", "1"); @@ -1538,7 +1538,7 @@ fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool { { run.builder.info( "WARNING: no codegen-backends config matched the requested path to build a codegen backend. \ - HELP: add backend to codegen-backends in config.toml.", + HELP: add backend to codegen-backends in bootstrap.toml.", ); return true; } @@ -1550,7 +1550,7 @@ fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool { impl Step for CodegenBackend { type Output = (); const ONLY_HOSTS: bool = true; - /// Only the backends specified in the `codegen-backends` entry of `config.toml` are built. + /// Only the backends specified in the `codegen-backends` entry of `bootstrap.toml` are built. const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index c393eb55c62..39f9680cb2f 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -519,7 +519,7 @@ impl Step for Rustc { // The REUSE-managed license files let license = |path: &Path| { - builder.install(path, &image.join("share/doc/rust/licences"), 0o644); + builder.install(path, &image.join("share/doc/rust/licenses"), 0o644); }; for entry in t!(std::fs::read_dir(builder.src.join("LICENSES"))).flatten() { license(&entry.path()); @@ -1000,9 +1000,9 @@ impl Step for PlainSourceTarball { let src_files = [ // tidy-alphabetical-start ".gitmodules", + "bootstrap.example.toml", "Cargo.lock", "Cargo.toml", - "config.example.toml", "configure", "CONTRIBUTING.md", "COPYRIGHT", @@ -2378,7 +2378,7 @@ impl Step for Bootstrap { let tarball = Tarball::new(builder, "bootstrap", &target.triple); let bootstrap_outdir = &builder.bootstrap_out; - for file in &["bootstrap", "rustc", "rustdoc", "sccache-plus-cl"] { + for file in &["bootstrap", "rustc", "rustdoc"] { tarball.add_file(bootstrap_outdir.join(exe(file, target)), "bootstrap/bin", 0o755); } @@ -2481,7 +2481,7 @@ impl Step for Gcc { fn run(self, builder: &Builder<'_>) -> Self::Output { let tarball = Tarball::new(builder, "gcc", &self.target.triple); let output = builder.ensure(super::gcc::Gcc { target: self.target }); - tarball.add_file(output.libgccjit, ".", 0o644); + tarball.add_file(output.libgccjit, "lib", 0o644); tarball.generate() } } diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 8e913f68184..a8da4146100 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -1218,7 +1218,7 @@ impl Step for RustcBook { cmd.env("RUSTC_BOOTSTRAP", "1"); // If the lib directories are in an unusual location (changed in - // config.toml), then this needs to explicitly update the dylib search + // bootstrap.toml), then this needs to explicitly update the dylib search // path. builder.add_rustc_lib_path(self.compiler, &mut cmd); let doc_generator_guard = builder.msg( diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 9817e47baa1..7aa5cb2b6e5 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -6,7 +6,6 @@ use std::process::Command; use std::sync::Mutex; use std::sync::mpsc::SyncSender; -use build_helper::ci::CiEnv; use build_helper::git::get_git_modified_files; use ignore::WalkBuilder; @@ -94,7 +93,7 @@ fn get_modified_rs_files(build: &Builder<'_>) -> Result<Option<Vec<String>>, Str return Ok(None); } - get_git_modified_files(&build.config.git_config(), Some(&build.config.src), &["rs"]) + get_git_modified_files(&build.config.git_config(), Some(&build.config.src), &["rs"]).map(Some) } #[derive(serde_derive::Deserialize)] @@ -104,7 +103,7 @@ struct RustfmtConfig { // Prints output describing a collection of paths, with lines such as "formatted modified file // foo/bar/baz" or "skipped 20 untracked files". -fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) { +fn print_paths(build: &Builder<'_>, verb: &str, adjective: Option<&str>, paths: &[String]) { let len = paths.len(); let adjective = if let Some(adjective) = adjective { format!("{adjective} ") } else { String::new() }; @@ -115,7 +114,7 @@ fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) { } else { println!("fmt: {verb} {len} {adjective}files"); } - if len > 1000 && !CiEnv::is_ci() { + if len > 1000 && !build.config.is_running_on_ci { println!("hint: if this number seems too high, try running `git fetch origin master`"); } } @@ -135,7 +134,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { // `--all` is specified or we are in CI. We check all files in CI to avoid bugs in // `get_modified_rs_files` letting regressions slip through; we also care about CI time less // since this is still very fast compared to building the compiler. - let all = all || CiEnv::is_ci(); + let all = all || build.config.is_running_on_ci; let mut builder = ignore::types::TypesBuilder::new(); builder.add_defaults(); @@ -190,7 +189,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { ) .map(|x| x.to_string()) .collect(); - print_paths("skipped", Some("untracked"), &untracked_paths); + print_paths(build, "skipped", Some("untracked"), &untracked_paths); for untracked_path in untracked_paths { // The leading `/` makes it an exact match against the @@ -319,7 +318,7 @@ pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { }); let mut paths = formatted_paths.into_inner().unwrap(); paths.sort(); - print_paths(if check { "checked" } else { "formatted" }, adjective, &paths); + print_paths(build, if check { "checked" } else { "formatted" }, adjective, &paths); drop(tx); diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index 5a4bc9bdbcb..48bb5cb8e87 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -12,8 +12,6 @@ use std::fs; use std::path::{Path, PathBuf}; use std::sync::OnceLock; -use build_helper::ci::CiEnv; - use crate::core::builder::{Builder, Cargo, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; use crate::utils::build_stamp::{BuildStamp, generate_smart_stamp_hash}; @@ -63,11 +61,7 @@ impl Step for Gcc { } build_gcc(&metadata, builder, target); - - let lib_alias = metadata.install_dir.join("lib/libgccjit.so.0"); - if !lib_alias.exists() { - t!(builder.symlink_file(&libgccjit_path, lib_alias)); - } + create_lib_alias(builder, &libgccjit_path); t!(metadata.stamp.write()); @@ -75,6 +69,15 @@ impl Step for Gcc { } } +/// Creates a libgccjit.so.0 alias next to libgccjit.so if it does not +/// already exist +fn create_lib_alias(builder: &Builder<'_>, libgccjit: &PathBuf) { + let lib_alias = libgccjit.parent().unwrap().join("libgccjit.so.0"); + if !lib_alias.exists() { + t!(builder.symlink_file(libgccjit, lib_alias)); + } +} + pub struct Meta { stamp: BuildStamp, out_dir: PathBuf, @@ -109,8 +112,10 @@ fn try_download_gcc(builder: &Builder<'_>, target: TargetSelection) -> Option<Pa builder.config.download_ci_gcc(&sha, &root); t!(gcc_stamp.write()); } - // FIXME: put libgccjit.so into a lib directory in dist::Gcc - Some(root.join("libgccjit.so")) + + let libgccjit = root.join("lib").join("libgccjit.so"); + create_lib_alias(builder, &libgccjit); + Some(libgccjit) } #[cfg(test)] @@ -177,6 +182,14 @@ fn libgccjit_built_path(install_dir: &Path) -> PathBuf { } fn build_gcc(metadata: &Meta, builder: &Builder<'_>, target: TargetSelection) { + if builder.build.cc_tool(target).is_like_clang() + || builder.build.cxx_tool(target).is_like_clang() + { + panic!( + "Attempting to build GCC using Clang, which is known to misbehave. Please use GCC as the host C/C++ compiler. " + ); + } + let Meta { stamp: _, out_dir, install_dir, root } = metadata; t!(fs::create_dir_all(out_dir)); @@ -187,7 +200,7 @@ fn build_gcc(metadata: &Meta, builder: &Builder<'_>, target: TargetSelection) { // source directories as read-only on Linux. // Therefore, as a part of the build in CI, we first copy the whole source directory // to the build directory, and perform the build from there. - let src_dir = if CiEnv::is_ci() { + let src_dir = if builder.config.is_running_on_ci { let src_dir = builder.gcc_out(target).join("src"); if src_dir.exists() { builder.remove_dir(&src_dir); @@ -203,18 +216,13 @@ fn build_gcc(metadata: &Meta, builder: &Builder<'_>, target: TargetSelection) { let mut configure_cmd = command(src_dir.join("configure")); configure_cmd .current_dir(out_dir) - // On CI, we compile GCC with Clang. - // The -Wno-everything flag is needed to make GCC compile with Clang 19. - // `-g -O2` are the default flags that are otherwise used by Make. - // FIXME(kobzol): change the flags once we have [gcc] configuration in config.toml. - .env("CXXFLAGS", "-Wno-everything -g -O2") - .env("CFLAGS", "-Wno-everything -g -O2") .arg("--enable-host-shared") - .arg("--enable-languages=jit") + .arg("--enable-languages=c,jit,lto") .arg("--enable-checking=release") .arg("--disable-bootstrap") .arg("--disable-multilib") .arg(format!("--prefix={}", install_dir.display())); + let cc = builder.build.cc(target).display().to_string(); let cc = builder .build @@ -265,7 +273,7 @@ fn detect_gcc_sha(config: &crate::Config, is_git: bool) -> String { get_closest_merge_commit( Some(&config.src), &config.git_config(), - &[config.src.join("src/gcc"), config.src.join("src/bootstrap/download-ci-gcc-stamp")], + &["src/gcc", "src/bootstrap/download-ci-gcc-stamp"], ) .unwrap() } else if let Some(info) = crate::utils::channel::read_commit_info_file(&config.src) { diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs index 4f96d67a5bd..3e5069225d2 100644 --- a/src/bootstrap/src/core/build_steps/install.rs +++ b/src/bootstrap/src/core/build_steps/install.rs @@ -85,11 +85,11 @@ fn install_sh( } else { assert!( is_dir_writable_for_user(&prefix), - "User doesn't have write access on `install.prefix` path in the `config.toml`.", + "User doesn't have write access on `install.prefix` path in the `bootstrap.toml`.", ); assert!( is_dir_writable_for_user(&sysconfdir), - "User doesn't have write access on `install.sysconfdir` path in `config.toml`." + "User doesn't have write access on `install.sysconfdir` path in `bootstrap.toml`." ); } diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 40d701f22c1..9ae1825fae8 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -14,7 +14,6 @@ use std::path::{Path, PathBuf}; use std::sync::OnceLock; use std::{env, fs}; -use build_helper::ci::CiEnv; use build_helper::git::get_closest_merge_commit; #[cfg(feature = "tracing")] use tracing::instrument; @@ -174,20 +173,19 @@ pub fn prebuilt_llvm_config( LlvmBuildStatus::ShouldBuild(Meta { stamp, res, out_dir, root: root.into() }) } +/// Paths whose changes invalidate LLVM downloads. +pub const LLVM_INVALIDATION_PATHS: &[&str] = &[ + "src/llvm-project", + "src/bootstrap/download-ci-llvm-stamp", + // the LLVM shared object file is named `LLVM-<LLVM-version>-rust-{version}-nightly` + "src/version", +]; + /// This retrieves the LLVM sha we *want* to use, according to git history. pub(crate) fn detect_llvm_sha(config: &Config, is_git: bool) -> String { let llvm_sha = if is_git { - get_closest_merge_commit( - Some(&config.src), - &config.git_config(), - &[ - config.src.join("src/llvm-project"), - config.src.join("src/bootstrap/download-ci-llvm-stamp"), - // the LLVM shared object file is named `LLVM-12-rust-{version}-nightly` - config.src.join("src/version"), - ], - ) - .unwrap() + get_closest_merge_commit(Some(&config.src), &config.git_config(), LLVM_INVALIDATION_PATHS) + .unwrap() } else if let Some(info) = crate::utils::channel::read_commit_info_file(&config.src) { info.sha.trim().to_owned() } else { @@ -207,10 +205,9 @@ pub(crate) fn detect_llvm_sha(config: &Config, is_git: bool) -> String { /// Returns whether the CI-found LLVM is currently usable. /// -/// This checks both the build triple platform to confirm we're usable at all, -/// and then verifies if the current HEAD matches the detected LLVM SHA head, -/// in which case LLVM is indicated as not available. -pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool { +/// This checks the build triple platform to confirm we're usable at all, and if LLVM +/// with/without assertions is available. +pub(crate) fn is_ci_llvm_available_for_target(config: &Config, asserts: bool) -> bool { // This is currently all tier 1 targets and tier 2 targets with host tools // (since others may not have CI artifacts) // https://doc.rust-lang.org/rustc/platform-support.html#tier-1 @@ -255,41 +252,9 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool { return false; } - if is_ci_llvm_modified(config) { - eprintln!("Detected LLVM as non-available: running in CI and modified LLVM in this change"); - return false; - } - true } -/// Returns true if we're running in CI with modified LLVM (and thus can't download it) -pub(crate) fn is_ci_llvm_modified(config: &Config) -> bool { - // If not running in a CI environment, return false. - if !CiEnv::is_ci() { - return false; - } - - // In rust-lang/rust managed CI, assert the existence of the LLVM submodule. - if CiEnv::is_rust_lang_managed_ci_job() { - assert!( - config.in_tree_llvm_info.is_managed_git_subrepository(), - "LLVM submodule must be fetched in rust-lang/rust managed CI builders." - ); - } - // If LLVM submodule isn't present, skip the change check as it won't work. - else if !config.in_tree_llvm_info.is_managed_git_subrepository() { - return false; - } - - let llvm_sha = detect_llvm_sha(config, true); - let head_sha = crate::output( - helpers::git(Some(&config.src)).arg("rev-parse").arg("HEAD").as_command_mut(), - ); - let head_sha = head_sha.trim(); - llvm_sha == head_sha -} - #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Llvm { pub target: TargetSelection, @@ -350,7 +315,7 @@ impl Step for Llvm { (true, true) => "RelWithDebInfo", }; - // NOTE: remember to also update `config.example.toml` when changing the + // NOTE: remember to also update `bootstrap.example.toml` when changing the // defaults! let llvm_targets = match &builder.config.llvm_targets { Some(s) => s, @@ -471,11 +436,14 @@ impl Step for Llvm { cfg.define("LLVM_BUILD_32_BITS", "ON"); } + if target.starts_with("x86_64") && target.contains("ohos") { + cfg.define("LLVM_TOOL_LLVM_RTDYLD_BUILD", "OFF"); + } + let mut enabled_llvm_projects = Vec::new(); if helpers::forcing_clang_based_tests() { enabled_llvm_projects.push("clang"); - enabled_llvm_projects.push("compiler-rt"); } if builder.config.llvm_polly { @@ -498,6 +466,10 @@ impl Step for Llvm { let mut enabled_llvm_runtimes = Vec::new(); + if helpers::forcing_clang_based_tests() { + enabled_llvm_runtimes.push("compiler-rt"); + } + if builder.config.llvm_offload { enabled_llvm_runtimes.push("offload"); //FIXME(ZuseZ4): LLVM intends to drop the offload dependency on openmp. @@ -735,57 +707,17 @@ fn configure_cmake( None => (builder.cc(target), builder.cxx(target).unwrap()), }; - // Handle msvc + ninja + ccache specially (this is what the bots use) - if target.is_msvc() && builder.ninja() && builder.config.ccache.is_some() { - let mut wrap_cc = env::current_exe().expect("failed to get cwd"); - wrap_cc.set_file_name("sccache-plus-cl.exe"); - - cfg.define("CMAKE_C_COMPILER", sanitize_cc(&wrap_cc)) - .define("CMAKE_CXX_COMPILER", sanitize_cc(&wrap_cc)); - cfg.env("SCCACHE_PATH", builder.config.ccache.as_ref().unwrap()) - .env("SCCACHE_TARGET", target.triple) - .env("SCCACHE_CC", &cc) - .env("SCCACHE_CXX", &cxx); - - // Building LLVM on MSVC can be a little ludicrous at times. We're so far - // off the beaten path here that I'm not really sure this is even half - // supported any more. Here we're trying to: - // - // * Build LLVM on MSVC - // * Build LLVM with `clang-cl` instead of `cl.exe` - // * Build a project with `sccache` - // * Build for 32-bit as well - // * Build with Ninja - // - // For `cl.exe` there are different binaries to compile 32/64 bit which - // we use but for `clang-cl` there's only one which internally - // multiplexes via flags. As a result it appears that CMake's detection - // of a compiler's architecture and such on MSVC **doesn't** pass any - // custom flags we pass in CMAKE_CXX_FLAGS below. This means that if we - // use `clang-cl.exe` it's always diagnosed as a 64-bit compiler which - // definitely causes problems since all the env vars are pointing to - // 32-bit libraries. - // - // To hack around this... again... we pass an argument that's - // unconditionally passed in the sccache shim. This'll get CMake to - // correctly diagnose it's doing a 32-bit compilation and LLVM will - // internally configure itself appropriately. - if builder.config.llvm_clang_cl.is_some() && target.contains("i686") { - cfg.env("SCCACHE_EXTRA_ARGS", "-m32"); + // If ccache is configured we inform the build a little differently how + // to invoke ccache while also invoking our compilers. + if use_compiler_launcher { + if let Some(ref ccache) = builder.config.ccache { + cfg.define("CMAKE_C_COMPILER_LAUNCHER", ccache) + .define("CMAKE_CXX_COMPILER_LAUNCHER", ccache); } - } else { - // If ccache is configured we inform the build a little differently how - // to invoke ccache while also invoking our compilers. - if use_compiler_launcher { - if let Some(ref ccache) = builder.config.ccache { - cfg.define("CMAKE_C_COMPILER_LAUNCHER", ccache) - .define("CMAKE_CXX_COMPILER_LAUNCHER", ccache); - } - } - cfg.define("CMAKE_C_COMPILER", sanitize_cc(&cc)) - .define("CMAKE_CXX_COMPILER", sanitize_cc(&cxx)) - .define("CMAKE_ASM_COMPILER", sanitize_cc(&cc)); } + cfg.define("CMAKE_C_COMPILER", sanitize_cc(&cc)) + .define("CMAKE_CXX_COMPILER", sanitize_cc(&cxx)) + .define("CMAKE_ASM_COMPILER", sanitize_cc(&cc)); cfg.build_arg("-j").build_arg(builder.jobs().to_string()); // FIXME(madsmtm): Allow `cmake-rs` to select flags by itself by passing @@ -809,7 +741,9 @@ fn configure_cmake( cflags.push(" "); cflags.push(s); } - + if target.contains("ohos") { + cflags.push(" -D_LINUX_SYSINFO_H"); + } if builder.config.llvm_clang_cl.is_some() { cflags.push(format!(" --target={target}")); } @@ -830,6 +764,9 @@ fn configure_cmake( cxxflags.push(" "); cxxflags.push(s); } + if target.contains("ohos") { + cxxflags.push(" -D_LINUX_SYSINFO_H"); + } if builder.config.llvm_clang_cl.is_some() { cxxflags.push(format!(" --target={target}")); } @@ -1216,6 +1153,10 @@ impl Step for Sanitizers { cfg.define("COMPILER_RT_USE_LIBCXX", "OFF"); cfg.define("LLVM_CONFIG_PATH", &llvm_config); + if self.target.contains("ohos") { + cfg.define("COMPILER_RT_USE_BUILTINS_LIBRARY", "ON"); + } + // On Darwin targets the sanitizer runtimes are build as universal binaries. // Unfortunately sccache currently lacks support to build them successfully. // Disable compiler launcher on Darwin targets to avoid potential issues. diff --git a/src/bootstrap/src/core/build_steps/perf.rs b/src/bootstrap/src/core/build_steps/perf.rs index 6962001fdc2..7f4e88bd73c 100644 --- a/src/bootstrap/src/core/build_steps/perf.rs +++ b/src/bootstrap/src/core/build_steps/perf.rs @@ -147,7 +147,7 @@ pub fn perf(builder: &Builder<'_>, args: &PerfArgs) { }; if is_profiling && builder.build.config.rust_debuginfo_level_rustc == DebuginfoLevel::None { builder.info(r#"WARNING: You are compiling rustc without debuginfo, this will make profiling less useful. -Consider setting `rust.debuginfo-level = 1` in `config.toml`."#); +Consider setting `rust.debuginfo-level = 1` in `bootstrap.toml`."#); } let compiler = builder.compiler(builder.top_stage, builder.config.build); diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs index 1ef86e674f0..5cacd5b9914 100644 --- a/src/bootstrap/src/core/build_steps/run.rs +++ b/src/bootstrap/src/core/build_steps/run.rs @@ -35,10 +35,10 @@ impl Step for BuildManifest { // (https://github.com/rust-lang/promote-release). let mut cmd = builder.tool_cmd(Tool::BuildManifest); let sign = builder.config.dist_sign_folder.as_ref().unwrap_or_else(|| { - panic!("\n\nfailed to specify `dist.sign-folder` in `config.toml`\n\n") + panic!("\n\nfailed to specify `dist.sign-folder` in `bootstrap.toml`\n\n") }); let addr = builder.config.dist_upload_addr.as_ref().unwrap_or_else(|| { - panic!("\n\nfailed to specify `dist.upload-addr` in `config.toml`\n\n") + panic!("\n\nfailed to specify `dist.upload-addr` in `bootstrap.toml`\n\n") }); let today = command("date").arg("+%Y-%m-%d").run_capture_stdout(builder).stdout(); diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index 45f9f52cb82..80d92135dd3 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -2,8 +2,8 @@ //! //! These are build-and-run steps for `./x.py setup`, which allows quickly setting up the directory //! for modifying, building, and running the compiler and library. Running arbitrary configuration -//! allows setting up things that cannot be simply captured inside the config.toml, in addition to -//! leading people away from manually editing most of the config.toml values. +//! allows setting up things that cannot be simply captured inside the bootstrap.toml, in addition to +//! leading people away from manually editing most of the bootstrap.toml values. use std::env::consts::EXE_SUFFIX; use std::fmt::Write as _; @@ -37,7 +37,7 @@ static PROFILE_DIR: &str = "src/bootstrap/defaults"; impl Profile { fn include_path(&self, src_path: &Path) -> PathBuf { - PathBuf::from(format!("{}/{PROFILE_DIR}/config.{}.toml", src_path.display(), self)) + PathBuf::from(format!("{}/{PROFILE_DIR}/bootstrap.{}.toml", src_path.display(), self)) } pub fn all() -> impl Iterator<Item = Self> { @@ -53,7 +53,7 @@ impl Profile { Compiler => "Contribute to the compiler itself", Tools => "Contribute to tools which depend on the compiler, but do not modify it directly (e.g. rustdoc, clippy, miri)", Dist => "Install Rust from source", - None => "Do not modify `config.toml`" + None => "Do not modify `bootstrap.toml`" } .to_string() } @@ -117,7 +117,7 @@ impl Step for Profile { return; } - let path = &run.builder.config.config.clone().unwrap_or(PathBuf::from("config.toml")); + let path = &run.builder.config.config.clone().unwrap_or(PathBuf::from("bootstrap.toml")); if path.exists() { eprintln!(); eprintln!( @@ -203,7 +203,7 @@ pub fn setup(config: &Config, profile: Profile) { ) } - let path = &config.config.clone().unwrap_or(PathBuf::from("config.toml")); + let path = &config.config.clone().unwrap_or(PathBuf::from("bootstrap.toml")); setup_config_toml(path, profile, config); } @@ -214,8 +214,9 @@ fn setup_config_toml(path: &Path, profile: Profile, config: &Config) { let latest_change_id = CONFIG_CHANGE_HISTORY.last().unwrap().change_id; let settings = format!( - "# Includes one of the default files in {PROFILE_DIR}\n\ - profile = \"{profile}\"\n\ + "# See bootstrap.example.toml for documentation of available options\n\ + #\n\ + profile = \"{profile}\" # Includes one of the default files in {PROFILE_DIR}\n\ change-id = {latest_change_id}\n" ); diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index cff286e99fa..81f6b473c45 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1119,7 +1119,7 @@ impl Step for Tidy { "\ ERROR: no `rustfmt` binary found in {PATH} INFO: `rust.channel` is currently set to \"{CHAN}\" -HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `config.toml` file +HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `bootstrap.toml` file HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`", PATH = inferred_rustfmt_dir.display(), CHAN = builder.config.channel, diff --git a/src/bootstrap/src/core/build_steps/toolstate.rs b/src/bootstrap/src/core/build_steps/toolstate.rs index a65623de95a..fc7acd1fa14 100644 --- a/src/bootstrap/src/core/build_steps/toolstate.rs +++ b/src/bootstrap/src/core/build_steps/toolstate.rs @@ -128,7 +128,7 @@ impl Step for ToolStateCheck { /// Checks tool state status. /// /// This is intended to be used in the `checktools.sh` script. To use - /// this, set `save-toolstates` in `config.toml` so that tool status will + /// this, set `save-toolstates` in `bootstrap.toml` so that tool status will /// be saved to a JSON file. Then, run `x.py test --no-fail-fast` for all /// of the tools to populate the JSON file. After that is done, this /// command can be run to check for any status failures, and exits with an @@ -254,7 +254,7 @@ impl Builder<'_> { /// Updates the actual toolstate of a tool. /// /// The toolstates are saved to the file specified by the key - /// `rust.save-toolstates` in `config.toml`. If unspecified, nothing will be + /// `rust.save-toolstates` in `bootstrap.toml`. If unspecified, nothing will be /// done. The file is updated immediately after this function completes. pub fn save_toolstate(&self, tool: &str, state: ToolState) { use std::io::Write; diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 62d23c4ae6b..a96ccdd12c2 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -215,7 +215,7 @@ impl Cargo { // dynamic libraries. We use this by default on Unix platforms to ensure // that our nightlies behave the same on Windows, that is they work out // of the box. This can be disabled by setting `rpath = false` in `[rust]` - // table of `config.toml` + // table of `bootstrap.toml` // // Ok, so the astute might be wondering "why isn't `-C rpath` used // here?" and that is indeed a good question to ask. This codegen @@ -1073,6 +1073,7 @@ impl Builder<'_> { lint_flags.push("-Wkeyword_idents_2024"); lint_flags.push("-Wunreachable_pub"); lint_flags.push("-Wunsafe_op_in_unsafe_fn"); + lint_flags.push("-Wunused_crate_dependencies"); } // This does not use RUSTFLAGS for two reasons. diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 0b6b8513cc3..a9058f888d3 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -31,9 +31,9 @@ mod cargo; mod tests; /// Builds and performs different [`Self::kind`]s of stuff and actions, taking -/// into account build configuration from e.g. config.toml. +/// into account build configuration from e.g. bootstrap.toml. pub struct Builder<'a> { - /// Build configuration from e.g. config.toml. + /// Build configuration from e.g. bootstrap.toml. pub build: &'a Build, /// The stage to use. Either implicitly determined based on subcommand, or @@ -332,7 +332,7 @@ impl PathSet { } const PATH_REMAP: &[(&str, &[&str])] = &[ - // config.toml uses `rust-analyzer-proc-macro-srv`, but the + // bootstrap.toml uses `rust-analyzer-proc-macro-srv`, but the // actual path is `proc-macro-srv-cli` ("rust-analyzer-proc-macro-srv", &["src/tools/rust-analyzer/crates/proc-macro-srv-cli"]), // Make `x test tests` function the same as `x t tests/*` diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index b062781e68a..fd3b28e4e6a 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -264,7 +264,7 @@ fn ci_rustc_if_unchanged_logic() { let mut paths = vec!["compiler"]; // Handle library tree the same way as in `Config::download_ci_rustc_commit`. - if build_helper::ci::CiEnv::is_ci() { + if builder.config.is_running_on_ci { paths.push("library"); } @@ -1074,7 +1074,7 @@ fn test_prebuilt_llvm_config_path_resolution() { let config = configure( r#" [llvm] - download-ci-llvm = true + download-ci-llvm = "if-unchanged" "#, ); diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index a07c40bdc83..cf4ef4ee310 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1,6 +1,6 @@ //! Serialized configuration of a build. //! -//! This module implements parsing `config.toml` configuration files to tweak +//! This module implements parsing `bootstrap.toml` configuration files to tweak //! how the build runs. use std::cell::{Cell, RefCell}; @@ -23,6 +23,7 @@ use tracing::{instrument, span}; use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX; use crate::core::build_steps::llvm; +use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS; pub use crate::core::config::flags::Subcommand; use crate::core::config::flags::{Color, Flags, Warnings}; use crate::core::download::is_download_ci_available; @@ -64,7 +65,7 @@ macro_rules! check_ci_llvm { /// useful in scenarios where developers want to see how the tarball sources were /// generated. /// -/// We also use this file to compare the host's config.toml against the CI rustc builder +/// We also use this file to compare the host's bootstrap.toml against the CI rustc builder /// configuration to detect any incompatible options. pub(crate) const BUILDER_CONFIG_FILENAME: &str = "builder-config"; @@ -184,12 +185,12 @@ pub enum GccCiMode { /// Global configuration for the entire build and/or bootstrap. /// -/// This structure is parsed from `config.toml`, and some of the fields are inferred from `git` or build-time parameters. +/// This structure is parsed from `bootstrap.toml`, and some of the fields are inferred from `git` or build-time parameters. /// /// Note that this structure is not decoded directly into, but rather it is /// filled out from the decoded forms of the structs below. For documentation /// each field, see the corresponding fields in -/// `config.example.toml`. +/// `bootstrap.example.toml`. #[derive(Default, Clone)] pub struct Config { pub change_id: Option<usize>, @@ -235,7 +236,7 @@ pub struct Config { pub keep_stage: Vec<u32>, pub keep_stage_std: Vec<u32>, pub src: PathBuf, - /// defaults to `config.toml` + /// defaults to `bootstrap.toml` pub config: Option<PathBuf>, pub jobs: Option<u32>, pub cmd: Subcommand, @@ -415,6 +416,8 @@ pub struct Config { /// Command for visual diff display, e.g. `diff-tool --color=always`. pub compiletest_diff_tool: Option<String>, + + pub is_running_on_ci: bool, } #[derive(Clone, Debug, Default)] @@ -470,7 +473,7 @@ impl std::str::FromStr for SplitDebuginfo { impl SplitDebuginfo { /// Returns the default `-Csplit-debuginfo` value for the current target. See the comment for - /// `rust.split-debuginfo` in `config.example.toml`. + /// `rust.split-debuginfo` in `bootstrap.example.toml`. fn default_for_platform(target: TargetSelection) -> Self { if target.contains("apple") { SplitDebuginfo::Unpacked @@ -677,7 +680,7 @@ impl Target { target } } -/// Structure of the `config.toml` file that configuration is read from. +/// Structure of the `bootstrap.toml` file that configuration is read from. /// /// This structure uses `Decodable` to automatically decode a TOML configuration /// file into this format, and then this is traversed and written into the above @@ -959,6 +962,7 @@ define_config! { jobs: Option<u32> = "jobs", compiletest_diff_tool: Option<String> = "compiletest-diff-tool", ccache: Option<StringOrBool> = "ccache", + exclude: Option<Vec<PathBuf>> = "exclude", } } @@ -1397,22 +1401,6 @@ impl Config { "flags.exclude" = ?flags.exclude ); - config.skip = flags - .skip - .into_iter() - .chain(flags.exclude) - .map(|p| { - // Never return top-level path here as it would break `--skip` - // logic on rustc's internal test framework which is utilized - // by compiletest. - if cfg!(windows) { - PathBuf::from(p.to_str().unwrap().replace('/', "\\")) - } else { - p - } - }) - .collect(); - #[cfg(feature = "tracing")] span!( target: "CONFIG_HANDLING", @@ -1437,55 +1425,60 @@ impl Config { config.llvm_profile_generate = flags.llvm_profile_generate; config.enable_bolt_settings = flags.enable_bolt_settings; config.bypass_bootstrap_lock = flags.bypass_bootstrap_lock; + config.is_running_on_ci = flags.ci.unwrap_or(CiEnv::is_ci()); // Infer the rest of the configuration. - // Infer the source directory. This is non-trivial because we want to support a downloaded bootstrap binary, - // running on a completely different machine from where it was compiled. - let mut cmd = helpers::git(None); - // NOTE: we cannot support running from outside the repository because the only other path we have available - // is set at compile time, which can be wrong if bootstrap was downloaded rather than compiled locally. - // We still support running outside the repository if we find we aren't in a git directory. - - // NOTE: We get a relative path from git to work around an issue on MSYS/mingw. If we used an absolute path, - // and end up using MSYS's git rather than git-for-windows, we would get a unix-y MSYS path. But as bootstrap - // has already been (kinda-cross-)compiled to Windows land, we require a normal Windows path. - cmd.arg("rev-parse").arg("--show-cdup"); - // Discard stderr because we expect this to fail when building from a tarball. - let output = cmd - .as_command_mut() - .stderr(std::process::Stdio::null()) - .output() - .ok() - .and_then(|output| if output.status.success() { Some(output) } else { None }); - if let Some(output) = output { - let git_root_relative = String::from_utf8(output.stdout).unwrap(); - // We need to canonicalize this path to make sure it uses backslashes instead of forward slashes, - // and to resolve any relative components. - let git_root = env::current_dir() - .unwrap() - .join(PathBuf::from(git_root_relative.trim())) - .canonicalize() - .unwrap(); - let s = git_root.to_str().unwrap(); - - // Bootstrap is quite bad at handling /? in front of paths - let git_root = match s.strip_prefix("\\\\?\\") { - Some(p) => PathBuf::from(p), - None => git_root, - }; - // If this doesn't have at least `stage0`, we guessed wrong. This can happen when, - // for example, the build directory is inside of another unrelated git directory. - // In that case keep the original `CARGO_MANIFEST_DIR` handling. - // - // NOTE: this implies that downloadable bootstrap isn't supported when the build directory is outside - // the source directory. We could fix that by setting a variable from all three of python, ./x, and x.ps1. - if git_root.join("src").join("stage0").exists() { - config.src = git_root; - } + if let Some(src) = flags.src { + config.src = src } else { - // We're building from a tarball, not git sources. - // We don't support pre-downloaded bootstrap in this case. + // Infer the source directory. This is non-trivial because we want to support a downloaded bootstrap binary, + // running on a completely different machine from where it was compiled. + let mut cmd = helpers::git(None); + // NOTE: we cannot support running from outside the repository because the only other path we have available + // is set at compile time, which can be wrong if bootstrap was downloaded rather than compiled locally. + // We still support running outside the repository if we find we aren't in a git directory. + + // NOTE: We get a relative path from git to work around an issue on MSYS/mingw. If we used an absolute path, + // and end up using MSYS's git rather than git-for-windows, we would get a unix-y MSYS path. But as bootstrap + // has already been (kinda-cross-)compiled to Windows land, we require a normal Windows path. + cmd.arg("rev-parse").arg("--show-cdup"); + // Discard stderr because we expect this to fail when building from a tarball. + let output = cmd + .as_command_mut() + .stderr(std::process::Stdio::null()) + .output() + .ok() + .and_then(|output| if output.status.success() { Some(output) } else { None }); + if let Some(output) = output { + let git_root_relative = String::from_utf8(output.stdout).unwrap(); + // We need to canonicalize this path to make sure it uses backslashes instead of forward slashes, + // and to resolve any relative components. + let git_root = env::current_dir() + .unwrap() + .join(PathBuf::from(git_root_relative.trim())) + .canonicalize() + .unwrap(); + let s = git_root.to_str().unwrap(); + + // Bootstrap is quite bad at handling /? in front of paths + let git_root = match s.strip_prefix("\\\\?\\") { + Some(p) => PathBuf::from(p), + None => git_root, + }; + // If this doesn't have at least `stage0`, we guessed wrong. This can happen when, + // for example, the build directory is inside of another unrelated git directory. + // In that case keep the original `CARGO_MANIFEST_DIR` handling. + // + // NOTE: this implies that downloadable bootstrap isn't supported when the build directory is outside + // the source directory. We could fix that by setting a variable from all three of python, ./x, and x.ps1. + if git_root.join("src").join("stage0").exists() { + config.src = git_root; + } + } else { + // We're building from a tarball, not git sources. + // We don't support pre-downloaded bootstrap in this case. + } } if cfg!(test) { @@ -1500,26 +1493,35 @@ impl Config { config.stage0_metadata = build_helper::stage0_parser::parse_stage0_file(); - // Find configuration file, with the following cascading fallback (first match wins): - // - `--config <path>` - // - `RUST_BOOTSTRAP_CONFIG` - // - `./config.toml` - // - `config.toml` in the root directory. + // Locate the configuration file using the following priority (first match wins): + // 1. `--config <path>` (explicit flag) + // 2. `RUST_BOOTSTRAP_CONFIG` environment variable + // 3. `./bootstrap.toml` (local file) + // 4. `<root>/bootstrap.toml` + // 5. `./config.toml` (fallback for backward compatibility) + // 6. `<root>/config.toml` let toml_path = flags .config .clone() .or_else(|| env::var_os("RUST_BOOTSTRAP_CONFIG").map(PathBuf::from)); let using_default_path = toml_path.is_none(); - let mut toml_path = toml_path.unwrap_or_else(|| PathBuf::from("config.toml")); + let mut toml_path = toml_path.unwrap_or_else(|| PathBuf::from("bootstrap.toml")); + if using_default_path && !toml_path.exists() { - toml_path = config.src.join(toml_path); + toml_path = config.src.join(PathBuf::from("bootstrap.toml")); + if !toml_path.exists() { + toml_path = PathBuf::from("config.toml"); + if !toml_path.exists() { + toml_path = config.src.join(PathBuf::from("config.toml")); + } + } } let file_content = t!(fs::read_to_string(config.src.join("src/ci/channel"))); let ci_channel = file_content.trim_end(); // Give a hard error if `--config` or `RUST_BOOTSTRAP_CONFIG` are set to a missing path, - // but not if `config.toml` hasn't been created. + // but not if `bootstrap.toml` hasn't been created. let mut toml = if !using_default_path || toml_path.exists() { config.config = Some(if cfg!(not(test)) { toml_path.canonicalize().unwrap() @@ -1540,7 +1542,7 @@ impl Config { // same ones used to call the tests (if custom ones are not defined in the toml). If we // don't do that, bootstrap will use its own detection logic to find a suitable rustc // and Cargo, which doesn't work when the caller is specìfying a custom local rustc or - // Cargo in their config.toml. + // Cargo in their bootstrap.toml. let build = toml.build.get_or_insert_with(Default::default); build.rustc = build.rustc.take().or(std::env::var_os("RUSTC").map(|p| p.into())); build.cargo = build.cargo.take().or(std::env::var_os("CARGO").map(|p| p.into())); @@ -1563,7 +1565,7 @@ impl Config { include_path.push("src"); include_path.push("bootstrap"); include_path.push("defaults"); - include_path.push(format!("config.{include}.toml")); + include_path.push(format!("bootstrap.{include}.toml")); let included_toml = get_toml(&include_path).unwrap_or_else(|e| { eprintln!( "ERROR: Failed to parse default config profile at '{}': {e}", @@ -1658,8 +1660,29 @@ impl Config { jobs, compiletest_diff_tool, mut ccache, + exclude, } = toml.build.unwrap_or_default(); + let mut paths: Vec<PathBuf> = flags.skip.into_iter().chain(flags.exclude).collect(); + + if let Some(exclude) = exclude { + paths.extend(exclude); + } + + config.skip = paths + .into_iter() + .map(|p| { + // Never return top-level path here as it would break `--skip` + // logic on rustc's internal test framework which is utilized + // by compiletest. + if cfg!(windows) { + PathBuf::from(p.to_str().unwrap().replace('/', "\\")) + } else { + p + } + }) + .collect(); + config.jobs = Some(threads_from_config(flags.jobs.unwrap_or(jobs.unwrap_or(0)))); if let Some(file_build) = build { @@ -2024,7 +2047,7 @@ impl Config { config.description = description; // We need to override `rust.channel` if it's manually specified when using the CI rustc. - // This is because if the compiler uses a different channel than the one specified in config.toml, + // This is because if the compiler uses a different channel than the one specified in bootstrap.toml, // tests may fail due to using a different channel than the one used by the compiler during tests. if let Some(commit) = &config.download_rustc_commit { if is_user_configured_rust_channel { @@ -2410,7 +2433,7 @@ impl Config { // CI should always run stage 2 builds, unless it specifically states otherwise #[cfg(not(test))] - if flags.stage.is_none() && build_helper::ci::CiEnv::is_ci() { + if flags.stage.is_none() && config.is_running_on_ci { match config.cmd { Subcommand::Test { .. } | Subcommand::Miri { .. } @@ -2632,7 +2655,7 @@ impl Config { if !self.llvm_from_ci { // This happens when LLVM submodule is updated in CI, we should disable ci-rustc without an error // to not break CI. For non-CI environments, we should return an error. - if CiEnv::is_ci() { + if self.is_running_on_ci { println!("WARNING: LLVM submodule has changes, `download-rustc` will be disabled."); return None; } else { @@ -2649,7 +2672,7 @@ impl Config { return None; }, Err(e) => { - eprintln!("ERROR: Failed to parse CI rustc config.toml: {e}"); + eprintln!("ERROR: Failed to parse CI rustc bootstrap.toml: {e}"); exit!(2); }, }; @@ -2812,7 +2835,7 @@ impl Config { /// /// `relative_path` should be relative to the root of the git repository, not an absolute path. /// - /// This *does not* update the submodule if `config.toml` explicitly says + /// This *does not* update the submodule if `bootstrap.toml` explicitly says /// not to, or if we're not in a git repository (like a plain source /// tarball). Typically [`crate::Build::require_submodule`] should be /// used instead to provide a nice error to the user if the submodule is @@ -3021,7 +3044,7 @@ impl Config { // // If you update "library" logic here, update `builder::tests::ci_rustc_if_unchanged_logic` test // logic accordingly. - if !CiEnv::is_ci() { + if !self.is_running_on_ci { allowed_paths.push(":!library"); } @@ -3036,7 +3059,9 @@ impl Config { } println!("ERROR: could not find commit hash for downloading rustc"); println!("HELP: maybe your repository history is too shallow?"); - println!("HELP: consider setting `rust.download-rustc=false` in config.toml"); + println!( + "HELP: consider setting `rust.download-rustc=false` in bootstrap.toml" + ); println!("HELP: or fetch enough history to include one upstream commit"); crate::exit!(1); } @@ -3047,7 +3072,7 @@ impl Config { .expect("git-commit-info is missing in the project root") }; - if CiEnv::is_ci() && { + if self.is_running_on_ci && { let head_sha = output(helpers::git(Some(&self.src)).arg("rev-parse").arg("HEAD").as_command_mut()); let head_sha = head_sha.trim(); @@ -3076,7 +3101,14 @@ impl Config { download_ci_llvm: Option<StringOrBool>, asserts: bool, ) -> bool { - let download_ci_llvm = download_ci_llvm.unwrap_or(StringOrBool::Bool(true)); + // We don't ever want to use `true` on CI, as we should not + // download upstream artifacts if there are any local modifications. + let default = if self.is_running_on_ci { + StringOrBool::String("if-unchanged".to_string()) + } else { + StringOrBool::Bool(true) + }; + let download_ci_llvm = download_ci_llvm.unwrap_or(default); let if_unchanged = || { if self.rust_info.is_from_tarball() { @@ -3089,13 +3121,13 @@ impl Config { #[cfg(not(test))] self.update_submodule("src/llvm-project"); - // Check for untracked changes in `src/llvm-project`. + // Check for untracked changes in `src/llvm-project` and other important places. let has_changes = self - .last_modified_commit(&["src/llvm-project"], "download-ci-llvm", true) + .last_modified_commit(LLVM_INVALIDATION_PATHS, "download-ci-llvm", true) .is_none(); // Return false if there are untracked changes, otherwise check if CI LLVM is available. - if has_changes { false } else { llvm::is_ci_llvm_available(self, asserts) } + if has_changes { false } else { llvm::is_ci_llvm_available_for_target(self, asserts) } }; match download_ci_llvm { @@ -3106,8 +3138,15 @@ impl Config { ); } + if b && self.is_running_on_ci { + // On CI, we must always rebuild LLVM if there were any modifications to it + panic!( + "`llvm.download-ci-llvm` cannot be set to `true` on CI. Use `if-unchanged` instead." + ); + } + // If download-ci-llvm=true we also want to check that CI llvm is available - b && llvm::is_ci_llvm_available(self, asserts) + b && llvm::is_ci_llvm_available_for_target(self, asserts) } StringOrBool::String(s) if s == "if-unchanged" => if_unchanged(), StringOrBool::String(other) => { diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index 3bb62bbe380..08bd87e03a1 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -54,7 +54,7 @@ pub struct Flags { /// TOML configuration file for build pub config: Option<PathBuf>, #[arg(global = true, long, value_hint = clap::ValueHint::DirPath, value_name = "DIR")] - /// Build directory, overrides `build.build-dir` in `config.toml` + /// Build directory, overrides `build.build-dir` in `bootstrap.toml` pub build_dir: Option<PathBuf>, #[arg(global = true, long, value_hint = clap::ValueHint::Other, value_name = "BUILD")] @@ -173,12 +173,15 @@ pub struct Flags { #[arg(global = true)] /// paths for the subcommand pub paths: Vec<PathBuf>, - /// override options in config.toml + /// override options in bootstrap.toml #[arg(global = true, value_hint = clap::ValueHint::Other, long, value_name = "section.option=value")] pub set: Vec<String>, /// arguments passed to subcommands #[arg(global = true, last(true), value_name = "ARGS")] pub free_args: Vec<String>, + /// Make bootstrap to behave as it's running on the CI environment or not. + #[arg(global = true, long, value_name = "bool")] + pub ci: Option<bool>, } impl Flags { @@ -448,7 +451,7 @@ pub enum Subcommand { /// Set up the environment for development #[command(long_about = format!( "\n -x.py setup creates a `config.toml` which changes the defaults for x.py itself, +x.py setup creates a `bootstrap.toml` which changes the defaults for x.py itself, as well as setting up a git pre-push hook, VS Code config and toolchain link. Arguments: This subcommand accepts a 'profile' to use for builds. For example: @@ -461,7 +464,7 @@ Arguments: ./x.py setup editor ./x.py setup link", Profile::all_for_help(" ").trim_end()))] Setup { - /// Either the profile for `config.toml` or another setup action. + /// Either the profile for `bootstrap.toml` or another setup action. /// May be omitted to set up interactively #[arg(value_name = "<PROFILE>|hook|editor|link")] profile: Option<PathBuf>, diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index eff5e033742..068e237c2cd 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -4,6 +4,7 @@ use std::fs::{File, remove_file}; use std::io::Write; use std::path::Path; +use build_helper::ci::CiEnv; use clap::CommandFactory; use serde::Deserialize; @@ -11,6 +12,7 @@ use super::flags::Flags; use super::{ChangeIdWrapper, Config, RUSTC_IF_UNCHANGED_ALLOWED_PATHS}; use crate::core::build_steps::clippy::{LintConfig, get_clippy_rules_in_order}; use crate::core::build_steps::llvm; +use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS; use crate::core::config::{LldMode, Target, TargetSelection, TomlConfig}; pub(crate) fn parse(config: &str) -> Config { @@ -23,13 +25,21 @@ pub(crate) fn parse(config: &str) -> Config { #[test] fn download_ci_llvm() { let config = parse(""); - let is_available = llvm::is_ci_llvm_available(&config, config.llvm_assertions); + let is_available = llvm::is_ci_llvm_available_for_target(&config, config.llvm_assertions); if is_available { assert!(config.llvm_from_ci); } - let config = parse("llvm.download-ci-llvm = true"); - let is_available = llvm::is_ci_llvm_available(&config, config.llvm_assertions); + let config = Config::parse_inner( + Flags::parse(&[ + "check".to_string(), + "--config=/does/not/exist".to_string(), + "--ci".to_string(), + "false".to_string(), + ]), + |&_| toml::from_str("llvm.download-ci-llvm = true"), + ); + let is_available = llvm::is_ci_llvm_available_for_target(&config, config.llvm_assertions); if is_available { assert!(config.llvm_from_ci); } @@ -40,7 +50,7 @@ fn download_ci_llvm() { let if_unchanged_config = parse("llvm.download-ci-llvm = \"if-unchanged\""); if if_unchanged_config.llvm_from_ci { let has_changes = if_unchanged_config - .last_modified_commit(&["src/llvm-project"], "download-ci-llvm", true) + .last_modified_commit(LLVM_INVALIDATION_PATHS, "download-ci-llvm", true) .is_none(); assert!( @@ -69,7 +79,7 @@ fn detect_src_and_out() { let expected_src = manifest_dir.ancestors().nth(2).unwrap(); assert_eq!(&cfg.src, expected_src); - // test if build-dir was manually given in config.toml + // test if build-dir was manually given in bootstrap.toml if let Some(custom_build_dir) = build_dir { assert_eq!(&cfg.out, Path::new(custom_build_dir)); } @@ -229,13 +239,15 @@ fn override_toml_duplicate() { #[test] fn profile_user_dist() { fn get_toml(file: &Path) -> Result<TomlConfig, toml::de::Error> { - let contents = - if file.ends_with("config.toml") || env::var_os("RUST_BOOTSTRAP_CONFIG").is_some() { - "profile = \"user\"".to_owned() - } else { - assert!(file.ends_with("config.dist.toml")); - std::fs::read_to_string(file).unwrap() - }; + let contents = if file.ends_with("bootstrap.toml") + || file.ends_with("config.toml") + || env::var_os("RUST_BOOTSTRAP_CONFIG").is_some() + { + "profile = \"user\"".to_owned() + } else { + assert!(file.ends_with("config.dist.toml") || file.ends_with("bootstrap.dist.toml")); + std::fs::read_to_string(file).unwrap() + }; toml::from_str(&contents).and_then(|table: toml::Value| TomlConfig::deserialize(table)) } @@ -402,7 +414,7 @@ fn jobs_precedence() { ); assert_eq!(config.jobs, Some(67890)); - // `--set build.jobs` should take precedence over `config.toml`. + // `--set build.jobs` should take precedence over `bootstrap.toml`. let config = Config::parse_inner( Flags::parse(&[ "check".to_owned(), @@ -420,7 +432,7 @@ fn jobs_precedence() { ); assert_eq!(config.jobs, Some(12345)); - // `--jobs` > `--set build.jobs` > `config.toml` + // `--jobs` > `--set build.jobs` > `bootstrap.toml` let config = Config::parse_inner( Flags::parse(&[ "check".to_owned(), @@ -515,3 +527,34 @@ fn test_explicit_stage() { assert!(!config.explicit_stage_from_config); assert!(!config.is_explicit_stage()); } + +#[test] +fn test_exclude() { + let exclude_path = "compiler"; + let config = parse(&format!("build.exclude=[\"{}\"]", exclude_path)); + + let first_excluded = config + .skip + .first() + .expect("Expected at least one excluded path") + .to_str() + .expect("Failed to convert excluded path to string"); + + assert_eq!(first_excluded, exclude_path); +} + +#[test] +fn test_ci_flag() { + let config = Config::parse_inner(Flags::parse(&["check".into(), "--ci=false".into()]), |&_| { + toml::from_str("") + }); + assert!(!config.is_running_on_ci); + + let config = Config::parse_inner(Flags::parse(&["check".into(), "--ci=true".into()]), |&_| { + toml::from_str("") + }); + assert!(config.is_running_on_ci); + + let config = Config::parse_inner(Flags::parse(&["check".into()]), |&_| toml::from_str("")); + assert_eq!(config.is_running_on_ci, CiEnv::is_ci()); +} diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 98eff664a5b..5bd947f6e63 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -6,7 +6,6 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::sync::OnceLock; -use build_helper::ci::CiEnv; use xz2::bufread::XzDecoder; use crate::core::config::BUILDER_CONFIG_FILENAME; @@ -124,7 +123,7 @@ impl Config { if let Ok(in_nix_shell) = in_nix_shell { eprintln!( "The IN_NIX_SHELL environment variable is `{in_nix_shell}`; \ - you may need to set `patch-binaries-for-nix=true` in config.toml" + you may need to set `patch-binaries-for-nix=true` in bootstrap.toml" ); } } @@ -262,7 +261,7 @@ impl Config { "--fail", ]); // Don't print progress in CI; the \r wrapping looks bad and downloads don't take long enough for progress to be useful. - if CiEnv::is_ci() { + if self.is_running_on_ci { curl.arg("--silent"); } else { curl.arg("--progress-bar"); @@ -699,7 +698,7 @@ impl Config { help_on_error = "ERROR: failed to download pre-built rustc from CI NOTE: old builds get deleted after a certain time -HELP: if trying to compile an old commit of rustc, disable `download-rustc` in config.toml: +HELP: if trying to compile an old commit of rustc, disable `download-rustc` in bootstrap.toml: [rust] download-rustc = false @@ -783,7 +782,7 @@ download-rustc = false println!("HELP: Consider rebasing to a newer commit if available."); } Err(e) => { - eprintln!("ERROR: Failed to parse CI LLVM config.toml: {e}"); + eprintln!("ERROR: Failed to parse CI LLVM bootstrap.toml: {e}"); exit!(2); } }; @@ -816,7 +815,7 @@ download-rustc = false HELP: There could be two reasons behind this: 1) The host triple is not supported for `download-ci-llvm`. 2) Old builds get deleted after a certain time. - HELP: In either case, disable `download-ci-llvm` in your config.toml: + HELP: In either case, disable `download-ci-llvm` in your bootstrap.toml: [llvm] download-ci-llvm = false @@ -845,7 +844,7 @@ download-rustc = false HELP: There could be two reasons behind this: 1) The host triple is not supported for `download-ci-gcc`. 2) Old builds get deleted after a certain time. - HELP: In either case, disable `download-ci-gcc` in your config.toml: + HELP: In either case, disable `download-ci-gcc` in your bootstrap.toml: [gcc] download-ci-gcc = false diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 583b8e1198a..dbfebd11f82 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -153,7 +153,7 @@ pub fn check(build: &mut Build) { Couldn't find required command: cmake You should install cmake, or set `download-ci-llvm = true` in the -`[llvm]` section of `config.toml` to download LLVM rather +`[llvm]` section of `bootstrap.toml` to download LLVM rather than building it. " ); @@ -339,7 +339,7 @@ than building it. None => panic!( "when targeting MUSL either the rust.musl-root \ option or the target.$TARGET.musl-root option must \ - be specified in config.toml" + be specified in bootstrap.toml" ), } } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 8dfd1bbfd60..ec5c0c53baa 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -15,6 +15,7 @@ //! //! More documentation can be found in each respective module below, and you can //! also check out the `src/bootstrap/README.md` file for more information. +#![cfg_attr(test, allow(unused))] use std::cell::{Cell, RefCell}; use std::collections::{BTreeSet, HashMap, HashSet}; @@ -27,6 +28,7 @@ use std::{env, fs, io, str}; use build_helper::ci::gha; use build_helper::exit; +use cc::Tool; use termcolor::{ColorChoice, StandardStream, WriteColor}; use utils::build_stamp::BuildStamp; use utils::channel::GitInfo; @@ -142,7 +144,7 @@ pub enum GitRepo { /// organize). #[derive(Clone)] pub struct Build { - /// User-specified configuration from `config.toml`. + /// User-specified configuration from `bootstrap.toml`. config: Config, // Version information @@ -537,7 +539,7 @@ impl Build { /// This avoids contributors checking in a submodule change by accident. fn update_existing_submodules(&self) { // Avoid running git when there isn't a git checkout, or the user has - // explicitly disabled submodules in `config.toml`. + // explicitly disabled submodules in `bootstrap.toml`. if !self.config.submodules() { return; } @@ -670,7 +672,7 @@ impl Build { } /// Gets the space-separated set of activated features for the standard library. - /// This can be configured with the `std-features` key in config.toml. + /// This can be configured with the `std-features` key in bootstrap.toml. fn std_features(&self, target: TargetSelection) -> String { let mut features: BTreeSet<&str> = self.config.rust_std_features.iter().map(|s| s.as_str()).collect(); @@ -1218,6 +1220,16 @@ Executed at: {executed_at}"#, self.cc.borrow()[&target].path().into() } + /// Returns the internal `cc::Tool` for the C compiler. + fn cc_tool(&self, target: TargetSelection) -> Tool { + self.cc.borrow()[&target].clone() + } + + /// Returns the internal `cc::Tool` for the C++ compiler. + fn cxx_tool(&self, target: TargetSelection) -> Tool { + self.cxx.borrow()[&target].clone() + } + /// Returns C flags that `cc-rs` thinks should be enabled for the /// specified target by default. fn cc_handled_clags(&self, target: TargetSelection, c: CLang) -> Vec<String> { @@ -1914,7 +1926,7 @@ Couldn't find required command: ninja (or ninja-build) You should install ninja as described at <https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages>, -or set `ninja = false` in the `[llvm]` section of `config.toml`. +or set `ninja = false` in the `[llvm]` section of `bootstrap.toml`. Alternatively, set `download-ci-llvm = true` in that `[llvm]` section to download LLVM rather than building it. " diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs index 1e84a7deff1..147b009d3f4 100644 --- a/src/bootstrap/src/utils/cc_detect.rs +++ b/src/bootstrap/src/utils/cc_detect.rs @@ -4,8 +4,8 @@ //! C and C++ compilers for each target configured. A compiler is found through //! a number of vectors (in order of precedence) //! -//! 1. Configuration via `target.$target.cc` in `config.toml`. -//! 2. Configuration via `target.$target.android-ndk` in `config.toml`, if +//! 1. Configuration via `target.$target.cc` in `bootstrap.toml`. +//! 2. Configuration via `target.$target.android-ndk` in `bootstrap.toml`, if //! applicable //! 3. Special logic to probe on OpenBSD //! 4. The `CC_$target` environment variable. @@ -122,7 +122,7 @@ pub fn find(build: &Build) { /// Probes and configures the C and C++ compilers for a single target. /// -/// This function uses both user-specified configuration (from `config.toml`) and auto-detection +/// This function uses both user-specified configuration (from `bootstrap.toml`) and auto-detection /// logic to determine the correct C/C++ compilers for the target. It also determines the appropriate /// archiver (`ar`) and sets up additional compilation flags (both handled and unhandled). pub fn find_target(build: &Build, target: TargetSelection) { @@ -186,7 +186,7 @@ pub fn find_target(build: &Build, target: TargetSelection) { } /// Determines the default compiler for a given target and language when not explicitly -/// configured in `config.toml`. +/// configured in `bootstrap.toml`. fn default_compiler( cfg: &mut cc::Build, compiler: Language, @@ -195,7 +195,7 @@ fn default_compiler( ) -> Option<PathBuf> { match &*target.triple { // When compiling for android we may have the NDK configured in the - // config.toml in which case we look there. Otherwise the default + // bootstrap.toml in which case we look there. Otherwise the default // compiler already takes into account the triple in question. t if t.contains("android") => { build.config.android_ndk.as_ref().map(|ndk| ndk_compiler(compiler, &target.triple, ndk)) diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 8036c592108..1a101b02f70 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -380,4 +380,14 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "Removed `src/tools/rls` tool as it was deprecated long time ago.", }, + ChangeInfo { + change_id: 137147, + severity: ChangeSeverity::Info, + summary: "Added new option `build.exclude` which works the same way as `--exclude` flag on `x`.", + }, + ChangeInfo { + change_id: 137081, + severity: ChangeSeverity::Warning, + summary: "The default configuration filename has changed from `config.toml` to `bootstrap.toml`. `config.toml` is deprecated but remains supported for backward compatibility.", + }, ]; diff --git a/src/bootstrap/src/utils/proc_macro_deps.rs b/src/bootstrap/src/utils/proc_macro_deps.rs index 34bf6bb7013..dbfd6f47dc6 100644 --- a/src/bootstrap/src/utils/proc_macro_deps.rs +++ b/src/bootstrap/src/utils/proc_macro_deps.rs @@ -6,18 +6,25 @@ pub static CRATES: &[&str] = &[ "annotate-snippets", "anstyle", "basic-toml", + "block-buffer", "bumpalo", + "cfg-if", + "cpufeatures", + "crypto-common", "darling", "darling_core", "derive_builder_core", + "digest", "fluent-bundle", "fluent-langneg", "fluent-syntax", "fnv", + "generic-array", "heck", "ident_case", "intl-memoizer", "intl_pluralrules", + "libc", "log", "memchr", "mime", @@ -25,12 +32,17 @@ pub static CRATES: &[&str] = &[ "minimal-lexical", "nom", "num-conv", + "once_cell", + "pest", + "pest_generator", + "pest_meta", "proc-macro2", "quote", "rinja_parser", "rustc-hash", "self_cell", "serde", + "sha2", "smallvec", "stable_deref_trait", "strsim", @@ -40,12 +52,15 @@ pub static CRATES: &[&str] = &[ "time-core", "tinystr", "type-map", + "typenum", + "ucd-trie", "unic-langid", "unic-langid-impl", "unic-langid-macros", "unicase", "unicode-ident", "unicode-width", + "version_check", "wasm-bindgen-backend", "wasm-bindgen-macro-support", "wasm-bindgen-shared", diff --git a/src/bootstrap/src/utils/render_tests.rs b/src/bootstrap/src/utils/render_tests.rs index 3f58328a5b5..418f3ff975d 100644 --- a/src/bootstrap/src/utils/render_tests.rs +++ b/src/bootstrap/src/utils/render_tests.rs @@ -10,7 +10,6 @@ use std::io::{BufRead, BufReader, Read, Write}; use std::process::{ChildStdout, Stdio}; use std::time::Duration; -use build_helper::ci::CiEnv; use termcolor::{Color, ColorSpec, WriteColor}; use crate::core::builder::Builder; @@ -187,7 +186,7 @@ impl<'a> Renderer<'a> { if self.builder.config.verbose_tests { self.render_test_outcome_verbose(outcome, test); - } else if CiEnv::is_ci() { + } else if self.builder.config.is_running_on_ci { self.render_test_outcome_ci(outcome, test); } else { self.render_test_outcome_terse(outcome, test); diff --git a/src/build_helper/src/git.rs b/src/build_helper/src/git.rs index 9f778a2fd77..693e0fc8f46 100644 --- a/src/build_helper/src/git.rs +++ b/src/build_helper/src/git.rs @@ -1,4 +1,4 @@ -use std::path::{Path, PathBuf}; +use std::path::Path; use std::process::{Command, Stdio}; use crate::ci::CiEnv; @@ -121,7 +121,7 @@ fn git_upstream_merge_base( pub fn get_closest_merge_commit( git_dir: Option<&Path>, config: &GitConfig<'_>, - target_paths: &[PathBuf], + target_paths: &[&str], ) -> Result<String, String> { let mut git = Command::new("git"); @@ -173,7 +173,7 @@ pub fn get_git_modified_files( config: &GitConfig<'_>, git_dir: Option<&Path>, extensions: &[&str], -) -> Result<Option<Vec<String>>, String> { +) -> Result<Vec<String>, String> { let merge_base = get_closest_merge_commit(git_dir, config, &[])?; let mut git = Command::new("git"); @@ -186,7 +186,10 @@ pub fn get_git_modified_files( let (status, name) = f.trim().split_once(char::is_whitespace).unwrap(); if status == "D" { None - } else if Path::new(name).extension().map_or(false, |ext| { + } else if Path::new(name).extension().map_or(extensions.is_empty(), |ext| { + // If there is no extension, we allow the path if `extensions` is empty + // If there is an extension, we allow it if `extension` is empty or it contains the + // extension. extensions.is_empty() || extensions.contains(&ext.to_str().unwrap()) }) { Some(name.to_owned()) @@ -195,7 +198,7 @@ pub fn get_git_modified_files( } }) .collect(); - Ok(Some(files)) + Ok(files) } /// Returns the files that haven't been added to git yet. diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs new file mode 100644 index 00000000000..2088ce29620 --- /dev/null +++ b/src/ci/citool/src/analysis.rs @@ -0,0 +1,362 @@ +use std::collections::{BTreeMap, HashMap, HashSet}; + +use build_helper::metrics::{ + BuildStep, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, format_build_steps, +}; + +use crate::metrics; +use crate::metrics::{JobMetrics, JobName, get_test_suites}; +use crate::utils::{output_details, pluralize}; + +pub fn output_bootstrap_stats(metrics: &JsonRoot) { + if !metrics.invocations.is_empty() { + println!("# Bootstrap steps"); + record_bootstrap_step_durations(&metrics); + record_test_suites(&metrics); + } +} + +fn record_bootstrap_step_durations(metrics: &JsonRoot) { + for invocation in &metrics.invocations { + let step = BuildStep::from_invocation(invocation); + let table = format_build_steps(&step); + eprintln!("Step `{}`\n{table}\n", invocation.cmdline); + output_details(&invocation.cmdline, || { + println!("<pre><code>{table}</code></pre>"); + }); + } + eprintln!("Recorded {} bootstrap invocation(s)", metrics.invocations.len()); +} + +fn record_test_suites(metrics: &JsonRoot) { + let suites = metrics::get_test_suites(&metrics); + + if !suites.is_empty() { + let aggregated = aggregate_test_suites(&suites); + let table = render_table(aggregated); + println!("\n# Test results\n"); + println!("{table}"); + } else { + eprintln!("No test suites found in metrics"); + } +} + +fn render_table(suites: BTreeMap<String, TestSuiteRecord>) -> String { + use std::fmt::Write; + + let mut table = "| Test suite | Passed ✅ | Ignored 🚫 | Failed ❌ |\n".to_string(); + writeln!(table, "|:------|------:|------:|------:|").unwrap(); + + fn compute_pct(value: f64, total: f64) -> f64 { + if total == 0.0 { 0.0 } else { value / total } + } + + fn write_row( + buffer: &mut String, + name: &str, + record: &TestSuiteRecord, + surround: &str, + ) -> std::fmt::Result { + let TestSuiteRecord { passed, ignored, failed } = record; + let total = (record.passed + record.ignored + record.failed) as f64; + let passed_pct = compute_pct(*passed as f64, total) * 100.0; + let ignored_pct = compute_pct(*ignored as f64, total) * 100.0; + let failed_pct = compute_pct(*failed as f64, total) * 100.0; + + write!(buffer, "| {surround}{name}{surround} |")?; + write!(buffer, " {surround}{passed} ({passed_pct:.0}%){surround} |")?; + write!(buffer, " {surround}{ignored} ({ignored_pct:.0}%){surround} |")?; + writeln!(buffer, " {surround}{failed} ({failed_pct:.0}%){surround} |")?; + + Ok(()) + } + + let mut total = TestSuiteRecord::default(); + for (name, record) in suites { + write_row(&mut table, &name, &record, "").unwrap(); + total.passed += record.passed; + total.ignored += record.ignored; + total.failed += record.failed; + } + write_row(&mut table, "Total", &total, "**").unwrap(); + table +} + +/// Computes a post merge CI analysis report of test differences +/// between the `parent` and `current` commits. +pub fn output_test_diffs(job_metrics: HashMap<JobName, JobMetrics>) { + let aggregated_test_diffs = aggregate_test_diffs(&job_metrics); + report_test_diffs(aggregated_test_diffs); +} + +#[derive(Default)] +struct TestSuiteRecord { + passed: u64, + ignored: u64, + failed: u64, +} + +fn test_metadata_name(metadata: &TestSuiteMetadata) -> String { + match metadata { + TestSuiteMetadata::CargoPackage { crates, stage, .. } => { + format!("{} (stage {stage})", crates.join(", ")) + } + TestSuiteMetadata::Compiletest { suite, stage, .. } => { + format!("{suite} (stage {stage})") + } + } +} + +fn aggregate_test_suites(suites: &[&TestSuite]) -> BTreeMap<String, TestSuiteRecord> { + let mut records: BTreeMap<String, TestSuiteRecord> = BTreeMap::new(); + for suite in suites { + let name = test_metadata_name(&suite.metadata); + let record = records.entry(name).or_default(); + for test in &suite.tests { + match test.outcome { + TestOutcome::Passed => { + record.passed += 1; + } + TestOutcome::Failed => { + record.failed += 1; + } + TestOutcome::Ignored { .. } => { + record.ignored += 1; + } + } + } + } + records +} + +/// Represents a difference in the outcome of tests between a base and a current commit. +/// Maps test diffs to jobs that contained them. +#[derive(Debug)] +struct AggregatedTestDiffs { + diffs: HashMap<TestDiff, Vec<JobName>>, +} + +fn aggregate_test_diffs(jobs: &HashMap<JobName, JobMetrics>) -> AggregatedTestDiffs { + let mut diffs: HashMap<TestDiff, Vec<JobName>> = HashMap::new(); + + // Aggregate test suites + for (name, metrics) in jobs { + if let Some(parent) = &metrics.parent { + let tests_parent = aggregate_tests(parent); + let tests_current = aggregate_tests(&metrics.current); + for diff in calculate_test_diffs(tests_parent, tests_current) { + diffs.entry(diff).or_default().push(name.to_string()); + } + } + } + + AggregatedTestDiffs { diffs } +} + +#[derive(Eq, PartialEq, Hash, Debug)] +enum TestOutcomeDiff { + ChangeOutcome { before: TestOutcome, after: TestOutcome }, + Missing { before: TestOutcome }, + Added(TestOutcome), +} + +#[derive(Eq, PartialEq, Hash, Debug)] +struct TestDiff { + test: Test, + diff: TestOutcomeDiff, +} + +fn calculate_test_diffs(parent: TestSuiteData, current: TestSuiteData) -> HashSet<TestDiff> { + let mut diffs = HashSet::new(); + for (test, outcome) in ¤t.tests { + match parent.tests.get(test) { + Some(before) => { + if before != outcome { + diffs.insert(TestDiff { + test: test.clone(), + diff: TestOutcomeDiff::ChangeOutcome { + before: before.clone(), + after: outcome.clone(), + }, + }); + } + } + None => { + diffs.insert(TestDiff { + test: test.clone(), + diff: TestOutcomeDiff::Added(outcome.clone()), + }); + } + } + } + for (test, outcome) in &parent.tests { + if !current.tests.contains_key(test) { + diffs.insert(TestDiff { + test: test.clone(), + diff: TestOutcomeDiff::Missing { before: outcome.clone() }, + }); + } + } + + diffs +} + +/// Aggregates test suite executions from all bootstrap invocations in a given CI job. +#[derive(Default)] +struct TestSuiteData { + tests: HashMap<Test, TestOutcome>, +} + +#[derive(Hash, PartialEq, Eq, Debug, Clone)] +struct Test { + name: String, + is_doctest: bool, +} + +/// Extracts all tests from the passed metrics and map them to their outcomes. +fn aggregate_tests(metrics: &JsonRoot) -> TestSuiteData { + let mut tests = HashMap::new(); + let test_suites = get_test_suites(&metrics); + for suite in test_suites { + for test in &suite.tests { + // Poor man's detection of doctests based on the "(line XYZ)" suffix + let is_doctest = matches!(suite.metadata, TestSuiteMetadata::CargoPackage { .. }) + && test.name.contains("(line"); + let test_entry = Test { name: generate_test_name(&test.name, &suite), is_doctest }; + tests.insert(test_entry, test.outcome.clone()); + } + } + TestSuiteData { tests } +} + +/// Normalizes Windows-style path delimiters to Unix-style paths +/// and adds suite metadata to the test name. +fn generate_test_name(name: &str, suite: &TestSuite) -> String { + let name = name.replace('\\', "/"); + let stage = match suite.metadata { + TestSuiteMetadata::CargoPackage { stage, .. } => stage, + TestSuiteMetadata::Compiletest { stage, .. } => stage, + }; + + format!("{name} (stage {stage})") +} + +/// Prints test changes in Markdown format to stdout. +fn report_test_diffs(diff: AggregatedTestDiffs) { + println!("# Test differences"); + if diff.diffs.is_empty() { + println!("No test diffs found"); + return; + } + + fn format_outcome(outcome: &TestOutcome) -> String { + match outcome { + TestOutcome::Passed => "pass".to_string(), + TestOutcome::Failed => "fail".to_string(), + TestOutcome::Ignored { ignore_reason } => { + let reason = match ignore_reason { + Some(reason) => format!(" ({reason})"), + None => String::new(), + }; + format!("ignore{reason}") + } + } + } + + fn format_diff(diff: &TestOutcomeDiff) -> String { + match diff { + TestOutcomeDiff::ChangeOutcome { before, after } => { + format!("{} -> {}", format_outcome(before), format_outcome(after)) + } + TestOutcomeDiff::Missing { before } => { + format!("{} -> [missing]", format_outcome(before)) + } + TestOutcomeDiff::Added(outcome) => { + format!("[missing] -> {}", format_outcome(outcome)) + } + } + } + + fn format_job_group(group: u64) -> String { + format!("**J{group}**") + } + + // It would be quite noisy to repeat the jobs that contained the test changes after/next to + // every test diff. At the same time, grouping the test diffs by + // [unique set of jobs that contained them] also doesn't work well, because the test diffs + // would have to be duplicated several times. + // Instead, we create a set of unique job groups, and then print a job group after each test. + // We then print the job groups at the end, as a sort of index. + let mut grouped_diffs: Vec<(&TestDiff, u64)> = vec![]; + let mut job_list_to_group: HashMap<&[JobName], u64> = HashMap::new(); + let mut job_index: Vec<&[JobName]> = vec![]; + + let original_diff_count = diff.diffs.len(); + let diffs = diff + .diffs + .into_iter() + .filter(|(diff, _)| !diff.test.is_doctest) + .map(|(diff, mut jobs)| { + jobs.sort(); + (diff, jobs) + }) + .collect::<Vec<_>>(); + let doctest_count = original_diff_count.saturating_sub(diffs.len()); + + let max_diff_count = 100; + for (diff, jobs) in diffs.iter().take(max_diff_count) { + let jobs = &*jobs; + let job_group = match job_list_to_group.get(jobs.as_slice()) { + Some(id) => *id, + None => { + let id = job_index.len() as u64; + job_index.push(jobs); + job_list_to_group.insert(jobs, id); + id + } + }; + grouped_diffs.push((diff, job_group)); + } + + // Sort diffs by job group and test name + grouped_diffs.sort_by(|(d1, g1), (d2, g2)| g1.cmp(&g2).then(d1.test.name.cmp(&d2.test.name))); + + output_details( + &format!("Show {} test {}\n", original_diff_count, pluralize("diff", original_diff_count)), + || { + for (diff, job_group) in grouped_diffs { + println!( + "- `{}`: {} ({})", + diff.test.name, + format_diff(&diff.diff), + format_job_group(job_group) + ); + } + + let extra_diffs = diffs.len().saturating_sub(max_diff_count); + if extra_diffs > 0 { + println!( + "\n(and {extra_diffs} additional {})", + pluralize("test diff", extra_diffs) + ); + } + + if doctest_count > 0 { + println!( + "\nAdditionally, {doctest_count} doctest {} were found. These are ignored, as they are noisy.", + pluralize("diff", doctest_count) + ); + } + + // Now print the job group index + println!("\n**Job group index**\n"); + for (group, jobs) in job_index.into_iter().enumerate() { + println!( + "- {}: {}", + format_job_group(group as u64), + jobs.iter().map(|j| format!("`{j}`")).collect::<Vec<_>>().join(", ") + ); + } + }, + ); +} diff --git a/src/ci/citool/src/jobs.rs b/src/ci/citool/src/jobs.rs index 0de8b740227..13880ad466a 100644 --- a/src/ci/citool/src/jobs.rs +++ b/src/ci/citool/src/jobs.rs @@ -185,6 +185,20 @@ fn calculate_jobs( env.extend(crate::yaml_map_to_json(&job.env)); let full_name = format!("{prefix} - {}", job.name); + // When the default `@bors try` job is executed (which is usually done + // for benchmarking performance, running crater or for downloading the + // built toolchain using `rustup-toolchain-install-master`), + // we inject the `DIST_TRY_BUILD` environment variable to the jobs + // to tell `opt-dist` to make the build faster by skipping certain steps. + if let RunType::TryJob { job_patterns } = run_type { + if job_patterns.is_none() { + env.insert( + "DIST_TRY_BUILD".to_string(), + serde_json::value::Value::Number(1.into()), + ); + } + } + GithubActionsJob { name: job.name, full_name, diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index cd690ebeb06..5a84ecb5e47 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -1,24 +1,25 @@ +mod analysis; mod cpu_usage; mod datadog; mod jobs; -mod merge_report; mod metrics; mod utils; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashMap}; use std::path::{Path, PathBuf}; use std::process::Command; +use analysis::output_bootstrap_stats; use anyhow::Context; use clap::Parser; use jobs::JobDatabase; use serde_yaml::Value; +use crate::analysis::output_test_diffs; use crate::cpu_usage::load_cpu_usage; use crate::datadog::upload_datadog_metric; use crate::jobs::RunType; -use crate::merge_report::post_merge_report; -use crate::metrics::postprocess_metrics; +use crate::metrics::{JobMetrics, download_auto_job_metrics, download_job_metrics, load_metrics}; use crate::utils::load_env_var; const CI_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/.."); @@ -137,6 +138,49 @@ fn upload_ci_metrics(cpu_usage_csv: &Path) -> anyhow::Result<()> { Ok(()) } +fn postprocess_metrics( + metrics_path: PathBuf, + parent: Option<String>, + job_name: Option<String>, +) -> anyhow::Result<()> { + let metrics = load_metrics(&metrics_path)?; + output_bootstrap_stats(&metrics); + + let (Some(parent), Some(job_name)) = (parent, job_name) else { + return Ok(()); + }; + + // This command is executed also on PR builds, which might not have parent metrics + // available, because some PR jobs don't run on auto builds, and PR jobs do not upload metrics + // due to missing permissions. + // To avoid having to detect if this is a PR job, and to avoid having failed steps in PR jobs, + // we simply print an error if the parent metrics were not found, but otherwise exit + // successfully. + match download_job_metrics(&job_name, &parent).context("cannot download parent metrics") { + Ok(parent_metrics) => { + let job_metrics = HashMap::from([( + job_name, + JobMetrics { parent: Some(parent_metrics), current: metrics }, + )]); + output_test_diffs(job_metrics); + } + Err(error) => { + eprintln!("Metrics for job `{job_name}` and commit `{parent}` not found: {error:?}"); + } + } + + Ok(()) +} + +fn post_merge_report(db: JobDatabase, current: String, parent: String) -> anyhow::Result<()> { + let metrics = download_auto_job_metrics(&db, &parent, ¤t)?; + + println!("\nComparing {parent} (parent) -> {current} (this PR)\n"); + output_test_diffs(metrics); + + Ok(()) +} + #[derive(clap::Parser)] enum Args { /// Calculate a list of jobs that should be executed on CI. @@ -154,13 +198,19 @@ enum Args { #[clap(long = "type", default_value = "auto")] job_type: JobType, }, - /// Postprocess the metrics.json file generated by bootstrap. + /// Postprocess the metrics.json file generated by bootstrap and output + /// various statistics. + /// If `--parent` and `--job-name` are provided, also display a diff + /// against previous metrics that are downloaded from CI. PostprocessMetrics { /// Path to the metrics.json file metrics_path: PathBuf, - /// Path to a file where the postprocessed metrics summary will be stored. - /// Usually, this will be GITHUB_STEP_SUMMARY on CI. - summary_path: PathBuf, + /// A parent SHA against which to compare. + #[clap(long, requires("job_name"))] + parent: Option<String>, + /// The name of the current job. + #[clap(long, requires("parent"))] + job_name: Option<String>, }, /// Upload CI metrics to Datadog. UploadBuildMetrics { @@ -211,11 +261,11 @@ fn main() -> anyhow::Result<()> { Args::UploadBuildMetrics { cpu_usage_csv } => { upload_ci_metrics(&cpu_usage_csv)?; } - Args::PostprocessMetrics { metrics_path, summary_path } => { - postprocess_metrics(&metrics_path, &summary_path)?; + Args::PostprocessMetrics { metrics_path, parent, job_name } => { + postprocess_metrics(metrics_path, parent, job_name)?; } - Args::PostMergeReport { current: commit, parent } => { - post_merge_report(load_db(default_jobs_file)?, parent, commit)?; + Args::PostMergeReport { current, parent } => { + post_merge_report(load_db(default_jobs_file)?, current, parent)?; } } diff --git a/src/ci/citool/src/merge_report.rs b/src/ci/citool/src/merge_report.rs deleted file mode 100644 index 17e42d49286..00000000000 --- a/src/ci/citool/src/merge_report.rs +++ /dev/null @@ -1,257 +0,0 @@ -use std::cmp::Reverse; -use std::collections::HashMap; - -use anyhow::Context; -use build_helper::metrics::{JsonRoot, TestOutcome}; - -use crate::jobs::JobDatabase; -use crate::metrics::get_test_suites; - -type Sha = String; -type JobName = String; - -/// Computes a post merge CI analysis report between the `parent` and `current` commits. -pub fn post_merge_report(job_db: JobDatabase, parent: Sha, current: Sha) -> anyhow::Result<()> { - let jobs = download_all_metrics(&job_db, &parent, ¤t)?; - let diffs = aggregate_test_diffs(&jobs)?; - report_test_changes(diffs); - - Ok(()) -} - -struct JobMetrics { - parent: Option<JsonRoot>, - current: JsonRoot, -} - -/// Download before/after metrics for all auto jobs in the job database. -fn download_all_metrics( - job_db: &JobDatabase, - parent: &str, - current: &str, -) -> anyhow::Result<HashMap<JobName, JobMetrics>> { - let mut jobs = HashMap::default(); - - for job in &job_db.auto_jobs { - eprintln!("Downloading metrics of job {}", job.name); - let metrics_parent = match download_job_metrics(&job.name, parent) { - Ok(metrics) => Some(metrics), - Err(error) => { - eprintln!( - r#"Did not find metrics for job `{}` at `{}`: {error:?}. -Maybe it was newly added?"#, - job.name, parent - ); - None - } - }; - let metrics_current = download_job_metrics(&job.name, current)?; - jobs.insert( - job.name.clone(), - JobMetrics { parent: metrics_parent, current: metrics_current }, - ); - } - Ok(jobs) -} - -fn download_job_metrics(job_name: &str, sha: &str) -> anyhow::Result<JsonRoot> { - let url = get_metrics_url(job_name, sha); - let mut response = ureq::get(&url).call()?; - if !response.status().is_success() { - return Err(anyhow::anyhow!( - "Cannot fetch metrics from {url}: {}\n{}", - response.status(), - response.body_mut().read_to_string()? - )); - } - let data: JsonRoot = response - .body_mut() - .read_json() - .with_context(|| anyhow::anyhow!("cannot deserialize metrics from {url}"))?; - Ok(data) -} - -fn get_metrics_url(job_name: &str, sha: &str) -> String { - let suffix = if job_name.ends_with("-alt") { "-alt" } else { "" }; - format!("https://ci-artifacts.rust-lang.org/rustc-builds{suffix}/{sha}/metrics-{job_name}.json") -} - -fn aggregate_test_diffs( - jobs: &HashMap<JobName, JobMetrics>, -) -> anyhow::Result<Vec<AggregatedTestDiffs>> { - let mut job_diffs = vec![]; - - // Aggregate test suites - for (name, metrics) in jobs { - if let Some(parent) = &metrics.parent { - let tests_parent = aggregate_tests(parent); - let tests_current = aggregate_tests(&metrics.current); - let test_diffs = calculate_test_diffs(tests_parent, tests_current); - if !test_diffs.is_empty() { - job_diffs.push((name.clone(), test_diffs)); - } - } - } - - // Aggregate jobs with the same diff, as often the same diff will appear in many jobs - let job_diffs: HashMap<Vec<(Test, TestOutcomeDiff)>, Vec<String>> = - job_diffs.into_iter().fold(HashMap::new(), |mut acc, (job, diffs)| { - acc.entry(diffs).or_default().push(job); - acc - }); - - Ok(job_diffs - .into_iter() - .map(|(test_diffs, jobs)| AggregatedTestDiffs { jobs, test_diffs }) - .collect()) -} - -fn calculate_test_diffs( - reference: TestSuiteData, - current: TestSuiteData, -) -> Vec<(Test, TestOutcomeDiff)> { - let mut diffs = vec![]; - for (test, outcome) in ¤t.tests { - match reference.tests.get(test) { - Some(before) => { - if before != outcome { - diffs.push(( - test.clone(), - TestOutcomeDiff::ChangeOutcome { - before: before.clone(), - after: outcome.clone(), - }, - )); - } - } - None => diffs.push((test.clone(), TestOutcomeDiff::Added(outcome.clone()))), - } - } - for (test, outcome) in &reference.tests { - if !current.tests.contains_key(test) { - diffs.push((test.clone(), TestOutcomeDiff::Missing { before: outcome.clone() })); - } - } - - diffs -} - -/// Represents a difference in the outcome of tests between a base and a current commit. -#[derive(Debug)] -struct AggregatedTestDiffs { - /// All jobs that had the exact same test diffs. - jobs: Vec<String>, - test_diffs: Vec<(Test, TestOutcomeDiff)>, -} - -#[derive(Eq, PartialEq, Hash, Debug)] -enum TestOutcomeDiff { - ChangeOutcome { before: TestOutcome, after: TestOutcome }, - Missing { before: TestOutcome }, - Added(TestOutcome), -} - -/// Aggregates test suite executions from all bootstrap invocations in a given CI job. -#[derive(Default)] -struct TestSuiteData { - tests: HashMap<Test, TestOutcome>, -} - -#[derive(Hash, PartialEq, Eq, Debug, Clone)] -struct Test { - name: String, -} - -/// Extracts all tests from the passed metrics and map them to their outcomes. -fn aggregate_tests(metrics: &JsonRoot) -> TestSuiteData { - let mut tests = HashMap::new(); - let test_suites = get_test_suites(&metrics); - for suite in test_suites { - for test in &suite.tests { - let test_entry = Test { name: normalize_test_name(&test.name) }; - tests.insert(test_entry, test.outcome.clone()); - } - } - TestSuiteData { tests } -} - -/// Normalizes Windows-style path delimiters to Unix-style paths. -fn normalize_test_name(name: &str) -> String { - name.replace('\\', "/") -} - -/// Prints test changes in Markdown format to stdout. -fn report_test_changes(mut diffs: Vec<AggregatedTestDiffs>) { - println!("## Test differences"); - if diffs.is_empty() { - println!("No test diffs found"); - return; - } - - // Sort diffs in decreasing order by diff count - diffs.sort_by_key(|entry| Reverse(entry.test_diffs.len())); - - fn format_outcome(outcome: &TestOutcome) -> String { - match outcome { - TestOutcome::Passed => "pass".to_string(), - TestOutcome::Failed => "fail".to_string(), - TestOutcome::Ignored { ignore_reason } => { - let reason = match ignore_reason { - Some(reason) => format!(" ({reason})"), - None => String::new(), - }; - format!("ignore{reason}") - } - } - } - - fn format_diff(diff: &TestOutcomeDiff) -> String { - match diff { - TestOutcomeDiff::ChangeOutcome { before, after } => { - format!("{} -> {}", format_outcome(before), format_outcome(after)) - } - TestOutcomeDiff::Missing { before } => { - format!("{} -> [missing]", format_outcome(before)) - } - TestOutcomeDiff::Added(outcome) => { - format!("[missing] -> {}", format_outcome(outcome)) - } - } - } - - let max_diff_count = 10; - let max_job_count = 5; - let max_test_count = 10; - - for diff in diffs.iter().take(max_diff_count) { - let mut jobs = diff.jobs.clone(); - jobs.sort(); - - let jobs = jobs.iter().take(max_job_count).map(|j| format!("`{j}`")).collect::<Vec<_>>(); - - let extra_jobs = diff.jobs.len().saturating_sub(max_job_count); - let suffix = if extra_jobs > 0 { - format!(" (and {extra_jobs} {})", pluralize("other", extra_jobs)) - } else { - String::new() - }; - println!("- {}{suffix}", jobs.join(",")); - - let extra_tests = diff.test_diffs.len().saturating_sub(max_test_count); - for (test, outcome_diff) in diff.test_diffs.iter().take(max_test_count) { - println!(" - {}: {}", test.name, format_diff(&outcome_diff)); - } - if extra_tests > 0 { - println!(" - (and {extra_tests} additional {})", pluralize("tests", extra_tests)); - } - } - - let extra_diffs = diffs.len().saturating_sub(max_diff_count); - if extra_diffs > 0 { - println!("\n(and {extra_diffs} additional {})", pluralize("diff", extra_diffs)); - } -} - -fn pluralize(text: &str, count: usize) -> String { - if count == 1 { text.to_string() } else { format!("{text}s") } -} diff --git a/src/ci/citool/src/metrics.rs b/src/ci/citool/src/metrics.rs index 83b3d5ceed0..086aa5009f3 100644 --- a/src/ci/citool/src/metrics.rs +++ b/src/ci/citool/src/metrics.rs @@ -1,146 +1,12 @@ -use std::collections::BTreeMap; -use std::fs::File; -use std::io::Write; +use std::collections::HashMap; use std::path::Path; use anyhow::Context; -use build_helper::metrics::{ - BuildStep, JsonNode, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, format_build_steps, -}; +use build_helper::metrics::{JsonNode, JsonRoot, TestSuite}; -pub fn postprocess_metrics(metrics_path: &Path, summary_path: &Path) -> anyhow::Result<()> { - let metrics = load_metrics(metrics_path)?; +use crate::jobs::JobDatabase; - let mut file = File::options() - .append(true) - .create(true) - .open(summary_path) - .with_context(|| format!("Cannot open summary file at {summary_path:?}"))?; - - if !metrics.invocations.is_empty() { - writeln!(file, "# Bootstrap steps")?; - record_bootstrap_step_durations(&metrics, &mut file)?; - record_test_suites(&metrics, &mut file)?; - } - - Ok(()) -} - -fn record_bootstrap_step_durations(metrics: &JsonRoot, file: &mut File) -> anyhow::Result<()> { - for invocation in &metrics.invocations { - let step = BuildStep::from_invocation(invocation); - let table = format_build_steps(&step); - eprintln!("Step `{}`\n{table}\n", invocation.cmdline); - writeln!( - file, - r"<details> -<summary>{}</summary> -<pre><code>{table}</code></pre> -</details> -", - invocation.cmdline - )?; - } - eprintln!("Recorded {} bootstrap invocation(s)", metrics.invocations.len()); - - Ok(()) -} - -fn record_test_suites(metrics: &JsonRoot, file: &mut File) -> anyhow::Result<()> { - let suites = get_test_suites(&metrics); - - if !suites.is_empty() { - let aggregated = aggregate_test_suites(&suites); - let table = render_table(aggregated); - writeln!(file, "\n# Test results\n")?; - writeln!(file, "{table}")?; - } else { - eprintln!("No test suites found in metrics"); - } - - Ok(()) -} - -fn render_table(suites: BTreeMap<String, TestSuiteRecord>) -> String { - use std::fmt::Write; - - let mut table = "| Test suite | Passed ✅ | Ignored 🚫 | Failed ❌ |\n".to_string(); - writeln!(table, "|:------|------:|------:|------:|").unwrap(); - - fn compute_pct(value: f64, total: f64) -> f64 { - if total == 0.0 { 0.0 } else { value / total } - } - - fn write_row( - buffer: &mut String, - name: &str, - record: &TestSuiteRecord, - surround: &str, - ) -> std::fmt::Result { - let TestSuiteRecord { passed, ignored, failed } = record; - let total = (record.passed + record.ignored + record.failed) as f64; - let passed_pct = compute_pct(*passed as f64, total) * 100.0; - let ignored_pct = compute_pct(*ignored as f64, total) * 100.0; - let failed_pct = compute_pct(*failed as f64, total) * 100.0; - - write!(buffer, "| {surround}{name}{surround} |")?; - write!(buffer, " {surround}{passed} ({passed_pct:.0}%){surround} |")?; - write!(buffer, " {surround}{ignored} ({ignored_pct:.0}%){surround} |")?; - writeln!(buffer, " {surround}{failed} ({failed_pct:.0}%){surround} |")?; - - Ok(()) - } - - let mut total = TestSuiteRecord::default(); - for (name, record) in suites { - write_row(&mut table, &name, &record, "").unwrap(); - total.passed += record.passed; - total.ignored += record.ignored; - total.failed += record.failed; - } - write_row(&mut table, "Total", &total, "**").unwrap(); - table -} - -#[derive(Default)] -struct TestSuiteRecord { - passed: u64, - ignored: u64, - failed: u64, -} - -fn test_metadata_name(metadata: &TestSuiteMetadata) -> String { - match metadata { - TestSuiteMetadata::CargoPackage { crates, stage, .. } => { - format!("{} (stage {stage})", crates.join(", ")) - } - TestSuiteMetadata::Compiletest { suite, stage, .. } => { - format!("{suite} (stage {stage})") - } - } -} - -fn aggregate_test_suites(suites: &[&TestSuite]) -> BTreeMap<String, TestSuiteRecord> { - let mut records: BTreeMap<String, TestSuiteRecord> = BTreeMap::new(); - for suite in suites { - let name = test_metadata_name(&suite.metadata); - let record = records.entry(name).or_default(); - for test in &suite.tests { - match test.outcome { - TestOutcome::Passed => { - record.passed += 1; - } - TestOutcome::Failed => { - record.failed += 1; - } - TestOutcome::Ignored { .. } => { - record.ignored += 1; - } - } - } - } - records -} +pub type JobName = String; pub fn get_test_suites(metrics: &JsonRoot) -> Vec<&TestSuite> { fn visit_test_suites<'a>(nodes: &'a [JsonNode], suites: &mut Vec<&'a TestSuite>) { @@ -163,10 +29,68 @@ pub fn get_test_suites(metrics: &JsonRoot) -> Vec<&TestSuite> { suites } -fn load_metrics(path: &Path) -> anyhow::Result<JsonRoot> { +pub fn load_metrics(path: &Path) -> anyhow::Result<JsonRoot> { let metrics = std::fs::read_to_string(path) .with_context(|| format!("Cannot read JSON metrics from {path:?}"))?; let metrics: JsonRoot = serde_json::from_str(&metrics) .with_context(|| format!("Cannot deserialize JSON metrics from {path:?}"))?; Ok(metrics) } + +pub struct JobMetrics { + pub parent: Option<JsonRoot>, + pub current: JsonRoot, +} + +/// Download before/after metrics for all auto jobs in the job database. +/// `parent` and `current` should be commit SHAs. +pub fn download_auto_job_metrics( + job_db: &JobDatabase, + parent: &str, + current: &str, +) -> anyhow::Result<HashMap<JobName, JobMetrics>> { + let mut jobs = HashMap::default(); + + for job in &job_db.auto_jobs { + eprintln!("Downloading metrics of job {}", job.name); + let metrics_parent = match download_job_metrics(&job.name, parent) { + Ok(metrics) => Some(metrics), + Err(error) => { + eprintln!( + r#"Did not find metrics for job `{}` at `{parent}`: {error:?}. +Maybe it was newly added?"#, + job.name + ); + None + } + }; + let metrics_current = download_job_metrics(&job.name, current)?; + jobs.insert( + job.name.clone(), + JobMetrics { parent: metrics_parent, current: metrics_current }, + ); + } + Ok(jobs) +} + +pub fn download_job_metrics(job_name: &str, sha: &str) -> anyhow::Result<JsonRoot> { + let url = get_metrics_url(job_name, sha); + let mut response = ureq::get(&url).call()?; + if !response.status().is_success() { + return Err(anyhow::anyhow!( + "Cannot fetch metrics from {url}: {}\n{}", + response.status(), + response.body_mut().read_to_string()? + )); + } + let data: JsonRoot = response + .body_mut() + .read_json() + .with_context(|| anyhow::anyhow!("cannot deserialize metrics from {url}"))?; + Ok(data) +} + +fn get_metrics_url(job_name: &str, sha: &str) -> String { + let suffix = if job_name.ends_with("-alt") { "-alt" } else { "" }; + format!("https://ci-artifacts.rust-lang.org/rustc-builds{suffix}/{sha}/metrics-{job_name}.json") +} diff --git a/src/ci/citool/src/utils.rs b/src/ci/citool/src/utils.rs index 9cc220987bd..b9b1bf4d455 100644 --- a/src/ci/citool/src/utils.rs +++ b/src/ci/citool/src/utils.rs @@ -9,3 +9,23 @@ pub fn load_env_var(name: &str) -> anyhow::Result<String> { pub fn read_to_string<P: AsRef<Path>>(path: P) -> anyhow::Result<String> { std::fs::read_to_string(&path).with_context(|| format!("Cannot read file {:?}", path.as_ref())) } + +pub fn pluralize(text: &str, count: usize) -> String { + if count == 1 { text.to_string() } else { format!("{text}s") } +} + +/// Outputs a HTML <details> section with the provided summary. +/// Output printed by `func` will be contained within the section. +pub fn output_details<F>(summary: &str, func: F) +where + F: FnOnce(), +{ + println!( + r"<details> +<summary>{summary}</summary> + +" + ); + func(); + println!("</details>\n"); +} diff --git a/src/ci/citool/tests/jobs.rs b/src/ci/citool/tests/jobs.rs index 788f5e7e4f6..c644f885be3 100644 --- a/src/ci/citool/tests/jobs.rs +++ b/src/ci/citool/tests/jobs.rs @@ -14,10 +14,10 @@ fn auto_jobs() { #[test] fn try_jobs() { let stdout = get_matrix("push", "commit", "refs/heads/try"); - insta::assert_snapshot!(stdout, @r#" + insta::assert_snapshot!(stdout, @r###" jobs=[{"name":"dist-x86_64-linux","full_name":"try - dist-x86_64-linux","os":"ubuntu-22.04-16core-64gb","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_TRY_BUILD":1,"TOOLSTATE_PUBLISH":1}}] run_type=try - "#); + "###); } #[test] @@ -30,10 +30,10 @@ try-job: aarch64-gnu try-job: dist-i686-msvc"#, "refs/heads/try", ); - insta::assert_snapshot!(stdout, @r#" - jobs=[{"name":"aarch64-gnu","full_name":"try - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DIST_TRY_BUILD":1,"TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"dist-i686-msvc","full_name":"try - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"DIST_TRY_BUILD":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}}] + insta::assert_snapshot!(stdout, @r###" + jobs=[{"name":"aarch64-gnu","full_name":"try - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"dist-i686-msvc","full_name":"try - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}}] run_type=try - "#); + "###); } #[test] diff --git a/src/ci/citool/tests/test-jobs.yml b/src/ci/citool/tests/test-jobs.yml index ff4d1772f59..3593b3f7df6 100644 --- a/src/ci/citool/tests/test-jobs.yml +++ b/src/ci/citool/tests/test-jobs.yml @@ -53,13 +53,6 @@ envs: try: <<: *production - # The following env var activates faster `try` builds in `opt-dist` by, e.g. - # - building only the more commonly useful components (we rarely need e.g. rust-docs in try - # builds) - # - not running `opt-dist`'s post-optimization smoke tests on the resulting toolchain - # - # If you *want* these to happen however, temporarily comment it before triggering a try build. - DIST_TRY_BUILD: 1 auto: <<: *production diff --git a/src/ci/docker/host-x86_64/dist-ohos/Dockerfile b/src/ci/docker/host-x86_64/dist-ohos/Dockerfile index bbbf0b3adf2..2c514fa0d4d 100644 --- a/src/ci/docker/host-x86_64/dist-ohos/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-ohos/Dockerfile @@ -22,6 +22,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY scripts/ohos-sdk.sh /scripts/ RUN sh /scripts/ohos-sdk.sh +COPY scripts/ohos-openssl.sh /scripts/ +RUN sh /scripts/ohos-openssl.sh + COPY scripts/ohos/aarch64-unknown-linux-ohos-clang.sh /usr/local/bin/ COPY scripts/ohos/aarch64-unknown-linux-ohos-clang++.sh /usr/local/bin/ COPY scripts/ohos/armv7-unknown-linux-ohos-clang.sh /usr/local/bin/ @@ -30,6 +33,14 @@ COPY scripts/ohos/x86_64-unknown-linux-ohos-clang.sh /usr/local/bin/ COPY scripts/ohos/x86_64-unknown-linux-ohos-clang++.sh /usr/local/bin/ # env +ENV AARCH64_UNKNOWN_LINUX_OHOS_OPENSSL_DIR=/opt/ohos-openssl/prelude/arm64-v8a +ENV ARMV7_UNKNOWN_LINUX_OHOS_OPENSSL_DIR=/opt/ohos-openssl/prelude/armeabi-v7a +ENV X86_64_UNKNOWN_LINUX_OHOS_OPENSSL_DIR=/opt/ohos-openssl/prelude/x86_64 + +ENV AARCH64_UNKNOWN_LINUX_OHOS_OPENSSL_NO_VENDOR=1 +ENV ARMV7_UNKNOWN_LINUX_OHOS_OPENSSL_NO_VENDOR=1 +ENV X86_64_UNKNOWN_LINUX_OHOS_OPENSSL_NO_VENDOR=1 + ENV TARGETS=aarch64-unknown-linux-ohos ENV TARGETS=$TARGETS,armv7-unknown-linux-ohos ENV TARGETS=$TARGETS,x86_64-unknown-linux-ohos @@ -49,9 +60,12 @@ ENV \ ENV RUST_CONFIGURE_ARGS \ --enable-profiler \ - --disable-docs + --disable-docs \ + --tools=cargo,clippy,rustdocs,rustfmt,rust-analyzer,rust-analyzer-proc-macro-srv,analysis,src,wasm-component-ld \ + --enable-extended \ + --enable-sanitizers -ENV SCRIPT python3 ../x.py dist --host='' --target $TARGETS +ENV SCRIPT python3 ../x.py dist --host=$TARGETS --target $TARGETS COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index f54ecef1e30..ae5bf8946dd 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -101,7 +101,9 @@ ENV SCRIPT python3 ../x.py build --set rust.debug=true opt-dist && \ ./build/$HOSTS/stage0-tools-bin/opt-dist linux-ci -- python3 ../x.py dist \ --host $HOSTS --target $HOSTS \ --include-default-paths \ - build-manifest bootstrap gcc + build-manifest bootstrap && \ + # Use GCC for building GCC, as it seems to behave badly when built with Clang + CC=/rustroot/bin/cc CXX=/rustroot/bin/c++ python3 ../x.py dist gcc ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang # This is the only builder which will create source tarballs diff --git a/src/ci/docker/host-x86_64/dist-x86_64-netbsd/build-netbsd-toolchain.sh b/src/ci/docker/host-x86_64/dist-x86_64-netbsd/build-netbsd-toolchain.sh index 4a42f5da29f..ad21836253b 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-netbsd/build-netbsd-toolchain.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-netbsd/build-netbsd-toolchain.sh @@ -41,8 +41,6 @@ cd netbsd mkdir -p /x-tools/x86_64-unknown-netbsd/sysroot -# URL=https://ci-mirrors.rust-lang.org/rustc - # Hashes come from https://cdn.netbsd.org/pub/NetBSD/security/hashes/NetBSD-9.0_hashes.asc SRC_SHA=2c791ae009a6929c6fc893ec5df7e62910ee8207e0b2159d6937309c03efe175b6ae1e445829a13d041b6851334ad35c521f2fa03c97675d4a05f1fafe58ede0 GNUSRC_SHA=3710085a73feecf6a843415271ec794c90146b03f6bbd30f07c9e0c79febf8995d557e40194f1e05db655e4f5ef2fae97563f8456fceaae65d4ea98857a83b1c @@ -51,22 +49,16 @@ SYSSRC_SHA=60b9ddf4cc6402256473e2e1eefeabd9001aa4e205208715ecc6d6fc3f5b400e46994 BASE_SHA=b5926b107cebf40c3c19b4f6cd039b610987dd7f819e7cdde3bd1e5230a856906e7930b15ab242d52ced9f0bda01d574be59488b8dbb95fa5df2987d0a70995f COMP_SHA=38ea54f30d5fc2afea87e5096f06873e00182789e8ad9cec0cb3e9f7c538c1aa4779e63fd401a36ba02676158e83fa5c95e8e87898db59c1914fb206aecd82d2 -# FIXME: the archive URL is being used temporarily while the CDN is down. -# We should serve this from our own CDN -# SOURCE_URL=https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.0/source/sets -SOURCE_URL=http://archive.netbsd.org/pub/NetBSD-archive/NetBSD-9.0/source/sets -download src.tgz "$SOURCE_URL/src.tgz" "$SRC_SHA" tar xzf src.tgz -download gnusrc.tgz "$SOURCE_URL/gnusrc.tgz" "$GNUSRC_SHA" tar xzf gnusrc.tgz -download sharesrc.tgz "$SOURCE_URL/sharesrc.tgz" "$SHARESRC_SHA" tar xzf sharesrc.tgz -download syssrc.tgz "$SOURCE_URL/syssrc.tgz" "$SYSSRC_SHA" tar xzf syssrc.tgz - -# FIXME: the archive URL is being used temporarily while the CDN is down. -# We should serve this from our own CDN -# BINARY_URL=https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.0/amd64/binary/sets -BINARY_URL=http://archive.netbsd.org/pub/NetBSD-archive/NetBSD-9.0/amd64/binary/sets -download base.tar.xz "$BINARY_URL/base.tar.xz" "$BASE_SHA" \ +SOURCE_URL=https://ci-mirrors.rust-lang.org/rustc/2025-03-14-netbsd-9.0-src +download src.tgz "$SOURCE_URL-src.tgz" "$SRC_SHA" tar xzf src.tgz +download gnusrc.tgz "$SOURCE_URL-gnusrc.tgz" "$GNUSRC_SHA" tar xzf gnusrc.tgz +download sharesrc.tgz "$SOURCE_URL-sharesrc.tgz" "$SHARESRC_SHA" tar xzf sharesrc.tgz +download syssrc.tgz "$SOURCE_URL-syssrc.tgz" "$SYSSRC_SHA" tar xzf syssrc.tgz + +BINARY_URL=https://ci-mirrors.rust-lang.org/rustc/2025-03-14-netbsd-9.0-amd64-binary +download base.tar.xz "$BINARY_URL-base.tar.xz" "$BASE_SHA" \ tar xJf base.tar.xz -C /x-tools/x86_64-unknown-netbsd/sysroot ./usr/include ./usr/lib ./lib -download comp.tar.xz "$BINARY_URL/comp.tar.xz" "$COMP_SHA" \ +download comp.tar.xz "$BINARY_URL-comp.tar.xz" "$COMP_SHA" \ tar xJf comp.tar.xz -C /x-tools/x86_64-unknown-netbsd/sysroot ./usr/include ./usr/lib cd usr/src diff --git a/src/ci/docker/host-x86_64/mingw-check/check-default-config-profiles.sh b/src/ci/docker/host-x86_64/mingw-check/check-default-config-profiles.sh index d706927d6d9..0c85d4b449d 100755 --- a/src/ci/docker/host-x86_64/mingw-check/check-default-config-profiles.sh +++ b/src/ci/docker/host-x86_64/mingw-check/check-default-config-profiles.sh @@ -8,5 +8,6 @@ config_dir="../src/bootstrap/defaults" # Loop through each configuration file in the directory for config_file in "$config_dir"/*.toml; do - python3 ../x.py check --config $config_file --dry-run + # Disable CI mode, because it is not compatible with all profiles + python3 ../x.py check --config $config_file --dry-run --ci=false done diff --git a/src/ci/docker/scripts/ohos-openssl.sh b/src/ci/docker/scripts/ohos-openssl.sh new file mode 100644 index 00000000000..713ab6131e3 --- /dev/null +++ b/src/ci/docker/scripts/ohos-openssl.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -ex + +URL=https://github.com/ohos-rs/ohos-openssl/archive/refs/tags/0.1.0.tar.gz + +mkdir -p /opt/ohos-openssl +curl -fL $URL | tar xz -C /opt/ohos-openssl --strip-components=1 diff --git a/src/ci/docker/scripts/ohos-sdk.sh b/src/ci/docker/scripts/ohos-sdk.sh index 321be2b8697..47d630ca76b 100755 --- a/src/ci/docker/scripts/ohos-sdk.sh +++ b/src/ci/docker/scripts/ohos-sdk.sh @@ -1,9 +1,10 @@ #!/bin/sh set -ex -URL=https://repo.huaweicloud.com/openharmony/os/4.0-Release/ohos-sdk-windows_linux-public.tar.gz +URL=https://repo.huaweicloud.com/openharmony/os/5.0.0-Release/ohos-sdk-windows_linux-public.tar.gz -curl $URL | tar xz -C /tmp ohos-sdk/linux/native-linux-x64-4.0.10.13-Release.zip +curl $URL | tar xz -C /tmp linux/native-linux-x64-5.0.0.71-Release.zip mkdir /opt/ohos-sdk cd /opt/ohos-sdk -unzip -qq /tmp/ohos-sdk/linux/native-linux-x64-4.0.10.13-Release.zip +unzip -qq /tmp/linux/native-linux-x64-5.0.0.71-Release.zip +rm /tmp/linux/native-linux-x64-5.0.0.71-Release.zip diff --git a/src/ci/docker/scripts/sccache.sh b/src/ci/docker/scripts/sccache.sh index f66671c64d2..dba617d8bc8 100644 --- a/src/ci/docker/scripts/sccache.sh +++ b/src/ci/docker/scripts/sccache.sh @@ -6,10 +6,10 @@ set -ex case "$(uname -m)" in x86_64) - url="https://ci-mirrors.rust-lang.org/rustc/2025-01-07-sccache-v0.9.1-x86_64-unknown-linux-musl" + url="https://ci-mirrors.rust-lang.org/rustc/2025-02-24-sccache-v0.10.0-x86_64-unknown-linux-musl" ;; aarch64) - url="https://ci-mirrors.rust-lang.org/rustc/2025-01-07-sccache-v0.9.1-aarch64-unknown-linux-musl" + url="https://ci-mirrors.rust-lang.org/rustc/2025-02-24-sccache-v0.10.0-aarch64-unknown-linux-musl" ;; *) echo "unsupported architecture: $(uname -m)" diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index d8c3625af28..f62ed23d038 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -82,15 +82,13 @@ envs: AWS_REGION: us-west-1 TOOLSTATE_PUBLISH: 1 + # Try builds started through `@bors try` (without specifying custom jobs + # in the PR description) will be passed the `DIST_TRY_BUILD` environment + # variable by citool. + # This tells the `opt-dist` tool to skip building certain components + # and skip running tests, so that the try build finishes faster. try: <<: *production - # The following env var activates faster `try` builds in `opt-dist` by, e.g. - # - building only the more commonly useful components (we rarely need e.g. rust-docs in try - # builds) - # - not running `opt-dist`'s post-optimization smoke tests on the resulting toolchain - # - # If you *want* these to happen however, temporarily comment it before triggering a try build. - DIST_TRY_BUILD: 1 auto: <<: *production @@ -176,7 +174,7 @@ auto: <<: *job-linux-4c - name: dist-ohos - <<: *job-linux-4c + <<: *job-linux-4c-largedisk - name: dist-powerpc-linux <<: *job-linux-4c @@ -262,13 +260,16 @@ auto: - name: test-various <<: *job-linux-4c - - name: x86_64-fuchsia - # Only run this job on the nightly channel. Fuchsia requires - # nightly features to compile, and this job would fail if - # executed on beta and stable. - only_on_channel: nightly - doc_url: https://rustc-dev-guide.rust-lang.org/tests/fuchsia.html - <<: *job-linux-8c + # FIXME: temporarily disabled due to fuchsia server rate limits. See + # <https://rust-lang.zulipchat.com/#narrow/channel/242791-t-infra/topic/fuchsia.20failure/with/506637259>. + # + #- name: x86_64-fuchsia + # # Only run this job on the nightly channel. Fuchsia requires + # # nightly features to compile, and this job would fail if + # # executed on beta and stable. + # only_on_channel: nightly + # doc_url: https://rustc-dev-guide.rust-lang.org/tests/fuchsia.html + # <<: *job-linux-8c # Tests integration with Rust for Linux. # Builds stage 1 compiler and tries to compile a few RfL examples with it. diff --git a/src/ci/run.sh b/src/ci/run.sh index 54fbf8b6912..6980d8220e5 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -112,7 +112,11 @@ export RUST_RELEASE_CHANNEL=$(releaseChannel) RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --release-channel=$RUST_RELEASE_CHANNEL" if [ "$DEPLOY$DEPLOY_ALT" = "1" ]; then - RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp" + if [[ "$CI_JOB_NAME" == *ohos* ]]; then + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-static-stdcpp" + else + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-static-stdcpp" + fi RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.remap-debuginfo" if [ "$DEPLOY_ALT" != "" ] && isLinux; then @@ -225,8 +229,8 @@ trap datecheck EXIT # sccache server at the start of the build, but no need to worry if this fails. SCCACHE_IDLE_TIMEOUT=10800 sccache --start-server || true -# Our build may overwrite config.toml, so we remove it here -rm -f config.toml +# Our build may overwrite bootstrap.toml, so we remove it here +rm -f bootstrap.toml $SRC/configure $RUST_CONFIGURE_ARGS @@ -261,5 +265,5 @@ else fi echo "::group::sccache stats" -sccache --show-stats || true +sccache --show-adv-stats || true echo "::endgroup::" diff --git a/src/ci/scripts/install-sccache.sh b/src/ci/scripts/install-sccache.sh index e143152f330..b055e76a805 100755 --- a/src/ci/scripts/install-sccache.sh +++ b/src/ci/scripts/install-sccache.sh @@ -8,11 +8,13 @@ IFS=$'\n\t' source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" if isMacOS; then - curl -fo /usr/local/bin/sccache "${MIRRORS_BASE}/2021-08-25-sccache-v0.2.15-x86_64-apple-darwin" + curl -fo /usr/local/bin/sccache \ + "${MIRRORS_BASE}/2025-02-24-sccache-v0.10.0-x86_64-apple-darwin" chmod +x /usr/local/bin/sccache elif isWindows; then mkdir -p sccache - curl -fo sccache/sccache.exe "${MIRRORS_BASE}/2018-04-26-sccache-x86_64-pc-windows-msvc" + curl -fo sccache/sccache.exe \ + "${MIRRORS_BASE}/2025-02-24-sccache-v0.10.0-x86_64-pc-windows-msvc.exe" ciCommandAddPath "$(pwd)/sccache" fi diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index eb779d9ab05..6baf43397e8 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -8536f201ffdb2c24925d7f9e87996d7dca93428b +493c38ba371929579fe136df26eccd9516347c7a diff --git a/src/doc/rustc-dev-guide/src/backend/debugging.md b/src/doc/rustc-dev-guide/src/backend/debugging.md index 805291017c2..4f8712dfaf3 100644 --- a/src/doc/rustc-dev-guide/src/backend/debugging.md +++ b/src/doc/rustc-dev-guide/src/backend/debugging.md @@ -38,7 +38,7 @@ which means that LLVM assertion failures can show up as compiler crashes (not ICEs but "real" crashes) and other sorts of weird behavior. If you are encountering these, it is a good idea to try using a compiler with LLVM assertions enabled - either an "alt" nightly or a compiler you build yourself -by setting `[llvm] assertions=true` in your config.toml - and see whether +by setting `[llvm] assertions=true` in your bootstrap.toml - and see whether anything turns up. The rustc build process builds the LLVM tools into @@ -160,7 +160,7 @@ from `./build/<host-triple>/llvm/bin/` with the LLVM IR emitted by rustc. When investigating the implementation of LLVM itself, you should be aware of its [internal debug infrastructure][llvm-debug]. This is provided in LLVM Debug builds, which you enable for rustc -LLVM builds by changing this setting in the config.toml: +LLVM builds by changing this setting in the bootstrap.toml: ``` [llvm] # Indicates whether the LLVM assertions are enabled or not diff --git a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md index 0b45956b160..18c822aad79 100644 --- a/src/doc/rustc-dev-guide/src/backend/updating-llvm.md +++ b/src/doc/rustc-dev-guide/src/backend/updating-llvm.md @@ -144,7 +144,7 @@ so let's go through each in detail. Note that `profile = "compiler"` and other defaults set by `./x setup` download LLVM from CI instead of building it from source. You should disable this temporarily to make sure your changes are being used. - This is done by having the following setting in `config.toml`: + This is done by having the following setting in `bootstrap.toml`: ```toml [llvm] diff --git a/src/doc/rustc-dev-guide/src/building/compiler-documenting.md b/src/doc/rustc-dev-guide/src/building/compiler-documenting.md index 948571ce82e..b031462ea15 100644 --- a/src/doc/rustc-dev-guide/src/building/compiler-documenting.md +++ b/src/doc/rustc-dev-guide/src/building/compiler-documenting.md @@ -36,7 +36,7 @@ like the standard library (std) or the compiler (rustc). - Document internal rustc items Compiler documentation is not built by default. - To create it by default with `x doc`, modify `config.toml`: + To create it by default with `x doc`, modify `bootstrap.toml`: ```toml [build] diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index f9a089c23f2..067e2871118 100644 --- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md @@ -159,15 +159,15 @@ similar to the one declared in section [What is `x.py`](#what-is-xpy), but it works as an independent process to execute the `x.py` rather than calling the shell to run the platform related scripts. -## Create a `config.toml` +## Create a `bootstrap.toml` To start, run `./x setup` and select the `compiler` defaults. This will do some initialization -and create a `config.toml` for you with reasonable defaults. If you use a different default (which +and create a `bootstrap.toml` for you with reasonable defaults. If you use a different default (which you'll likely want to do if you want to contribute to an area of rust other than the compiler, such as rustdoc), make sure to read information about that default (located in `src/bootstrap/defaults`) as the build process may be different for other defaults. -Alternatively, you can write `config.toml` by hand. See `config.example.toml` for all the available +Alternatively, you can write `bootstrap.toml` by hand. See `bootstrap.example.toml` for all the available settings and explanations of them. See `src/bootstrap/defaults` for common settings to change. If you have already built `rustc` and you change settings related to LLVM, then you may have to @@ -206,7 +206,7 @@ See the chapters on Note that building will require a relatively large amount of storage space. You may want to have upwards of 10 or 15 gigabytes available to build the compiler. -Once you've created a `config.toml`, you are now ready to run +Once you've created a `bootstrap.toml`, you are now ready to run `x`. There are a lot of options here, but let's start with what is probably the best "go to" command for building a local compiler: @@ -326,7 +326,7 @@ involve proc macros or build scripts, you must be sure to explicitly build targe host platform (in this case, `x86_64-unknown-linux-gnu`). If you want to always build for other targets without needing to pass flags to `x build`, -you can configure this in the `[build]` section of your `config.toml` like so: +you can configure this in the `[build]` section of your `bootstrap.toml` like so: ```toml [build] @@ -336,8 +336,8 @@ target = ["x86_64-unknown-linux-gnu", "wasm32-wasip1"] Note that building for some targets requires having external dependencies installed (e.g. building musl targets requires a local copy of musl). Any target-specific configuration (e.g. the path to a local copy of musl) -will need to be provided by your `config.toml`. -Please see `config.example.toml` for information on target-specific configuration keys. +will need to be provided by your `bootstrap.toml`. +Please see `bootstrap.example.toml` for information on target-specific configuration keys. For examples of the complete configuration necessary to build a target, please visit [the rustc book](https://doc.rust-lang.org/rustc/platform-support.html), diff --git a/src/doc/rustc-dev-guide/src/building/new-target.md b/src/doc/rustc-dev-guide/src/building/new-target.md index 14d10d4a59d..09ffbe8c882 100644 --- a/src/doc/rustc-dev-guide/src/building/new-target.md +++ b/src/doc/rustc-dev-guide/src/building/new-target.md @@ -37,7 +37,7 @@ able to configure Rust to treat your build as the system LLVM to avoid redundant builds. You can tell Rust to use a pre-built version of LLVM using the `target` section -of `config.toml`: +of `bootstrap.toml`: ```toml [target.x86_64-unknown-linux-gnu] @@ -55,8 +55,8 @@ for codegen tests. This tool is normally built with LLVM, but if you use your own preinstalled LLVM, you will need to provide `FileCheck` in some other way. On Debian-based systems, you can install the `llvm-N-tools` package (where `N` is the LLVM version number, e.g. `llvm-8-tools`). Alternately, you can specify -the path to `FileCheck` with the `llvm-filecheck` config item in `config.toml` -or you can disable codegen test with the `codegen-tests` item in `config.toml`. +the path to `FileCheck` with the `llvm-filecheck` config item in `bootstrap.toml` +or you can disable codegen test with the `codegen-tests` item in `bootstrap.toml`. ## Creating a target specification @@ -141,14 +141,14 @@ After this, run `cargo update -p libc` to update the lockfiles. Beware that if you patch to a local `path` dependency, this will enable warnings for that dependency. Some dependencies are not warning-free, and due -to the `deny-warnings` setting in `config.toml`, the build may suddenly start +to the `deny-warnings` setting in `bootstrap.toml`, the build may suddenly start to fail. To work around warnings, you may want to: - Modify the dependency to remove the warnings -- Or for local development purposes, suppress the warnings by setting deny-warnings = false in config.toml. +- Or for local development purposes, suppress the warnings by setting deny-warnings = false in bootstrap.toml. ```toml -# config.toml +# bootstrap.toml [rust] deny-warnings = false ``` diff --git a/src/doc/rustc-dev-guide/src/building/optimized-build.md b/src/doc/rustc-dev-guide/src/building/optimized-build.md index f8ca1d0dc39..0849464eab3 100644 --- a/src/doc/rustc-dev-guide/src/building/optimized-build.md +++ b/src/doc/rustc-dev-guide/src/building/optimized-build.md @@ -13,7 +13,7 @@ This page describes how you can use these approaches when building `rustc` yours Link-time optimization is a powerful compiler technique that can increase program performance. To enable (Thin-)LTO when building `rustc`, set the `rust.lto` config option to `"thin"` -in `config.toml`: +in `bootstrap.toml`: ```toml [rust] @@ -34,7 +34,7 @@ Enabling LTO on Linux has [produced] speed-ups by up to 10%. Using a different memory allocator for `rustc` can provide significant performance benefits. If you want to enable the `jemalloc` allocator, you can set the `rust.jemalloc` option to `true` -in `config.toml`: +in `bootstrap.toml`: ```toml [rust] @@ -46,7 +46,7 @@ jemalloc = true ## Codegen units Reducing the amount of codegen units per `rustc` crate can produce a faster build of the compiler. -You can modify the number of codegen units for `rustc` and `libstd` in `config.toml` with the +You can modify the number of codegen units for `rustc` and `libstd` in `bootstrap.toml` with the following options: ```toml @@ -67,7 +67,7 @@ RUSTFLAGS="-C target_cpu=x86-64-v3" ./x build ... ``` If you also want to compile LLVM for a specific instruction set, you can set `llvm` flags -in `config.toml`: +in `bootstrap.toml`: ```toml [llvm] diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index 2498838144e..43ff2ba726f 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -123,6 +123,30 @@ Another way is without a plugin, and creating your own logic in your configuration. The following code will work for any checkout of rust-lang/rust (newer than Febuary 2025): ```lua +local function expand_config_variables(option) + local var_placeholders = { + ['${workspaceFolder}'] = function(_) + return vim.lsp.buf.list_workspace_folders()[1] + end, + } + + if type(option) == "table" then + local mt = getmetatable(option) + local result = {} + for k, v in pairs(option) do + result[expand_config_variables(k)] = expand_config_variables(v) + end + return setmetatable(result, mt) + end + if type(option) ~= "string" then + return option + end + local ret = option + for key, fn in pairs(var_placeholders) do + ret = ret:gsub(key, fn) + end + return ret +end lspconfig.rust_analyzer.setup { root_dir = function() local default = lspconfig.rust_analyzer.config_def.default_config.root_dir() @@ -142,7 +166,7 @@ lspconfig.rust_analyzer.setup { -- load rust-lang/rust settings local file = io.open(config) local json = vim.json.decode(file:read("*a")) - client.config.settings["rust-analyzer"] = json.lsp["rust-analyzer"].initialization_options + client.config.settings["rust-analyzer"] = expand_config_variables(json.lsp["rust-analyzer"].initialization_options) client.notify("workspace/didChangeConfiguration", { settings = client.config.settings }) end return true @@ -305,7 +329,7 @@ subsequent rebuilds: ``` If you don't want to include the flag with every command, you can enable it in -the `config.toml`: +the `bootstrap.toml`: ```toml [rust] @@ -384,20 +408,20 @@ ln -s ./src/tools/nix-dev-shell/envrc-shell ./.envrc # Use nix-shell ### Note Note that when using nix on a not-NixOS distribution, it may be necessary to set -**`patch-binaries-for-nix = true` in `config.toml`**. Bootstrap tries to detect +**`patch-binaries-for-nix = true` in `bootstrap.toml`**. Bootstrap tries to detect whether it's running in nix and enable patching automatically, but this detection can have false negatives. -You can also use your nix shell to manage `config.toml`: +You can also use your nix shell to manage `bootstrap.toml`: ```nix let config = pkgs.writeText "rustc-config" '' - # Your config.toml content goes here + # Your bootstrap.toml content goes here '' pkgs.mkShell { /* ... */ - # This environment variable tells bootstrap where our config.toml is. + # This environment variable tells bootstrap where our bootstrap.toml is. RUST_BOOTSTRAP_CONFIG = config; } ``` diff --git a/src/doc/rustc-dev-guide/src/compiler-debugging.md b/src/doc/rustc-dev-guide/src/compiler-debugging.md index c16b3ee7abd..47f39762022 100644 --- a/src/doc/rustc-dev-guide/src/compiler-debugging.md +++ b/src/doc/rustc-dev-guide/src/compiler-debugging.md @@ -11,13 +11,13 @@ chapter](./backend/debugging.md)). ## Configuring the compiler By default, rustc is built without most debug information. To enable debug info, -set `debug = true` in your config.toml. +set `debug = true` in your bootstrap.toml. Setting `debug = true` turns on many different debug options (e.g., `debug-assertions`, `debug-logging`, etc.) which can be individually tweaked if you want to, but many people simply set `debug = true`. -If you want to use GDB to debug rustc, please set `config.toml` with options: +If you want to use GDB to debug rustc, please set `bootstrap.toml` with options: ```toml [rust] @@ -35,14 +35,14 @@ debuginfo-level = 2 The default configuration will enable `symbol-mangling-version` v0. This requires at least GDB v10.2, -otherwise you need to disable new symbol-mangling-version in `config.toml`. +otherwise you need to disable new symbol-mangling-version in `bootstrap.toml`. ```toml [rust] new-symbol-mangling = false ``` -> See the comments in `config.example.toml` for more info. +> See the comments in `bootstrap.example.toml` for more info. You will need to rebuild the compiler after changing any configuration option. @@ -373,7 +373,7 @@ error: aborting due to previous error ## Configuring CodeLLDB for debugging `rustc` -If you are using VSCode, and have edited your `config.toml` to request debugging +If you are using VSCode, and have edited your `bootstrap.toml` to request debugging level 1 or 2 for the parts of the code you're interested in, then you should be able to use the [CodeLLDB] extension in VSCode to debug it. diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index 9817326f07b..09a7f912b98 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -81,7 +81,7 @@ smaller user-facing changes. into a PR that ends up not getting merged!** [See this document][mcpinfo] for more info on MCPs. -[mcpinfo]: https://forge.rust-lang.org/compiler/mcp.html +[mcpinfo]: https://forge.rust-lang.org/compiler/proposals-and-stabilization.html#how-do-i-submit-an-mcp [zulip]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler ### Performance diff --git a/src/doc/rustc-dev-guide/src/fuzzing.md b/src/doc/rustc-dev-guide/src/fuzzing.md index 869fc2f71cc..b588ca104cb 100644 --- a/src/doc/rustc-dev-guide/src/fuzzing.md +++ b/src/doc/rustc-dev-guide/src/fuzzing.md @@ -123,7 +123,7 @@ what actually results in superior throughput. You may want to build rustc from source with debug assertions to find additional bugs, though this is a trade-off: it can slow down fuzzing by requiring extra work for every execution. To enable debug assertions, add this -to `config.toml` when compiling rustc: +to `bootstrap.toml` when compiling rustc: ```toml [rust] diff --git a/src/doc/rustc-dev-guide/src/implementing_new_features.md b/src/doc/rustc-dev-guide/src/implementing_new_features.md index fda38ef4fc0..d7561bbbad2 100644 --- a/src/doc/rustc-dev-guide/src/implementing_new_features.md +++ b/src/doc/rustc-dev-guide/src/implementing_new_features.md @@ -44,7 +44,7 @@ like this; for example, the compiler team recommends filing a Major Change Proposal ([MCP][mcp]) as a lightweight way to garner support and feedback without requiring full consensus. -[mcp]: https://forge.rust-lang.org/compiler/mcp.html#public-facing-changes-require-rfcbot-fcp +[mcp]: https://forge.rust-lang.org/compiler/proposals-and-stabilization.html#how-do-i-submit-an-mcp You don't need to have the implementation fully ready for r+ to propose an FCP, but it is generally a good idea to have at least a proof diff --git a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md index 3078ae094c3..6bc21b6deeb 100644 --- a/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md +++ b/src/doc/rustc-dev-guide/src/llvm-coverage-instrumentation.md @@ -34,7 +34,7 @@ Detailed instructions and examples are documented in the [coverage map]: https://llvm.org/docs/CoverageMappingFormat.html [rustc-book-instrument-coverage]: https://doc.rust-lang.org/nightly/rustc/instrument-coverage.html -## Recommended `config.toml` settings +## Recommended `bootstrap.toml` settings When working on the coverage instrumentation code, it is usually necessary to **enable the profiler runtime** by setting `profiler = true` in `[build]`. @@ -83,7 +83,7 @@ statically links coverage-instrumented binaries with LLVM runtime code In the `rustc` source tree, `library/profiler_builtins` bundles the LLVM `compiler-rt` code into a Rust library crate. Note that when building `rustc`, -`profiler_builtins` is only included when `build.profiler = true` is set in `config.toml`. +`profiler_builtins` is only included when `build.profiler = true` is set in `bootstrap.toml`. When compiling with `-C instrument-coverage`, [`CrateLoader::postprocess()`][crate-loader-postprocess] dynamically loads @@ -115,7 +115,7 @@ human-readable coverage report. > Tests in `coverage-run` mode have an implicit `//@ needs-profiler-runtime` > directive, so they will be skipped if the profiler runtime has not been -> [enabled in `config.toml`](#recommended-configtoml-settings). +> [enabled in `bootstrap.toml`](#recommended-configtoml-settings). Finally, the [`tests/codegen/instrument-coverage/testprog.rs`] test compiles a simple Rust program with `-C instrument-coverage` and compares the compiled program's LLVM IR to diff --git a/src/doc/rustc-dev-guide/src/notification-groups/about.md b/src/doc/rustc-dev-guide/src/notification-groups/about.md index 74629aa08ac..af305f0103a 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/about.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/about.md @@ -23,7 +23,7 @@ Here's the list of the notification groups: - [ARM](./arm.md) - [Cleanup Crew](./cleanup-crew.md) - [Emscripten](./emscripten.md) -- [LLVM](./llvm.md) +- [LLVM Icebreakers](./llvm.md) - [RISC-V](./risc-v.md) - [WASI](./wasi.md) - [WebAssembly](./wasm.md) @@ -83,7 +83,7 @@ group. For example: @rustbot ping arm @rustbot ping cleanup-crew @rustbot ping emscripten -@rustbot ping llvm +@rustbot ping icebreakers-llvm @rustbot ping risc-v @rustbot ping wasi @rustbot ping wasm diff --git a/src/doc/rustc-dev-guide/src/notification-groups/llvm.md b/src/doc/rustc-dev-guide/src/notification-groups/llvm.md index 2eff63713a9..9d008728543 100644 --- a/src/doc/rustc-dev-guide/src/notification-groups/llvm.md +++ b/src/doc/rustc-dev-guide/src/notification-groups/llvm.md @@ -1,13 +1,16 @@ -# LLVM Notification group +# LLVM Icebreakers Notification group **Github Label:** [A-LLVM] <br> -**Ping command:** `@rustbot ping llvm` +**Ping command:** `@rustbot ping icebreakers-llvm` [A-LLVM]: https://github.com/rust-lang/rust/labels/A-LLVM -The "LLVM Notification Group" are focused on bugs that center around LLVM. -These bugs often arise because of LLVM optimizations gone awry, or as -the result of an LLVM upgrade. The goal here is: +*Note*: this notification group is *not* the same as the LLVM working group +(WG-llvm). + +The "LLVM Icebreakers Notification Group" are focused on bugs that center around +LLVM. These bugs often arise because of LLVM optimizations gone awry, or as the +result of an LLVM upgrade. The goal here is: - to determine whether the bug is a result of us generating invalid LLVM IR, or LLVM misoptimizing; diff --git a/src/doc/rustc-dev-guide/src/overview.md b/src/doc/rustc-dev-guide/src/overview.md index 21ab0040646..92d0c7b0c38 100644 --- a/src/doc/rustc-dev-guide/src/overview.md +++ b/src/doc/rustc-dev-guide/src/overview.md @@ -351,7 +351,7 @@ approach is to turn [`RefCell`]s into [`Mutex`]s -- that is, we switch to thread-safe internal mutability. However, there are ongoing challenges with lock contention, maintaining query-system invariants under concurrency, and the complexity of the code base. One can try out the current -work by enabling parallel compilation in `config.toml`. It's still early days, +work by enabling parallel compilation in `bootstrap.toml`. It's still early days, but there are already some promising performance improvements. [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html diff --git a/src/doc/rustc-dev-guide/src/profile-guided-optimization.md b/src/doc/rustc-dev-guide/src/profile-guided-optimization.md index 995752b0b8b..39bc8b5e862 100644 --- a/src/doc/rustc-dev-guide/src/profile-guided-optimization.md +++ b/src/doc/rustc-dev-guide/src/profile-guided-optimization.md @@ -120,7 +120,7 @@ The `rustc` version of this can be found in `library/profiler_builtins` which basically packs the C code from `compiler-rt` into a Rust crate. In order for `profiler_builtins` to be built, `profiler = true` must be set -in `rustc`'s `config.toml`. +in `rustc`'s `bootstrap.toml`. [compiler-rt-profile]: https://github.com/llvm/llvm-project/tree/main/compiler-rt/lib/profile diff --git a/src/doc/rustc-dev-guide/src/profiling.md b/src/doc/rustc-dev-guide/src/profiling.md index df987e00a58..de06bd7cda7 100644 --- a/src/doc/rustc-dev-guide/src/profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling.md @@ -87,7 +87,7 @@ Example output for the compiler: Since this doesn't seem to work with incremental compilation or `./x check`, you will be compiling rustc _a lot_. -I recommend changing a few settings in `config.toml` to make it bearable: +I recommend changing a few settings in `bootstrap.toml` to make it bearable: ``` [rust] # A debug build takes _a third_ as long on my machine, diff --git a/src/doc/rustc-dev-guide/src/profiling/with_perf.md b/src/doc/rustc-dev-guide/src/profiling/with_perf.md index 51a22d18577..742ea1c41a6 100644 --- a/src/doc/rustc-dev-guide/src/profiling/with_perf.md +++ b/src/doc/rustc-dev-guide/src/profiling/with_perf.md @@ -6,7 +6,7 @@ This is a guide for how to profile rustc with [perf](https://perf.wiki.kernel.or - Get a clean checkout of rust-lang/master, or whatever it is you want to profile. -- Set the following settings in your `config.toml`: +- Set the following settings in your `bootstrap.toml`: - `debuginfo-level = 1` - enables line debuginfo - `jemalloc = false` - lets you do memory use profiling with valgrind - leave everything else the defaults diff --git a/src/doc/rustc-dev-guide/src/profiling/with_rustc_perf.md b/src/doc/rustc-dev-guide/src/profiling/with_rustc_perf.md index eda8c3a179c..c47fed24e6e 100644 --- a/src/doc/rustc-dev-guide/src/profiling/with_rustc_perf.md +++ b/src/doc/rustc-dev-guide/src/profiling/with_rustc_perf.md @@ -9,7 +9,7 @@ which will download and build the suite for you, build a local compiler toolchai You can use the `./x perf <command> [options]` command to use this integration. -You can use normal bootstrap flags for this command, such as `--stage 1` or `--stage 2`, for example to modify the stage of the created sysroot. It might also be useful to configure `config.toml` to better support profiling, e.g. set `rust.debuginfo-level = 1` to add source line information to the built compiler. +You can use normal bootstrap flags for this command, such as `--stage 1` or `--stage 2`, for example to modify the stage of the created sysroot. It might also be useful to configure `bootstrap.toml` to better support profiling, e.g. set `rust.debuginfo-level = 1` to add source line information to the built compiler. `x perf` currently supports the following commands: - `benchmark <id>`: Benchmark the compiler and store the results under the passed `id`. diff --git a/src/doc/rustc-dev-guide/src/profiling/wpa_profiling.md b/src/doc/rustc-dev-guide/src/profiling/wpa_profiling.md index a800c5717e3..d2680d40853 100644 --- a/src/doc/rustc-dev-guide/src/profiling/wpa_profiling.md +++ b/src/doc/rustc-dev-guide/src/profiling/wpa_profiling.md @@ -44,7 +44,7 @@ compiler we're using to build rustc will aid our analysis greatly by allowing WP symbols correctly. Unfortunately, the stage 0 compiler does not have symbols turned on which is why we'll need to build a stage 1 compiler and then a stage 2 compiler ourselves. -To do this, make sure you have set `debuginfo-level = 1` in your `config.toml` file. This tells +To do this, make sure you have set `debuginfo-level = 1` in your `bootstrap.toml` file. This tells rustc to generate debug information which includes stack frames when bootstrapping. Now you can build the stage 1 compiler: `x build --stage 1 -i library` or however diff --git a/src/doc/rustc-dev-guide/src/rustdoc.md b/src/doc/rustc-dev-guide/src/rustdoc.md index 2a0e212f98e..356698148e4 100644 --- a/src/doc/rustc-dev-guide/src/rustdoc.md +++ b/src/doc/rustc-dev-guide/src/rustdoc.md @@ -58,12 +58,12 @@ does is call the `main()` that's in this crate's `lib.rs`, though.) * If you want to copy those docs to a webserver, copy all of `build/host/doc`, since that's where the CSS, JS, fonts, and landing page are. - * For frontend debugging, disable the `rust.docs-minification` option in [`config.toml`]. + * For frontend debugging, disable the `rust.docs-minification` option in [`bootstrap.toml`]. * Use `./x test tests/rustdoc*` to run the tests using a stage1 rustdoc. * See [Rustdoc internals] for more information about tests. -[`config.toml`]: ./building/how-to-build-and-run.md +[`bootstrap.toml`]: ./building/how-to-build-and-run.md ## Code structure diff --git a/src/doc/rustc-dev-guide/src/sanitizers.md b/src/doc/rustc-dev-guide/src/sanitizers.md index 73e888eae68..b1654b15e08 100644 --- a/src/doc/rustc-dev-guide/src/sanitizers.md +++ b/src/doc/rustc-dev-guide/src/sanitizers.md @@ -32,7 +32,7 @@ implementation: * The sanitizer runtime libraries are part of the [compiler-rt] project, and [will be built][sanitizer-build] on [supported targets][sanitizer-targets] - when enabled in `config.toml`: + when enabled in `bootstrap.toml`: ```toml [build] @@ -80,7 +80,7 @@ Sanitizers are validated by code generation tests in [`tests/ui/sanitizer/`][test-ui] directory. Testing sanitizer functionality requires the sanitizer runtimes (built when -`sanitizer = true` in `config.toml`) and target providing support for particular +`sanitizer = true` in `bootstrap.toml`) and target providing support for particular sanitizer. When sanitizer is unsupported on given target, sanitizers tests will be ignored. This behaviour is controlled by compiletest `needs-sanitizer-*` directives. diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md index 0c0f750a45d..c04f296ba0b 100644 --- a/src/doc/rustc-dev-guide/src/tests/ci.md +++ b/src/doc/rustc-dev-guide/src/tests/ci.md @@ -180,6 +180,8 @@ their results can be seen [here](https://github.com/rust-lang-ci/rust/actions), although usually you will be notified of the result by a comment made by bors on the corresponding PR. +Note that if you start the default try job using `@bors try`, it will skip building several `dist` components and running post-optimization tests, to make the build duration shorter. If you want to execute the full build as it would happen before a merge, add an explicit `try-job` pattern with the name of the default try job (currently `dist-x86_64-linux`). + Multiple try builds can execute concurrently across different PRs. <div class="warning"> @@ -435,7 +437,7 @@ To learn more about the dashboard, see the [Datadog CI docs]. ## Determining the CI configuration -If you want to determine which `config.toml` settings are used in CI for a +If you want to determine which `bootstrap.toml` settings are used in CI for a particular job, it is probably easiest to just look at the build log. To do this: diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index a6996e39822..2c35381eadf 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -525,10 +525,10 @@ data into a human-readable code coverage report. Instrumented binaries need to be linked against the LLVM profiler runtime, so `coverage-run` tests are **automatically skipped** unless the profiler runtime -is enabled in `config.toml`: +is enabled in `bootstrap.toml`: ```toml -# config.toml +# bootstrap.toml [build] profiler = true ``` diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index d5b896a8eee..81aa35f1a46 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -160,9 +160,9 @@ settings: stable support for `asm!` - `needs-profiler-runtime` — ignores the test if the profiler runtime was not enabled for the target - (`build.profiler = true` in rustc's `config.toml`) + (`build.profiler = true` in rustc's `bootstrap.toml`) - `needs-sanitizer-support` — ignores if the sanitizer support was not enabled - for the target (`sanitizers = true` in rustc's `config.toml`) + for the target (`sanitizers = true` in rustc's `bootstrap.toml`) - `needs-sanitizer-{address,hwaddress,leak,memory,thread}` — ignores if the corresponding sanitizer is not enabled for the target (AddressSanitizer, hardware-assisted AddressSanitizer, LeakSanitizer, MemorySanitizer or @@ -172,7 +172,7 @@ settings: flag, or running on fuchsia. - `needs-unwind` — ignores if the target does not support unwinding - `needs-rust-lld` — ignores if the rust lld support is not enabled (`rust.lld = - true` in `config.toml`) + true` in `bootstrap.toml`) - `needs-threads` — ignores if the target does not have threading support - `needs-subprocess` — ignores if the target does not have subprocess support - `needs-symlink` — ignores if the target does not support symlinks. This can be diff --git a/src/doc/rustc-dev-guide/src/tests/docker.md b/src/doc/rustc-dev-guide/src/tests/docker.md index a8a388ef90c..032da1ca1e8 100644 --- a/src/doc/rustc-dev-guide/src/tests/docker.md +++ b/src/doc/rustc-dev-guide/src/tests/docker.md @@ -21,7 +21,7 @@ The [`src/ci/docker/run.sh`] script is used to build a specific Docker image, ru build Rust within the image, and either run tests or prepare a set of archives designed for distribution. The script will mount your local Rust source tree in read-only mode, and an `obj` directory in read-write mode. All the compiler artifacts will be stored in the `obj` directory. The shell will start out in the `obj`directory. From there, it will execute `../src/ci/run.sh` which starts the build as defined by the Docker image. You can run `src/ci/docker/run.sh <image-name>` directly. A few important notes regarding the `run.sh` script: -- When executed on CI, the script expects that all submodules are checked out. If some submodule that is accessed by the job is not available, the build will result in an error. You should thus make sure that you have all required submodules checked out locally. You can either do that manually through git, or set `submodules = true` in your `config.toml` and run a command such as `x build` to let bootstrap download the most important submodules (this might not be enough for the given CI job that you are trying to execute though). +- When executed on CI, the script expects that all submodules are checked out. If some submodule that is accessed by the job is not available, the build will result in an error. You should thus make sure that you have all required submodules checked out locally. You can either do that manually through git, or set `submodules = true` in your `bootstrap.toml` and run a command such as `x build` to let bootstrap download the most important submodules (this might not be enough for the given CI job that you are trying to execute though). - `<image-name>` corresponds to a single directory located in one of the `src/ci/docker/host-*` directories. Note that image name does not necessarily correspond to a job name, as some jobs execute the same image, but with different environment variables or Docker build arguments (this is a part of the complexity that makes it difficult to run CI jobs locally). - If you are executing a "dist" job (job beginning with `dist-`), you should set the `DEPLOY=1` environment variable. - If you are executing an "alternative dist" job (job beginning with `dist-` and ending with `-alt`), you should set the `DEPLOY_ALT=1` environment variable. diff --git a/src/doc/rustc-dev-guide/src/tests/running.md b/src/doc/rustc-dev-guide/src/tests/running.md index 03d4123cb02..73c38736812 100644 --- a/src/doc/rustc-dev-guide/src/tests/running.md +++ b/src/doc/rustc-dev-guide/src/tests/running.md @@ -18,7 +18,7 @@ a subset of test collections, and merge queue CI will exercise all of the test collection. </div> -```bash +```text ./x test ``` @@ -45,7 +45,7 @@ tests. For example, a good "smoke test" that can be used after modifying rustc to see if things are generally working correctly would be to exercise the `ui` test suite ([`tests/ui`]): -```bash +```text ./x test tests/ui ``` @@ -53,14 +53,14 @@ Of course, the choice of test suites is somewhat arbitrary, and may not suit the task you are doing. For example, if you are hacking on debuginfo, you may be better off with the debuginfo test suite: -```bash +```text ./x test tests/debuginfo ``` If you only need to test a specific subdirectory of tests for any given test suite, you can pass that directory as a filter to `./x test`: -```bash +```text ./x test tests/ui/const-generics ``` @@ -73,7 +73,7 @@ suite, you can pass that directory as a filter to `./x test`: Likewise, you can test a single file by passing its path: -```bash +```text ./x test tests/ui/const-generics/const-test.rs ``` @@ -81,19 +81,19 @@ Likewise, you can test a single file by passing its path: have to use the `--test-args` argument as described [below](#running-an-individual-test). -```bash +```text ./x test src/tools/miri --test-args tests/fail/uninit/padding-enum.rs ``` ### Run only the tidy script -```bash +```text ./x test tidy ``` ### Run tests on the standard library -```bash +```text ./x test --stage 0 library/std ``` @@ -102,13 +102,13 @@ crates, you have to specify those explicitly. ### Run the tidy script and tests on the standard library -```bash +```text ./x test --stage 0 tidy library/std ``` ### Run tests on the standard library using a stage 1 compiler -```bash +```text ./x test --stage 1 library/std ``` @@ -122,7 +122,7 @@ the tests **usually** work fine with stage 1, there are some limitations. ### Run all tests using a stage 2 compiler -```bash +```text ./x test --stage 2 ``` @@ -134,13 +134,13 @@ You almost never need to do this; CI will run these tests for you. You may want to run unit tests on a specific file with following: -```bash +```text ./x test compiler/rustc_data_structures/src/thin_vec/tests.rs ``` But unfortunately, it's impossible. You should invoke the following instead: -```bash +```text ./x test compiler/rustc_data_structures/ --test-args thin_vec ``` @@ -151,7 +151,7 @@ often the test they are trying to fix. As mentioned earlier, you may pass the full file path to achieve this, or alternatively one may invoke `x` with the `--test-args` option: -```bash +```text ./x test tests/ui --test-args issue-1234 ``` @@ -189,7 +189,7 @@ just like when running the tests without the `--bless` flag. There are a few options for running tests: -* `config.toml` has the `rust.verbose-tests` option. If `false`, each test will +* `bootstrap.toml` has the `rust.verbose-tests` option. If `false`, each test will print a single dot (the default). If `true`, the name of every test will be printed. This is equivalent to the `--quiet` option in the [Rust test harness](https://doc.rust-lang.org/rustc/tests/). @@ -203,7 +203,7 @@ When `--pass $mode` is passed, these tests will be forced to run under the given `$mode` unless the directive `//@ ignore-pass` exists in the test file. For example, you can run all the tests in `tests/ui` as `check-pass`: -```bash +```text ./x test tests/ui --pass check ``` @@ -219,7 +219,7 @@ first look for expected output in `foo.polonius.stderr`, falling back to the usual `foo.stderr` if not found. The following will run the UI test suite in Polonius mode: -```bash +```text ./x test tests/ui --compare-mode=polonius ``` @@ -232,7 +232,7 @@ just `.rs` files, so after [creating a rustup toolchain](../building/how-to-build-and-run.md#creating-a-rustup-toolchain), you can do something like: -```bash +```text rustc +stage1 tests/ui/issue-1234.rs ``` @@ -252,7 +252,7 @@ execution* so be careful where it is used. To do this, first build `remote-test-server` for the remote machine, e.g. for RISC-V -```sh +```text ./x build src/tools/remote-test-server --target riscv64gc-unknown-linux-gnu ``` @@ -264,7 +264,7 @@ On the remote machine, run the `remote-test-server` with the `--bind 0.0.0.0:12345` flag (and optionally `-v` for verbose output). Output should look like this: -```sh +```text $ ./remote-test-server -v --bind 0.0.0.0:12345 starting test server listening on 0.0.0.0:12345! @@ -278,7 +278,7 @@ restrictive IP address when binding. You can test if the `remote-test-server` is working by connecting to it and sending `ping\n`. It should reply `pong`: -```sh +```text $ nc $REMOTE_IP 12345 ping pong @@ -288,7 +288,7 @@ To run tests using the remote runner, set the `TEST_DEVICE_ADDR` environment variable then use `x` as usual. For example, to run `ui` tests for a RISC-V machine with the IP address `1.2.3.4` use -```sh +```text export TEST_DEVICE_ADDR="1.2.3.4:12345" ./x test tests/ui --target riscv64gc-unknown-linux-gnu ``` @@ -296,7 +296,7 @@ export TEST_DEVICE_ADDR="1.2.3.4:12345" If `remote-test-server` was run with the verbose flag, output on the test machine may look something like -``` +```text [...] run "/tmp/work/test1007/a" run "/tmp/work/test1008/a" @@ -353,7 +353,7 @@ coordinate running tests (see [src/bootstrap/src/core/build_steps/test.rs]). First thing to know is that it only supports linux x86_64 at the moment. We will extend its support later on. -You need to update `codegen-backends` value in your `config.toml` file in the +You need to update `codegen-backends` value in your `bootstrap.toml` file in the `[rust]` section and add "gcc" in the array: ```toml @@ -362,21 +362,21 @@ codegen-backends = ["llvm", "gcc"] Then you need to install libgccjit 12. For example with `apt`: -```bash -$ apt install libgccjit-12-dev +```text +apt install libgccjit-12-dev ``` Now you can run the following command: -```bash -$ ./x test compiler/rustc_codegen_gcc/ +```text +./x test compiler/rustc_codegen_gcc/ ``` If it cannot find the `.so` library (if you installed it with `apt` for example), you need to pass the library file path with `LIBRARY_PATH`: -```bash -$ LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/12/ ./x test compiler/rustc_codegen_gcc/ +```text +LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/12/ ./x test compiler/rustc_codegen_gcc/ ``` If you encounter bugs or problems, don't hesitate to open issues on the diff --git a/src/doc/rustc-dev-guide/src/tracing.md b/src/doc/rustc-dev-guide/src/tracing.md index af484ab5f8f..0cfdf306e92 100644 --- a/src/doc/rustc-dev-guide/src/tracing.md +++ b/src/doc/rustc-dev-guide/src/tracing.md @@ -185,11 +185,11 @@ rustc. While calls to `error!`, `warn!` and `info!` are included in every build of the compiler, calls to `debug!` and `trace!` are only included in the program if -`debug-logging=true` is turned on in config.toml (it is +`debug-logging=true` is turned on in bootstrap.toml (it is turned off by default), so if you don't see `DEBUG` logs, especially if you run the compiler with `RUSTC_LOG=rustc rustc some.rs` and only see `INFO` logs, make sure that `debug-logging=true` is turned on in your -config.toml. +bootstrap.toml. ## Logging etiquette and conventions diff --git a/src/doc/rustc/src/instrument-coverage.md b/src/doc/rustc/src/instrument-coverage.md index 41da47e9206..57679f82f48 100644 --- a/src/doc/rustc/src/instrument-coverage.md +++ b/src/doc/rustc/src/instrument-coverage.md @@ -27,7 +27,7 @@ Rust's source-based code coverage requires the Rust "profiler runtime". Without The Rust `nightly` distribution channel includes the profiler runtime, by default. -> **Important**: If you are building the Rust compiler from the source distribution, the profiler runtime is _not_ enabled in the default `config.example.toml`. Edit your `config.toml` file and ensure the `profiler` feature is set it to `true` (either under the `[build]` section, or under the settings for an individual `[target.<triple>]`): +> **Important**: If you are building the Rust compiler from the source distribution, the profiler runtime is _not_ enabled in the default `bootstrap.example.toml`. Edit your `bootstrap.toml` file and ensure the `profiler` feature is set it to `true` (either under the `[build]` section, or under the settings for an individual `[target.<triple>]`): > > ```toml > # Build the profiler runtime (required when compiling with options that depend diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index c74a9e98496..e8f8684740a 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -89,9 +89,11 @@ target | notes -------|------- `aarch64-pc-windows-msvc` | ARM64 Windows MSVC `aarch64-unknown-linux-musl` | ARM64 Linux with musl 1.2.3 +[`aarch64-unknown-linux-ohos`](platform-support/openharmony.md) | ARM64 OpenHarmony `arm-unknown-linux-gnueabi` | Armv6 Linux (kernel 3.2, glibc 2.17) `arm-unknown-linux-gnueabihf` | Armv6 Linux, hardfloat (kernel 3.2, glibc 2.17) `armv7-unknown-linux-gnueabihf` | Armv7-A Linux, hardfloat (kernel 3.2, glibc 2.17) +[`armv7-unknown-linux-ohos`](platform-support/openharmony.md) | Armv7-A OpenHarmony [`loongarch64-unknown-linux-gnu`](platform-support/loongarch-linux.md) | LoongArch64 Linux, LP64D ABI (kernel 5.19, glibc 2.36) [`loongarch64-unknown-linux-musl`](platform-support/loongarch-linux.md) | LoongArch64 Linux, LP64D ABI (kernel 5.19, musl 1.2.5) `powerpc-unknown-linux-gnu` | PowerPC Linux (kernel 3.2, glibc 2.17) @@ -104,6 +106,7 @@ target | notes [`x86_64-unknown-freebsd`](platform-support/freebsd.md) | 64-bit x86 FreeBSD [`x86_64-unknown-illumos`](platform-support/illumos.md) | illumos `x86_64-unknown-linux-musl` | 64-bit Linux with musl 1.2.3 +[`x86_64-unknown-linux-ohos`](platform-support/openharmony.md) | x86_64 OpenHarmony [`x86_64-unknown-netbsd`](platform-support/netbsd.md) | NetBSD/amd64 ## Tier 2 without Host Tools @@ -142,7 +145,6 @@ target | std | notes [`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android [`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ARM64 MinGW (Windows 10+), LLVM ABI [`aarch64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | ARM64 Fuchsia -[`aarch64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | ARM64 OpenHarmony `aarch64-unknown-none` | * | Bare ARM64, hardfloat `aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat [`aarch64-unknown-uefi`](platform-support/unknown-uefi.md) | ? | ARM64 UEFI @@ -158,7 +160,6 @@ target | std | notes `armv7-unknown-linux-gnueabi` | ✓ | Armv7-A Linux (kernel 4.15, glibc 2.27) `armv7-unknown-linux-musleabi` | ✓ | Armv7-A Linux with musl 1.2.3 `armv7-unknown-linux-musleabihf` | ✓ | Armv7-A Linux with musl 1.2.3, hardfloat -[`armv7-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | Armv7-A OpenHarmony [`armv7a-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare Armv7-A [`armv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R [`armv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R, hardfloat @@ -204,7 +205,6 @@ target | std | notes [`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | 64-bit x86 MinGW (Windows 10+), LLVM ABI [`x86_64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | 64-bit x86 Fuchsia `x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27) -[`x86_64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | x86_64 OpenHarmony [`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | Freestanding/bare-metal x86_64, softfloat [`x86_64-unknown-redox`](platform-support/redox.md) | ✓ | Redox OS [`x86_64-unknown-uefi`](platform-support/unknown-uefi.md) | ? | 64-bit UEFI @@ -407,7 +407,7 @@ target | std | host | notes [`wasm32-wali-linux-musl`](platform-support/wasm32-wali-linux.md) | ? | | WebAssembly with [WALI](https://github.com/arjunr2/WALI) [`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ✓ | | x86 64-bit tvOS [`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator -[`x86_64-pc-cygwin`](platform-support/x86_64-pc-cygwin.md) | ? | | 64-bit x86 Cygwin | +[`x86_64-pc-cygwin`](platform-support/x86_64-pc-cygwin.md) | ✓ | | 64-bit x86 Cygwin | [`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS with default network stack (io-pkt) | [`x86_64-pc-nto-qnx710_iosock`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS with new network stack (io-sock) | [`x86_64-pc-nto-qnx800`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 8.0 RTOS | diff --git a/src/doc/rustc/src/platform-support/TEMPLATE.md b/src/doc/rustc/src/platform-support/TEMPLATE.md index 87dde722558..96c79973a16 100644 --- a/src/doc/rustc/src/platform-support/TEMPLATE.md +++ b/src/doc/rustc/src/platform-support/TEMPLATE.md @@ -28,7 +28,7 @@ What format do binaries use by default? ELF, PE, something else? ## Building the target If Rust doesn't build the target by default, how can users build it? Can users -just add it to the `target` list in `config.toml`? +just add it to the `target` list in `bootstrap.toml`? ## Building Rust programs diff --git a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md index 7a6609b2d76..e2f2379ec44 100644 --- a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md +++ b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md @@ -54,7 +54,7 @@ exec /path/to/ohos-sdk/linux/native/llvm/bin/clang++ \ ## Building the target -To build a rust toolchain, create a `config.toml` with the following contents: +To build a rust toolchain, create a `bootstrap.toml` with the following contents: ```toml profile = "compiler" diff --git a/src/doc/rustc/src/platform-support/apple-ios.md b/src/doc/rustc/src/platform-support/apple-ios.md index 5045f810400..cfb458fdb73 100644 --- a/src/doc/rustc/src/platform-support/apple-ios.md +++ b/src/doc/rustc/src/platform-support/apple-ios.md @@ -47,7 +47,7 @@ $ rustup target add x86_64-apple-ios ``` The tier 3 targets can be built by enabling them for a `rustc` build in -`config.toml`, by adding, for example: +`bootstrap.toml`, by adding, for example: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/apple-tvos.md b/src/doc/rustc/src/platform-support/apple-tvos.md index 7a3b601579a..166bb1b6db2 100644 --- a/src/doc/rustc/src/platform-support/apple-tvos.md +++ b/src/doc/rustc/src/platform-support/apple-tvos.md @@ -52,7 +52,7 @@ The following APIs are currently known to have missing or incomplete support: ## Building the target The targets can be built by enabling them for a `rustc` build in -`config.toml`, by adding, for example: +`bootstrap.toml`, by adding, for example: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/apple-visionos.md b/src/doc/rustc/src/platform-support/apple-visionos.md index 56224d7e20d..a7bbae168a4 100644 --- a/src/doc/rustc/src/platform-support/apple-visionos.md +++ b/src/doc/rustc/src/platform-support/apple-visionos.md @@ -31,7 +31,7 @@ case `XROS_DEPLOYMENT_TARGET`. ## Building the target The targets can be built by enabling them for a `rustc` build in -`config.toml`, by adding, for example: +`bootstrap.toml`, by adding, for example: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/apple-watchos.md b/src/doc/rustc/src/platform-support/apple-watchos.md index 8ba35f70b85..0bf8cdf3614 100644 --- a/src/doc/rustc/src/platform-support/apple-watchos.md +++ b/src/doc/rustc/src/platform-support/apple-watchos.md @@ -37,7 +37,7 @@ case `WATCHOS_DEPLOYMENT_TARGET`. ## Building the target The targets can be built by enabling them for a `rustc` build in -`config.toml`, by adding, for example: +`bootstrap.toml`, by adding, for example: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/arm64e-apple-darwin.md b/src/doc/rustc/src/platform-support/arm64e-apple-darwin.md index 322a07c5739..3200b7ae1b6 100644 --- a/src/doc/rustc/src/platform-support/arm64e-apple-darwin.md +++ b/src/doc/rustc/src/platform-support/arm64e-apple-darwin.md @@ -16,7 +16,7 @@ See the docs on [`*-apple-darwin`](apple-darwin.md) for general macOS requiremen ## Building the target -You can build Rust with support for the targets by adding it to the `target` list in `config.toml`: +You can build Rust with support for the targets by adding it to the `target` list in `bootstrap.toml`: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/arm64e-apple-ios.md b/src/doc/rustc/src/platform-support/arm64e-apple-ios.md index 3d8ba5c282a..aa99276a68f 100644 --- a/src/doc/rustc/src/platform-support/arm64e-apple-ios.md +++ b/src/doc/rustc/src/platform-support/arm64e-apple-ios.md @@ -14,7 +14,7 @@ See the docs on [`*-apple-ios`](apple-ios.md) for general iOS requirements. ## Building the target -You can build Rust with support for the targets by adding it to the `target` list in `config.toml`: +You can build Rust with support for the targets by adding it to the `target` list in `bootstrap.toml`: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/arm64e-apple-tvos.md b/src/doc/rustc/src/platform-support/arm64e-apple-tvos.md index ec8a996549e..332ea750f20 100644 --- a/src/doc/rustc/src/platform-support/arm64e-apple-tvos.md +++ b/src/doc/rustc/src/platform-support/arm64e-apple-tvos.md @@ -15,7 +15,7 @@ To build this target Xcode 12 or higher on macOS is required. ## Building the target -You can build Rust with support for the targets by adding it to the `target` list in `config.toml`: +You can build Rust with support for the targets by adding it to the `target` list in `bootstrap.toml`: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md b/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md index 15bf55d35a2..67903ae6401 100644 --- a/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md +++ b/src/doc/rustc/src/platform-support/arm64ec-pc-windows-msvc.md @@ -56,7 +56,7 @@ To put this in practice: ## Building the target You can build Rust with support for the targets by adding it to the `target` -list in `config.toml`: +list in `bootstrap.toml`: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md b/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md index 3c3e35a51b8..3a5b5a38017 100644 --- a/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md +++ b/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md @@ -21,7 +21,7 @@ The target definition can be seen [here](https://github.com/rust-lang/rust/blob/ ## Building the target Because it is Tier 3, rust does not yet ship pre-compiled artifacts for this target. -Therefore, you can build Rust with support for the target by adding it to the target list in config.toml, a sample configuration is shown below. It is expected that the user already have a working GNU compiler toolchain and update the paths accordingly. +Therefore, you can build Rust with support for the target by adding it to the target list in bootstrap.toml, a sample configuration is shown below. It is expected that the user already have a working GNU compiler toolchain and update the paths accordingly. ```toml [llvm] diff --git a/src/doc/rustc/src/platform-support/armv6k-nintendo-3ds.md b/src/doc/rustc/src/platform-support/armv6k-nintendo-3ds.md index 160986aeae9..a085aef2d04 100644 --- a/src/doc/rustc/src/platform-support/armv6k-nintendo-3ds.md +++ b/src/doc/rustc/src/platform-support/armv6k-nintendo-3ds.md @@ -50,7 +50,7 @@ This target generates binaries in the ELF format. ## Building the target You can build Rust with support for the target by adding it to the `target` -list in `config.toml` and providing paths to the devkitARM toolchain. +list in `bootstrap.toml` and providing paths to the devkitARM toolchain. ```toml [build] diff --git a/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabihf.md b/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabihf.md index 1c8acc09c77..f687f6f0695 100644 --- a/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabihf.md +++ b/src/doc/rustc/src/platform-support/armv7-unknown-linux-uclibceabihf.md @@ -22,7 +22,7 @@ If you don't already have a suitable toolchain, download one [here](https://tool ### Configure rust -The target can be built by enabling it for a `rustc` build, by placing the following in `config.toml`: +The target can be built by enabling it for a `rustc` build, by placing the following in `bootstrap.toml`: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md index 32e4f855313..f749b37aa7a 100644 --- a/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md +++ b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md @@ -36,7 +36,7 @@ If you don't already have a suitable toolchain, you can download from [here](htt ### Configure rust -The target can be built by enabling it for a `rustc` build, by placing the following in `config.toml`: +The target can be built by enabling it for a `rustc` build, by placing the following in `bootstrap.toml`: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index 489f46e1cb9..bed5b81adc5 100644 --- a/src/doc/rustc/src/platform-support/fuchsia.md +++ b/src/doc/rustc/src/platform-support/fuchsia.md @@ -180,7 +180,7 @@ Fuchsia as well. A recent version (14+) of clang should be sufficient to compile Rust for Fuchsia. x86-64 and AArch64 Fuchsia targets can be enabled using the following -configuration in `config.toml`: +configuration in `bootstrap.toml`: ```toml [build] @@ -212,7 +212,7 @@ cxx = "clang++" By default, the Rust compiler installs itself to `/usr/local` on most UNIX systems. You may want to install it to another location (e.g. a local `install` -directory) by setting a custom prefix in `config.toml`: +directory) by setting a custom prefix in `bootstrap.toml`: ```toml [install] @@ -695,7 +695,7 @@ We can then use the script to start our test environment with: ) ``` -Where `${RUST_SRC_PATH}/build` is the `build-dir` set in `config.toml`. +Where `${RUST_SRC_PATH}/build` is the `build-dir` set in `bootstrap.toml`. Once our environment is started, we can run our tests using `x.py` as usual. The test runner script will run the compiled tests on an emulated Fuchsia device. To @@ -705,7 +705,7 @@ run the full `tests/ui` test suite: ( \ source config-env.sh && \ ./x.py \ - --config config.toml \ + --config bootstrap.toml \ --stage=2 \ test tests/ui \ --target x86_64-unknown-fuchsia \ @@ -893,7 +893,7 @@ through our `x.py` invocation. The full invocation is: ( \ source config-env.sh && \ ./x.py \ - --config config.toml \ + --config bootstrap.toml \ --stage=2 \ test tests/${TEST} \ --target x86_64-unknown-fuchsia \ diff --git a/src/doc/rustc/src/platform-support/hermit.md b/src/doc/rustc/src/platform-support/hermit.md index 5aa787e53e1..df7bc495fce 100644 --- a/src/doc/rustc/src/platform-support/hermit.md +++ b/src/doc/rustc/src/platform-support/hermit.md @@ -31,7 +31,7 @@ Hermit binaries have the ELF format. ## Building the target -You can build Rust with support for the targets by adding it to the `target` list in `config.toml`. +You can build Rust with support for the targets by adding it to the `target` list in `bootstrap.toml`. To run the Hermit build scripts, you also have to enable your host target. The build scripts rely on `llvm-tools` and binaries are linked using `rust-lld`, so those have to be enabled as well. diff --git a/src/doc/rustc/src/platform-support/hexagon-unknown-linux-musl.md b/src/doc/rustc/src/platform-support/hexagon-unknown-linux-musl.md index d858337a949..cfd2b2bac9c 100644 --- a/src/doc/rustc/src/platform-support/hexagon-unknown-linux-musl.md +++ b/src/doc/rustc/src/platform-support/hexagon-unknown-linux-musl.md @@ -44,7 +44,7 @@ Because it is Tier 3, rust does not yet ship pre-compiled artifacts for this target. Therefore, you can build Rust with support for the target by adding it to the -target list in `config.toml`, a sample configuration is shown below. +target list in `bootstrap.toml`, a sample configuration is shown below. ```toml [build] diff --git a/src/doc/rustc/src/platform-support/hexagon-unknown-none-elf.md b/src/doc/rustc/src/platform-support/hexagon-unknown-none-elf.md index a0e26b798ac..c7726eacaf4 100644 --- a/src/doc/rustc/src/platform-support/hexagon-unknown-none-elf.md +++ b/src/doc/rustc/src/platform-support/hexagon-unknown-none-elf.md @@ -28,7 +28,7 @@ This target generates PIC ELF binaries. ## Building the target You can build Rust with support for the target by adding it to the `target` -list in `config.toml`: +list in `bootstrap.toml`: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/i686-apple-darwin.md b/src/doc/rustc/src/platform-support/i686-apple-darwin.md index d69fa97ce63..abb64dcc986 100644 --- a/src/doc/rustc/src/platform-support/i686-apple-darwin.md +++ b/src/doc/rustc/src/platform-support/i686-apple-darwin.md @@ -17,7 +17,7 @@ You'll need the macOS 10.13 SDK shipped with Xcode 9. The location of the SDK can be passed to `rustc` using the common `SDKROOT` environment variable. Once you have that, you can build Rust with support for the target by adding -it to the `target` list in `config.toml`: +it to the `target` list in `bootstrap.toml`: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/kmc-solid.md b/src/doc/rustc/src/platform-support/kmc-solid.md index bbcd0f711c6..44f47927286 100644 --- a/src/doc/rustc/src/platform-support/kmc-solid.md +++ b/src/doc/rustc/src/platform-support/kmc-solid.md @@ -32,7 +32,7 @@ The target can be built by enabling it for a `rustc` build. target = ["aarch64-kmc-solid_asp3"] ``` -Make sure `aarch64-kmc-elf-gcc` is included in `$PATH`. Alternatively, you can use GNU Arm Embedded Toolchain by adding the following to `config.toml`: +Make sure `aarch64-kmc-elf-gcc` is included in `$PATH`. Alternatively, you can use GNU Arm Embedded Toolchain by adding the following to `bootstrap.toml`: ```toml [target.aarch64-kmc-solid_asp3] diff --git a/src/doc/rustc/src/platform-support/loongarch-linux.md b/src/doc/rustc/src/platform-support/loongarch-linux.md index 45eb0a81216..2c9f712ce82 100644 --- a/src/doc/rustc/src/platform-support/loongarch-linux.md +++ b/src/doc/rustc/src/platform-support/loongarch-linux.md @@ -65,7 +65,7 @@ These targets are distributed through `rustup`, and otherwise require no special configuration. If you need to build your own Rust for some reason though, the targets can be -simply enabled in `config.toml`. For example: +simply enabled in `bootstrap.toml`. For example: ```toml [build] @@ -73,7 +73,7 @@ target = ["loongarch64-unknown-linux-gnu"] ``` Make sure the LoongArch toolchain binaries are reachable from `$PATH`. -Alternatively, you can explicitly configure the paths in `config.toml`: +Alternatively, you can explicitly configure the paths in `bootstrap.toml`: ```toml [target.loongarch64-unknown-linux-gnu] diff --git a/src/doc/rustc/src/platform-support/loongarch-none.md b/src/doc/rustc/src/platform-support/loongarch-none.md index bafa85c26e2..6c5d8669830 100644 --- a/src/doc/rustc/src/platform-support/loongarch-none.md +++ b/src/doc/rustc/src/platform-support/loongarch-none.md @@ -46,7 +46,7 @@ scripts. ## Building the target You can build Rust with support for the targets by adding them to the `target` -list in `config.toml`: +list in `bootstrap.toml`: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/mips-release-6.md b/src/doc/rustc/src/platform-support/mips-release-6.md index 9203a31e9f4..b779477996d 100644 --- a/src/doc/rustc/src/platform-support/mips-release-6.md +++ b/src/doc/rustc/src/platform-support/mips-release-6.md @@ -67,7 +67,7 @@ The following procedure outlines the build process for the MIPS64 R6 target with ### Prerequisite: Disable debuginfo -An LLVM bug makes rustc crash if debug or debug info generation is enabled. You need to edit `config.toml` to disable this: +An LLVM bug makes rustc crash if debug or debug info generation is enabled. You need to edit `bootstrap.toml` to disable this: ```toml [rust] @@ -83,7 +83,7 @@ The crate `rustix` may try to link itself against MIPS R2 assembly, resulting in export RUSTFLAGS="--cfg rustix_use_libc" ``` -This will trigger warnings during build, as `-D warnings` is enabled by default. Disable `-D warnings` by editing `config.toml` to append the following: +This will trigger warnings during build, as `-D warnings` is enabled by default. Disable `-D warnings` by editing `bootstrap.toml` to append the following: ```toml [rust] @@ -116,7 +116,7 @@ target = ["mipsisa64r6el-unknown-linux-gnuabi64"] Make sure that `mipsisa64r6el-unknown-linux-gnuabi64-gcc` is available from your executable search path (`$PATH`). -Alternatively, you can specify the directories to all necessary toolchain executables in `config.toml`: +Alternatively, you can specify the directories to all necessary toolchain executables in `bootstrap.toml`: ```toml [target.mipsisa64r6el-unknown-linux-gnuabi64] diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md index 77e8caaee4c..e097d32277d 100644 --- a/src/doc/rustc/src/platform-support/nto-qnx.md +++ b/src/doc/rustc/src/platform-support/nto-qnx.md @@ -124,7 +124,7 @@ For conditional compilation, following QNX specific attributes are defined: ## Building the target -1. Create a `config.toml` +1. Create a `bootstrap.toml` Example content: diff --git a/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md b/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md index 1af1410d4bb..ab8641ff69a 100644 --- a/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md +++ b/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md @@ -32,7 +32,7 @@ What format do binaries use by default? ELF, PE, something else? ## Building the target If Rust doesn't build the target by default, how can users build it? Can users -just add it to the `target` list in `config.toml`? +just add it to the `target` list in `bootstrap.toml`? ## Building Rust programs diff --git a/src/doc/rustc/src/platform-support/openharmony.md b/src/doc/rustc/src/platform-support/openharmony.md index 1632f44aeec..ab50cbcdf97 100644 --- a/src/doc/rustc/src/platform-support/openharmony.md +++ b/src/doc/rustc/src/platform-support/openharmony.md @@ -1,6 +1,6 @@ # `*-unknown-linux-ohos` -**Tier: 2** +**Tier: 2 (with Host Tools)** * aarch64-unknown-linux-ohos * armv7-unknown-linux-ohos @@ -18,6 +18,20 @@ system. - Amanieu d'Antras ([@Amanieu](https://github.com/Amanieu)) - Lu Binglun ([@lubinglun](https://github.com/lubinglun)) +## Requirements + +All the ohos targets of Tier 2 with host tools support all extended rust tools. +(exclude `miri`, the support of `miri` will be added soon) + +### Host toolchain + +The targets require a reasonably up-to-date OpenHarmony SDK on the host. + +The targets support `cargo`, which require [ohos-openssl](https://github.com/ohos-rs/ohos-openssl). + +`miri` isn't supported yet, since its dependencies (`libffi` and `tikv-jemalloc-sys`) don't support +compiling for the OHOS targets. + ## Setup The OpenHarmony SDK doesn't currently support Rust compilation directly, so @@ -131,7 +145,7 @@ linker = "/path/to/x86_64-unknown-linux-ohos-clang.sh" ## Building the target from source Instead of using `rustup`, you can instead build a rust toolchain from source. -Create a `config.toml` with the following contents: +Create a `bootstrap.toml` with the following contents: ```toml profile = "compiler" diff --git a/src/doc/rustc/src/platform-support/pc-windows-gnullvm.md b/src/doc/rustc/src/platform-support/pc-windows-gnullvm.md index 89c4cdb2afc..f14fe7df422 100644 --- a/src/doc/rustc/src/platform-support/pc-windows-gnullvm.md +++ b/src/doc/rustc/src/platform-support/pc-windows-gnullvm.md @@ -29,7 +29,7 @@ Like with any other Windows target, created binaries are in PE format. These targets can be easily cross-compiled using [llvm-mingw](https://github.com/mstorsjo/llvm-mingw) toolchain or [MSYS2 CLANG*](https://www.msys2.org/docs/environments/) environments. -Just fill `[target.*]` sections for both build and resulting compiler and set installation prefix in `config.toml`. +Just fill `[target.*]` sections for both build and resulting compiler and set installation prefix in `bootstrap.toml`. Then run `./x.py install`. In my case I had ran `./x.py install --host x86_64-pc-windows-gnullvm --target x86_64-pc-windows-gnullvm` inside MSYS2 MINGW64 shell so `x86_64-pc-windows-gnu` was my build toolchain. diff --git a/src/doc/rustc/src/platform-support/powerpc64le-unknown-linux-musl.md b/src/doc/rustc/src/platform-support/powerpc64le-unknown-linux-musl.md index 3bd3f5d8b7f..e1e3d6d31c0 100644 --- a/src/doc/rustc/src/platform-support/powerpc64le-unknown-linux-musl.md +++ b/src/doc/rustc/src/platform-support/powerpc64le-unknown-linux-musl.md @@ -23,7 +23,7 @@ The target can be built by enabling it for a `rustc` build. target = ["powerpc64le-unknown-linux-musl"] ``` -Make sure your C compiler is included in `$PATH`, then add it to the `config.toml`: +Make sure your C compiler is included in `$PATH`, then add it to the `bootstrap.toml`: ```toml [target.powerpc64le-unknown-linux-musl] diff --git a/src/doc/rustc/src/platform-support/redox.md b/src/doc/rustc/src/platform-support/redox.md index 2bba92d504c..c1a96f1cfc4 100644 --- a/src/doc/rustc/src/platform-support/redox.md +++ b/src/doc/rustc/src/platform-support/redox.md @@ -27,7 +27,7 @@ Redox OS binaries use ELF as file format. ## Building the target -You can build Rust with support for the targets by adding it to the `target` list in `config.toml`. In addition a copy of [relibc] needs to be present in the linker search path. +You can build Rust with support for the targets by adding it to the `target` list in `bootstrap.toml`. In addition a copy of [relibc] needs to be present in the linker search path. ```toml [build] diff --git a/src/doc/rustc/src/platform-support/riscv32im-risc0-zkvm-elf.md b/src/doc/rustc/src/platform-support/riscv32im-risc0-zkvm-elf.md index 1fdd594012c..79455b0fbc4 100644 --- a/src/doc/rustc/src/platform-support/riscv32im-risc0-zkvm-elf.md +++ b/src/doc/rustc/src/platform-support/riscv32im-risc0-zkvm-elf.md @@ -43,7 +43,7 @@ Calling `extern "C"` on the target uses the C calling convention outlined in the ## Building for the zkVM Programs for the zkVM could be built by adding it to the `target` list in -`config.toml`. However, we recommend building programs in our starter template +`bootstrap.toml`. However, we recommend building programs in our starter template generated by the [cargo-risczero] utility and the [risc0-build] crate. This crate calls `rustc` with `-C "link-arg=-Ttext=` so that it maps the text in the appropriate location as well as generating variables that represent the ELF and diff --git a/src/doc/rustc/src/platform-support/riscv32imac-unknown-xous-elf.md b/src/doc/rustc/src/platform-support/riscv32imac-unknown-xous-elf.md index f024cd25bf7..12928edfcac 100644 --- a/src/doc/rustc/src/platform-support/riscv32imac-unknown-xous-elf.md +++ b/src/doc/rustc/src/platform-support/riscv32imac-unknown-xous-elf.md @@ -24,7 +24,7 @@ The target can be built by enabling it for a `rustc` build. target = ["riscv32imac-unknown-xous-elf"] ``` -Make sure your C compiler is included in `$PATH`, then add it to the `config.toml`: +Make sure your C compiler is included in `$PATH`, then add it to the `bootstrap.toml`: ```toml [target.riscv32imac-unknown-xous-elf] diff --git a/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md index dda2a50c33d..1ab867fe71e 100644 --- a/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md +++ b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md @@ -26,7 +26,7 @@ These targets are distributed through `rustup`, and otherwise require no special configuration. If you need to build your own Rust for some reason though, the targets can be -enabled in `config.toml`. For example: +enabled in `bootstrap.toml`. For example: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md index 5b3dc683038..5e6275d6979 100644 --- a/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md +++ b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-musl.md @@ -22,7 +22,7 @@ The target can be built by enabling it for a `rustc` build. target = ["riscv64gc-unknown-linux-musl"] ``` -Make sure your C compiler is included in `$PATH`, then add it to the `config.toml`: +Make sure your C compiler is included in `$PATH`, then add it to the `bootstrap.toml`: ```toml [target.riscv64gc-unknown-linux-musl] diff --git a/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md index 6f09ce42dbb..1aa2704cf95 100644 --- a/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md +++ b/src/doc/rustc/src/platform-support/s390x-unknown-linux-gnu.md @@ -34,7 +34,7 @@ This target is distributed through `rustup`, and otherwise requires no special configuration. If you need to build your own Rust for some reason though, the target can be -enabled in `config.toml`. For example: +enabled in `bootstrap.toml`. For example: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/s390x-unknown-linux-musl.md b/src/doc/rustc/src/platform-support/s390x-unknown-linux-musl.md index e00f8db7f8e..3c334620cfc 100644 --- a/src/doc/rustc/src/platform-support/s390x-unknown-linux-musl.md +++ b/src/doc/rustc/src/platform-support/s390x-unknown-linux-musl.md @@ -33,7 +33,7 @@ Because it is Tier 3, Rust does not yet ship pre-compiled artifacts for this target. Therefore, you can build Rust with support for the target by adding it to the -target list in `config.toml`, a sample configuration is shown below. +target list in `bootstrap.toml`, a sample configuration is shown below. ```toml [build] diff --git a/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md b/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md index f579b1fb8d4..c19b7d7681a 100644 --- a/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md +++ b/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md @@ -34,7 +34,7 @@ considerations for binary layout will require linker options or linker scripts. ## Building the target You can build Rust with support for the target by adding it to the `target` -list in `config.toml`: +list in `bootstrap.toml`: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/unikraft-linux-musl.md b/src/doc/rustc/src/platform-support/unikraft-linux-musl.md index c589208c099..b40e99825e5 100644 --- a/src/doc/rustc/src/platform-support/unikraft-linux-musl.md +++ b/src/doc/rustc/src/platform-support/unikraft-linux-musl.md @@ -34,7 +34,7 @@ Instead, the Unikraft build system will produce the final Unikernel image for th ## Building the targets -You can build Rust with support for the targets by adding it to the `target` list in `config.toml`: +You can build Rust with support for the targets by adding it to the `target` list in `bootstrap.toml`: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/unknown-uefi.md b/src/doc/rustc/src/platform-support/unknown-uefi.md index e6917502182..e9979cc912c 100644 --- a/src/doc/rustc/src/platform-support/unknown-uefi.md +++ b/src/doc/rustc/src/platform-support/unknown-uefi.md @@ -252,7 +252,7 @@ This section contains information on how to use std on UEFI. ### Build std The building std part is pretty much the same as the official [docs](https://rustc-dev-guide.rust-lang.org/getting-started.html). -The linker that should be used is `rust-lld`. Here is a sample `config.toml`: +The linker that should be used is `rust-lld`. Here is a sample `bootstrap.toml`: ```toml [rust] lld = true diff --git a/src/doc/rustc/src/platform-support/vxworks.md b/src/doc/rustc/src/platform-support/vxworks.md index 6aa3d8b7361..a2b91f3769d 100644 --- a/src/doc/rustc/src/platform-support/vxworks.md +++ b/src/doc/rustc/src/platform-support/vxworks.md @@ -33,7 +33,7 @@ Rust for each target can be cross-compiled with its specific target vsb configur ## Building the target -You can build Rust with support for the targets by adding it to the `target` list in `config.toml`. In addition the workbench and wr-cc have to configured and activated. +You can build Rust with support for the targets by adding it to the `target` list in `bootstrap.toml`. In addition the workbench and wr-cc have to configured and activated. ```toml [build] diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md b/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md index d364852b1c1..6949c657db8 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md @@ -61,7 +61,7 @@ Building this target can be done by: * Configure the `wasm32-unknown-emscripten` target to get built. * Ensure the `WebAssembly` target backend is not disabled in LLVM. -These are all controlled through `config.toml` options. It should be possible +These are all controlled through `bootstrap.toml` options. It should be possible to build this target on any platform. A minimal example configuration would be: ```toml diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md index ba95ab7af6d..150f69e03c6 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md @@ -65,7 +65,7 @@ Building this target can be done by: * Configure LLD to be built. * Ensure the `WebAssembly` target backend is not disabled in LLVM. -These are all controlled through `config.toml` options. It should be possible +These are all controlled through `bootstrap.toml` options. It should be possible to build this target on any platform. ## Building Rust programs diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md index 1b0a312ca9c..af20b62b9f6 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md @@ -107,7 +107,7 @@ flag, for example: Users need to install or built wasi-sdk since release 20.0 https://github.com/WebAssembly/wasi-sdk/releases/tag/wasi-sdk-20 -and specify path to *wasi-root* `config.toml` +and specify path to *wasi-root* `bootstrap.toml` ```toml [target.wasm32-wasip1-threads] @@ -115,7 +115,7 @@ wasi-root = ".../wasi-libc/sysroot" ``` After that users can build this by adding it to the `target` list in -`config.toml`, or with `-Zbuild-std`. +`bootstrap.toml`, or with `-Zbuild-std`. ## Building Rust programs diff --git a/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md index a717f5dad79..157fff419d3 100644 --- a/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md +++ b/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md @@ -64,7 +64,7 @@ This target does not support `panic=unwind` at this time. ## Building the target You can build Rust with support for the target by adding it to the `target` -list in `config.toml`, and the target also requires `lld` to be built to work. +list in `bootstrap.toml`, and the target also requires `lld` to be built to work. ```toml [build] diff --git a/src/doc/rustc/src/platform-support/win7-windows-gnu.md b/src/doc/rustc/src/platform-support/win7-windows-gnu.md index 180a1dc6d26..3a819b0a4e2 100644 --- a/src/doc/rustc/src/platform-support/win7-windows-gnu.md +++ b/src/doc/rustc/src/platform-support/win7-windows-gnu.md @@ -23,7 +23,7 @@ Like any other Windows target, the created binaries are in PE format. ## Building the target -You can build Rust with support for the targets by adding it to the target list in config.toml: +You can build Rust with support for the targets by adding it to the target list in bootstrap.toml: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/win7-windows-msvc.md b/src/doc/rustc/src/platform-support/win7-windows-msvc.md index 77b7d68212b..cbbb44b47aa 100644 --- a/src/doc/rustc/src/platform-support/win7-windows-msvc.md +++ b/src/doc/rustc/src/platform-support/win7-windows-msvc.md @@ -24,7 +24,7 @@ Like any other Windows target, the created binaries are in PE format. ## Building the target -You can build Rust with support for the targets by adding it to the target list in config.toml: +You can build Rust with support for the targets by adding it to the target list in bootstrap.toml: ```toml [build] @@ -73,7 +73,7 @@ Windows SDK, which can be acquired using [`xwin`](https://github.com/Jake-Shadle clang-cl /imsvc "$XWIN/crt/include" /imsvc "$XWIN/sdk/include/ucrt" /imsvc "$XWIN/sdk/include/um" /imsvc "$XWIN/sdk/include/shared" --target="x86_64-pc-windows-msvc" "$@" ``` -- In your config.toml, add the following lines: +- In your bootstrap.toml, add the following lines: ```toml [target.x86_64-win7-windows-msvc] diff --git a/src/doc/rustc/src/platform-support/x86_64-unknown-none.md b/src/doc/rustc/src/platform-support/x86_64-unknown-none.md index bd5fd1d0502..3b8aae3a389 100644 --- a/src/doc/rustc/src/platform-support/x86_64-unknown-none.md +++ b/src/doc/rustc/src/platform-support/x86_64-unknown-none.md @@ -39,7 +39,7 @@ scripts. ## Building the target You can build Rust with support for the target by adding it to the `target` -list in `config.toml`: +list in `bootstrap.toml`: ```toml [build] diff --git a/src/doc/rustc/src/platform-support/x86_64h-apple-darwin.md b/src/doc/rustc/src/platform-support/x86_64h-apple-darwin.md index 6c2a6a41101..545fffb84f9 100644 --- a/src/doc/rustc/src/platform-support/x86_64h-apple-darwin.md +++ b/src/doc/rustc/src/platform-support/x86_64h-apple-darwin.md @@ -29,7 +29,7 @@ respects. ## Building the target Users on Apple targets can build this by adding it to the `target` list in -`config.toml`, or with `-Zbuild-std`. +`bootstrap.toml`, or with `-Zbuild-std`. ## Building Rust programs diff --git a/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md b/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md index dbb741422a8..e7414aa9119 100644 --- a/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md +++ b/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md @@ -56,4 +56,4 @@ $Env:RUSTFLAGS = "-Z control-flow-guard" cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc ``` -Alternatively, if you are building the standard library from source, you can set `control-flow-guard = true` in the config.toml file. +Alternatively, if you are building the standard library from source, you can set `control-flow-guard = true` in the bootstrap.toml file. diff --git a/src/doc/unstable-book/src/language-features/asm-goto-with-outputs.md b/src/doc/unstable-book/src/language-features/asm-goto-with-outputs.md new file mode 100644 index 00000000000..3cce5d1d74c --- /dev/null +++ b/src/doc/unstable-book/src/language-features/asm-goto-with-outputs.md @@ -0,0 +1,27 @@ +# `asm_goto_with_outputs` + +The tracking issue for this feature is: [#119364] + +[#119364]: https://github.com/rust-lang/rust/issues/119364 + +------------------------ + +This feature allows label operands to be used together with output operands. + +Example: +```rust,ignore (partial-example, x86-only) + +unsafe { + let a: usize; + asm!( + "mov {}, 1" + "jmp {}", + out(reg) a, + label { + println!("Jumped from asm {}!", a); + } + ); +} +``` + +The output operands are assigned before the label blocks are executed. diff --git a/src/doc/unstable-book/src/language-features/asm-goto.md b/src/doc/unstable-book/src/language-features/asm-goto.md deleted file mode 100644 index 823118bcae1..00000000000 --- a/src/doc/unstable-book/src/language-features/asm-goto.md +++ /dev/null @@ -1,32 +0,0 @@ -# `asm_goto` - -The tracking issue for this feature is: [#119364] - -[#119364]: https://github.com/rust-lang/rust/issues/119364 - ------------------------- - -This feature adds a `label <block>` operand type to `asm!`. - -Example: -```rust,ignore (partial-example, x86-only) - -unsafe { - asm!( - "jmp {}", - label { - println!("Jumped from asm!"); - } - ); -} -``` - -The block must have unit type or diverge. The block starts a new safety context, -so despite outer `unsafe`, you need extra unsafe to perform unsafe operations -within `label <block>`. - -When `label <block>` is used together with `noreturn` option, it means that the -assembly will not fallthrough. It's allowed to jump to a label within the -assembly. In this case, the entire `asm!` expression will have an unit type as -opposed to diverging, if not all label blocks diverge. The `asm!` expression -still diverges if `noreturn` option is used and all label blocks diverge. diff --git a/src/doc/unstable-book/src/language-features/offset-of-enum.md b/src/doc/unstable-book/src/language-features/offset-of-enum.md new file mode 100644 index 00000000000..1960d6299eb --- /dev/null +++ b/src/doc/unstable-book/src/language-features/offset-of-enum.md @@ -0,0 +1,29 @@ +# `offset_of_slice` + +The tracking issue for this feature is: [#120141] + +[#120141]: https://github.com/rust-lang/rust/issues/120141 + +------------------------ + +When the `offset_of_enum` feature is enabled, the [`offset_of!`] macro may be used to obtain the +offsets of fields of `enum`s; to express this, `enum` variants may be traversed as if they were +fields. Variants themselves do not have an offset, so they cannot appear as the last path component. + +```rust +#![feature(offset_of_enum)] +use std::mem; + +#[repr(u8)] +enum Enum { + A(u8, u16), + B { one: u8, two: u16 }, +} + +assert_eq!(mem::offset_of!(Enum, A.0), 1); +assert_eq!(mem::offset_of!(Enum, B.two), 2); + +assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0); +``` + +[`offset_of!`]: ../../std/mem/macro.offset_of.html diff --git a/src/doc/unstable-book/src/language-features/offset-of-slice.md b/src/doc/unstable-book/src/language-features/offset-of-slice.md new file mode 100644 index 00000000000..c887fa07f67 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/offset-of-slice.md @@ -0,0 +1,30 @@ +# `offset_of_slice` + +The tracking issue for this feature is: [#126151] + +[#126151]: https://github.com/rust-lang/rust/issues/126151 + +------------------------ + +When the `offset_of_slice` feature is enabled, the [`offset_of!`] macro may be used to determine +the offset of fields whose type is `[T]`, that is, a slice of dynamic size. + +In general, fields whose type is dynamically sized do not have statically known offsets because +they do not have statically known alignments. However, `[T]` has the same alignment as `T`, so +it specifically may be allowed. + +```rust +#![feature(offset_of_slice)] + +#[repr(C)] +pub struct Struct { + head: u32, + tail: [u8], +} + +fn main() { + assert_eq!(std::mem::offset_of!(Struct, tail), 4); +} +``` + +[`offset_of!`]: ../../std/mem/macro.offset_of.html diff --git a/src/doc/unstable-book/src/language-features/register-tool.md b/src/doc/unstable-book/src/language-features/register-tool.md new file mode 100644 index 00000000000..58b923aab57 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/register-tool.md @@ -0,0 +1,55 @@ +# `register_tool` + +The tracking issue for this feature is: [#66079] + +[#66079]: https://github.com/rust-lang/rust/issues/66079 + +------------------------ + +The `register_tool` language feature informs the compiler that attributes in your code are meant to be used with tools other than the compiler itself. This can be useful if your code has semantic meaning without the external tool, but enables additional features when the tool is present. + +`register_tool` also allows configuring lint levels for external tools. + +Tool attributes are only meant for ignorable attributes. If your code *changes* meaning when the attribute is present, it should not use a tool attribute (because it cannot be compiled with anything other than the external tool, and in a sense is a fork of the language). + +------------------------ + +`#![register_tool(tool)]` is an attribute, and is only valid at the crate root. +Attributes using the registered tool are checked for valid syntax, and lint attributes are checked to be in a valid format. However, the compiler cannot validate the semantics of the attribute, nor can it tell whether the configured lint is present in the external tool. + +Semantically, `clippy::*`, `rustdoc::*`, and `rustfmt::*` lints and attributes all behave as if `#![register_tool(clippy, rustdoc, rustfmt)]` were injected into the crate root, except that the `rustdoc` namespace can only be used for lints, not for attributes. +When compiling with `-Z unstable-features`, `rustc::*` lints can also be used. Like `rustdoc`, the `rustc` namespace can only be used with lints, not attributes. + +The compiler will emit an error if it encounters a lint/attribute whose namespace isn't a registered tool. + +Tool namespaces cannot be nested; `register_tool(main_tool::subtool)` is an error. + +## Examples + +Tool attributes: + +```rust +#![feature(register_tool)] +#![register_tool(c2rust)] + +// Mark which C header file this module was generated from. +#[c2rust::header_src = "operations.h"] +pub mod operations_h { + use std::ffi::c_int; + + // Mark which source line this struct was generated from. + #[c2rust::src_loc = "11:0"] + pub struct Point { + pub x: c_int, + pub y: c_int, + } +} +``` + +Tool lints: + +``` +#![feature(register_tool)] +#![register_tool(bevy)] +#![deny(bevy::duplicate_bevy_dependencies)] +``` diff --git a/src/etc/completions/x.fish b/src/etc/completions/x.fish index 933557ab0d7..4f22bc511de 100644 --- a/src/etc/completions/x.fish +++ b/src/etc/completions/x.fish @@ -1,6 +1,6 @@ # Print an optspec for argparse to handle cmd's options that are independent of any subcommand. function __fish_x_global_optspecs - string join \n v/verbose i/incremental config= build-dir= build= host= target= exclude= skip= include-default-paths rustc-error-format= on-fail= dry-run dump-bootstrap-shims stage= keep-stage= keep-stage-std= src= j/jobs= warnings= error-format= json-output color= bypass-bootstrap-lock rust-profile-generate= rust-profile-use= llvm-profile-use= llvm-profile-generate enable-bolt-settings skip-stage0-validation reproducible-artifact= set= h/help + string join \n v/verbose i/incremental config= build-dir= build= host= target= exclude= skip= include-default-paths rustc-error-format= on-fail= dry-run dump-bootstrap-shims stage= keep-stage= keep-stage-std= src= j/jobs= warnings= error-format= json-output color= bypass-bootstrap-lock rust-profile-generate= rust-profile-use= llvm-profile-use= llvm-profile-generate enable-bolt-settings skip-stage0-validation reproducible-artifact= set= ci= h/help end function __fish_x_needs_command @@ -25,7 +25,7 @@ function __fish_x_using_subcommand end complete -c x -n "__fish_x_needs_command" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_needs_command" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_needs_command" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_needs_command" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_needs_command" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_needs_command" -l target -d 'target targets to build' -r -f @@ -45,7 +45,8 @@ complete -c x -n "__fish_x_needs_command" -l rust-profile-generate -d 'generate complete -c x -n "__fish_x_needs_command" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_needs_command" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_needs_command" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_needs_command" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_needs_command" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_needs_command" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_needs_command" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_needs_command" -s i -l incremental -d 'use incremental compilation' complete -c x -n "__fish_x_needs_command" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -75,7 +76,7 @@ complete -c x -n "__fish_x_needs_command" -a "suggest" -d 'Suggest a subset of t complete -c x -n "__fish_x_needs_command" -a "vendor" -d 'Vendor dependencies' complete -c x -n "__fish_x_needs_command" -a "perf" -d 'Perform profiling and benchmarking of the compiler using `rustc-perf`' complete -c x -n "__fish_x_using_subcommand build" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand build" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand build" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand build" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand build" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand build" -l target -d 'target targets to build' -r -f @@ -95,7 +96,8 @@ complete -c x -n "__fish_x_using_subcommand build" -l rust-profile-generate -d ' complete -c x -n "__fish_x_using_subcommand build" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand build" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand build" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand build" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand build" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand build" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand build" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand build" -s i -l incremental -d 'use incremental compilation' complete -c x -n "__fish_x_using_subcommand build" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -108,7 +110,7 @@ complete -c x -n "__fish_x_using_subcommand build" -l enable-bolt-settings -d 'E complete -c x -n "__fish_x_using_subcommand build" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x -n "__fish_x_using_subcommand build" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x -n "__fish_x_using_subcommand check" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand check" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand check" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand check" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand check" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand check" -l target -d 'target targets to build' -r -f @@ -128,7 +130,8 @@ complete -c x -n "__fish_x_using_subcommand check" -l rust-profile-generate -d ' complete -c x -n "__fish_x_using_subcommand check" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand check" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand check" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand check" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand check" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand check" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand check" -l all-targets -d 'Check all targets' complete -c x -n "__fish_x_using_subcommand check" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand check" -s i -l incremental -d 'use incremental compilation' @@ -146,7 +149,7 @@ complete -c x -n "__fish_x_using_subcommand clippy" -s D -d 'clippy lints to den complete -c x -n "__fish_x_using_subcommand clippy" -s W -d 'clippy lints to warn on' -r complete -c x -n "__fish_x_using_subcommand clippy" -s F -d 'clippy lints to forbid' -r complete -c x -n "__fish_x_using_subcommand clippy" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand clippy" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand clippy" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand clippy" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand clippy" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand clippy" -l target -d 'target targets to build' -r -f @@ -166,7 +169,8 @@ complete -c x -n "__fish_x_using_subcommand clippy" -l rust-profile-generate -d complete -c x -n "__fish_x_using_subcommand clippy" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand clippy" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand clippy" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand clippy" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand clippy" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand clippy" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand clippy" -l fix complete -c x -n "__fish_x_using_subcommand clippy" -l allow-dirty complete -c x -n "__fish_x_using_subcommand clippy" -l allow-staged @@ -182,7 +186,7 @@ complete -c x -n "__fish_x_using_subcommand clippy" -l enable-bolt-settings -d ' complete -c x -n "__fish_x_using_subcommand clippy" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x -n "__fish_x_using_subcommand clippy" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x -n "__fish_x_using_subcommand fix" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand fix" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand fix" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand fix" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand fix" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand fix" -l target -d 'target targets to build' -r -f @@ -202,7 +206,8 @@ complete -c x -n "__fish_x_using_subcommand fix" -l rust-profile-generate -d 'ge complete -c x -n "__fish_x_using_subcommand fix" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand fix" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand fix" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand fix" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand fix" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand fix" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand fix" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand fix" -s i -l incremental -d 'use incremental compilation' complete -c x -n "__fish_x_using_subcommand fix" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -215,7 +220,7 @@ complete -c x -n "__fish_x_using_subcommand fix" -l enable-bolt-settings -d 'Ena complete -c x -n "__fish_x_using_subcommand fix" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x -n "__fish_x_using_subcommand fix" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x -n "__fish_x_using_subcommand fmt" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand fmt" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand fmt" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand fmt" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand fmt" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand fmt" -l target -d 'target targets to build' -r -f @@ -235,7 +240,8 @@ complete -c x -n "__fish_x_using_subcommand fmt" -l rust-profile-generate -d 'ge complete -c x -n "__fish_x_using_subcommand fmt" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand fmt" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand fmt" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand fmt" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand fmt" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand fmt" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand fmt" -l check -d 'check formatting instead of applying' complete -c x -n "__fish_x_using_subcommand fmt" -l all -d 'apply to all appropriate files, not just those that have been modified' complete -c x -n "__fish_x_using_subcommand fmt" -s v -l verbose -d 'use verbose output (-vv for very verbose)' @@ -250,7 +256,7 @@ complete -c x -n "__fish_x_using_subcommand fmt" -l enable-bolt-settings -d 'Ena complete -c x -n "__fish_x_using_subcommand fmt" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x -n "__fish_x_using_subcommand fmt" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x -n "__fish_x_using_subcommand doc" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand doc" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand doc" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand doc" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand doc" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand doc" -l target -d 'target targets to build' -r -f @@ -270,7 +276,8 @@ complete -c x -n "__fish_x_using_subcommand doc" -l rust-profile-generate -d 'ge complete -c x -n "__fish_x_using_subcommand doc" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand doc" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand doc" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand doc" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand doc" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand doc" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand doc" -l open -d 'open the docs in a browser' complete -c x -n "__fish_x_using_subcommand doc" -l json -d 'render the documentation in JSON format in addition to the usual HTML format' complete -c x -n "__fish_x_using_subcommand doc" -s v -l verbose -d 'use verbose output (-vv for very verbose)' @@ -291,7 +298,7 @@ complete -c x -n "__fish_x_using_subcommand test" -l compare-mode -d 'mode descr complete -c x -n "__fish_x_using_subcommand test" -l pass -d 'force {check,build,run}-pass tests to this mode' -r complete -c x -n "__fish_x_using_subcommand test" -l run -d 'whether to execute run-* tests' -r complete -c x -n "__fish_x_using_subcommand test" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand test" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand test" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand test" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand test" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand test" -l target -d 'target targets to build' -r -f @@ -311,7 +318,8 @@ complete -c x -n "__fish_x_using_subcommand test" -l rust-profile-generate -d 'g complete -c x -n "__fish_x_using_subcommand test" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand test" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand test" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand test" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand test" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand test" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand test" -l no-fail-fast -d 'run all tests regardless of failure' complete -c x -n "__fish_x_using_subcommand test" -l no-doc -d 'do not run doc tests' complete -c x -n "__fish_x_using_subcommand test" -l doc -d 'only run doc tests' @@ -333,7 +341,7 @@ complete -c x -n "__fish_x_using_subcommand test" -l skip-stage0-validation -d ' complete -c x -n "__fish_x_using_subcommand test" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x -n "__fish_x_using_subcommand miri" -l test-args -d 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)' -r complete -c x -n "__fish_x_using_subcommand miri" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand miri" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand miri" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand miri" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand miri" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand miri" -l target -d 'target targets to build' -r -f @@ -353,7 +361,8 @@ complete -c x -n "__fish_x_using_subcommand miri" -l rust-profile-generate -d 'g complete -c x -n "__fish_x_using_subcommand miri" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand miri" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand miri" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand miri" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand miri" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand miri" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand miri" -l no-fail-fast -d 'run all tests regardless of failure' complete -c x -n "__fish_x_using_subcommand miri" -l no-doc -d 'do not run doc tests' complete -c x -n "__fish_x_using_subcommand miri" -l doc -d 'only run doc tests' @@ -370,7 +379,7 @@ complete -c x -n "__fish_x_using_subcommand miri" -l skip-stage0-validation -d ' complete -c x -n "__fish_x_using_subcommand miri" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x -n "__fish_x_using_subcommand bench" -l test-args -r complete -c x -n "__fish_x_using_subcommand bench" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand bench" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand bench" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand bench" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand bench" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand bench" -l target -d 'target targets to build' -r -f @@ -390,7 +399,8 @@ complete -c x -n "__fish_x_using_subcommand bench" -l rust-profile-generate -d ' complete -c x -n "__fish_x_using_subcommand bench" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand bench" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand bench" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand bench" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand bench" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand bench" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand bench" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand bench" -s i -l incremental -d 'use incremental compilation' complete -c x -n "__fish_x_using_subcommand bench" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -404,7 +414,7 @@ complete -c x -n "__fish_x_using_subcommand bench" -l skip-stage0-validation -d complete -c x -n "__fish_x_using_subcommand bench" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x -n "__fish_x_using_subcommand clean" -l stage -d 'Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used' -r complete -c x -n "__fish_x_using_subcommand clean" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand clean" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand clean" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand clean" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand clean" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand clean" -l target -d 'target targets to build' -r -f @@ -423,7 +433,8 @@ complete -c x -n "__fish_x_using_subcommand clean" -l rust-profile-generate -d ' complete -c x -n "__fish_x_using_subcommand clean" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand clean" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand clean" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand clean" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand clean" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand clean" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand clean" -l all -d 'Clean the entire build directory (not used by default)' complete -c x -n "__fish_x_using_subcommand clean" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand clean" -s i -l incremental -d 'use incremental compilation' @@ -437,7 +448,7 @@ complete -c x -n "__fish_x_using_subcommand clean" -l enable-bolt-settings -d 'E complete -c x -n "__fish_x_using_subcommand clean" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x -n "__fish_x_using_subcommand clean" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x -n "__fish_x_using_subcommand dist" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand dist" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand dist" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand dist" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand dist" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand dist" -l target -d 'target targets to build' -r -f @@ -457,7 +468,8 @@ complete -c x -n "__fish_x_using_subcommand dist" -l rust-profile-generate -d 'g complete -c x -n "__fish_x_using_subcommand dist" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand dist" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand dist" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand dist" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand dist" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand dist" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand dist" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand dist" -s i -l incremental -d 'use incremental compilation' complete -c x -n "__fish_x_using_subcommand dist" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -470,7 +482,7 @@ complete -c x -n "__fish_x_using_subcommand dist" -l enable-bolt-settings -d 'En complete -c x -n "__fish_x_using_subcommand dist" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x -n "__fish_x_using_subcommand dist" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x -n "__fish_x_using_subcommand install" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand install" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand install" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand install" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand install" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand install" -l target -d 'target targets to build' -r -f @@ -490,7 +502,8 @@ complete -c x -n "__fish_x_using_subcommand install" -l rust-profile-generate -d complete -c x -n "__fish_x_using_subcommand install" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand install" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand install" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand install" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand install" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand install" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand install" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand install" -s i -l incremental -d 'use incremental compilation' complete -c x -n "__fish_x_using_subcommand install" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -504,7 +517,7 @@ complete -c x -n "__fish_x_using_subcommand install" -l skip-stage0-validation - complete -c x -n "__fish_x_using_subcommand install" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x -n "__fish_x_using_subcommand run" -l args -d 'arguments for the tool' -r complete -c x -n "__fish_x_using_subcommand run" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand run" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand run" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand run" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand run" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand run" -l target -d 'target targets to build' -r -f @@ -524,7 +537,8 @@ complete -c x -n "__fish_x_using_subcommand run" -l rust-profile-generate -d 'ge complete -c x -n "__fish_x_using_subcommand run" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand run" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand run" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand run" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand run" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand run" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand run" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand run" -s i -l incremental -d 'use incremental compilation' complete -c x -n "__fish_x_using_subcommand run" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -537,7 +551,7 @@ complete -c x -n "__fish_x_using_subcommand run" -l enable-bolt-settings -d 'Ena complete -c x -n "__fish_x_using_subcommand run" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x -n "__fish_x_using_subcommand run" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x -n "__fish_x_using_subcommand setup" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand setup" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand setup" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand setup" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand setup" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand setup" -l target -d 'target targets to build' -r -f @@ -557,7 +571,8 @@ complete -c x -n "__fish_x_using_subcommand setup" -l rust-profile-generate -d ' complete -c x -n "__fish_x_using_subcommand setup" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand setup" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand setup" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand setup" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand setup" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand setup" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand setup" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand setup" -s i -l incremental -d 'use incremental compilation' complete -c x -n "__fish_x_using_subcommand setup" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -570,7 +585,7 @@ complete -c x -n "__fish_x_using_subcommand setup" -l enable-bolt-settings -d 'E complete -c x -n "__fish_x_using_subcommand setup" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x -n "__fish_x_using_subcommand setup" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x -n "__fish_x_using_subcommand suggest" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand suggest" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand suggest" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand suggest" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand suggest" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand suggest" -l target -d 'target targets to build' -r -f @@ -590,7 +605,8 @@ complete -c x -n "__fish_x_using_subcommand suggest" -l rust-profile-generate -d complete -c x -n "__fish_x_using_subcommand suggest" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand suggest" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand suggest" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand suggest" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand suggest" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand suggest" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand suggest" -l run -d 'run suggested tests' complete -c x -n "__fish_x_using_subcommand suggest" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand suggest" -s i -l incremental -d 'use incremental compilation' @@ -605,7 +621,7 @@ complete -c x -n "__fish_x_using_subcommand suggest" -l skip-stage0-validation - complete -c x -n "__fish_x_using_subcommand suggest" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x -n "__fish_x_using_subcommand vendor" -l sync -d 'Additional `Cargo.toml` to sync and vendor' -r -F complete -c x -n "__fish_x_using_subcommand vendor" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand vendor" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand vendor" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand vendor" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand vendor" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand vendor" -l target -d 'target targets to build' -r -f @@ -625,7 +641,8 @@ complete -c x -n "__fish_x_using_subcommand vendor" -l rust-profile-generate -d complete -c x -n "__fish_x_using_subcommand vendor" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand vendor" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand vendor" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand vendor" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand vendor" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand vendor" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand vendor" -l versioned-dirs -d 'Always include version in subdir name' complete -c x -n "__fish_x_using_subcommand vendor" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand vendor" -s i -l incremental -d 'use incremental compilation' @@ -639,7 +656,7 @@ complete -c x -n "__fish_x_using_subcommand vendor" -l enable-bolt-settings -d ' complete -c x -n "__fish_x_using_subcommand vendor" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x -n "__fish_x_using_subcommand vendor" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x -n "__fish_x_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l target -d 'target targets to build' -r -f @@ -659,7 +676,8 @@ complete -c x -n "__fish_x_using_subcommand perf; and not __fish_seen_subcommand complete -c x -n "__fish_x_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -s i -l incremental -d 'use incremental compilation' complete -c x -n "__fish_x_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -681,7 +699,7 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',Opt\t'',Clippy\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l target -d 'target targets to build' -r -f @@ -700,7 +718,8 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -s i -l incremental -d 'use incremental compilation' complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -717,7 +736,7 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',Opt\t'',Clippy\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l target -d 'target targets to build' -r -f @@ -736,7 +755,8 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -s i -l incremental -d 'use incremental compilation' complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -753,7 +773,7 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',Opt\t'',Clippy\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l target -d 'target targets to build' -r -f @@ -772,7 +792,8 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -s i -l incremental -d 'use incremental compilation' complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -789,7 +810,7 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',Opt\t'',Clippy\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l target -d 'target targets to build' -r -f @@ -808,7 +829,8 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -s i -l incremental -d 'use incremental compilation' complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -821,7 +843,7 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -l config -d 'TOML configuration file for build' -r -F -complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -l build -d 'build target of the stage0 compiler' -r -f complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -l host -d 'host targets to build' -r -f complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -l target -d 'target targets to build' -r -f @@ -841,7 +863,8 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -l set -d 'override options in config.toml' -r -f +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -s i -l incremental -d 'use incremental compilation' complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -l include-default-paths -d 'include default paths in addition to the provided ones' diff --git a/src/etc/completions/x.ps1 b/src/etc/completions/x.ps1 index b848b95d88f..638b87edfb2 100644 --- a/src/etc/completions/x.ps1 +++ b/src/etc/completions/x.ps1 @@ -22,7 +22,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { $completions = @(switch ($command) { 'x' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -43,7 +43,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -79,7 +80,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { } 'x;build' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -100,7 +101,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -119,7 +121,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { } 'x;check' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -140,7 +142,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--all-targets', '--all-targets', [CompletionResultType]::ParameterName, 'Check all targets') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -164,7 +167,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('-W', '-W ', [CompletionResultType]::ParameterName, 'clippy lints to warn on') [CompletionResult]::new('-F', '-F ', [CompletionResultType]::ParameterName, 'clippy lints to forbid') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -185,7 +188,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--fix', '--fix', [CompletionResultType]::ParameterName, 'fix') [CompletionResult]::new('--allow-dirty', '--allow-dirty', [CompletionResultType]::ParameterName, 'allow-dirty') [CompletionResult]::new('--allow-staged', '--allow-staged', [CompletionResultType]::ParameterName, 'allow-staged') @@ -207,7 +211,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { } 'x;fix' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -228,7 +232,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -247,7 +252,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { } 'x;fmt' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -268,7 +273,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--check', '--check', [CompletionResultType]::ParameterName, 'check formatting instead of applying') [CompletionResult]::new('--all', '--all', [CompletionResultType]::ParameterName, 'apply to all appropriate files, not just those that have been modified') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -289,7 +295,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { } 'x;doc' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -310,7 +316,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--open', '--open', [CompletionResultType]::ParameterName, 'open the docs in a browser') [CompletionResult]::new('--json', '--json', [CompletionResultType]::ParameterName, 'render the documentation in JSON format in addition to the usual HTML format') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -337,7 +344,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--pass', '--pass', [CompletionResultType]::ParameterName, 'force {check,build,run}-pass tests to this mode') [CompletionResult]::new('--run', '--run', [CompletionResultType]::ParameterName, 'whether to execute run-* tests') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -358,7 +365,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--no-fail-fast', '--no-fail-fast', [CompletionResultType]::ParameterName, 'run all tests regardless of failure') [CompletionResult]::new('--no-doc', '--no-doc', [CompletionResultType]::ParameterName, 'do not run doc tests') [CompletionResult]::new('--doc', '--doc', [CompletionResultType]::ParameterName, 'only run doc tests') @@ -386,7 +394,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { 'x;miri' { [CompletionResult]::new('--test-args', '--test-args', [CompletionResultType]::ParameterName, 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -407,7 +415,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--no-fail-fast', '--no-fail-fast', [CompletionResultType]::ParameterName, 'run all tests regardless of failure') [CompletionResult]::new('--no-doc', '--no-doc', [CompletionResultType]::ParameterName, 'do not run doc tests') [CompletionResult]::new('--doc', '--doc', [CompletionResultType]::ParameterName, 'only run doc tests') @@ -430,7 +439,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { 'x;bench' { [CompletionResult]::new('--test-args', '--test-args', [CompletionResultType]::ParameterName, 'test-args') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -451,7 +460,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -471,7 +481,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { 'x;clean' { [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -491,7 +501,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--all', '--all', [CompletionResultType]::ParameterName, 'Clean the entire build directory (not used by default)') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -511,7 +522,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { } 'x;dist' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -532,7 +543,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -551,7 +563,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { } 'x;install' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -572,7 +584,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -592,7 +605,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { 'x;run' { [CompletionResult]::new('--args', '--args', [CompletionResultType]::ParameterName, 'arguments for the tool') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -613,7 +626,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -632,7 +646,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { } 'x;setup' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -653,7 +667,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -672,7 +687,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { } 'x;suggest' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -693,7 +708,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--run', '--run', [CompletionResultType]::ParameterName, 'run suggested tests') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -714,7 +730,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { 'x;vendor' { [CompletionResult]::new('--sync', '--sync', [CompletionResultType]::ParameterName, 'Additional `Cargo.toml` to sync and vendor') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -735,7 +751,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--versioned-dirs', '--versioned-dirs', [CompletionResultType]::ParameterName, 'Always include version in subdir name') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -755,7 +772,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { } 'x;perf' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -776,7 +793,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -804,7 +822,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -824,7 +842,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -847,7 +866,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -867,7 +886,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -890,7 +910,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -910,7 +930,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -933,7 +954,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -953,7 +974,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -972,7 +994,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { } 'x;perf;compare' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -993,7 +1015,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish index ff4f7425da6..75771ec9a81 100644 --- a/src/etc/completions/x.py.fish +++ b/src/etc/completions/x.py.fish @@ -1,6 +1,6 @@ # Print an optspec for argparse to handle cmd's options that are independent of any subcommand. function __fish_x.py_global_optspecs - string join \n v/verbose i/incremental config= build-dir= build= host= target= exclude= skip= include-default-paths rustc-error-format= on-fail= dry-run dump-bootstrap-shims stage= keep-stage= keep-stage-std= src= j/jobs= warnings= error-format= json-output color= bypass-bootstrap-lock rust-profile-generate= rust-profile-use= llvm-profile-use= llvm-profile-generate enable-bolt-settings skip-stage0-validation reproducible-artifact= set= h/help + string join \n v/verbose i/incremental config= build-dir= build= host= target= exclude= skip= include-default-paths rustc-error-format= on-fail= dry-run dump-bootstrap-shims stage= keep-stage= keep-stage-std= src= j/jobs= warnings= error-format= json-output color= bypass-bootstrap-lock rust-profile-generate= rust-profile-use= llvm-profile-use= llvm-profile-generate enable-bolt-settings skip-stage0-validation reproducible-artifact= set= ci= h/help end function __fish_x.py_needs_command @@ -25,7 +25,7 @@ function __fish_x.py_using_subcommand end complete -c x.py -n "__fish_x.py_needs_command" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_needs_command" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_needs_command" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_needs_command" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_needs_command" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_needs_command" -l target -d 'target targets to build' -r -f @@ -45,7 +45,8 @@ complete -c x.py -n "__fish_x.py_needs_command" -l rust-profile-generate -d 'gen complete -c x.py -n "__fish_x.py_needs_command" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_needs_command" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_needs_command" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_needs_command" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_needs_command" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_needs_command" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_needs_command" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_needs_command" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_x.py_needs_command" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -75,7 +76,7 @@ complete -c x.py -n "__fish_x.py_needs_command" -a "suggest" -d 'Suggest a subse complete -c x.py -n "__fish_x.py_needs_command" -a "vendor" -d 'Vendor dependencies' complete -c x.py -n "__fish_x.py_needs_command" -a "perf" -d 'Perform profiling and benchmarking of the compiler using `rustc-perf`' complete -c x.py -n "__fish_x.py_using_subcommand build" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand build" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand build" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand build" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand build" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand build" -l target -d 'target targets to build' -r -f @@ -95,7 +96,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand build" -l rust-profile-generat complete -c x.py -n "__fish_x.py_using_subcommand build" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand build" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand build" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand build" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand build" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand build" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand build" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand build" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_x.py_using_subcommand build" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -108,7 +110,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand build" -l enable-bolt-settings complete -c x.py -n "__fish_x.py_using_subcommand build" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x.py -n "__fish_x.py_using_subcommand build" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x.py -n "__fish_x.py_using_subcommand check" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand check" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand check" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand check" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand check" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand check" -l target -d 'target targets to build' -r -f @@ -128,7 +130,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand check" -l rust-profile-generat complete -c x.py -n "__fish_x.py_using_subcommand check" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand check" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand check" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand check" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand check" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand check" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand check" -l all-targets -d 'Check all targets' complete -c x.py -n "__fish_x.py_using_subcommand check" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand check" -s i -l incremental -d 'use incremental compilation' @@ -146,7 +149,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand clippy" -s D -d 'clippy lints complete -c x.py -n "__fish_x.py_using_subcommand clippy" -s W -d 'clippy lints to warn on' -r complete -c x.py -n "__fish_x.py_using_subcommand clippy" -s F -d 'clippy lints to forbid' -r complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l target -d 'target targets to build' -r -f @@ -166,7 +169,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l rust-profile-genera complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l fix complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l allow-dirty complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l allow-staged @@ -182,7 +186,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l enable-bolt-setting complete -c x.py -n "__fish_x.py_using_subcommand clippy" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x.py -n "__fish_x.py_using_subcommand clippy" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x.py -n "__fish_x.py_using_subcommand fix" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand fix" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand fix" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand fix" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand fix" -l target -d 'target targets to build' -r -f @@ -202,7 +206,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand fix" -l rust-profile-generate complete -c x.py -n "__fish_x.py_using_subcommand fix" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand fix" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand fix" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand fix" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fix" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand fix" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand fix" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_x.py_using_subcommand fix" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -215,7 +220,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand fix" -l enable-bolt-settings - complete -c x.py -n "__fish_x.py_using_subcommand fix" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x.py -n "__fish_x.py_using_subcommand fix" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l target -d 'target targets to build' -r -f @@ -235,7 +240,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l rust-profile-generate complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l check -d 'check formatting instead of applying' complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l all -d 'apply to all appropriate files, not just those that have been modified' complete -c x.py -n "__fish_x.py_using_subcommand fmt" -s v -l verbose -d 'use verbose output (-vv for very verbose)' @@ -250,7 +256,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l enable-bolt-settings - complete -c x.py -n "__fish_x.py_using_subcommand fmt" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x.py -n "__fish_x.py_using_subcommand fmt" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x.py -n "__fish_x.py_using_subcommand doc" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand doc" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand doc" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand doc" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand doc" -l target -d 'target targets to build' -r -f @@ -270,7 +276,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand doc" -l rust-profile-generate complete -c x.py -n "__fish_x.py_using_subcommand doc" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand doc" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand doc" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand doc" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand doc" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand doc" -l open -d 'open the docs in a browser' complete -c x.py -n "__fish_x.py_using_subcommand doc" -l json -d 'render the documentation in JSON format in addition to the usual HTML format' complete -c x.py -n "__fish_x.py_using_subcommand doc" -s v -l verbose -d 'use verbose output (-vv for very verbose)' @@ -291,7 +298,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand test" -l compare-mode -d 'mode complete -c x.py -n "__fish_x.py_using_subcommand test" -l pass -d 'force {check,build,run}-pass tests to this mode' -r complete -c x.py -n "__fish_x.py_using_subcommand test" -l run -d 'whether to execute run-* tests' -r complete -c x.py -n "__fish_x.py_using_subcommand test" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand test" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand test" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand test" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand test" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand test" -l target -d 'target targets to build' -r -f @@ -311,7 +318,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand test" -l rust-profile-generate complete -c x.py -n "__fish_x.py_using_subcommand test" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand test" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand test" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand test" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand test" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand test" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand test" -l no-fail-fast -d 'run all tests regardless of failure' complete -c x.py -n "__fish_x.py_using_subcommand test" -l no-doc -d 'do not run doc tests' complete -c x.py -n "__fish_x.py_using_subcommand test" -l doc -d 'only run doc tests' @@ -333,7 +341,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand test" -l skip-stage0-validatio complete -c x.py -n "__fish_x.py_using_subcommand test" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x.py -n "__fish_x.py_using_subcommand miri" -l test-args -d 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)' -r complete -c x.py -n "__fish_x.py_using_subcommand miri" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand miri" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand miri" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand miri" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand miri" -l target -d 'target targets to build' -r -f @@ -353,7 +361,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand miri" -l rust-profile-generate complete -c x.py -n "__fish_x.py_using_subcommand miri" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand miri" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand miri" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand miri" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand miri" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand miri" -l no-fail-fast -d 'run all tests regardless of failure' complete -c x.py -n "__fish_x.py_using_subcommand miri" -l no-doc -d 'do not run doc tests' complete -c x.py -n "__fish_x.py_using_subcommand miri" -l doc -d 'only run doc tests' @@ -370,7 +379,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand miri" -l skip-stage0-validatio complete -c x.py -n "__fish_x.py_using_subcommand miri" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x.py -n "__fish_x.py_using_subcommand bench" -l test-args -r complete -c x.py -n "__fish_x.py_using_subcommand bench" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand bench" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand bench" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand bench" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand bench" -l target -d 'target targets to build' -r -f @@ -390,7 +399,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand bench" -l rust-profile-generat complete -c x.py -n "__fish_x.py_using_subcommand bench" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand bench" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand bench" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand bench" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand bench" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand bench" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand bench" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_x.py_using_subcommand bench" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -404,7 +414,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand bench" -l skip-stage0-validati complete -c x.py -n "__fish_x.py_using_subcommand bench" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x.py -n "__fish_x.py_using_subcommand clean" -l stage -d 'Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used' -r complete -c x.py -n "__fish_x.py_using_subcommand clean" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand clean" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand clean" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand clean" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand clean" -l target -d 'target targets to build' -r -f @@ -423,7 +433,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand clean" -l rust-profile-generat complete -c x.py -n "__fish_x.py_using_subcommand clean" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand clean" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand clean" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand clean" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand clean" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand clean" -l all -d 'Clean the entire build directory (not used by default)' complete -c x.py -n "__fish_x.py_using_subcommand clean" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand clean" -s i -l incremental -d 'use incremental compilation' @@ -437,7 +448,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand clean" -l enable-bolt-settings complete -c x.py -n "__fish_x.py_using_subcommand clean" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x.py -n "__fish_x.py_using_subcommand clean" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x.py -n "__fish_x.py_using_subcommand dist" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand dist" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand dist" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand dist" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand dist" -l target -d 'target targets to build' -r -f @@ -457,7 +468,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand dist" -l rust-profile-generate complete -c x.py -n "__fish_x.py_using_subcommand dist" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand dist" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand dist" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand dist" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand dist" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand dist" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand dist" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_x.py_using_subcommand dist" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -470,7 +482,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand dist" -l enable-bolt-settings complete -c x.py -n "__fish_x.py_using_subcommand dist" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x.py -n "__fish_x.py_using_subcommand dist" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x.py -n "__fish_x.py_using_subcommand install" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand install" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand install" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand install" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand install" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand install" -l target -d 'target targets to build' -r -f @@ -490,7 +502,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand install" -l rust-profile-gener complete -c x.py -n "__fish_x.py_using_subcommand install" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand install" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand install" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand install" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand install" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand install" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand install" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand install" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_x.py_using_subcommand install" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -504,7 +517,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand install" -l skip-stage0-valida complete -c x.py -n "__fish_x.py_using_subcommand install" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x.py -n "__fish_x.py_using_subcommand run" -l args -d 'arguments for the tool' -r complete -c x.py -n "__fish_x.py_using_subcommand run" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand run" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand run" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand run" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand run" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand run" -l target -d 'target targets to build' -r -f @@ -524,7 +537,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand run" -l rust-profile-generate complete -c x.py -n "__fish_x.py_using_subcommand run" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand run" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand run" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand run" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand run" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand run" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand run" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand run" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_x.py_using_subcommand run" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -537,7 +551,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand run" -l enable-bolt-settings - complete -c x.py -n "__fish_x.py_using_subcommand run" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x.py -n "__fish_x.py_using_subcommand run" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x.py -n "__fish_x.py_using_subcommand setup" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand setup" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand setup" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand setup" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand setup" -l target -d 'target targets to build' -r -f @@ -557,7 +571,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand setup" -l rust-profile-generat complete -c x.py -n "__fish_x.py_using_subcommand setup" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand setup" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand setup" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand setup" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand setup" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand setup" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand setup" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_x.py_using_subcommand setup" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -570,7 +585,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand setup" -l enable-bolt-settings complete -c x.py -n "__fish_x.py_using_subcommand setup" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x.py -n "__fish_x.py_using_subcommand setup" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l target -d 'target targets to build' -r -f @@ -590,7 +605,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l rust-profile-gener complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l run -d 'run suggested tests' complete -c x.py -n "__fish_x.py_using_subcommand suggest" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand suggest" -s i -l incremental -d 'use incremental compilation' @@ -605,7 +621,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand suggest" -l skip-stage0-valida complete -c x.py -n "__fish_x.py_using_subcommand suggest" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l sync -d 'Additional `Cargo.toml` to sync and vendor' -r -F complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l target -d 'target targets to build' -r -f @@ -625,7 +641,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l rust-profile-genera complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l versioned-dirs -d 'Always include version in subdir name' complete -c x.py -n "__fish_x.py_using_subcommand vendor" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand vendor" -s i -l incremental -d 'use incremental compilation' @@ -639,7 +656,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l enable-bolt-setting complete -c x.py -n "__fish_x.py_using_subcommand vendor" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x.py -n "__fish_x.py_using_subcommand vendor" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x.py -n "__fish_x.py_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l target -d 'target targets to build' -r -f @@ -659,7 +676,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and not __fish_seen_subc complete -c x.py -n "__fish_x.py_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_x.py_using_subcommand perf; and not __fish_seen_subcommand_from eprintln samply cachegrind benchmark compare" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -681,7 +699,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',Opt\t'',Clippy\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l target -d 'target targets to build' -r -f @@ -700,7 +718,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -717,7 +736,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',Opt\t'',Clippy\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l target -d 'target targets to build' -r -f @@ -736,7 +755,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -753,7 +773,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',Opt\t'',Clippy\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l target -d 'target targets to build' -r -f @@ -772,7 +792,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -789,7 +810,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',Opt\t'',Clippy\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l target -d 'target targets to build' -r -f @@ -808,7 +829,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l include-default-paths -d 'include default paths in addition to the provided ones' @@ -821,7 +843,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -s h -l help -d 'Print help (see more with \'--help\')' complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -l config -d 'TOML configuration file for build' -r -F -complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)" +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -l build -d 'build target of the stage0 compiler' -r -f complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -l host -d 'host targets to build' -r -f complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -l target -d 'target targets to build' -r -f @@ -841,7 +863,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -l reproducible-artifact -d 'Additional reproducible artifacts that should be added to the reproducible artifacts archive' -r -complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -l set -d 'override options in config.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -l set -d 'override options in bootstrap.toml' -r -f +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -l ci -d 'Make bootstrap to behave as it\'s running on the CI environment or not' -r -f -a "{true\t'',false\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -s v -l verbose -d 'use verbose output (-vv for very verbose)' complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -s i -l incremental -d 'use incremental compilation' complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -l include-default-paths -d 'include default paths in addition to the provided ones' diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1 index e5ee174f4ca..0a716619106 100644 --- a/src/etc/completions/x.py.ps1 +++ b/src/etc/completions/x.py.ps1 @@ -22,7 +22,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { $completions = @(switch ($command) { 'x.py' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -43,7 +43,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -79,7 +80,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { } 'x.py;build' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -100,7 +101,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -119,7 +121,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { } 'x.py;check' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -140,7 +142,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--all-targets', '--all-targets', [CompletionResultType]::ParameterName, 'Check all targets') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -164,7 +167,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('-W', '-W ', [CompletionResultType]::ParameterName, 'clippy lints to warn on') [CompletionResult]::new('-F', '-F ', [CompletionResultType]::ParameterName, 'clippy lints to forbid') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -185,7 +188,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--fix', '--fix', [CompletionResultType]::ParameterName, 'fix') [CompletionResult]::new('--allow-dirty', '--allow-dirty', [CompletionResultType]::ParameterName, 'allow-dirty') [CompletionResult]::new('--allow-staged', '--allow-staged', [CompletionResultType]::ParameterName, 'allow-staged') @@ -207,7 +211,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { } 'x.py;fix' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -228,7 +232,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -247,7 +252,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { } 'x.py;fmt' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -268,7 +273,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--check', '--check', [CompletionResultType]::ParameterName, 'check formatting instead of applying') [CompletionResult]::new('--all', '--all', [CompletionResultType]::ParameterName, 'apply to all appropriate files, not just those that have been modified') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -289,7 +295,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { } 'x.py;doc' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -310,7 +316,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--open', '--open', [CompletionResultType]::ParameterName, 'open the docs in a browser') [CompletionResult]::new('--json', '--json', [CompletionResultType]::ParameterName, 'render the documentation in JSON format in addition to the usual HTML format') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -337,7 +344,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--pass', '--pass', [CompletionResultType]::ParameterName, 'force {check,build,run}-pass tests to this mode') [CompletionResult]::new('--run', '--run', [CompletionResultType]::ParameterName, 'whether to execute run-* tests') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -358,7 +365,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--no-fail-fast', '--no-fail-fast', [CompletionResultType]::ParameterName, 'run all tests regardless of failure') [CompletionResult]::new('--no-doc', '--no-doc', [CompletionResultType]::ParameterName, 'do not run doc tests') [CompletionResult]::new('--doc', '--doc', [CompletionResultType]::ParameterName, 'only run doc tests') @@ -386,7 +394,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { 'x.py;miri' { [CompletionResult]::new('--test-args', '--test-args', [CompletionResultType]::ParameterName, 'extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -407,7 +415,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--no-fail-fast', '--no-fail-fast', [CompletionResultType]::ParameterName, 'run all tests regardless of failure') [CompletionResult]::new('--no-doc', '--no-doc', [CompletionResultType]::ParameterName, 'do not run doc tests') [CompletionResult]::new('--doc', '--doc', [CompletionResultType]::ParameterName, 'only run doc tests') @@ -430,7 +439,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { 'x.py;bench' { [CompletionResult]::new('--test-args', '--test-args', [CompletionResultType]::ParameterName, 'test-args') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -451,7 +460,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -471,7 +481,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { 'x.py;clean' { [CompletionResult]::new('--stage', '--stage', [CompletionResultType]::ParameterName, 'Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -491,7 +501,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--all', '--all', [CompletionResultType]::ParameterName, 'Clean the entire build directory (not used by default)') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -511,7 +522,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { } 'x.py;dist' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -532,7 +543,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -551,7 +563,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { } 'x.py;install' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -572,7 +584,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -592,7 +605,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { 'x.py;run' { [CompletionResult]::new('--args', '--args', [CompletionResultType]::ParameterName, 'arguments for the tool') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -613,7 +626,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -632,7 +646,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { } 'x.py;setup' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -653,7 +667,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -672,7 +687,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { } 'x.py;suggest' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -693,7 +708,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--run', '--run', [CompletionResultType]::ParameterName, 'run suggested tests') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -714,7 +730,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { 'x.py;vendor' { [CompletionResult]::new('--sync', '--sync', [CompletionResultType]::ParameterName, 'Additional `Cargo.toml` to sync and vendor') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -735,7 +751,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('--versioned-dirs', '--versioned-dirs', [CompletionResultType]::ParameterName, 'Always include version in subdir name') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') @@ -755,7 +772,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { } 'x.py;perf' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -776,7 +793,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -804,7 +822,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -824,7 +842,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -847,7 +866,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -867,7 +886,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -890,7 +910,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -910,7 +930,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -933,7 +954,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -953,7 +974,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') @@ -972,7 +994,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { } 'x.py;perf;compare' { [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') - [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`') + [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler') [CompletionResult]::new('--host', '--host', [CompletionResultType]::ParameterName, 'host targets to build') [CompletionResult]::new('--target', '--target', [CompletionResultType]::ParameterName, 'target targets to build') @@ -993,7 +1015,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--rust-profile-use', '--rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build') [CompletionResult]::new('--llvm-profile-use', '--llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build') [CompletionResult]::new('--reproducible-artifact', '--reproducible-artifact', [CompletionResultType]::ParameterName, 'Additional reproducible artifacts that should be added to the reproducible artifacts archive') - [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in config.toml') + [CompletionResult]::new('--set', '--set', [CompletionResultType]::ParameterName, 'override options in bootstrap.toml') + [CompletionResult]::new('--ci', '--ci', [CompletionResultType]::ParameterName, 'Make bootstrap to behave as it''s running on the CI environment or not') [CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)') [CompletionResult]::new('-i', '-i', [CompletionResultType]::ParameterName, 'use incremental compilation') diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh index 4952b57b8ab..79b239c672d 100644 --- a/src/etc/completions/x.py.sh +++ b/src/etc/completions/x.py.sh @@ -85,7 +85,7 @@ _x.py() { case "${cmd}" in x.py) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]... build check clippy fix fmt doc test miri bench clean dist install run setup suggest vendor perf" + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]... build check clippy fix fmt doc test miri bench clean dist install run setup suggest vendor perf" if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -266,6 +266,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -274,7 +278,7 @@ _x.py() { return 0 ;; x.py__bench) - opts="-v -i -j -h --test-args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --test-args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -459,6 +463,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -467,7 +475,7 @@ _x.py() { return 0 ;; x.py__build) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -648,6 +656,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -656,7 +668,7 @@ _x.py() { return 0 ;; x.py__check) - opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -837,6 +849,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -845,7 +861,7 @@ _x.py() { return 0 ;; x.py__clean) - opts="-v -i -j -h --all --stage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --all --stage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1023,6 +1039,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -1031,7 +1051,7 @@ _x.py() { return 0 ;; x.py__clippy) - opts="-A -D -W -F -v -i -j -h --fix --allow-dirty --allow-staged --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-A -D -W -F -v -i -j -h --fix --allow-dirty --allow-staged --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1228,6 +1248,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -1236,7 +1260,7 @@ _x.py() { return 0 ;; x.py__dist) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1417,6 +1441,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -1425,7 +1453,7 @@ _x.py() { return 0 ;; x.py__doc) - opts="-v -i -j -h --open --json --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --open --json --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1606,6 +1634,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -1614,7 +1646,7 @@ _x.py() { return 0 ;; x.py__fix) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1795,6 +1827,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -1803,7 +1839,7 @@ _x.py() { return 0 ;; x.py__fmt) - opts="-v -i -j -h --check --all --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --check --all --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1984,6 +2020,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -1992,7 +2032,7 @@ _x.py() { return 0 ;; x.py__install) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -2173,6 +2213,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -2181,7 +2225,7 @@ _x.py() { return 0 ;; x.py__miri) - opts="-v -i -j -h --no-fail-fast --test-args --no-doc --doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --no-fail-fast --test-args --no-doc --doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -2366,6 +2410,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -2374,7 +2422,7 @@ _x.py() { return 0 ;; x.py__perf) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]... eprintln samply cachegrind benchmark compare" + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]... eprintln samply cachegrind benchmark compare" if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -2555,6 +2603,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -2563,7 +2615,7 @@ _x.py() { return 0 ;; x.py__perf__benchmark) - opts="-v -i -j -h --include --exclude --scenarios --profiles --verbose --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help <benchmark-id> [PATHS]... [ARGS]..." + opts="-v -i -j -h --include --exclude --scenarios --profiles --verbose --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help <benchmark-id> [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -2756,6 +2808,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -2764,7 +2820,7 @@ _x.py() { return 0 ;; x.py__perf__cachegrind) - opts="-v -i -j -h --include --exclude --scenarios --profiles --verbose --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --include --exclude --scenarios --profiles --verbose --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -2957,6 +3013,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -2965,7 +3025,7 @@ _x.py() { return 0 ;; x.py__perf__compare) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help <BASE> <MODIFIED> [PATHS]... [ARGS]..." + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help <BASE> <MODIFIED> [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3146,6 +3206,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -3154,7 +3218,7 @@ _x.py() { return 0 ;; x.py__perf__eprintln) - opts="-v -i -j -h --include --exclude --scenarios --profiles --verbose --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --include --exclude --scenarios --profiles --verbose --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3347,6 +3411,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -3355,7 +3423,7 @@ _x.py() { return 0 ;; x.py__perf__samply) - opts="-v -i -j -h --include --exclude --scenarios --profiles --verbose --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --include --exclude --scenarios --profiles --verbose --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3548,6 +3616,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -3556,7 +3628,7 @@ _x.py() { return 0 ;; x.py__run) - opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3741,6 +3813,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -3749,7 +3825,7 @@ _x.py() { return 0 ;; x.py__setup) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [<PROFILE>|hook|editor|link] [PATHS]... [ARGS]..." + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [<PROFILE>|hook|editor|link] [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3930,6 +4006,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -3938,7 +4018,7 @@ _x.py() { return 0 ;; x.py__suggest) - opts="-v -i -j -h --run --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --run --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -4119,6 +4199,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -4127,7 +4211,7 @@ _x.py() { return 0 ;; x.py__test) - opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -4332,6 +4416,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -4340,7 +4428,7 @@ _x.py() { return 0 ;; x.py__vendor) - opts="-v -i -j -h --sync --versioned-dirs --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --sync --versioned-dirs --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -4525,6 +4613,10 @@ _x.py() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh index 71afd5e73ca..fccea8484d7 100644 --- a/src/etc/completions/x.py.zsh +++ b/src/etc/completions/x.py.zsh @@ -16,7 +16,7 @@ _x.py() { local context curcontext="$curcontext" state line _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -37,7 +37,8 @@ _x.py() { '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -66,7 +67,7 @@ _x.py() { (build) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -87,7 +88,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -108,7 +110,7 @@ _arguments "${_arguments_options[@]}" : \ (check) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -129,7 +131,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--all-targets[Check all targets]' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ @@ -155,7 +158,7 @@ _arguments "${_arguments_options[@]}" : \ '*-W+[clippy lints to warn on]:LINT:_default' \ '*-F+[clippy lints to forbid]:LINT:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -176,7 +179,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--fix[]' \ '--allow-dirty[]' \ '--allow-staged[]' \ @@ -200,7 +204,7 @@ _arguments "${_arguments_options[@]}" : \ (fix) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -221,7 +225,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -242,7 +247,7 @@ _arguments "${_arguments_options[@]}" : \ (fmt) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -263,7 +268,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--check[check formatting instead of applying]' \ '--all[apply to all appropriate files, not just those that have been modified]' \ '*-v[use verbose output (-vv for very verbose)]' \ @@ -286,7 +292,7 @@ _arguments "${_arguments_options[@]}" : \ (doc) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -307,7 +313,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--open[open the docs in a browser]' \ '--json[render the documentation in JSON format in addition to the usual HTML format]' \ '*-v[use verbose output (-vv for very verbose)]' \ @@ -336,7 +343,7 @@ _arguments "${_arguments_options[@]}" : \ '--pass=[force {check,build,run}-pass tests to this mode]:check | build | run:_default' \ '--run=[whether to execute run-* tests]:auto | always | never:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -357,7 +364,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--no-fail-fast[run all tests regardless of failure]' \ '--no-doc[do not run doc tests]' \ '--doc[only run doc tests]' \ @@ -387,7 +395,7 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '*--test-args=[extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)]:ARGS:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -408,7 +416,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--no-fail-fast[run all tests regardless of failure]' \ '--no-doc[do not run doc tests]' \ '--doc[only run doc tests]' \ @@ -433,7 +442,7 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '*--test-args=[]:TEST_ARGS:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -454,7 +463,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -476,7 +486,7 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '--stage=[Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used]:N:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -496,7 +506,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--all[Clean the entire build directory (not used by default)]' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ @@ -518,7 +529,7 @@ _arguments "${_arguments_options[@]}" : \ (dist) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -539,7 +550,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -560,7 +572,7 @@ _arguments "${_arguments_options[@]}" : \ (install) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -581,7 +593,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -603,7 +616,7 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '*--args=[arguments for the tool]:ARGS:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -624,7 +637,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -645,7 +659,7 @@ _arguments "${_arguments_options[@]}" : \ (setup) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -666,7 +680,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -681,14 +696,14 @@ _arguments "${_arguments_options[@]}" : \ '--skip-stage0-validation[Skip stage0 compiler validation]' \ '-h[Print help (see more with '\''--help'\'')]' \ '--help[Print help (see more with '\''--help'\'')]' \ -'::profile -- Either the profile for `config.toml` or another setup action. May be omitted to set up interactively:_files' \ +'::profile -- Either the profile for `bootstrap.toml` or another setup action. May be omitted to set up interactively:_files' \ '*::paths -- paths for the subcommand:_files' \ && ret=0 ;; (suggest) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -709,7 +724,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--run[run suggested tests]' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ @@ -732,7 +748,7 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '*--sync=[Additional \`Cargo.toml\` to sync and vendor]:SYNC:_files' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -753,7 +769,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--versioned-dirs[Always include version in subdir name]' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ @@ -775,7 +792,7 @@ _arguments "${_arguments_options[@]}" : \ (perf) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -796,7 +813,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -830,7 +848,7 @@ _arguments "${_arguments_options[@]}" : \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc Opt Clippy)' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -850,7 +868,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -875,7 +894,7 @@ _arguments "${_arguments_options[@]}" : \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc Opt Clippy)' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -895,7 +914,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -920,7 +940,7 @@ _arguments "${_arguments_options[@]}" : \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc Opt Clippy)' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -940,7 +960,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -965,7 +986,7 @@ _arguments "${_arguments_options[@]}" : \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc Opt Clippy)' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -985,7 +1006,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -1007,7 +1029,7 @@ _arguments "${_arguments_options[@]}" : \ (compare) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -1028,7 +1050,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ diff --git a/src/etc/completions/x.sh b/src/etc/completions/x.sh index 26a44b3ff2f..2dd322bcfc1 100644 --- a/src/etc/completions/x.sh +++ b/src/etc/completions/x.sh @@ -85,7 +85,7 @@ _x() { case "${cmd}" in x) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]... build check clippy fix fmt doc test miri bench clean dist install run setup suggest vendor perf" + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]... build check clippy fix fmt doc test miri bench clean dist install run setup suggest vendor perf" if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -266,6 +266,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -274,7 +278,7 @@ _x() { return 0 ;; x__bench) - opts="-v -i -j -h --test-args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --test-args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -459,6 +463,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -467,7 +475,7 @@ _x() { return 0 ;; x__build) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -648,6 +656,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -656,7 +668,7 @@ _x() { return 0 ;; x__check) - opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -837,6 +849,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -845,7 +861,7 @@ _x() { return 0 ;; x__clean) - opts="-v -i -j -h --all --stage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --all --stage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1023,6 +1039,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -1031,7 +1051,7 @@ _x() { return 0 ;; x__clippy) - opts="-A -D -W -F -v -i -j -h --fix --allow-dirty --allow-staged --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-A -D -W -F -v -i -j -h --fix --allow-dirty --allow-staged --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1228,6 +1248,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -1236,7 +1260,7 @@ _x() { return 0 ;; x__dist) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1417,6 +1441,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -1425,7 +1453,7 @@ _x() { return 0 ;; x__doc) - opts="-v -i -j -h --open --json --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --open --json --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1606,6 +1634,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -1614,7 +1646,7 @@ _x() { return 0 ;; x__fix) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1795,6 +1827,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -1803,7 +1839,7 @@ _x() { return 0 ;; x__fmt) - opts="-v -i -j -h --check --all --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --check --all --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -1984,6 +2020,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -1992,7 +2032,7 @@ _x() { return 0 ;; x__install) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -2173,6 +2213,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -2181,7 +2225,7 @@ _x() { return 0 ;; x__miri) - opts="-v -i -j -h --no-fail-fast --test-args --no-doc --doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --no-fail-fast --test-args --no-doc --doc --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -2366,6 +2410,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -2374,7 +2422,7 @@ _x() { return 0 ;; x__perf) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]... eprintln samply cachegrind benchmark compare" + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]... eprintln samply cachegrind benchmark compare" if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -2555,6 +2603,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -2563,7 +2615,7 @@ _x() { return 0 ;; x__perf__benchmark) - opts="-v -i -j -h --include --exclude --scenarios --profiles --verbose --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help <benchmark-id> [PATHS]... [ARGS]..." + opts="-v -i -j -h --include --exclude --scenarios --profiles --verbose --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help <benchmark-id> [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -2756,6 +2808,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -2764,7 +2820,7 @@ _x() { return 0 ;; x__perf__cachegrind) - opts="-v -i -j -h --include --exclude --scenarios --profiles --verbose --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --include --exclude --scenarios --profiles --verbose --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -2957,6 +3013,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -2965,7 +3025,7 @@ _x() { return 0 ;; x__perf__compare) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help <BASE> <MODIFIED> [PATHS]... [ARGS]..." + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help <BASE> <MODIFIED> [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3146,6 +3206,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -3154,7 +3218,7 @@ _x() { return 0 ;; x__perf__eprintln) - opts="-v -i -j -h --include --exclude --scenarios --profiles --verbose --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --include --exclude --scenarios --profiles --verbose --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3347,6 +3411,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -3355,7 +3423,7 @@ _x() { return 0 ;; x__perf__samply) - opts="-v -i -j -h --include --exclude --scenarios --profiles --verbose --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --include --exclude --scenarios --profiles --verbose --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3548,6 +3616,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -3556,7 +3628,7 @@ _x() { return 0 ;; x__run) - opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3741,6 +3813,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -3749,7 +3825,7 @@ _x() { return 0 ;; x__setup) - opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [<PROFILE>|hook|editor|link] [PATHS]... [ARGS]..." + opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [<PROFILE>|hook|editor|link] [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3930,6 +4006,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -3938,7 +4018,7 @@ _x() { return 0 ;; x__suggest) - opts="-v -i -j -h --run --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --run --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -4119,6 +4199,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -4127,7 +4211,7 @@ _x() { return 0 ;; x__test) - opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --no-fail-fast --test-args --compiletest-rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --no-capture --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -4332,6 +4416,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; @@ -4340,7 +4428,7 @@ _x() { return 0 ;; x__vendor) - opts="-v -i -j -h --sync --versioned-dirs --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..." + opts="-v -i -j -h --sync --versioned-dirs --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -4525,6 +4613,10 @@ _x() { fi return 0 ;; + --ci) + COMPREPLY=($(compgen -W "true false" -- "${cur}")) + return 0 + ;; *) COMPREPLY=() ;; diff --git a/src/etc/completions/x.zsh b/src/etc/completions/x.zsh index b08eb06f8e6..32b297b6cd5 100644 --- a/src/etc/completions/x.zsh +++ b/src/etc/completions/x.zsh @@ -16,7 +16,7 @@ _x() { local context curcontext="$curcontext" state line _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -37,7 +37,8 @@ _x() { '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -66,7 +67,7 @@ _x() { (build) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -87,7 +88,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -108,7 +110,7 @@ _arguments "${_arguments_options[@]}" : \ (check) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -129,7 +131,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--all-targets[Check all targets]' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ @@ -155,7 +158,7 @@ _arguments "${_arguments_options[@]}" : \ '*-W+[clippy lints to warn on]:LINT:_default' \ '*-F+[clippy lints to forbid]:LINT:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -176,7 +179,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--fix[]' \ '--allow-dirty[]' \ '--allow-staged[]' \ @@ -200,7 +204,7 @@ _arguments "${_arguments_options[@]}" : \ (fix) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -221,7 +225,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -242,7 +247,7 @@ _arguments "${_arguments_options[@]}" : \ (fmt) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -263,7 +268,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--check[check formatting instead of applying]' \ '--all[apply to all appropriate files, not just those that have been modified]' \ '*-v[use verbose output (-vv for very verbose)]' \ @@ -286,7 +292,7 @@ _arguments "${_arguments_options[@]}" : \ (doc) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -307,7 +313,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--open[open the docs in a browser]' \ '--json[render the documentation in JSON format in addition to the usual HTML format]' \ '*-v[use verbose output (-vv for very verbose)]' \ @@ -336,7 +343,7 @@ _arguments "${_arguments_options[@]}" : \ '--pass=[force {check,build,run}-pass tests to this mode]:check | build | run:_default' \ '--run=[whether to execute run-* tests]:auto | always | never:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -357,7 +364,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--no-fail-fast[run all tests regardless of failure]' \ '--no-doc[do not run doc tests]' \ '--doc[only run doc tests]' \ @@ -387,7 +395,7 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '*--test-args=[extra arguments to be passed for the test tool being used (e.g. libtest, compiletest or rustdoc)]:ARGS:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -408,7 +416,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--no-fail-fast[run all tests regardless of failure]' \ '--no-doc[do not run doc tests]' \ '--doc[only run doc tests]' \ @@ -433,7 +442,7 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '*--test-args=[]:TEST_ARGS:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -454,7 +463,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -476,7 +486,7 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '--stage=[Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used]:N:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -496,7 +506,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--all[Clean the entire build directory (not used by default)]' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ @@ -518,7 +529,7 @@ _arguments "${_arguments_options[@]}" : \ (dist) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -539,7 +550,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -560,7 +572,7 @@ _arguments "${_arguments_options[@]}" : \ (install) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -581,7 +593,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -603,7 +616,7 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '*--args=[arguments for the tool]:ARGS:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -624,7 +637,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -645,7 +659,7 @@ _arguments "${_arguments_options[@]}" : \ (setup) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -666,7 +680,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -681,14 +696,14 @@ _arguments "${_arguments_options[@]}" : \ '--skip-stage0-validation[Skip stage0 compiler validation]' \ '-h[Print help (see more with '\''--help'\'')]' \ '--help[Print help (see more with '\''--help'\'')]' \ -'::profile -- Either the profile for `config.toml` or another setup action. May be omitted to set up interactively:_files' \ +'::profile -- Either the profile for `bootstrap.toml` or another setup action. May be omitted to set up interactively:_files' \ '*::paths -- paths for the subcommand:_files' \ && ret=0 ;; (suggest) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -709,7 +724,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--run[run suggested tests]' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ @@ -732,7 +748,7 @@ _arguments "${_arguments_options[@]}" : \ _arguments "${_arguments_options[@]}" : \ '*--sync=[Additional \`Cargo.toml\` to sync and vendor]:SYNC:_files' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -753,7 +769,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '--versioned-dirs[Always include version in subdir name]' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ @@ -775,7 +792,7 @@ _arguments "${_arguments_options[@]}" : \ (perf) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -796,7 +813,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -830,7 +848,7 @@ _arguments "${_arguments_options[@]}" : \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc Opt Clippy)' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -850,7 +868,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -875,7 +894,7 @@ _arguments "${_arguments_options[@]}" : \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc Opt Clippy)' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -895,7 +914,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -920,7 +940,7 @@ _arguments "${_arguments_options[@]}" : \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc Opt Clippy)' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -940,7 +960,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -965,7 +986,7 @@ _arguments "${_arguments_options[@]}" : \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc Opt Clippy)' \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -985,7 +1006,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ @@ -1007,7 +1029,7 @@ _arguments "${_arguments_options[@]}" : \ (compare) _arguments "${_arguments_options[@]}" : \ '--config=[TOML configuration file for build]:FILE:_files' \ -'--build-dir=[Build directory, overrides \`build.build-dir\` in \`config.toml\`]:DIR:_files -/' \ +'--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[build target of the stage0 compiler]:BUILD:' \ '--host=[host targets to build]:HOST:' \ '--target=[target targets to build]:TARGET:' \ @@ -1028,7 +1050,8 @@ _arguments "${_arguments_options[@]}" : \ '--rust-profile-use=[use PGO profile for rustc build]:PROFILE:_files' \ '--llvm-profile-use=[use PGO profile for LLVM build]:PROFILE:_files' \ '*--reproducible-artifact=[Additional reproducible artifacts that should be added to the reproducible artifacts archive]:REPRODUCIBLE_ARTIFACT:_default' \ -'*--set=[override options in config.toml]:section.option=value:' \ +'*--set=[override options in bootstrap.toml]:section.option=value:' \ +'--ci=[Make bootstrap to behave as it'\''s running on the CI environment or not]:bool:(true false)' \ '*-v[use verbose output (-vv for very verbose)]' \ '*--verbose[use verbose output (-vv for very verbose)]' \ '-i[use incremental compilation]' \ diff --git a/src/etc/lldb_batchmode.py b/src/etc/lldb_batchmode.py index cf88c53e085..5cc9bb23628 100644 --- a/src/etc/lldb_batchmode.py +++ b/src/etc/lldb_batchmode.py @@ -40,7 +40,7 @@ def print_debug(s): def normalize_whitespace(s): """Replace newlines, tabs, multiple spaces, etc with exactly one space""" - return re.sub("\s+", " ", s) + return re.sub(r"\s+", " ", s) def breakpoint_callback(frame, bp_loc, dict): @@ -234,7 +234,7 @@ try: if ( command == "run" or command == "r" - or re.match("^process\s+launch.*", command) + or re.match(r"^process\s+launch.*", command) ): # Before starting to run the program, let the thread sleep a bit, so all # breakpoint added events can be processed diff --git a/src/gcc b/src/gcc -Subproject 48664a6cab29d48138ffa004b7978d52ef73e3a +Subproject 13cc8243226a9028bb08ab6c5e1c5fe6d533bcd diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 185898c31b7..6ace626fdcd 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -2,8 +2,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet, IndexEntry}; use rustc_hir as hir; use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; use rustc_middle::bug; -use rustc_middle::ty::fold::fold_regions; -use rustc_middle::ty::{self, Region, Ty}; +use rustc_middle::ty::{self, Region, Ty, fold_regions}; use rustc_span::def_id::DefId; use rustc_span::symbol::{Symbol, kw}; use rustc_trait_selection::traits::auto_trait::{self, RegionTarget}; diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index ab169f3c2a4..1541e7201ce 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -8,7 +8,6 @@ use std::{mem, ops}; use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit}; use rustc_data_structures::fx::FxHashSet; -use rustc_feature::Features; use rustc_session::parse::ParseSess; use rustc_span::Span; use rustc_span::symbol::{Symbol, sym}; @@ -132,18 +131,13 @@ impl Cfg { /// Checks whether the given configuration can be matched in the current session. /// /// Equivalent to `attr::cfg_matches`. - // FIXME: Actually make use of `features`. - pub(crate) fn matches(&self, psess: &ParseSess, features: Option<&Features>) -> bool { + pub(crate) fn matches(&self, psess: &ParseSess) -> bool { match *self { Cfg::False => false, Cfg::True => true, - Cfg::Not(ref child) => !child.matches(psess, features), - Cfg::All(ref sub_cfgs) => { - sub_cfgs.iter().all(|sub_cfg| sub_cfg.matches(psess, features)) - } - Cfg::Any(ref sub_cfgs) => { - sub_cfgs.iter().any(|sub_cfg| sub_cfg.matches(psess, features)) - } + Cfg::Not(ref child) => !child.matches(psess), + Cfg::All(ref sub_cfgs) => sub_cfgs.iter().all(|sub_cfg| sub_cfg.matches(psess)), + Cfg::Any(ref sub_cfgs) => sub_cfgs.iter().any(|sub_cfg| sub_cfg.matches(psess)), Cfg::Cfg(name, value) => psess.config.contains(&(name, value)), } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0f476c8c9ff..de6dc088176 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -125,7 +125,7 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext< items.extend(doc.items.values().flat_map(|(item, renamed, _)| { // Now we actually lower the imports, skipping everything else. if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind { - let name = renamed.unwrap_or_else(|| cx.tcx.hir_name(item.hir_id())); + let name = renamed.unwrap_or(kw::Empty); // using kw::Empty is a bit of a hack clean_use_statement(item, name, path, hir::UseKind::Glob, cx, &mut inserted) } else { // skip everything else @@ -1088,7 +1088,7 @@ fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[hir::Attrib enum FunctionArgs<'tcx> { Body(hir::BodyId), - Names(&'tcx [Ident]), + Names(&'tcx [Option<Ident>]), } fn clean_function<'tcx>( @@ -1117,13 +1117,15 @@ fn clean_function<'tcx>( fn clean_args_from_types_and_names<'tcx>( cx: &mut DocContext<'tcx>, types: &[hir::Ty<'tcx>], - names: &[Ident], + names: &[Option<Ident>], ) -> Arguments { - fn nonempty_name(ident: &Ident) -> Option<Symbol> { - if ident.name == kw::Underscore || ident.name == kw::Empty { - None - } else { + fn nonempty_name(ident: &Option<Ident>) -> Option<Symbol> { + if let Some(ident) = ident + && ident.name != kw::Underscore + { Some(ident.name) + } else { + None } } @@ -1216,11 +1218,11 @@ fn clean_poly_fn_sig<'tcx>( .iter() .map(|t| Argument { type_: clean_middle_ty(t.map_bound(|t| *t), cx, None, None), - name: names - .next() - .map(|i| i.name) - .filter(|i| !i.is_empty()) - .unwrap_or(kw::Underscore), + name: if let Some(Some(ident)) = names.next() { + ident.name + } else { + kw::Underscore + }, is_const: false, }) .collect(), @@ -1488,6 +1490,9 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo // The only time this happens is if we're inside the rustdoc for Fn(), // which only has one associated type, which is not a GAT, so whatever. } + GenericArgs::ReturnTypeNotation => { + // Never move these. + } } bounds.extend(mem::take(pred_bounds)); false @@ -1626,8 +1631,7 @@ fn first_non_private<'tcx>( if let Some(use_def_id) = reexp.id() && let Some(local_use_def_id) = use_def_id.as_local() && let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(local_use_def_id) - && !item.ident.name.is_empty() - && let hir::ItemKind::Use(path, _) = item.kind + && let hir::ItemKind::Use(path, hir::UseKind::Single(_)) = item.kind { for res in &path.res { if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res { @@ -1772,7 +1776,7 @@ fn maybe_expand_private_type_alias<'tcx>( } else { return None; }; - let hir::ItemKind::TyAlias(ty, generics) = alias else { return None }; + let hir::ItemKind::TyAlias(_, ty, generics) = alias else { return None }; let final_seg = &path.segments.last().expect("segments were empty"); let mut args = DefIdMap::default(); @@ -2553,36 +2557,42 @@ fn clean_generic_args<'tcx>( generic_args: &hir::GenericArgs<'tcx>, cx: &mut DocContext<'tcx>, ) -> GenericArgs { - // FIXME(return_type_notation): Fix RTN parens rendering - if let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() { - let inputs = inputs.iter().map(|x| clean_ty(x, cx)).collect(); - let output = match output.kind { - hir::TyKind::Tup(&[]) => None, - _ => Some(Box::new(clean_ty(output, cx))), - }; - GenericArgs::Parenthesized { inputs, output } - } else { - let args = generic_args - .args - .iter() - .map(|arg| match arg { - hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => { - GenericArg::Lifetime(clean_lifetime(lt, cx)) - } - hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), - hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty.as_unambig_ty(), cx)), - hir::GenericArg::Const(ct) => { - GenericArg::Const(Box::new(clean_const(ct.as_unambig_ct(), cx))) - } - hir::GenericArg::Infer(_inf) => GenericArg::Infer, - }) - .collect(); - let constraints = generic_args - .constraints - .iter() - .map(|c| clean_assoc_item_constraint(c, cx)) - .collect::<ThinVec<_>>(); - GenericArgs::AngleBracketed { args, constraints } + match generic_args.parenthesized { + hir::GenericArgsParentheses::No => { + let args = generic_args + .args + .iter() + .map(|arg| match arg { + hir::GenericArg::Lifetime(lt) if !lt.is_anonymous() => { + GenericArg::Lifetime(clean_lifetime(lt, cx)) + } + hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), + hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty.as_unambig_ty(), cx)), + hir::GenericArg::Const(ct) => { + GenericArg::Const(Box::new(clean_const(ct.as_unambig_ct(), cx))) + } + hir::GenericArg::Infer(_inf) => GenericArg::Infer, + }) + .collect(); + let constraints = generic_args + .constraints + .iter() + .map(|c| clean_assoc_item_constraint(c, cx)) + .collect::<ThinVec<_>>(); + GenericArgs::AngleBracketed { args, constraints } + } + hir::GenericArgsParentheses::ParenSugar => { + let Some((inputs, output)) = generic_args.paren_sugar_inputs_output() else { + bug!(); + }; + let inputs = inputs.iter().map(|x| clean_ty(x, cx)).collect(); + let output = match output.kind { + hir::TyKind::Tup(&[]) => None, + _ => Some(Box::new(clean_ty(output, cx))), + }; + GenericArgs::Parenthesized { inputs, output } + } + hir::GenericArgsParentheses::ReturnTypeNotation => GenericArgs::ReturnTypeNotation, } } @@ -2785,20 +2795,24 @@ fn clean_maybe_renamed_item<'tcx>( use hir::ItemKind; let def_id = item.owner_id.to_def_id(); - let mut name = renamed.unwrap_or_else(|| cx.tcx.hir_name(item.hir_id())); + let mut name = renamed.unwrap_or_else(|| { + // FIXME: using kw::Empty is a bit of a hack + cx.tcx.hir_opt_name(item.hir_id()).unwrap_or(kw::Empty) + }); + cx.with_param_env(def_id, |cx| { let kind = match item.kind { - ItemKind::Static(ty, mutability, body_id) => StaticItem(Static { + ItemKind::Static(_, ty, mutability, body_id) => StaticItem(Static { type_: Box::new(clean_ty(ty, cx)), mutability, expr: Some(body_id), }), - ItemKind::Const(ty, generics, body_id) => ConstantItem(Box::new(Constant { + ItemKind::Const(_, ty, generics, body_id) => ConstantItem(Box::new(Constant { generics: clean_generics(generics, cx), type_: clean_ty(ty, cx), kind: ConstantKind::Local { body: body_id, def_id }, })), - ItemKind::TyAlias(hir_ty, generics) => { + ItemKind::TyAlias(_, hir_ty, generics) => { *cx.current_type_aliases.entry(def_id).or_insert(0) += 1; let rustdoc_ty = clean_ty(hir_ty, cx); let type_ = @@ -2831,34 +2845,34 @@ fn clean_maybe_renamed_item<'tcx>( )); return ret; } - ItemKind::Enum(ref def, generics) => EnumItem(Enum { + ItemKind::Enum(_, ref def, generics) => EnumItem(Enum { variants: def.variants.iter().map(|v| clean_variant(v, cx)).collect(), generics: clean_generics(generics, cx), }), - ItemKind::TraitAlias(generics, bounds) => TraitAliasItem(TraitAlias { + ItemKind::TraitAlias(_, generics, bounds) => TraitAliasItem(TraitAlias { generics: clean_generics(generics, cx), bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(), }), - ItemKind::Union(ref variant_data, generics) => UnionItem(Union { + ItemKind::Union(_, ref variant_data, generics) => UnionItem(Union { generics: clean_generics(generics, cx), fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(), }), - ItemKind::Struct(ref variant_data, generics) => StructItem(Struct { + ItemKind::Struct(_, ref variant_data, generics) => StructItem(Struct { ctor_kind: variant_data.ctor_kind(), generics: clean_generics(generics, cx), fields: variant_data.fields().iter().map(|x| clean_field(x, cx)).collect(), }), ItemKind::Impl(impl_) => return clean_impl(impl_, item.owner_id.def_id, cx), - ItemKind::Macro(macro_def, MacroKind::Bang) => MacroItem(Macro { + ItemKind::Macro(_, macro_def, MacroKind::Bang) => MacroItem(Macro { source: display_macro_source(cx, name, macro_def), macro_rules: macro_def.macro_rules, }), - ItemKind::Macro(_, macro_kind) => clean_proc_macro(item, &mut name, macro_kind, cx), + ItemKind::Macro(_, _, macro_kind) => clean_proc_macro(item, &mut name, macro_kind, cx), // proc macros can have a name set by attributes ItemKind::Fn { ref sig, generics, body: body_id, .. } => { clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx) } - ItemKind::Trait(_, _, generics, bounds, item_ids) => { + ItemKind::Trait(_, _, _, generics, bounds, item_ids) => { let items = item_ids .iter() .map(|ti| clean_trait_item(cx.tcx.hir_trait_item(ti.id), cx)) @@ -2871,7 +2885,7 @@ fn clean_maybe_renamed_item<'tcx>( bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(), })) } - ItemKind::ExternCrate(orig_name) => { + ItemKind::ExternCrate(orig_name, _) => { return clean_extern_crate(item, name, orig_name, cx); } ItemKind::Use(path, kind) => { diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs index 88db853d7c3..31f9c284d7d 100644 --- a/src/librustdoc/clean/render_macro_matchers.rs +++ b/src/librustdoc/clean/render_macro_matchers.rs @@ -4,8 +4,8 @@ use rustc_ast_pretty::pprust::PrintState; use rustc_ast_pretty::pprust::state::State as Printer; use rustc_middle::ty::TyCtxt; use rustc_session::parse::ParseSess; -use rustc_span::Span; use rustc_span::symbol::{Ident, Symbol, kw}; +use rustc_span::{FileName, Span}; /// Render a macro matcher in a format suitable for displaying to the user /// as part of an item declaration. @@ -63,7 +63,7 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option<String // Create a Parser. let psess = ParseSess::new(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec()); - let file_name = source_map.span_to_filename(span); + let file_name = FileName::macro_expansion_source_code(&snippet); let mut parser = match rustc_parse::new_parser_from_source_str(&psess, file_name, snippet.clone()) { Ok(parser) => parser, diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index b8db82e540c..41943b94d1e 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -102,6 +102,10 @@ pub(crate) fn merge_bounds( } } }, + PP::ReturnTypeNotation => { + // Cannot merge bounds with RTN. + return false; + } }; true }) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 228d9108e4e..c991d32ea22 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -5,7 +5,7 @@ use std::{fmt, iter}; use arrayvec::ArrayVec; use rustc_abi::{ExternAbi, VariantIdx}; -use rustc_attr_parsing::{ConstStability, Deprecation, Stability, StableSince}; +use rustc_attr_parsing::{AttributeKind, ConstStability, Deprecation, Stability, StableSince}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId}; @@ -226,7 +226,7 @@ impl ExternalCrate { .filter_map(|&id| { let item = tcx.hir_item(id); match item.kind { - hir::ItemKind::Mod(_) => { + hir::ItemKind::Mod(..) => { as_keyword(Res::Def(DefKind::Mod, id.owner_id.to_def_id())) } _ => None, @@ -282,7 +282,7 @@ impl ExternalCrate { .filter_map(|&id| { let item = tcx.hir_item(id); match item.kind { - hir::ItemKind::Mod(_) => { + hir::ItemKind::Mod(..) => { as_primitive(Res::Def(DefKind::Mod, id.owner_id.to_def_id())) } _ => None, @@ -756,12 +756,7 @@ impl Item { Some(tcx.visibility(def_id)) } - pub(crate) fn attributes( - &self, - tcx: TyCtxt<'_>, - cache: &Cache, - keep_as_is: bool, - ) -> Vec<String> { + pub(crate) fn attributes(&self, tcx: TyCtxt<'_>, cache: &Cache, is_json: bool) -> Vec<String> { const ALLOWED_ATTRIBUTES: &[Symbol] = &[sym::export_name, sym::link_section, sym::no_mangle, sym::non_exhaustive]; @@ -772,8 +767,24 @@ impl Item { .other_attrs .iter() .filter_map(|attr| { - if keep_as_is { - Some(rustc_hir_pretty::attribute_to_string(&tcx, attr)) + if is_json { + match attr { + hir::Attribute::Parsed(AttributeKind::Deprecation { .. }) => { + // rustdoc-json stores this in `Item::deprecation`, so we + // don't want it it `Item::attrs`. + None + } + rustc_hir::Attribute::Parsed(rustc_attr_parsing::AttributeKind::Repr( + .., + )) => { + // We have separate pretty-printing logic for `#[repr(..)]` attributes. + // For example, there are circumstances where `#[repr(transparent)]` + // is applied but should not be publicly shown in rustdoc + // because it isn't public API. + None + } + _ => Some(rustc_hir_pretty::attribute_to_string(&tcx, attr)), + } } else if ALLOWED_ATTRIBUTES.contains(&attr.name_or_empty()) { Some( rustc_hir_pretty::attribute_to_string(&tcx, attr) @@ -786,8 +797,9 @@ impl Item { } }) .collect(); - if !keep_as_is - && let Some(def_id) = self.def_id() + + // Add #[repr(...)] + if let Some(def_id) = self.def_id() && let ItemType::Struct | ItemType::Enum | ItemType::Union = self.type_() { let adt = tcx.adt_def(def_id); @@ -1056,6 +1068,13 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute> .meta_item() .and_then(|item| rustc_expand::config::parse_cfg(item, sess)) { + // The result is unused here but we can gate unstable predicates + rustc_attr_parsing::cfg_matches( + cfg_mi, + tcx.sess, + rustc_ast::CRATE_NODE_ID, + Some(tcx.features()), + ); match Cfg::parse(cfg_mi) { Ok(new_cfg) => cfg &= new_cfg, Err(e) => { @@ -2259,8 +2278,12 @@ impl GenericArg { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) enum GenericArgs { + /// `<args, constraints = ..>` AngleBracketed { args: ThinVec<GenericArg>, constraints: ThinVec<AssocItemConstraint> }, + /// `(inputs) -> output` Parenthesized { inputs: ThinVec<Type>, output: Option<Box<Type>> }, + /// `(..)` + ReturnTypeNotation, } impl GenericArgs { @@ -2270,6 +2293,7 @@ impl GenericArgs { args.is_empty() && constraints.is_empty() } GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(), + GenericArgs::ReturnTypeNotation => false, } } pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> { @@ -2294,6 +2318,7 @@ impl GenericArgs { }) .into_iter(), ), + GenericArgs::ReturnTypeNotation => Box::new([].into_iter()), } } } @@ -2305,8 +2330,10 @@ impl<'a> IntoIterator for &'a GenericArgs { match self { GenericArgs::AngleBracketed { args, .. } => Box::new(args.iter().cloned()), GenericArgs::Parenthesized { inputs, .. } => { + // FIXME: This isn't really right, since `Fn(A, B)` is `Fn<(A, B)>` Box::new(inputs.iter().cloned().map(GenericArg::Type)) } + GenericArgs::ReturnTypeNotation => Box::new([].into_iter()), } } } diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index 18ad442d017..12f8b26b1e3 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -80,7 +80,7 @@ impl<'tcx> HirCollector<'tcx> { pub fn collect_crate(mut self) -> Vec<ScrapedDocTest> { let tcx = self.tcx; - self.visit_testable("".to_string(), CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID), |this| { + self.visit_testable(None, CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID), |this| { tcx.hir_walk_toplevel_module(this) }); self.collector.tests @@ -90,7 +90,7 @@ impl<'tcx> HirCollector<'tcx> { impl HirCollector<'_> { fn visit_testable<F: FnOnce(&mut Self)>( &mut self, - name: String, + name: Option<String>, def_id: LocalDefId, sp: Span, nested: F, @@ -98,14 +98,15 @@ impl HirCollector<'_> { let ast_attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id)); if let Some(ref cfg) = extract_cfg_from_attrs(ast_attrs.iter(), self.tcx, &FxHashSet::default()) - && !cfg.matches(&self.tcx.sess.psess, Some(self.tcx.features())) + && !cfg.matches(&self.tcx.sess.psess) { return; } - let has_name = !name.is_empty(); - if has_name { + let mut has_name = false; + if let Some(name) = name { self.collector.cur_path.push(name); + has_name = true; } // The collapse-docs pass won't combine sugared/raw doc attributes, or included files with @@ -153,9 +154,9 @@ impl<'tcx> intravisit::Visitor<'tcx> for HirCollector<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'_>) { let name = match &item.kind { hir::ItemKind::Impl(impl_) => { - rustc_hir_pretty::id_to_string(&self.tcx, impl_.self_ty.hir_id) + Some(rustc_hir_pretty::id_to_string(&self.tcx, impl_.self_ty.hir_id)) } - _ => item.ident.to_string(), + _ => item.kind.ident().map(|ident| ident.to_string()), }; self.visit_testable(name, item.owner_id.def_id, item.span, |this| { @@ -164,31 +165,46 @@ impl<'tcx> intravisit::Visitor<'tcx> for HirCollector<'tcx> { } fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'_>) { - self.visit_testable(item.ident.to_string(), item.owner_id.def_id, item.span, |this| { - intravisit::walk_trait_item(this, item); - }); + self.visit_testable( + Some(item.ident.to_string()), + item.owner_id.def_id, + item.span, + |this| { + intravisit::walk_trait_item(this, item); + }, + ); } fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'_>) { - self.visit_testable(item.ident.to_string(), item.owner_id.def_id, item.span, |this| { - intravisit::walk_impl_item(this, item); - }); + self.visit_testable( + Some(item.ident.to_string()), + item.owner_id.def_id, + item.span, + |this| { + intravisit::walk_impl_item(this, item); + }, + ); } fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'_>) { - self.visit_testable(item.ident.to_string(), item.owner_id.def_id, item.span, |this| { - intravisit::walk_foreign_item(this, item); - }); + self.visit_testable( + Some(item.ident.to_string()), + item.owner_id.def_id, + item.span, + |this| { + intravisit::walk_foreign_item(this, item); + }, + ); } fn visit_variant(&mut self, v: &'tcx hir::Variant<'_>) { - self.visit_testable(v.ident.to_string(), v.def_id, v.span, |this| { + self.visit_testable(Some(v.ident.to_string()), v.def_id, v.span, |this| { intravisit::walk_variant(this, v); }); } fn visit_field_def(&mut self, f: &'tcx hir::FieldDef<'_>) { - self.visit_testable(f.ident.to_string(), f.def_id, f.span, |this| { + self.visit_testable(Some(f.ident.to_string()), f.def_id, f.span, |this| { intravisit::walk_field_def(this, f); }); } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index e93b9eb272a..41e9a5a6651 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -332,6 +332,9 @@ impl clean::GenericArgs { } } } + clean::GenericArgs::ReturnTypeNotation => { + f.write_str("(..)")?; + } } Ok(()) }) diff --git a/src/librustdoc/html/length_limit/tests.rs b/src/librustdoc/html/length_limit/tests.rs index 2185c034890..4ebecfd5f24 100644 --- a/src/librustdoc/html/length_limit/tests.rs +++ b/src/librustdoc/html/length_limit/tests.rs @@ -9,41 +9,41 @@ fn empty() { #[test] fn basic() { let mut buf = HtmlWithLimit::new(60); - buf.push("Hello "); + let _ = buf.push("Hello "); buf.open_tag("em"); - buf.push("world"); + let _ = buf.push("world"); buf.close_tag(); - buf.push("!"); + let _ = buf.push("!"); assert_eq!(buf.finish(), "Hello <em>world</em>!"); } #[test] fn no_tags() { let mut buf = HtmlWithLimit::new(60); - buf.push("Hello"); - buf.push(" world!"); + let _ = buf.push("Hello"); + let _ = buf.push(" world!"); assert_eq!(buf.finish(), "Hello world!"); } #[test] fn limit_0() { let mut buf = HtmlWithLimit::new(0); - buf.push("Hello "); + let _ = buf.push("Hello "); buf.open_tag("em"); - buf.push("world"); + let _ = buf.push("world"); buf.close_tag(); - buf.push("!"); + let _ = buf.push("!"); assert_eq!(buf.finish(), ""); } #[test] fn exactly_limit() { let mut buf = HtmlWithLimit::new(12); - buf.push("Hello "); + let _ = buf.push("Hello "); buf.open_tag("em"); - buf.push("world"); + let _ = buf.push("world"); buf.close_tag(); - buf.push("!"); + let _ = buf.push("!"); assert_eq!(buf.finish(), "Hello <em>world</em>!"); } @@ -51,11 +51,11 @@ fn exactly_limit() { fn multiple_nested_tags() { let mut buf = HtmlWithLimit::new(60); buf.open_tag("p"); - buf.push("This is a "); + let _ = buf.push("This is a "); buf.open_tag("em"); - buf.push("paragraph"); + let _ = buf.push("paragraph"); buf.open_tag("strong"); - buf.push("!"); + let _ = buf.push("!"); buf.close_tag(); buf.close_tag(); buf.close_tag(); @@ -66,11 +66,11 @@ fn multiple_nested_tags() { fn forgot_to_close_tags() { let mut buf = HtmlWithLimit::new(60); buf.open_tag("p"); - buf.push("This is a "); + let _ = buf.push("This is a "); buf.open_tag("em"); - buf.push("paragraph"); + let _ = buf.push("paragraph"); buf.open_tag("strong"); - buf.push("!"); + let _ = buf.push("!"); assert_eq!(buf.finish(), "<p>This is a <em>paragraph<strong>!</strong></em></p>"); } @@ -78,10 +78,10 @@ fn forgot_to_close_tags() { fn past_the_limit() { let mut buf = HtmlWithLimit::new(20); buf.open_tag("p"); - (0..10).try_for_each(|n| { + let _ = (0..10).try_for_each(|n| { buf.open_tag("strong"); - buf.push("word#")?; - buf.push(&n.to_string())?; + let _ = buf.push("word#")?; + let _ = buf.push(&n.to_string())?; buf.close_tag(); ControlFlow::Continue(()) }); @@ -100,8 +100,8 @@ fn past_the_limit() { fn quickly_past_the_limit() { let mut buf = HtmlWithLimit::new(6); buf.open_tag("p"); - buf.push("Hello"); - buf.push(" World"); + let _ = buf.push("Hello"); + let _ = buf.push(" World"); // intentionally not closing <p> before finishing assert_eq!(buf.finish(), "<p>Hello</p>"); } @@ -110,7 +110,7 @@ fn quickly_past_the_limit() { fn close_too_many() { let mut buf = HtmlWithLimit::new(60); buf.open_tag("p"); - buf.push("Hello"); + let _ = buf.push("Hello"); buf.close_tag(); // This call does not panic because there are valid cases // where `close_tag()` is called with no tags left to close. diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 079651e8603..5aab4199d43 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -1200,11 +1200,12 @@ impl LangString { data.ignore = Ignore::All; seen_rust_tags = !seen_other_tags; } - LangStringToken::LangToken(x) if x.starts_with("ignore-") => { - if enable_per_target_ignores { - ignores.push(x.trim_start_matches("ignore-").to_owned()); - seen_rust_tags = !seen_other_tags; - } + LangStringToken::LangToken(x) + if let Some(ignore) = x.strip_prefix("ignore-") + && enable_per_target_ignores => + { + ignores.push(ignore.to_owned()); + seen_rust_tags = !seen_other_tags; } LangStringToken::LangToken("rust") => { data.rust = true; @@ -1226,37 +1227,39 @@ impl LangString { data.standalone_crate = true; seen_rust_tags = !seen_other_tags || seen_rust_tags; } - LangStringToken::LangToken(x) if x.starts_with("edition") => { - data.edition = x[7..].parse::<Edition>().ok(); + LangStringToken::LangToken(x) + if let Some(edition) = x.strip_prefix("edition") => + { + data.edition = edition.parse::<Edition>().ok(); } LangStringToken::LangToken(x) - if x.starts_with("rust") && x[4..].parse::<Edition>().is_ok() => + if let Some(edition) = x.strip_prefix("rust") + && edition.parse::<Edition>().is_ok() + && let Some(extra) = extra => { - if let Some(extra) = extra { - extra.error_invalid_codeblock_attr_with_help( - format!("unknown attribute `{x}`"), - |lint| { - lint.help(format!( - "there is an attribute with a similar name: `edition{}`", - &x[4..], - )); - }, - ); - } + extra.error_invalid_codeblock_attr_with_help( + format!("unknown attribute `{x}`"), + |lint| { + lint.help(format!( + "there is an attribute with a similar name: `edition{edition}`" + )); + }, + ); } LangStringToken::LangToken(x) - if allow_error_code_check && x.starts_with('E') && x.len() == 5 => + if allow_error_code_check + && let Some(error_code) = x.strip_prefix('E') + && error_code.len() == 4 => { - if x[1..].parse::<u32>().is_ok() { + if error_code.parse::<u32>().is_ok() { data.error_codes.push(x.to_owned()); seen_rust_tags = !seen_other_tags || seen_rust_tags; } else { seen_other_tags = true; } } - LangStringToken::LangToken(x) if extra.is_some() => { - let s = x.to_lowercase(); - if let Some(help) = match s.as_str() { + LangStringToken::LangToken(x) if let Some(extra) = extra => { + if let Some(help) = match x.to_lowercase().as_str() { "compile-fail" | "compile_fail" | "compilefail" => Some( "use `compile_fail` to invert the results of this test, so that it \ passes if it cannot be compiled and fails if it can", @@ -1273,33 +1276,27 @@ impl LangString { "use `test_harness` to run functions marked `#[test]` instead of a \ potentially-implicit `main` function", ), - "standalone" | "standalone_crate" | "standalone-crate" => { - if let Some(extra) = extra - && extra.sp.at_least_rust_2024() - { - Some( - "use `standalone_crate` to compile this code block \ + "standalone" | "standalone_crate" | "standalone-crate" + if extra.sp.at_least_rust_2024() => + { + Some( + "use `standalone_crate` to compile this code block \ separately", - ) - } else { - None - } + ) } _ => None, } { - if let Some(extra) = extra { - extra.error_invalid_codeblock_attr_with_help( - format!("unknown attribute `{x}`"), - |lint| { - lint.help(help).help( - "this code block may be skipped during testing, \ + extra.error_invalid_codeblock_attr_with_help( + format!("unknown attribute `{x}`"), + |lint| { + lint.help(help).help( + "this code block may be skipped during testing, \ because unknown attributes are treated as markers for \ code samples written in other programming languages, \ unless it is also explicitly marked as `rust`", - ); - }, - ); - } + ); + }, + ); } seen_other_tags = true; data.unknown.push(x.to_owned()); @@ -1568,7 +1565,7 @@ fn markdown_summary_with_limit( let mut buf = HtmlWithLimit::new(length_limit); let mut stopped_early = false; - p.try_for_each(|event| { + let _ = p.try_for_each(|event| { match &event { Event::Text(text) => { let r = diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index b2ad2fa773a..8dfde1679fe 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1465,8 +1465,6 @@ pub(crate) fn notable_traits_button( ty: &clean::Type, cx: &Context<'_>, ) -> Option<impl fmt::Display> { - let mut has_notable_trait = false; - if ty.is_unit() { // Very common fast path. return None; @@ -1484,27 +1482,19 @@ pub(crate) fn notable_traits_button( return None; } - if let Some(impls) = cx.cache().impls.get(&did) { - for i in impls { - let impl_ = i.inner_impl(); - if impl_.polarity != ty::ImplPolarity::Positive { - continue; - } - - if !ty.is_doc_subtype_of(&impl_.for_, cx.cache()) { + let impls = cx.cache().impls.get(&did)?; + let has_notable_trait = impls + .iter() + .map(Impl::inner_impl) + .filter(|impl_| { + impl_.polarity == ty::ImplPolarity::Positive // Two different types might have the same did, // without actually being the same. - continue; - } - if let Some(trait_) = &impl_.trait_ { - let trait_did = trait_.def_id(); - - if cx.cache().traits.get(&trait_did).is_some_and(|t| t.is_notable_trait(cx.tcx())) { - has_notable_trait = true; - } - } - } - } + && ty.is_doc_subtype_of(&impl_.for_, cx.cache()) + }) + .filter_map(|impl_| impl_.trait_.as_ref()) + .filter_map(|trait_| cx.cache().traits.get(&trait_.def_id())) + .any(|t| t.is_notable_trait(cx.tcx())); has_notable_trait.then(|| { cx.types_with_notable_traits.borrow_mut().insert(ty.clone()); diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index 3228f71df07..3676051b1bd 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -242,10 +242,9 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { // Now that we confirmed it's a file import, we want to get the span for the module // name only and not all the "mod foo;". if let Node::Item(item) = self.tcx.hir_node(id) { - self.matches.insert( - item.ident.span, - LinkFromSrc::Local(clean::Span::new(m.spans.inner_span)), - ); + let (ident, _) = item.expect_mod(); + self.matches + .insert(ident.span, LinkFromSrc::Local(clean::Span::new(m.spans.inner_span))); } } else { // If it's a "mod foo {}", we want to look to its documentation page. @@ -273,22 +272,22 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { fn visit_item(&mut self, item: &'tcx Item<'tcx>) { match item.kind { ItemKind::Static(..) - | ItemKind::Const(_, _, _) + | ItemKind::Const(..) | ItemKind::Fn { .. } - | ItemKind::Macro(_, _) - | ItemKind::TyAlias(_, _) - | ItemKind::Enum(_, _) - | ItemKind::Struct(_, _) - | ItemKind::Union(_, _) - | ItemKind::Trait(_, _, _, _, _) - | ItemKind::TraitAlias(_, _) => self.extract_info_from_hir_id(item.hir_id()), + | ItemKind::Macro(..) + | ItemKind::TyAlias(..) + | ItemKind::Enum(..) + | ItemKind::Struct(..) + | ItemKind::Union(..) + | ItemKind::Trait(..) + | ItemKind::TraitAlias(..) => self.extract_info_from_hir_id(item.hir_id()), ItemKind::Impl(_) - | ItemKind::Use(_, _) - | ItemKind::ExternCrate(_) + | ItemKind::Use(..) + | ItemKind::ExternCrate(..) | ItemKind::ForeignMod { .. } | ItemKind::GlobalAsm { .. } // We already have "visit_mod" above so no need to check it here. - | ItemKind::Mod(_) => {} + | ItemKind::Mod(..) => {} } intravisit::walk_item(self, item); } diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts index 4b43c00730d..e94c6beabea 100644 --- a/src/librustdoc/html/static/js/rustdoc.d.ts +++ b/src/librustdoc/html/static/js/rustdoc.d.ts @@ -4,6 +4,10 @@ /* eslint-disable */ declare global { + /** Map from crate name to directory structure, for source view */ + declare var srcIndex: Map<string, rustdoc.Dir>; + /** Defined and documented in `main.js` */ + declare function nonnull(x: T|null, msg: string|undefined); interface Window { /** Make the current theme easy to find */ currentTheme: HTMLLinkElement|null; @@ -41,6 +45,23 @@ declare global { */ rustdocShowSourceSidebar: function(), /** + * Close the sidebar in source code view + */ + rustdocCloseSourceSidebar?: function(), + /** + * Shows the sidebar in source code view + */ + rustdocShowSourceSidebar?: function(), + /** + * Toggles the sidebar in source code view + */ + rustdocToggleSrcSidebar?: function(), + /** + * create's the sidebar in source code view. + * called in generated `src-files.js`. + */ + createSrcSidebar?: function(), + /** * Set up event listeners for a scraped source example. */ updateScrapedExample?: function(HTMLElement, HTMLElement), @@ -438,4 +459,12 @@ declare namespace rustdoc { type TypeImpls = { [cratename: string]: Array<Array<string|0>> } + + /** + * Directory structure for source code view, + * defined in generated `src-files.js`. + * + * is a tuple of (filename, subdirs, filenames). + */ + type Dir = [string, rustdoc.Dir[], string[]] } diff --git a/src/librustdoc/html/static/js/src-script.js b/src/librustdoc/html/static/js/src-script.js index fc27241334b..b9ab6e85603 100644 --- a/src/librustdoc/html/static/js/src-script.js +++ b/src/librustdoc/html/static/js/src-script.js @@ -3,10 +3,8 @@ // Local js definitions: /* global addClass, onEachLazy, removeClass, browserSupportsHistoryApi */ -/* global updateLocalStorage, getVar */ +/* global updateLocalStorage, getVar, nonnull */ -// Eventually fix this. -// @ts-nocheck "use strict"; @@ -29,6 +27,14 @@ function closeSidebarIfMobile() { } } +/** + * @param {rustdoc.Dir} elem + * @param {HTMLElement} parent + * @param {string} fullPath + * @param {boolean} hasFoundFile + * + * @returns {boolean} - new value for hasFoundFile + */ function createDirEntry(elem, parent, fullPath, hasFoundFile) { const dirEntry = document.createElement("details"); const summary = document.createElement("summary"); @@ -95,7 +101,7 @@ window.rustdocToggleSrcSidebar = () => { // This function is called from "src-files.js", generated in `html/render/write_shared.rs`. // eslint-disable-next-line no-unused-vars function createSrcSidebar() { - const container = document.querySelector("nav.sidebar"); + const container = nonnull(document.querySelector("nav.sidebar")); const sidebar = document.createElement("div"); sidebar.id = "src-sidebar"; @@ -111,6 +117,7 @@ function createSrcSidebar() { // Focus on the current file in the source files sidebar. const selected_elem = sidebar.getElementsByClassName("selected")[0]; if (typeof selected_elem !== "undefined") { + // @ts-expect-error selected_elem.focus(); } } @@ -130,11 +137,12 @@ function highlightSrcLines() { to = from; from = tmp; } - let elem = document.getElementById(from); + const from_s = "" + from; + let elem = document.getElementById(from_s); if (!elem) { return; } - const x = document.getElementById(from); + const x = document.getElementById(from_s); if (x) { x.scrollIntoView(); } @@ -142,7 +150,7 @@ function highlightSrcLines() { removeClass(e, "line-highlighted"); }); for (let i = from; i <= to; ++i) { - elem = document.getElementById(i); + elem = document.getElementById("" + i); if (!elem) { break; } @@ -153,11 +161,12 @@ function highlightSrcLines() { const handleSrcHighlight = (function() { let prev_line_id = 0; + /** @type {function(string): void} */ const set_fragment = name => { const x = window.scrollX, y = window.scrollY; if (browserSupportsHistoryApi()) { - history.replaceState(null, null, "#" + name); + history.replaceState(null, "", "#" + name); highlightSrcLines(); } else { location.replace("#" + name); @@ -166,6 +175,7 @@ const handleSrcHighlight = (function() { window.scrollTo(x, y); }; + // @ts-expect-error return ev => { let cur_line_id = parseInt(ev.target.id, 10); // This event handler is attached to the entire line number column, but it should only @@ -191,7 +201,7 @@ const handleSrcHighlight = (function() { } else { prev_line_id = cur_line_id; - set_fragment(cur_line_id); + set_fragment("" + cur_line_id); } }; }()); diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 425b915b5f9..748d2ef33c3 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -22,6 +22,28 @@ const settingsDataset = (function() { })(); /** + * Assert that the passed value is nonnull, then return it. + * + * Takes an optional error message argument. + * + * Must be defined in this file, as it is loaded before all others. + * + * @template T + * @param {T|null} x + * @param {string=} msg + * @returns T + */ +// used in other files, not yet used in this one. +// eslint-disable-next-line no-unused-vars +function nonnull(x, msg) { + if (x === null) { + throw (msg || "unexpected null value!"); + } else { + return x; + } +} + +/** * Get a configuration value. If it's not set, get the default. * * @param {string} settingName diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 6369433a4b5..a5351b350dd 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -176,6 +176,7 @@ impl FromClean<clean::GenericArgs> for GenericArgs { inputs: inputs.into_json(renderer), output: output.map(|a| (*a).into_json(renderer)), }, + ReturnTypeNotation => GenericArgs::ReturnTypeNotation, } } } diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 45b8dafa907..f8f670f575b 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -240,7 +240,7 @@ impl DocVisitor<'_> for CoverageCalculator<'_, '_> { data: hir::VariantData::Tuple(_, _, _), .. }) | hir::Node::Item(hir::Item { - kind: hir::ItemKind::Struct(hir::VariantData::Tuple(_, _, _), _), + kind: hir::ItemKind::Struct(_, hir::VariantData::Tuple(_, _, _), _), .. }) ) diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 68e381fa3f1..254549e72c6 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -144,9 +144,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { && inserted.insert(def_id) { let item = self.cx.tcx.hir_expect_item(local_def_id); - top_level_module - .items - .insert((local_def_id, Some(item.ident.name)), (item, None, None)); + let (ident, _, _) = item.expect_macro(); + top_level_module.items.insert((local_def_id, Some(ident.name)), (item, None, None)); } } @@ -224,11 +223,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { def_id: LocalDefId, res: Res, renamed: Option<Symbol>, - glob: bool, please_inline: bool, ) -> bool { debug!("maybe_inline_local (renamed: {renamed:?}) res: {res:?}"); + let glob = renamed.is_none(); if renamed == Some(kw::Underscore) { // We never inline `_` reexports. return false; @@ -286,7 +285,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { is_hidden && // If it's a doc hidden module, we need to keep it in case some of its inner items // are re-exported. - !matches!(item, Node::Item(&hir::Item { kind: hir::ItemKind::Mod(_), .. })) + !matches!(item, Node::Item(&hir::Item { kind: hir::ItemKind::Mod(..), .. })) ) || // The imported item is public and not `doc(hidden)` so no need to inline it. self.reexport_public_and_not_hidden(def_id, res_did) @@ -297,7 +296,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let is_bang_macro = matches!( item, - Node::Item(&hir::Item { kind: hir::ItemKind::Macro(_, MacroKind::Bang), .. }) + Node::Item(&hir::Item { kind: hir::ItemKind::Macro(_, _, MacroKind::Bang), .. }) ); if !self.view_item_stack.insert(res_did) && !is_bang_macro { @@ -311,7 +310,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { Node::Item(_) if is_bang_macro && !please_inline && renamed.is_some() && is_hidden => { return false; } - Node::Item(&hir::Item { kind: hir::ItemKind::Mod(m), .. }) if glob => { + Node::Item(&hir::Item { kind: hir::ItemKind::Mod(_, m), .. }) if glob => { let prev = mem::replace(&mut self.inlining, true); for &i in m.item_ids { let i = tcx.hir_item(i); @@ -378,7 +377,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // attribute can still be visible. || match item.kind { hir::ItemKind::Impl(..) => true, - hir::ItemKind::Macro(_, MacroKind::Bang) => { + hir::ItemKind::Macro(_, _, MacroKind::Bang) => { self.cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export) } _ => false, @@ -419,7 +418,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } return; } - let name = renamed.unwrap_or(item.ident.name); + let get_name = || renamed.unwrap_or(item.kind.ident().unwrap().name); let tcx = self.cx.tcx; let def_id = item.owner_id.to_def_id(); @@ -459,15 +458,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } _ => false, }); - let is_glob = kind == hir::UseKind::Glob; - let ident = if is_glob { None } else { Some(name) }; - if self.maybe_inline_local( - item.owner_id.def_id, - res, - ident, - is_glob, - please_inline, - ) { + let ident = match kind { + hir::UseKind::Single(ident) => Some(renamed.unwrap_or(ident.name)), + hir::UseKind::Glob => None, + hir::UseKind::ListStem => unreachable!(), + }; + if self.maybe_inline_local(item.owner_id.def_id, res, ident, please_inline) + { debug!("Inlining {:?}", item.owner_id.def_id); continue; } @@ -475,7 +472,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { self.add_to_current_mod(item, renamed, import_id); } } - hir::ItemKind::Macro(macro_def, _) => { + hir::ItemKind::Macro(_, macro_def, _) => { // `#[macro_export] macro_rules!` items are handled separately in `visit()`, // above, since they need to be documented at the module top level. Accordingly, // we only want to handle macros if one of three conditions holds: @@ -495,8 +492,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { self.add_to_current_mod(item, renamed, import_id); } } - hir::ItemKind::Mod(m) => { - self.enter_mod(item.owner_id.def_id, m, name, renamed, import_id); + hir::ItemKind::Mod(_, m) => { + self.enter_mod(item.owner_id.def_id, m, get_name(), renamed, import_id); } hir::ItemKind::Fn { .. } | hir::ItemKind::ExternCrate(..) @@ -512,7 +509,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { hir::ItemKind::Const(..) => { // Underscore constants do not correspond to a nameable item and // so are never useful in documentation. - if name != kw::Underscore { + if get_name() != kw::Underscore { self.add_to_current_mod(item, renamed, import_id); } } diff --git a/src/llvm-project b/src/llvm-project -Subproject 1c3bb96fdb6db7b8e8f24edb016099c223fdd27 +Subproject acaea3d2bb8f351b740db7ebce7d7a40b9e2148 diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 8ec7cffe066..137fe4c4c35 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -30,7 +30,7 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc /// This integer is incremented with every breaking change to the API, /// and is returned along with the JSON blob as [`Crate::format_version`]. /// Consuming code should assert that this value matches the format version(s) that it supports. -pub const FORMAT_VERSION: u32 = 41; +pub const FORMAT_VERSION: u32 = 43; /// The root of the emitted JSON blob. /// @@ -120,9 +120,23 @@ pub struct Item { pub docs: Option<String>, /// This mapping resolves [intra-doc links](https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md) from the docstring to their IDs pub links: HashMap<String, Id>, - /// Stringified versions of parsed attributes on this item. - /// Essentially debug printed (e.g. `#[inline]` becomes something similar to `#[attr="Inline(Hint)"]`). - /// Equivalent to the hir pretty-printing of attributes. + /// Attributes on this item. + /// + /// Does not include `#[deprecated]` attributes: see the [`Self::deprecation`] field instead. + /// + /// Some attributes appear in pretty-printed Rust form, regardless of their formatting + /// in the original source code. For example: + /// - `#[non_exhaustive]` and `#[must_use]` are represented as themselves. + /// - `#[no_mangle]` and `#[export_name]` are also represented as themselves. + /// - `#[repr(C)]` and other reprs also appear as themselves, + /// though potentially with a different order: e.g. `repr(i8, C)` may become `repr(C, i8)`. + /// Multiple repr attributes on the same item may be combined into an equivalent single attr. + /// + /// Other attributes may appear debug-printed. For example: + /// - `#[inline]` becomes something similar to `#[attr="Inline(Hint)"]`. + /// + /// As an internal implementation detail subject to change, this debug-printing format + /// is currently equivalent to the HIR pretty-printing of parsed attributes. pub attrs: Vec<String>, /// Information about the item’s deprecation, if present. pub deprecation: Option<Deprecation>, @@ -229,6 +243,8 @@ pub enum GenericArgs { /// The output type provided after the `->`, if present. output: Option<Type>, }, + /// `T::method(..)` + ReturnTypeNotation, } /// One argument in a list of generic arguments to a path segment. diff --git a/src/tools/cargo b/src/tools/cargo -Subproject ab1463d632528e39daf35f263e10c14cbe590ce +Subproject 307cbfda3119f06600e43cd38283f4a746fe1f8 diff --git a/src/tools/clippy/.github/workflows/clippy_mq.yml b/src/tools/clippy/.github/workflows/clippy_mq.yml index c337a96bdac..741e7457331 100644 --- a/src/tools/clippy/.github/workflows/clippy_mq.yml +++ b/src/tools/clippy/.github/workflows/clippy_mq.yml @@ -27,6 +27,8 @@ jobs: host: x86_64-pc-windows-msvc - os: macos-13 host: x86_64-apple-darwin + - os: macos-latest + host: aarch64-apple-darwin runs-on: ${{ matrix.os }} diff --git a/src/tools/clippy/.github/workflows/remark.yml b/src/tools/clippy/.github/workflows/remark.yml index 13902f78b54..7e7e26818c0 100644 --- a/src/tools/clippy/.github/workflows/remark.yml +++ b/src/tools/clippy/.github/workflows/remark.yml @@ -37,6 +37,7 @@ jobs: - name: Linkcheck book run: | rustup toolchain install nightly --component rust-docs + rustup override set nightly curl https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/linkcheck.sh -o linkcheck.sh sh linkcheck.sh clippy --path ./book diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index 51441ab9fc0..1bf4b51ff0f 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -5570,6 +5570,7 @@ Released 2018-09-13 [`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type [`disallowed_types`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression +[`doc_comment_double_space_linebreaks`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_comment_double_space_linebreaks [`doc_include_without_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_include_without_cfg [`doc_lazy_continuation`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_lazy_continuation [`doc_link_code`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_code @@ -6372,6 +6373,7 @@ Released 2018-09-13 [`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold [`missing-docs-in-crate-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#missing-docs-in-crate-items [`module-item-order-groupings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#module-item-order-groupings +[`module-items-ordered-within-groupings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#module-items-ordered-within-groupings [`msrv`]: https://doc.rust-lang.org/clippy/lint_configuration.html#msrv [`pass-by-value-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pass-by-value-size-limit [`pub-underscore-fields-behavior`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pub-underscore-fields-behavior diff --git a/src/tools/clippy/COPYRIGHT b/src/tools/clippy/COPYRIGHT index 219693d63d9..f402dcf465a 100644 --- a/src/tools/clippy/COPYRIGHT +++ b/src/tools/clippy/COPYRIGHT @@ -1,6 +1,6 @@ // REUSE-IgnoreStart -Copyright 2014-2024 The Rust Project Developers +Copyright 2014-2025 The Rust Project Developers Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml index c4588002dc9..94c170d73af 100644 --- a/src/tools/clippy/Cargo.toml +++ b/src/tools/clippy/Cargo.toml @@ -33,7 +33,7 @@ anstream = "0.6.18" [dev-dependencies] cargo_metadata = "0.18.1" -ui_test = "0.26.4" +ui_test = "0.29.2" regex = "1.5.5" serde = { version = "1.0.145", features = ["derive"] } serde_json = "1.0.122" diff --git a/src/tools/clippy/LICENSE-APACHE b/src/tools/clippy/LICENSE-APACHE index 506582c31d6..9990a0cec47 100644 --- a/src/tools/clippy/LICENSE-APACHE +++ b/src/tools/clippy/LICENSE-APACHE @@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work. same "printed page" as the copyright notice for easier identification within third-party archives. -Copyright 2014-2024 The Rust Project Developers +Copyright 2014-2025 The Rust Project Developers Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/tools/clippy/LICENSE-MIT b/src/tools/clippy/LICENSE-MIT index 6d8ee9afb61..5d6e36ef6bf 100644 --- a/src/tools/clippy/LICENSE-MIT +++ b/src/tools/clippy/LICENSE-MIT @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2014-2024 The Rust Project Developers +Copyright (c) 2014-2025 The Rust Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md index 32c1d33e2ed..20a5e997e62 100644 --- a/src/tools/clippy/README.md +++ b/src/tools/clippy/README.md @@ -277,7 +277,7 @@ If you want to contribute to Clippy, you can find more information in [CONTRIBUT <!-- REUSE-IgnoreStart --> -Copyright 2014-2024 The Rust Project Developers +Copyright 2014-2025 The Rust Project Developers Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)> or the MIT license diff --git a/src/tools/clippy/book/src/development/macro_expansions.md b/src/tools/clippy/book/src/development/macro_expansions.md index 36092f82e26..ed547130b35 100644 --- a/src/tools/clippy/book/src/development/macro_expansions.md +++ b/src/tools/clippy/book/src/development/macro_expansions.md @@ -150,9 +150,85 @@ if foo_span.in_external_macro(cx.sess().source_map()) { } ``` +### The `is_from_proc_macro` function +A common point of confusion is the existence of [`is_from_proc_macro`] +and how it differs from the other [`in_external_macro`]/[`from_expansion`] functions. + +While [`in_external_macro`] and [`from_expansion`] both work perfectly fine for detecting expanded code +from *declarative* macros (i.e. `macro_rules!` and macros 2.0), +detecting *proc macro*-generated code is a bit more tricky, as proc macros can (and often do) +freely manipulate the span of returned tokens. + +In practice, this often happens through the use of [`quote::quote_spanned!`] with a span from the input tokens. + +In those cases, there is no *reliable* way for the compiler (and tools like Clippy) +to distinguish code that comes from such a proc macro from code that the user wrote directly, +and [`in_external_macro`] will return `false`. + +This is usually not an issue for the compiler and actually helps proc macro authors create better error messages, +as it allows associating parts of the expansion with parts of the macro input and lets the compiler +point the user to the relevant code in case of a compile error. + +However, for Clippy this is inconvenient, because most of the time *we don't* want +to lint proc macro-generated code and this makes it impossible to tell what is and isn't proc macro code. + +> NOTE: this is specifically only an issue when a proc macro explicitly sets the span to that of an **input span**. +> +> For example, other common ways of creating `TokenStream`s, such as `"fn foo() {...}".parse::<TokenStream>()`, +> sets each token's span to `Span::call_site()`, which already marks the span as coming from a proc macro +> and the usual span methods have no problem detecting that as a macro span. + +As such, Clippy has its own `is_from_proc_macro` function which tries to *approximate* +whether a span comes from a proc macro, by checking whether the source text at the given span +lines up with the given AST node. + +This function is typically used in combination with the other mentioned macro span functions, +but is usually called much later into the condition chain as it's a bit heavier than most other conditions, +so that the other cheaper conditions can fail faster. For example, the `borrow_deref_ref` lint: +```rs +impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef { + fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &rustc_hir::Expr<'tcx>) { + if let ... = ... + && ... + && !e.span.from_expansion() + && ... + && ... + && !is_from_proc_macro(cx, e) + && ... + { + ... + } + } +} +``` + +### Testing lints with macro expansions +To test that all of these cases are handled correctly in your lint, +we have a helper auxiliary crate that exposes various macros, used by tests like so: +```rust +//@aux-build:proc_macros.rs + +extern crate proc_macros; + +fn main() { + proc_macros::external!{ code_that_should_trigger_your_lint } + proc_macros::with_span!{ span code_that_should_trigger_your_lint } +} +``` +This exercises two cases: +- `proc_macros::external!` is a simple proc macro that echos the input tokens back but with a macro span: +this represents the usual, common case where an external macro expands to code that your lint would trigger, +and is correctly handled by `in_external_macro` and `Span::from_expansion`. + +- `proc_macros::with_span!` echos back the input tokens starting from the second token +with the span of the first token: this is where the other functions will fail and `is_from_proc_macro` is needed + + [`ctxt`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html#method.ctxt [expansion]: https://rustc-dev-guide.rust-lang.org/macro-expansion.html#expansion-and-ast-integration [`from_expansion`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html#method.from_expansion [`in_external_macro`]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html#method.in_external_macro [Span]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/struct.Span.html [SyntaxContext]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_span/hygiene/struct.SyntaxContext.html +[`is_from_proc_macro`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/fn.is_from_proc_macro.html +[`quote::quote_spanned!`]: https://docs.rs/quote/latest/quote/macro.quote_spanned.html diff --git a/src/tools/clippy/book/src/development/the_team.md b/src/tools/clippy/book/src/development/the_team.md index 6bc0783b166..da5d084ed97 100644 --- a/src/tools/clippy/book/src/development/the_team.md +++ b/src/tools/clippy/book/src/development/the_team.md @@ -102,8 +102,7 @@ is responsible for maintaining Clippy. 5. **Update the changelog** - This needs to be done for every release, every six weeks. This is usually - done by @xFrednet. + This needs to be done for every release, every six weeks. ### Membership diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md index 28b613ea329..3726d6e8a86 100644 --- a/src/tools/clippy/book/src/lint_configuration.md +++ b/src/tools/clippy/book/src/lint_configuration.md @@ -744,6 +744,19 @@ The named groupings of different source item kinds within modules. * [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering) +## `module-items-ordered-within-groupings` +Whether the items within module groups should be ordered alphabetically or not. + +This option can be configured to "all", "none", or a list of specific grouping names that should be checked +(e.g. only "enums"). + +**Default Value:** `"none"` + +--- +**Affected lints:** +* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering) + + ## `msrv` The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml` @@ -806,6 +819,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio * [`option_as_ref_deref`](https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref) * [`option_map_unwrap_or`](https://rust-lang.github.io/rust-clippy/master/index.html#option_map_unwrap_or) * [`ptr_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#ptr_as_ptr) +* [`question_mark`](https://rust-lang.github.io/rust-clippy/master/index.html#question_mark) * [`redundant_field_names`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names) * [`redundant_static_lifetimes`](https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes) * [`repeat_vec_with_capacity`](https://rust-lang.github.io/rust-clippy/master/index.html#repeat_vec_with_capacity) diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs index a61acbaa96b..798f8b3aa5a 100644 --- a/src/tools/clippy/clippy_config/src/conf.rs +++ b/src/tools/clippy/clippy_config/src/conf.rs @@ -3,14 +3,17 @@ use crate::types::{ DisallowedPath, DisallowedPathWithoutReplacement, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename, SourceItemOrdering, SourceItemOrderingCategory, SourceItemOrderingModuleItemGroupings, SourceItemOrderingModuleItemKind, SourceItemOrderingTraitAssocItemKind, SourceItemOrderingTraitAssocItemKinds, + SourceItemOrderingWithinModuleItemGroupings, }; use clippy_utils::msrvs::Msrv; +use itertools::Itertools; use rustc_errors::Applicability; use rustc_session::Session; use rustc_span::edit_distance::edit_distance; use rustc_span::{BytePos, Pos, SourceFile, Span, SyntaxContext}; use serde::de::{IgnoredAny, IntoDeserializer, MapAccess, Visitor}; use serde::{Deserialize, Deserializer, Serialize}; +use std::collections::HashMap; use std::fmt::{Debug, Display, Formatter}; use std::ops::Range; use std::path::PathBuf; @@ -79,6 +82,7 @@ const DEFAULT_SOURCE_ITEM_ORDERING: &[SourceItemOrderingCategory] = { #[derive(Default)] struct TryConf { conf: Conf, + value_spans: HashMap<String, Range<usize>>, errors: Vec<ConfError>, warnings: Vec<ConfError>, } @@ -87,6 +91,7 @@ impl TryConf { fn from_toml_error(file: &SourceFile, error: &toml::de::Error) -> Self { Self { conf: Conf::default(), + value_spans: HashMap::default(), errors: vec![ConfError::from_toml(file, error)], warnings: vec![], } @@ -210,6 +215,7 @@ macro_rules! define_Conf { } fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error> where V: MapAccess<'de> { + let mut value_spans = HashMap::new(); let mut errors = Vec::new(); let mut warnings = Vec::new(); $(let mut $name = None;)* @@ -232,6 +238,7 @@ macro_rules! define_Conf { } None => { $name = Some(value); + value_spans.insert(name.get_ref().as_str().to_string(), value_span); // $new_conf is the same as one of the defined `$name`s, so // this variable is defined in line 2 of this function. $(match $new_conf { @@ -250,7 +257,7 @@ macro_rules! define_Conf { } } let conf = Conf { $($name: $name.unwrap_or_else(defaults::$name),)* }; - Ok(TryConf { conf, errors, warnings }) + Ok(TryConf { conf, value_spans, errors, warnings }) } } @@ -596,6 +603,13 @@ define_Conf! { /// The named groupings of different source item kinds within modules. #[lints(arbitrary_source_item_ordering)] module_item_order_groupings: SourceItemOrderingModuleItemGroupings = DEFAULT_MODULE_ITEM_ORDERING_GROUPS.into(), + /// Whether the items within module groups should be ordered alphabetically or not. + /// + /// This option can be configured to "all", "none", or a list of specific grouping names that should be checked + /// (e.g. only "enums"). + #[lints(arbitrary_source_item_ordering)] + module_items_ordered_within_groupings: SourceItemOrderingWithinModuleItemGroupings = + SourceItemOrderingWithinModuleItemGroupings::None, /// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml` #[default_text = "current version"] #[lints( @@ -654,6 +668,7 @@ define_Conf! { option_as_ref_deref, option_map_unwrap_or, ptr_as_ptr, + question_mark, redundant_field_names, redundant_static_lifetimes, repeat_vec_with_capacity, @@ -815,6 +830,36 @@ fn deserialize(file: &SourceFile) -> TryConf { &mut conf.conf.allow_renamed_params_for, DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS, ); + + // Confirms that the user has not accidentally configured ordering requirements for groups that + // aren't configured. + if let SourceItemOrderingWithinModuleItemGroupings::Custom(groupings) = + &conf.conf.module_items_ordered_within_groupings + { + for grouping in groupings { + if !conf.conf.module_item_order_groupings.is_grouping(grouping) { + // Since this isn't fixable by rustfix, don't emit a `Suggestion`. This just adds some useful + // info for the user instead. + + let names = conf.conf.module_item_order_groupings.grouping_names(); + let suggestion = suggest_candidate(grouping, names.iter().map(String::as_str)) + .map(|s| format!(" perhaps you meant `{s}`?")) + .unwrap_or_default(); + let names = names.iter().map(|s| format!("`{s}`")).join(", "); + let message = format!( + "unknown ordering group: `{grouping}` was not specified in `module-items-ordered-within-groupings`,{suggestion} expected one of: {names}" + ); + + let span = conf + .value_spans + .get("module_item_order_groupings") + .cloned() + .unwrap_or_default(); + conf.errors.push(ConfError::spanned(file, message, None, span)); + } + } + } + // TODO: THIS SHOULD BE TESTED, this comment will be gone soon if conf.conf.allowed_idents_below_min_chars.iter().any(|e| e == "..") { conf.conf @@ -860,6 +905,7 @@ impl Conf { let TryConf { mut conf, + value_spans: _, errors, warnings, } = match path { @@ -950,17 +996,10 @@ impl serde::de::Error for FieldError { } } - let suggestion = expected - .iter() - .filter_map(|expected| { - let dist = edit_distance(field, expected, 4)?; - Some((dist, expected)) - }) - .min_by_key(|&(dist, _)| dist) - .map(|(_, suggestion)| Suggestion { - message: "perhaps you meant", - suggestion, - }); + let suggestion = suggest_candidate(field, expected).map(|suggestion| Suggestion { + message: "perhaps you meant", + suggestion, + }); Self { error: msg, suggestion } } @@ -998,6 +1037,22 @@ fn calculate_dimensions(fields: &[&str]) -> (usize, Vec<usize>) { (rows, column_widths) } +/// Given a user-provided value that couldn't be matched to a known option, finds the most likely +/// candidate among candidates that the user might have meant. +fn suggest_candidate<'a, I>(value: &str, candidates: I) -> Option<&'a str> +where + I: IntoIterator<Item = &'a str>, +{ + candidates + .into_iter() + .filter_map(|expected| { + let dist = edit_distance(value, expected, 4)?; + Some((dist, expected)) + }) + .min_by_key(|&(dist, _)| dist) + .map(|(_, suggestion)| suggestion) +} + #[cfg(test)] mod tests { use serde::de::IgnoredAny; diff --git a/src/tools/clippy/clippy_config/src/types.rs b/src/tools/clippy/clippy_config/src/types.rs index c72291e9799..8faac9ecffe 100644 --- a/src/tools/clippy/clippy_config/src/types.rs +++ b/src/tools/clippy/clippy_config/src/types.rs @@ -305,6 +305,7 @@ impl SourceItemOrderingModuleItemKind { pub struct SourceItemOrderingModuleItemGroupings { groups: Vec<(String, Vec<SourceItemOrderingModuleItemKind>)>, lut: HashMap<SourceItemOrderingModuleItemKind, usize>, + back_lut: HashMap<SourceItemOrderingModuleItemKind, String>, } impl SourceItemOrderingModuleItemGroupings { @@ -320,6 +321,30 @@ impl SourceItemOrderingModuleItemGroupings { lut } + fn build_back_lut( + groups: &[(String, Vec<SourceItemOrderingModuleItemKind>)], + ) -> HashMap<SourceItemOrderingModuleItemKind, String> { + let mut lut = HashMap::new(); + for (group_name, items) in groups { + for item in items { + lut.insert(item.clone(), group_name.clone()); + } + } + lut + } + + pub fn grouping_name_of(&self, item: &SourceItemOrderingModuleItemKind) -> Option<&String> { + self.back_lut.get(item) + } + + pub fn grouping_names(&self) -> Vec<String> { + self.groups.iter().map(|(name, _)| name.clone()).collect() + } + + pub fn is_grouping(&self, grouping: &str) -> bool { + self.groups.iter().any(|(g, _)| g == grouping) + } + pub fn module_level_order_of(&self, item: &SourceItemOrderingModuleItemKind) -> Option<usize> { self.lut.get(item).copied() } @@ -330,7 +355,8 @@ impl From<&[(&str, &[SourceItemOrderingModuleItemKind])]> for SourceItemOrdering let groups: Vec<(String, Vec<SourceItemOrderingModuleItemKind>)> = value.iter().map(|item| (item.0.to_string(), item.1.to_vec())).collect(); let lut = Self::build_lut(&groups); - Self { groups, lut } + let back_lut = Self::build_back_lut(&groups); + Self { groups, lut, back_lut } } } @@ -348,6 +374,7 @@ impl<'de> Deserialize<'de> for SourceItemOrderingModuleItemGroupings { let groups = Vec::<(String, Vec<SourceItemOrderingModuleItemKind>)>::deserialize(deserializer)?; let items_total: usize = groups.iter().map(|(_, v)| v.len()).sum(); let lut = Self::build_lut(&groups); + let back_lut = Self::build_back_lut(&groups); let mut expected_items = SourceItemOrderingModuleItemKind::all_variants(); for item in lut.keys() { @@ -370,7 +397,7 @@ impl<'de> Deserialize<'de> for SourceItemOrderingModuleItemGroupings { )); } - Ok(Self { groups, lut }) + Ok(Self { groups, lut, back_lut }) } else if items_total != all_items.len() { Err(de::Error::custom(format!( "Some module item kinds were configured more than once, or were missing, in the source ordering configuration. \ @@ -482,6 +509,83 @@ impl Serialize for SourceItemOrderingTraitAssocItemKinds { } } +/// Describes which specific groupings should have their items ordered +/// alphabetically. +/// +/// This is separate from defining and enforcing groupings. For example, +/// defining enums are grouped before structs still allows for an enum B to be +/// placed before an enum A. Only when enforcing ordering within the grouping, +/// will it be checked if A is placed before B. +#[derive(Clone, Debug)] +pub enum SourceItemOrderingWithinModuleItemGroupings { + /// All groupings should have their items ordered. + All, + + /// None of the groupings should have their order checked. + None, + + /// Only the specified groupings should have their order checked. + Custom(Vec<String>), +} + +impl SourceItemOrderingWithinModuleItemGroupings { + pub fn ordered_within(&self, grouping_name: &String) -> bool { + match self { + SourceItemOrderingWithinModuleItemGroupings::All => true, + SourceItemOrderingWithinModuleItemGroupings::None => false, + SourceItemOrderingWithinModuleItemGroupings::Custom(groups) => groups.contains(grouping_name), + } + } +} + +/// Helper struct for deserializing the [`SourceItemOrderingWithinModuleItemGroupings`]. +#[derive(Deserialize)] +#[serde(untagged)] +enum StringOrVecOfString { + String(String), + Vec(Vec<String>), +} + +impl<'de> Deserialize<'de> for SourceItemOrderingWithinModuleItemGroupings { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + let description = "The available options for configuring an ordering within module item groups are: \ + \"all\", \"none\", or a list of module item group names \ + (as configured with the `module-item-order-groupings` configuration option)."; + + match StringOrVecOfString::deserialize(deserializer) { + Ok(StringOrVecOfString::String(preset)) if preset == "all" => { + Ok(SourceItemOrderingWithinModuleItemGroupings::All) + }, + Ok(StringOrVecOfString::String(preset)) if preset == "none" => { + Ok(SourceItemOrderingWithinModuleItemGroupings::None) + }, + Ok(StringOrVecOfString::String(preset)) => Err(de::Error::custom(format!( + "Unknown configuration option: {preset}.\n{description}" + ))), + Ok(StringOrVecOfString::Vec(groupings)) => { + Ok(SourceItemOrderingWithinModuleItemGroupings::Custom(groupings)) + }, + Err(e) => Err(de::Error::custom(format!("{e}\n{description}"))), + } + } +} + +impl Serialize for SourceItemOrderingWithinModuleItemGroupings { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: ser::Serializer, + { + match self { + SourceItemOrderingWithinModuleItemGroupings::All => serializer.serialize_str("all"), + SourceItemOrderingWithinModuleItemGroupings::None => serializer.serialize_str("none"), + SourceItemOrderingWithinModuleItemGroupings::Custom(vec) => vec.serialize(serializer), + } + } +} + // these impls are never actually called but are used by the various config options that default to // empty lists macro_rules! unimplemented_serialize { diff --git a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs index c0ae4960e10..57cabe43703 100644 --- a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs +++ b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -2,11 +2,12 @@ use clippy_config::Conf; use clippy_config::types::{ SourceItemOrderingCategory, SourceItemOrderingModuleItemGroupings, SourceItemOrderingModuleItemKind, SourceItemOrderingTraitAssocItemKind, SourceItemOrderingTraitAssocItemKinds, + SourceItemOrderingWithinModuleItemGroupings, }; use clippy_utils::diagnostics::span_lint_and_note; use rustc_hir::{ - AssocItemKind, FieldDef, HirId, ImplItemRef, IsAuto, Item, ItemKind, Mod, QPath, TraitItemRef, TyKind, UseKind, - Variant, VariantData, + AssocItemKind, FieldDef, HirId, ImplItemRef, IsAuto, Item, ItemKind, Mod, QPath, TraitItemRef, TyKind, Variant, + VariantData, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; @@ -36,7 +37,7 @@ declare_clippy_lint! { /// 2. Individual ordering rules per item kind. /// /// The item kinds that can be linted are: - /// - Module (with customized groupings, alphabetical within) + /// - Module (with customized groupings, alphabetical within - configurable) /// - Trait (with customized order of associated items, alphabetical within) /// - Enum, Impl, Struct (purely alphabetical) /// @@ -57,8 +58,31 @@ declare_clippy_lint! { /// | `PascalCase` | "ty_alias", "opaque_ty", "enum", "struct", "union", "trait", "trait_alias", "impl" | /// | `lower_snake_case` | "fn" | /// + /// The groups' names are arbitrary and can be changed to suit the + /// conventions that should be enforced for a specific project. + /// /// All item kinds must be accounted for to create an enforceable linting - /// rule set. + /// rule set. Following are some example configurations that may be useful. + /// + /// Example: *module inclusions and use statements to be at the top* + /// + /// ```toml + /// module-item-order-groupings = [ + /// [ "modules", [ "extern_crate", "mod", "foreign_mod" ], ], + /// [ "use", [ "use", ], ], + /// [ "everything_else", [ "macro", "global_asm", "static", "const", "ty_alias", "enum", "struct", "union", "trait", "trait_alias", "impl", "fn", ], ], + /// ] + /// ``` + /// + /// Example: *only consts and statics should be alphabetically ordered* + /// + /// It is also possible to configure a selection of module item groups that + /// should be ordered alphabetically. This may be useful if for example + /// statics and consts should be ordered, but the rest should be left open. + /// + /// ```toml + /// module-items-ordered-within-groupings = ["UPPER_SNAKE_CASE"] + /// ``` /// /// ### Known Problems /// @@ -143,6 +167,7 @@ pub struct ArbitrarySourceItemOrdering { enable_ordering_for_struct: bool, enable_ordering_for_trait: bool, module_item_order_groupings: SourceItemOrderingModuleItemGroupings, + module_items_ordered_within_groupings: SourceItemOrderingWithinModuleItemGroupings, } impl ArbitrarySourceItemOrdering { @@ -157,6 +182,7 @@ impl ArbitrarySourceItemOrdering { enable_ordering_for_struct: conf.source_item_ordering.contains(&Struct), enable_ordering_for_trait: conf.source_item_ordering.contains(&Trait), module_item_order_groupings: conf.module_item_order_groupings.clone(), + module_items_ordered_within_groupings: conf.module_items_ordered_within_groupings.clone(), } } @@ -176,11 +202,7 @@ impl ArbitrarySourceItemOrdering { } /// Produces a linting warning for incorrectly ordered item members. - fn lint_member_name<T: LintContext>( - cx: &T, - ident: &rustc_span::symbol::Ident, - before_ident: &rustc_span::symbol::Ident, - ) { + fn lint_member_name<T: LintContext>(cx: &T, ident: &rustc_span::Ident, before_ident: &rustc_span::Ident) { span_lint_and_note( cx, ARBITRARY_SOURCE_ITEM_ORDERING, @@ -191,22 +213,19 @@ impl ArbitrarySourceItemOrdering { ); } - fn lint_member_item<T: LintContext>(cx: &T, item: &Item<'_>, before_item: &Item<'_>) { - let span = if item.ident.as_str().is_empty() { - &item.span + fn lint_member_item<T: LintContext>(cx: &T, item: &Item<'_>, before_item: &Item<'_>, msg: &'static str) { + let span = if let Some(ident) = item.kind.ident() { + ident.span } else { - &item.ident.span + item.span }; - let (before_span, note) = if before_item.ident.as_str().is_empty() { - ( - &before_item.span, - "should be placed before the following item".to_owned(), - ) + let (before_span, note) = if let Some(ident) = before_item.kind.ident() { + (ident.span, format!("should be placed before `{}`", ident.as_str(),)) } else { ( - &before_item.ident.span, - format!("should be placed before `{}`", before_item.ident.as_str(),), + before_item.span, + "should be placed before the following item".to_owned(), ) }; @@ -215,14 +234,7 @@ impl ArbitrarySourceItemOrdering { return; } - span_lint_and_note( - cx, - ARBITRARY_SOURCE_ITEM_ORDERING, - *span, - "incorrect ordering of items (must be alphabetically ordered)", - Some(*before_span), - note, - ); + span_lint_and_note(cx, ARBITRARY_SOURCE_ITEM_ORDERING, span, msg, Some(before_span), note); } /// Produces a linting warning for incorrectly ordered trait items. @@ -244,7 +256,7 @@ impl ArbitrarySourceItemOrdering { impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { match &item.kind { - ItemKind::Enum(enum_def, _generics) if self.enable_ordering_for_enum => { + ItemKind::Enum(_, enum_def, _generics) if self.enable_ordering_for_enum => { let mut cur_v: Option<&Variant<'_>> = None; for variant in enum_def.variants { if variant.span.in_external_macro(cx.sess().source_map()) { @@ -259,7 +271,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { cur_v = Some(variant); } }, - ItemKind::Struct(VariantData::Struct { fields, .. }, _generics) if self.enable_ordering_for_struct => { + ItemKind::Struct(_, VariantData::Struct { fields, .. }, _generics) if self.enable_ordering_for_struct => { let mut cur_f: Option<&FieldDef<'_>> = None; for field in *fields { if field.span.in_external_macro(cx.sess().source_map()) { @@ -274,7 +286,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { cur_f = Some(field); } }, - ItemKind::Trait(is_auto, _safety, _generics, _generic_bounds, item_ref) + ItemKind::Trait(is_auto, _safety, _ident, _generics, _generic_bounds, item_ref) if self.enable_ordering_for_trait && *is_auto == IsAuto::No => { let mut cur_t: Option<&TraitItemRef> = None; @@ -351,50 +363,24 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { continue; } - // The following exceptions (skipping with `continue;`) may not be - // complete, edge cases have not been explored further than what - // appears in the existing code base. - if item.ident.name == rustc_span::symbol::kw::Empty { - if let ItemKind::Impl(_) = item.kind { - // Sorting trait impls for unnamed types makes no sense. - if get_item_name(item).is_empty() { - continue; - } - } else if let ItemKind::ForeignMod { .. } = item.kind { - continue; - } else if let ItemKind::GlobalAsm { .. } = item.kind { - continue; - } else if let ItemKind::Use(path, use_kind) = item.kind { - if path.segments.is_empty() { - // Use statements that contain braces get caught here. - // They will still be linted internally. - continue; - } else if path.segments.len() >= 2 - && (path.segments[0].ident.name == rustc_span::sym::std - || path.segments[0].ident.name == rustc_span::sym::core) - && path.segments[1].ident.name == rustc_span::sym::prelude - { - // Filters the autogenerated prelude use statement. - // e.g. `use std::prelude::rustc_2021` - } else if use_kind == UseKind::Glob { - // Filters glob kinds of uses. - // e.g. `use std::sync::*` - } else { - // This can be used for debugging. - // println!("Unknown autogenerated use statement: {:?}", item); - } - continue; - } - } + let ident = if let Some(ident) = item.kind.ident() { + ident + } else if let ItemKind::Impl(_) = item.kind + && !get_item_name(item).is_empty() + { + rustc_span::Ident::empty() // FIXME: a bit strange, is there a better way to do it? + } else { + continue; + }; - if item.ident.name.as_str().starts_with('_') { + if ident.name.as_str().starts_with('_') { // Filters out unnamed macro-like impls for various derives, // e.g. serde::Serialize or num_derive::FromPrimitive. continue; } - if item.ident.name == rustc_span::sym::std && item.span.is_dummy() { - if let ItemKind::ExternCrate(None) = item.kind { + if ident.name == rustc_span::sym::std && item.span.is_dummy() { + if let ItemKind::ExternCrate(None, _) = item.kind { // Filters the auto-included Rust standard library. continue; } @@ -402,6 +388,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { } let item_kind = convert_module_item_kind(&item.kind); + let grouping_name = self.module_item_order_groupings.grouping_name_of(&item_kind); let module_level_order = self .module_item_order_groupings .module_level_order_of(&item_kind) @@ -411,13 +398,27 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { use std::cmp::Ordering; // Better legibility. match module_level_order.cmp(&cur_t.order) { Ordering::Less => { - Self::lint_member_item(cx, item, cur_t.item); + Self::lint_member_item( + cx, + item, + cur_t.item, + "incorrect ordering of items (module item groupings specify another order)", + ); }, Ordering::Equal if item_kind == SourceItemOrderingModuleItemKind::Use => { // Skip ordering use statements, as these should be ordered by rustfmt. }, - Ordering::Equal if cur_t.name > get_item_name(item) => { - Self::lint_member_item(cx, item, cur_t.item); + Ordering::Equal + if (grouping_name.is_some_and(|grouping_name| { + self.module_items_ordered_within_groupings.ordered_within(grouping_name) + }) && cur_t.name > get_item_name(item)) => + { + Self::lint_member_item( + cx, + item, + cur_t.item, + "incorrect ordering of items (must be alphabetically ordered)", + ); }, Ordering::Equal | Ordering::Greater => { // Nothing to do in this case, they're already in the right order. @@ -525,6 +526,14 @@ fn get_item_name(item: &Item<'_>) -> String { String::new() } }, - _ => item.ident.name.as_str().to_owned(), + // FIXME: `Ident::empty` for anonymous items is a bit strange, is there + // a better way to do it? + _ => item + .kind + .ident() + .unwrap_or(rustc_span::Ident::empty()) + .name + .as_str() + .to_owned(), } } diff --git a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs index 2ddbc7a6a76..5c486eb90cc 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs @@ -36,7 +36,11 @@ fn check_duplicated_attr( } let Some(ident) = attr.ident() else { return }; let name = ident.name; - if name == sym::doc || name == sym::cfg_attr || name == sym::rustc_on_unimplemented || name == sym::reason { + if name == sym::doc + || name == sym::cfg_attr + || name == sym::cfg_attr_trace + || name == sym::rustc_on_unimplemented + || name == sym::reason { // FIXME: Would be nice to handle `cfg_attr` as well. Only problem is to check that cfg // conditions are the same. // `#[rustc_on_unimplemented]` contains duplicated subattributes, that's expected. diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs index f9a2f011a14..e04d2ad5d13 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs @@ -16,7 +16,7 @@ mod utils; use clippy_config::Conf; use clippy_utils::msrvs::{self, Msrv, MsrvStack}; use rustc_ast::{self as ast, Attribute, MetaItemInner, MetaItemKind}; -use rustc_hir::{ImplItem, Item, TraitItem}; +use rustc_hir::{ImplItem, Item, ItemKind, TraitItem}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::sym; @@ -466,8 +466,10 @@ impl Attributes { impl<'tcx> LateLintPass<'tcx> for Attributes { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { let attrs = cx.tcx.hir_attrs(item.hir_id()); - if is_relevant_item(cx, item) { - inline_always::check(cx, item.span, item.ident.name, attrs); + if let ItemKind::Fn { ident, .. } = item.kind + && is_relevant_item(cx, item) + { + inline_always::check(cx, item.span, ident.name, attrs); } repr_attributes::check(cx, item.span, attrs, self.msrv); } diff --git a/src/tools/clippy/clippy_lints/src/attrs/utils.rs b/src/tools/clippy/clippy_lints/src/attrs/utils.rs index 0e650e49392..a5ce2137bff 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/utils.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/utils.rs @@ -24,7 +24,7 @@ pub(super) fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool { if let ItemKind::Fn { body: eid, .. } = item.kind { is_relevant_expr(cx, cx.tcx.typeck_body(eid), cx.tcx.hir_body(eid).value) } else { - true + false } } diff --git a/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs b/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs index aab0af0d743..011962846cb 100644 --- a/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs +++ b/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_block_with_applicability; -use clippy_utils::{higher, is_from_proc_macro}; +use clippy_utils::{contains_return, higher, is_from_proc_macro}; use rustc_errors::Applicability; use rustc_hir::{BlockCheckMode, Expr, ExprKind, MatchSource}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -86,6 +86,13 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInConditions { if expr.span.from_expansion() || ex.span.from_expansion() { return; } + + // Linting should not be triggered to cases where `return` is included in the condition. + // #9911 + if contains_return(block.expr) { + return; + } + let mut applicability = Applicability::MachineApplicable; span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs index d143629da3a..64345c81a24 100644 --- a/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs @@ -2,11 +2,10 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::msrvs::Msrv; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::has_enclosing_paren; -use clippy_utils::{is_lint_allowed, msrvs, std_or_core}; +use clippy_utils::{is_expr_temporary_value, is_lint_allowed, msrvs, std_or_core}; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Ty, TyKind}; use rustc_lint::LateContext; -use rustc_middle::ty::adjustment::Adjust; use rustc_span::BytePos; use super::BORROW_AS_PTR; @@ -25,12 +24,7 @@ pub(super) fn check<'tcx>( let mut app = Applicability::MachineApplicable; let snip = snippet_with_context(cx, e.span, cast_expr.span.ctxt(), "..", &mut app).0; // Fix #9884 - if !e.is_place_expr(|base| { - cx.typeck_results() - .adjustments() - .get(base.hir_id) - .is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_)))) - }) { + if is_expr_temporary_value(cx, e) { return false; } diff --git a/src/tools/clippy/clippy_lints/src/comparison_chain.rs b/src/tools/clippy/clippy_lints/src/comparison_chain.rs index 61c92d441d0..0e7f01e44b0 100644 --- a/src/tools/clippy/clippy_lints/src/comparison_chain.rs +++ b/src/tools/clippy/clippy_lints/src/comparison_chain.rs @@ -53,7 +53,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.40.0"] pub COMPARISON_CHAIN, - style, + pedantic, "`if`s that can be rewritten with `match` and `cmp`" } diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index 0834618499c..7fa23dad698 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -137,6 +137,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::disallowed_names::DISALLOWED_NAMES_INFO, crate::disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS_INFO, crate::disallowed_types::DISALLOWED_TYPES_INFO, + crate::doc::DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS_INFO, crate::doc::DOC_INCLUDE_WITHOUT_CFG_INFO, crate::doc::DOC_LAZY_CONTINUATION_INFO, crate::doc::DOC_LINK_CODE_INFO, @@ -614,7 +615,6 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::operators::MODULO_ONE_INFO, crate::operators::NEEDLESS_BITWISE_BOOL_INFO, crate::operators::OP_REF_INFO, - crate::operators::PTR_EQ_INFO, crate::operators::REDUNDANT_COMPARISONS_INFO, crate::operators::SELF_ASSIGNMENT_INFO, crate::operators::VERBOSE_BIT_MASK_INFO, @@ -641,6 +641,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::ptr::INVALID_NULL_PTR_USAGE_INFO, crate::ptr::MUT_FROM_REF_INFO, crate::ptr::PTR_ARG_INFO, + crate::ptr::PTR_EQ_INFO, crate::ptr_offset_with_cast::PTR_OFFSET_WITH_CAST_INFO, crate::pub_underscore_fields::PUB_UNDERSCORE_FIELDS_INFO, crate::pub_use::PUB_USE_INFO, diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs index ffdd946aadb..886c325b355 100644 --- a/src/tools/clippy/clippy_lints/src/default.rs +++ b/src/tools/clippy/clippy_lints/src/default.rs @@ -134,7 +134,7 @@ impl<'tcx> LateLintPass<'tcx> for Default { && let ty::Adt(adt, args) = *binding_type.kind() && adt.is_struct() && let variant = adt.non_enum_variant() - && (adt.did().is_local() || !variant.is_field_list_non_exhaustive()) + && !variant.field_list_has_applicable_non_exhaustive() && let module_did = cx.tcx.parent_module(stmt.hir_id) && variant .fields diff --git a/src/tools/clippy/clippy_lints/src/disallowed_types.rs b/src/tools/clippy/clippy_lints/src/disallowed_types.rs index 3659946b704..38903596414 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_types.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_types.rs @@ -99,7 +99,7 @@ impl_lint_pass!(DisallowedTypes => [DISALLOWED_TYPES]); impl<'tcx> LateLintPass<'tcx> for DisallowedTypes { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { - if let ItemKind::Use(path, UseKind::Single) = &item.kind { + if let ItemKind::Use(path, UseKind::Single(_)) = &item.kind { for res in &path.res { self.check_res_emit(cx, res, item.span); } diff --git a/src/tools/clippy/clippy_lints/src/doc/doc_comment_double_space_linebreaks.rs b/src/tools/clippy/clippy_lints/src/doc/doc_comment_double_space_linebreaks.rs new file mode 100644 index 00000000000..4cc02702233 --- /dev/null +++ b/src/tools/clippy/clippy_lints/src/doc/doc_comment_double_space_linebreaks.rs @@ -0,0 +1,33 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use rustc_errors::Applicability; +use rustc_lint::LateContext; +use rustc_span::{BytePos, Span}; + +use super::DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS; + +pub fn check(cx: &LateContext<'_>, collected_breaks: &[Span]) { + if collected_breaks.is_empty() { + return; + } + + let breaks: Vec<_> = collected_breaks + .iter() + .map(|span| span.with_hi(span.lo() + BytePos(2))) + .collect(); + + span_lint_and_then( + cx, + DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS, + breaks.clone(), + "doc comment uses two spaces for a hard line break", + |diag| { + let suggs: Vec<_> = breaks.iter().map(|span| (*span, "\\".to_string())).collect(); + diag.tool_only_multipart_suggestion( + "replace this double space with a backslash:", + suggs, + Applicability::MachineApplicable, + ); + diag.help("replace this double space with a backslash: `\\`"); + }, + ); +} diff --git a/src/tools/clippy/clippy_lints/src/doc/mod.rs b/src/tools/clippy/clippy_lints/src/doc/mod.rs index 0296ff13112..36fd396cc1d 100644 --- a/src/tools/clippy/clippy_lints/src/doc/mod.rs +++ b/src/tools/clippy/clippy_lints/src/doc/mod.rs @@ -1,12 +1,10 @@ #![allow(clippy::lint_without_lint_pass)] -mod lazy_continuation; -mod too_long_first_doc_paragraph; - use clippy_config::Conf; use clippy_utils::attrs::is_doc_hidden; use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then}; use clippy_utils::macros::{is_panic, root_macro_call_first_node}; +use clippy_utils::source::snippet_opt; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::visitors::Visitable; use clippy_utils::{is_entrypoint_fn, is_trait_impl_item, method_chain_args}; @@ -33,12 +31,15 @@ use rustc_span::{Span, sym}; use std::ops::Range; use url::Url; +mod doc_comment_double_space_linebreaks; mod include_in_doc_without_cfg; +mod lazy_continuation; mod link_with_quotes; mod markdown; mod missing_headers; mod needless_doctest_main; mod suspicious_doc_comments; +mod too_long_first_doc_paragraph; declare_clippy_lint! { /// ### What it does @@ -567,6 +568,39 @@ declare_clippy_lint! { "link reference defined in list item or quote" } +declare_clippy_lint! { + /// ### What it does + /// Detects doc comment linebreaks that use double spaces to separate lines, instead of back-slash (`\`). + /// + /// ### Why is this bad? + /// Double spaces, when used as doc comment linebreaks, can be difficult to see, and may + /// accidentally be removed during automatic formatting or manual refactoring. The use of a back-slash (`\`) + /// is clearer in this regard. + /// + /// ### Example + /// The two replacement dots in this example represent a double space. + /// ```no_run + /// /// This command takes two numbers as inputs and·· + /// /// adds them together, and then returns the result. + /// fn add(l: i32, r: i32) -> i32 { + /// l + r + /// } + /// ``` + /// + /// Use instead: + /// ```no_run + /// /// This command takes two numbers as inputs and\ + /// /// adds them together, and then returns the result. + /// fn add(l: i32, r: i32) -> i32 { + /// l + r + /// } + /// ``` + #[clippy::version = "1.87.0"] + pub DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS, + pedantic, + "double-space used for doc comment linebreak instead of `\\`" +} + pub struct Documentation { valid_idents: FxHashSet<String>, check_private_items: bool, @@ -598,6 +632,7 @@ impl_lint_pass!(Documentation => [ DOC_OVERINDENTED_LIST_ITEMS, TOO_LONG_FIRST_DOC_PARAGRAPH, DOC_INCLUDE_WITHOUT_CFG, + DOC_COMMENT_DOUBLE_SPACE_LINEBREAKS ]); impl EarlyLintPass for Documentation { @@ -894,6 +929,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize let mut paragraph_range = 0..0; let mut code_level = 0; let mut blockquote_level = 0; + let mut collected_breaks: Vec<Span> = Vec::new(); let mut is_first_paragraph = true; let mut containers = Vec::new(); @@ -1010,11 +1046,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize start -= 1; } - if start > range.start { - start - range.start - } else { - 0 - } + start.saturating_sub(range.start) } } else { 0 @@ -1073,6 +1105,14 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize &containers[..], ); } + + if let Some(span) = fragments.span(cx, range.clone()) + && !span.from_expansion() + && let Some(snippet) = snippet_opt(cx, span) + && !snippet.trim().starts_with('\\') + && event == HardBreak { + collected_breaks.push(span); + } }, Text(text) => { paragraph_range.end = range.end; @@ -1123,6 +1163,9 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize FootnoteReference(_) => {} } } + + doc_comment_double_space_linebreaks::check(cx, &collected_breaks); + headers } diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs index f404bc59b3b..dcfee0b6d3c 100644 --- a/src/tools/clippy/clippy_lints/src/entry.rs +++ b/src/tools/clippy/clippy_lints/src/entry.rs @@ -1,5 +1,6 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; use clippy_utils::source::{reindent_multiline, snippet_indent, snippet_with_applicability, snippet_with_context}; +use clippy_utils::ty::is_copy; use clippy_utils::visitors::for_each_expr; use clippy_utils::{ SpanlessEq, can_move_expr_to_closure_no_visit, higher, is_expr_final_block_expr, is_expr_used_or_unified, @@ -84,14 +85,21 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass { return; }; + let lint_msg = format!("usage of `contains_key` followed by `insert` on a `{}`", map_ty.name()); let mut app = Applicability::MachineApplicable; let map_str = snippet_with_context(cx, contains_expr.map.span, contains_expr.call_ctxt, "..", &mut app).0; let key_str = snippet_with_context(cx, contains_expr.key.span, contains_expr.call_ctxt, "..", &mut app).0; + let sugg = if let Some(else_expr) = else_expr { let Some(else_search) = find_insert_calls(cx, &contains_expr, else_expr) else { return; }; + if then_search.is_key_used_and_no_copy || else_search.is_key_used_and_no_copy { + span_lint(cx, MAP_ENTRY, expr.span, lint_msg); + return; + } + if then_search.edits.is_empty() && else_search.edits.is_empty() { // No insertions return; @@ -184,15 +192,7 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass { } }; - span_lint_and_sugg( - cx, - MAP_ENTRY, - expr.span, - format!("usage of `contains_key` followed by `insert` on a `{}`", map_ty.name()), - "try", - sugg, - app, - ); + span_lint_and_sugg(cx, MAP_ENTRY, expr.span, lint_msg, "try", sugg, app); } } @@ -354,6 +354,8 @@ struct InsertSearcher<'cx, 'tcx> { key: &'tcx Expr<'tcx>, /// The context of the top level block. All insert calls must be in the same context. ctxt: SyntaxContext, + /// The spanless equality utility used to compare expressions. + spanless_eq: SpanlessEq<'cx, 'tcx>, /// Whether this expression can be safely moved into a closure. allow_insert_closure: bool, /// Whether this expression can use the entry api. @@ -364,6 +366,8 @@ struct InsertSearcher<'cx, 'tcx> { is_single_insert: bool, /// If the visitor has seen the map being used. is_map_used: bool, + /// If the visitor has seen the key being used. + is_key_used: bool, /// The locations where changes need to be made for the suggestion. edits: Vec<Edit<'tcx>>, /// A stack of loops the visitor is currently in. @@ -479,11 +483,11 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { } match try_parse_insert(self.cx, expr) { - Some(insert_expr) if SpanlessEq::new(self.cx).eq_expr(self.map, insert_expr.map) => { + Some(insert_expr) if self.spanless_eq.eq_expr(self.map, insert_expr.map) => { self.visit_insert_expr_arguments(&insert_expr); // Multiple inserts, inserts with a different key, and inserts from a macro can't use the entry api. if self.is_map_used - || !SpanlessEq::new(self.cx).eq_expr(self.key, insert_expr.key) + || !self.spanless_eq.eq_expr(self.key, insert_expr.key) || expr.span.ctxt() != self.ctxt { self.can_use_entry = false; @@ -502,9 +506,12 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { self.visit_non_tail_expr(insert_expr.value); self.is_single_insert = is_single_insert; }, - _ if is_any_expr_in_map_used(self.cx, self.map, expr) => { + _ if is_any_expr_in_map_used(self.cx, &mut self.spanless_eq, self.map, expr) => { self.is_map_used = true; }, + _ if self.spanless_eq.eq_expr(self.key, expr) => { + self.is_key_used = true; + }, _ => match expr.kind { ExprKind::If(cond_expr, then_expr, Some(else_expr)) => { self.is_single_insert = false; @@ -568,9 +575,14 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { /// Check if the given expression is used for each sub-expression in the given map. /// For example, in map `a.b.c.my_map`, The expression `a.b.c.my_map`, `a.b.c`, `a.b`, and `a` are /// all checked. -fn is_any_expr_in_map_used<'tcx>(cx: &LateContext<'tcx>, map: &'tcx Expr<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { +fn is_any_expr_in_map_used<'tcx>( + cx: &LateContext<'tcx>, + spanless_eq: &mut SpanlessEq<'_, 'tcx>, + map: &'tcx Expr<'tcx>, + expr: &'tcx Expr<'tcx>, +) -> bool { for_each_expr(cx, map, |e| { - if SpanlessEq::new(cx).eq_expr(e, expr) { + if spanless_eq.eq_expr(e, expr) { return ControlFlow::Break(()); } ControlFlow::Continue(()) @@ -582,6 +594,7 @@ struct InsertSearchResults<'tcx> { edits: Vec<Edit<'tcx>>, allow_insert_closure: bool, is_single_insert: bool, + is_key_used_and_no_copy: bool, } impl<'tcx> InsertSearchResults<'tcx> { fn as_single_insertion(&self) -> Option<Insertion<'tcx>> { @@ -694,11 +707,13 @@ fn find_insert_calls<'tcx>( map: contains_expr.map, key: contains_expr.key, ctxt: expr.span.ctxt(), + spanless_eq: SpanlessEq::new(cx), allow_insert_closure: true, can_use_entry: true, in_tail_pos: true, is_single_insert: true, is_map_used: false, + is_key_used: false, edits: Vec::new(), loops: Vec::new(), locals: HirIdSet::default(), @@ -706,10 +721,12 @@ fn find_insert_calls<'tcx>( s.visit_expr(expr); let allow_insert_closure = s.allow_insert_closure; let is_single_insert = s.is_single_insert; + let is_key_used_and_no_copy = s.is_key_used && !is_copy(cx, cx.typeck_results().expr_ty(contains_expr.key)); let edits = s.edits; s.can_use_entry.then_some(InsertSearchResults { edits, allow_insert_closure, is_single_insert, + is_key_used_and_no_copy, }) } diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs index 2e1f8ac615a..f01b5c840d2 100644 --- a/src/tools/clippy/clippy_lints/src/enum_clike.rs +++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs @@ -38,7 +38,7 @@ impl<'tcx> LateLintPass<'tcx> for UnportableVariant { if cx.tcx.data_layout.pointer_size.bits() != 64 { return; } - if let ItemKind::Enum(def, _) = &item.kind { + if let ItemKind::Enum(_, def, _) = &item.kind { for var in def.variants { if let Some(anon_const) = &var.disr_expr { let def_id = cx.tcx.hir_body_owner_def_id(anon_const.body); diff --git a/src/tools/clippy/clippy_lints/src/error_impl_error.rs b/src/tools/clippy/clippy_lints/src/error_impl_error.rs index 1e6447dc253..6525648efb1 100644 --- a/src/tools/clippy/clippy_lints/src/error_impl_error.rs +++ b/src/tools/clippy/clippy_lints/src/error_impl_error.rs @@ -37,8 +37,8 @@ declare_lint_pass!(ErrorImplError => [ERROR_IMPL_ERROR]); impl<'tcx> LateLintPass<'tcx> for ErrorImplError { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { match item.kind { - ItemKind::TyAlias(..) - if item.ident.name == sym::Error + ItemKind::TyAlias(ident, ..) + if ident.name == sym::Error && is_visible_outside_module(cx, item.owner_id.def_id) && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() && let Some(error_def_id) = cx.tcx.get_diagnostic_item(sym::Error) @@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError { span_lint( cx, ERROR_IMPL_ERROR, - item.ident.span, + ident.span, "exported type alias named `Error` that implements `Error`", ); }, diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index 9298f56b68b..de0fc2b1bf4 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -91,7 +91,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal { } // find `self` ty for this trait if relevant - if let ItemKind::Trait(_, _, _, _, items) = item.kind { + if let ItemKind::Trait(_, _, _, _, _, items) = item.kind { for trait_item in items { if trait_item.id.owner_id.def_id == fn_def_id { // be sure we have `self` parameter in this function @@ -162,25 +162,23 @@ impl<'tcx> Delegate<'tcx> for EscapeDelegate<'_, 'tcx> { } fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId) { - if cmt.place.projections.is_empty() { - if is_argument(self.cx.tcx, cmt.hir_id) { - // Skip closure arguments - let parent_id = self.cx.tcx.parent_hir_id(cmt.hir_id); - if let Node::Expr(..) = self.cx.tcx.parent_hir_node(parent_id) { - return; - } + if cmt.place.projections.is_empty() && is_argument(self.cx.tcx, cmt.hir_id) { + // Skip closure arguments + let parent_id = self.cx.tcx.parent_hir_id(cmt.hir_id); + if let Node::Expr(..) = self.cx.tcx.parent_hir_node(parent_id) { + return; + } - // skip if there is a `self` parameter binding to a type - // that contains `Self` (i.e.: `self: Box<Self>`), see #4804 - if let Some(trait_self_ty) = self.trait_self_ty { - if self.cx.tcx.hir_name(cmt.hir_id) == kw::SelfLower && cmt.place.ty().contains(trait_self_ty) { - return; - } + // skip if there is a `self` parameter binding to a type + // that contains `Self` (i.e.: `self: Box<Self>`), see #4804 + if let Some(trait_self_ty) = self.trait_self_ty { + if self.cx.tcx.hir_name(cmt.hir_id) == kw::SelfLower && cmt.place.ty().contains(trait_self_ty) { + return; } + } - if is_non_trait_box(cmt.place.ty()) && !self.is_large_box(cmt.place.ty()) { - self.set.insert(cmt.hir_id); - } + if is_non_trait_box(cmt.place.ty()) && !self.is_large_box(cmt.place.ty()) { + self.set.insert(cmt.hir_id); } } } diff --git a/src/tools/clippy/clippy_lints/src/excessive_bools.rs b/src/tools/clippy/clippy_lints/src/excessive_bools.rs index 54a1ac21c85..38d115b878c 100644 --- a/src/tools/clippy/clippy_lints/src/excessive_bools.rs +++ b/src/tools/clippy/clippy_lints/src/excessive_bools.rs @@ -15,12 +15,17 @@ declare_clippy_lint! { /// use of bools in structs. /// /// ### Why is this bad? - /// Excessive bools in a struct - /// is often a sign that it's used as a state machine, - /// which is much better implemented as an enum. - /// If it's not the case, excessive bools usually benefit - /// from refactoring into two-variant enums for better - /// readability and API. + /// Excessive bools in a struct is often a sign that + /// the type is being used to represent a state + /// machine, which is much better implemented as an + /// enum. + /// + /// The reason an enum is better for state machines + /// over structs is that enums more easily forbid + /// invalid states. + /// + /// Structs with too many booleans may benefit from refactoring + /// into multi variant enums for better readability and API. /// /// ### Example /// ```no_run @@ -122,7 +127,7 @@ fn check_fn_decl(cx: &LateContext<'_>, decl: &FnDecl<'_>, sp: Span, max: u64) { impl<'tcx> LateLintPass<'tcx> for ExcessiveBools { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { - if let ItemKind::Struct(variant_data, _) = &item.kind + if let ItemKind::Struct(_, variant_data, _) = &item.kind && variant_data.fields().len() as u64 > self.max_struct_bools && has_n_bools( variant_data.fields().iter().map(|field| field.ty), diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs index 591912cc8d5..5a74e97c97c 100644 --- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs +++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs @@ -76,7 +76,7 @@ impl LateLintPass<'_> for ExhaustiveItems { "exported enums should not be exhaustive", [].as_slice(), ), - ItemKind::Struct(v, ..) => ( + ItemKind::Struct(_, v, ..) => ( EXHAUSTIVE_STRUCTS, "exported structs should not be exhaustive", v.fields(), diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs index fc5f76179f9..3862ff7921d 100644 --- a/src/tools/clippy/clippy_lints/src/format_args.rs +++ b/src/tools/clippy/clippy_lints/src/format_args.rs @@ -9,7 +9,7 @@ use clippy_utils::macros::{ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::{SpanRangeExt, snippet}; use clippy_utils::ty::{implements_trait, is_type_lang_item}; -use clippy_utils::{is_diag_trait_item, is_from_proc_macro}; +use clippy_utils::{is_diag_trait_item, is_from_proc_macro, is_in_test}; use itertools::Itertools; use rustc_ast::{ FormatArgPosition, FormatArgPositionKind, FormatArgsPiece, FormatArgumentKind, FormatCount, FormatOptions, @@ -484,7 +484,8 @@ impl<'tcx> FormatArgsExpr<'_, 'tcx> { fn check_unnecessary_debug_formatting(&self, name: Symbol, value: &Expr<'tcx>) { let cx = self.cx; - if !value.span.from_expansion() + if !is_in_test(cx.tcx, value.hir_id) + && !value.span.from_expansion() && !is_from_proc_macro(cx, value) && let ty = cx.typeck_results().expr_ty(value) && self.can_display_format(ty) diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs index 6da5567d9c7..be887b03ae4 100644 --- a/src/tools/clippy/clippy_lints/src/from_over_into.rs +++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs @@ -176,8 +176,8 @@ fn convert_to_from( return None; }; let body = cx.tcx.hir_body(body_id); - let [input] = body.params else { return None }; - let PatKind::Binding(.., self_ident, None) = input.pat.kind else { + let [self_param] = body.params else { return None }; + let PatKind::Binding(.., self_ident, None) = self_param.pat.kind else { return None; }; @@ -194,12 +194,12 @@ fn convert_to_from( // impl Into<T> for U -> impl Into<T> for T // ~ ~ (self_ty.span, into.to_owned()), - // fn into(self) -> T -> fn from(self) -> T - // ~~~~ ~~~~ + // fn into(self: U) -> T -> fn from(self) -> T + // ~~~~ ~~~~ (impl_item.ident.span, String::from("from")), - // fn into([mut] self) -> T -> fn into([mut] v: T) -> T - // ~~~~ ~~~~ - (self_ident.span, format!("val: {from}")), + // fn into([mut] self: U) -> T -> fn into([mut] val: T) -> T + // ~~~~~~~ ~~~~~~ + (self_ident.span.to(self_param.ty_span), format!("val: {from}")), ]; if let FnRetTy::Return(_) = sig.decl.output { diff --git a/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs index 5ad83f886e2..041f6228fba 100644 --- a/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs +++ b/src/tools/clippy/clippy_lints/src/functions/renamed_function_params.rs @@ -5,7 +5,7 @@ use rustc_hir::hir_id::OwnerId; use rustc_hir::{Impl, ImplItem, ImplItemKind, ImplItemRef, ItemKind, Node, TraitRef}; use rustc_lint::LateContext; use rustc_span::Span; -use rustc_span::symbol::{Ident, Symbol, kw}; +use rustc_span::symbol::{Ident, kw}; use super::RENAMED_FUNCTION_PARAMS; @@ -51,22 +51,33 @@ struct RenamedFnArgs(Vec<(Span, String)>); impl RenamedFnArgs { /// Comparing between an iterator of default names and one with current names, /// then collect the ones that got renamed. - fn new<I, T>(default_names: &mut I, current_names: &mut T) -> Self + fn new<I1, I2>(default_idents: &mut I1, current_idents: &mut I2) -> Self where - I: Iterator<Item = Ident>, - T: Iterator<Item = Ident>, + I1: Iterator<Item = Option<Ident>>, + I2: Iterator<Item = Option<Ident>>, { let mut renamed: Vec<(Span, String)> = vec![]; - debug_assert!(default_names.size_hint() == current_names.size_hint()); - while let (Some(def_name), Some(cur_name)) = (default_names.next(), current_names.next()) { - let current_name = cur_name.name; - let default_name = def_name.name; - if is_unused_or_empty_symbol(current_name) || is_unused_or_empty_symbol(default_name) { - continue; - } - if current_name != default_name { - renamed.push((cur_name.span, default_name.to_string())); + debug_assert!(default_idents.size_hint() == current_idents.size_hint()); + while let (Some(default_ident), Some(current_ident)) = + (default_idents.next(), current_idents.next()) + { + let has_name_to_check = |ident: Option<Ident>| { + if let Some(ident) = ident + && ident.name != kw::Underscore + && !ident.name.as_str().starts_with('_') + { + Some(ident) + } else { + None + } + }; + + if let Some(default_ident) = has_name_to_check(default_ident) + && let Some(current_ident) = has_name_to_check(current_ident) + && default_ident.name != current_ident.name + { + renamed.push((current_ident.span, default_ident.to_string())); } } @@ -83,14 +94,6 @@ impl RenamedFnArgs { } } -fn is_unused_or_empty_symbol(symbol: Symbol) -> bool { - // FIXME: `body_param_names` currently returning empty symbols for `wild` as well, - // so we need to check if the symbol is empty first. - // Therefore the check of whether it's equal to [`kw::Underscore`] has no use for now, - // but it would be nice to keep it here just to be future-proof. - symbol.is_empty() || symbol == kw::Underscore || symbol.as_str().starts_with('_') -} - /// Get the [`trait_item_def_id`](ImplItemRef::trait_item_def_id) of a relevant impl item. fn trait_item_def_id_of_impl(items: &[ImplItemRef], target: OwnerId) -> Option<DefId> { items.iter().find_map(|item| { diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs index cade56f5822..07a92a4ed70 100644 --- a/src/tools/clippy/clippy_lints/src/functions/result.rs +++ b/src/tools/clippy/clippy_lints/src/functions/result.rs @@ -103,7 +103,7 @@ fn check_result_large_err<'tcx>(cx: &LateContext<'tcx>, err_ty: Ty<'tcx>, hir_ty .did() .as_local() && let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(local_def_id) - && let hir::ItemKind::Enum(ref def, _) = item.kind + && let hir::ItemKind::Enum(_, ref def, _) = item.kind { let variants_size = AdtVariantInfo::new(cx, *adt, subst); if let Some((first_variant, variants)) = variants_size.split_first() diff --git a/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs b/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs index 54b8adbc8ac..e4ace3bdabf 100644 --- a/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/ignored_unit_patterns.rs @@ -17,15 +17,15 @@ declare_clippy_lint! { /// ### Example /// ```no_run /// match std::fs::create_dir("tmp-work-dir") { - /// Ok(_) => println!("Working directory created"), - /// Err(s) => eprintln!("Could not create directory: {s}"), + /// Ok(_) => println!("Working directory created"), + /// Err(s) => eprintln!("Could not create directory: {s}"), /// } /// ``` /// Use instead: /// ```no_run /// match std::fs::create_dir("tmp-work-dir") { - /// Ok(()) => println!("Working directory created"), - /// Err(s) => eprintln!("Could not create directory: {s}"), + /// Ok(()) => println!("Working directory created"), + /// Err(s) => eprintln!("Could not create directory: {s}"), /// } /// ``` #[clippy::version = "1.73.0"] diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs index f2d16ff2e56..cbc3e2ccd5b 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs @@ -1,14 +1,14 @@ use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::msrvs::{self, Msrv}; -use clippy_utils::source::snippet_opt; +use clippy_utils::sugg::{Sugg, make_binop}; use clippy_utils::{ - SpanlessEq, higher, is_in_const_context, is_integer_literal, path_to_local, peel_blocks, peel_blocks_with_stmt, + SpanlessEq, eq_expr_value, higher, is_in_const_context, is_integer_literal, peel_blocks, peel_blocks_with_stmt, }; use rustc_ast::ast::LitKind; use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; -use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, HirId, QPath}; +use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::Span; @@ -170,22 +170,20 @@ fn check_gt( cx: &LateContext<'_>, condition_span: Span, expr_span: Span, - big_var: &Expr<'_>, - little_var: &Expr<'_>, + big_expr: &Expr<'_>, + little_expr: &Expr<'_>, if_block: &Expr<'_>, else_block: &Expr<'_>, msrv: Msrv, is_composited: bool, ) { - if let Some(big_var) = Var::new(big_var) - && let Some(little_var) = Var::new(little_var) - { + if is_side_effect_free(cx, big_expr) && is_side_effect_free(cx, little_expr) { check_subtraction( cx, condition_span, expr_span, - big_var, - little_var, + big_expr, + little_expr, if_block, else_block, msrv, @@ -194,18 +192,8 @@ fn check_gt( } } -struct Var { - span: Span, - hir_id: HirId, -} - -impl Var { - fn new(expr: &Expr<'_>) -> Option<Self> { - path_to_local(expr).map(|hir_id| Self { - span: expr.span, - hir_id, - }) - } +fn is_side_effect_free(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + eq_expr_value(cx, expr, expr) } #[allow(clippy::too_many_arguments)] @@ -213,8 +201,8 @@ fn check_subtraction( cx: &LateContext<'_>, condition_span: Span, expr_span: Span, - big_var: Var, - little_var: Var, + big_expr: &Expr<'_>, + little_expr: &Expr<'_>, if_block: &Expr<'_>, else_block: &Expr<'_>, msrv: Msrv, @@ -234,8 +222,8 @@ fn check_subtraction( cx, condition_span, expr_span, - little_var, - big_var, + little_expr, + big_expr, else_block, if_block, msrv, @@ -247,17 +235,15 @@ fn check_subtraction( && let ExprKind::Binary(op, left, right) = if_block.kind && let BinOpKind::Sub = op.node { - let local_left = path_to_local(left); - let local_right = path_to_local(right); - if Some(big_var.hir_id) == local_left && Some(little_var.hir_id) == local_right { + if eq_expr_value(cx, left, big_expr) && eq_expr_value(cx, right, little_expr) { // This part of the condition is voluntarily split from the one before to ensure that // if `snippet_opt` fails, it won't try the next conditions. - if let Some(big_var_snippet) = snippet_opt(cx, big_var.span) - && let Some(little_var_snippet) = snippet_opt(cx, little_var.span) - && (!is_in_const_context(cx) || msrv.meets(cx, msrvs::SATURATING_SUB_CONST)) + if (!is_in_const_context(cx) || msrv.meets(cx, msrvs::SATURATING_SUB_CONST)) + && let Some(big_expr_sugg) = Sugg::hir_opt(cx, big_expr).map(Sugg::maybe_par) + && let Some(little_expr_sugg) = Sugg::hir_opt(cx, little_expr) { let sugg = format!( - "{}{big_var_snippet}.saturating_sub({little_var_snippet}){}", + "{}{big_expr_sugg}.saturating_sub({little_expr_sugg}){}", if is_composited { "{ " } else { "" }, if is_composited { " }" } else { "" } ); @@ -271,11 +257,12 @@ fn check_subtraction( Applicability::MachineApplicable, ); } - } else if Some(little_var.hir_id) == local_left - && Some(big_var.hir_id) == local_right - && let Some(big_var_snippet) = snippet_opt(cx, big_var.span) - && let Some(little_var_snippet) = snippet_opt(cx, little_var.span) + } else if eq_expr_value(cx, left, little_expr) + && eq_expr_value(cx, right, big_expr) + && let Some(big_expr_sugg) = Sugg::hir_opt(cx, big_expr) + && let Some(little_expr_sugg) = Sugg::hir_opt(cx, little_expr) { + let sugg = make_binop(BinOpKind::Sub, &big_expr_sugg, &little_expr_sugg); span_lint_and_then( cx, INVERTED_SATURATING_SUB, @@ -284,12 +271,12 @@ fn check_subtraction( |diag| { diag.span_note( if_block.span, - format!("this subtraction underflows when `{little_var_snippet} < {big_var_snippet}`"), + format!("this subtraction underflows when `{little_expr_sugg} < {big_expr_sugg}`"), ); diag.span_suggestion( if_block.span, "try replacing it with", - format!("{big_var_snippet} - {little_var_snippet}"), + format!("{sugg}"), Applicability::MaybeIncorrect, ); }, diff --git a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs index 12dfb14c454..e55edb1fcaa 100644 --- a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs +++ b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs @@ -4,12 +4,12 @@ use clippy_utils::is_in_test; use clippy_utils::msrvs::Msrv; use rustc_attr_parsing::{RustcVersion, StabilityLevel, StableSince}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::{Expr, ExprKind, HirId}; +use rustc_hir::{Expr, ExprKind, HirId, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::TyCtxt; use rustc_session::impl_lint_pass; use rustc_span::def_id::DefId; -use rustc_span::{ExpnKind, Span}; +use rustc_span::{ExpnKind, Span, sym}; declare_clippy_lint! { /// ### What it does @@ -93,6 +93,21 @@ impl IncompatibleMsrv { // Intentionally not using `.from_expansion()`, since we do still care about macro expansions return; } + + // Functions coming from `core` while expanding a macro such as `assert*!()` get to cheat too: the + // macros may have existed prior to the checked MSRV, but their expansion with a recent compiler + // might use recent functions or methods. Compiling with an older compiler would not use those. + if span.from_expansion() + && cx.tcx.crate_name(def_id.krate) == sym::core + && span + .ctxt() + .outer_expn_data() + .macro_def_id + .is_some_and(|def_id| cx.tcx.crate_name(def_id.krate) == sym::core) + { + return; + } + if (self.check_in_tests || !is_in_test(cx.tcx, node)) && let Some(current) = self.msrv.current(cx) && let version = self.get_def_id_version(cx.tcx, def_id) @@ -118,8 +133,11 @@ impl<'tcx> LateLintPass<'tcx> for IncompatibleMsrv { self.emit_lint_if_under_msrv(cx, method_did, expr.hir_id, span); } }, - ExprKind::Call(call, [_]) => { - if let ExprKind::Path(qpath) = call.kind + ExprKind::Call(call, _) => { + // Desugaring into function calls by the compiler will use `QPath::LangItem` variants. Those should + // not be linted as they will not be generated in older compilers if the function is not available, + // and the compiler is allowed to call unstable functions. + if let ExprKind::Path(qpath @ (QPath::Resolved(..) | QPath::TypeRelative(..))) = call.kind && let Some(path_def_id) = cx.qpath_res(&qpath, call.hir_id).opt_def_id() { self.emit_lint_if_under_msrv(cx, path_def_id, expr.hir_id, call.span); diff --git a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs index 6a436fb4a9d..da5ca5e6772 100644 --- a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs +++ b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs @@ -32,11 +32,7 @@ declare_lint_pass!(InlineFnWithoutBody => [INLINE_FN_WITHOUT_BODY]); impl<'tcx> LateLintPass<'tcx> for InlineFnWithoutBody { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { if let TraitItemKind::Fn(_, TraitFn::Required(_)) = item.kind - && let Some(attr) = cx - .tcx - .hir_attrs(item.hir_id()) - .iter() - .find(|a| a.has_name(sym::inline)) + && let Some(attr) = cx.tcx.hir_attrs(item.hir_id()).iter().find(|a| a.has_name(sym::inline)) { span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs index 6363f717a5c..977fd5fce15 100644 --- a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs +++ b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs @@ -8,7 +8,6 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::{EnumDef, FieldDef, Item, ItemKind, OwnerId, Variant, VariantData}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; -use rustc_span::Span; use rustc_span::symbol::Symbol; declare_clippy_lint! { @@ -196,80 +195,176 @@ fn have_no_extra_prefix(prefixes: &[&str]) -> bool { prefixes.iter().all(|p| p == &"" || p == &"_") } -fn check_fields(cx: &LateContext<'_>, threshold: u64, item: &Item<'_>, fields: &[FieldDef<'_>]) { - if (fields.len() as u64) < threshold { - return; - } +impl ItemNameRepetitions { + /// Lint the names of enum variants against the name of the enum. + fn check_variants(&self, cx: &LateContext<'_>, item: &Item<'_>, def: &EnumDef<'_>) { + if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(item.owner_id.def_id) { + return; + } - check_struct_name_repetition(cx, item, fields); + if (def.variants.len() as u64) < self.enum_threshold { + return; + } - // if the SyntaxContext of the identifiers of the fields and struct differ dont lint them. - // this prevents linting in macros in which the location of the field identifier names differ - if !fields.iter().all(|field| item.ident.span.eq_ctxt(field.ident.span)) { - return; + let Some(ident) = item.kind.ident() else { + return; + }; + let item_name = ident.name.as_str(); + for var in def.variants { + check_enum_start(cx, item_name, var); + check_enum_end(cx, item_name, var); + } + + Self::check_enum_common_affix(cx, item, def); } - let mut pre: Vec<&str> = match fields.first() { - Some(first_field) => first_field.ident.name.as_str().split('_').collect(), - None => return, - }; - let mut post = pre.clone(); - post.reverse(); - for field in fields { - let field_split: Vec<&str> = field.ident.name.as_str().split('_').collect(); - if field_split.len() == 1 { + /// Lint the names of struct fields against the name of the struct. + fn check_fields(&self, cx: &LateContext<'_>, item: &Item<'_>, fields: &[FieldDef<'_>]) { + if (fields.len() as u64) < self.struct_threshold { return; } - pre = pre - .into_iter() - .zip(field_split.iter()) - .take_while(|(a, b)| &a == b) - .map(|e| e.0) - .collect(); - post = post - .into_iter() - .zip(field_split.iter().rev()) - .take_while(|(a, b)| &a == b) - .map(|e| e.0) - .collect(); + self.check_struct_name_repetition(cx, item, fields); + self.check_struct_common_affix(cx, item, fields); } - let prefix = pre.join("_"); - post.reverse(); - let postfix = match post.last() { - Some(&"") => post.join("_") + "_", - Some(_) | None => post.join("_"), - }; - if fields.len() > 1 { - let (what, value) = match ( - prefix.is_empty() || prefix.chars().all(|c| c == '_'), - postfix.is_empty(), - ) { - (true, true) => return, - (false, _) => ("pre", prefix), - (true, false) => ("post", postfix), + + fn check_enum_common_affix(cx: &LateContext<'_>, item: &Item<'_>, def: &EnumDef<'_>) { + let first = match def.variants.first() { + Some(variant) => variant.ident.name.as_str(), + None => return, }; - if fields.iter().all(|field| is_bool(field.ty)) { - // If all fields are booleans, we don't want to emit this lint. - return; + let mut pre = camel_case_split(first); + let mut post = pre.clone(); + post.reverse(); + for var in def.variants { + let name = var.ident.name.as_str(); + + let variant_split = camel_case_split(name); + if variant_split.len() == 1 { + return; + } + + pre = pre + .iter() + .zip(variant_split.iter()) + .take_while(|(a, b)| a == b) + .map(|e| *e.0) + .collect(); + post = post + .iter() + .zip(variant_split.iter().rev()) + .take_while(|(a, b)| a == b) + .map(|e| *e.0) + .collect(); } + let (what, value) = match (have_no_extra_prefix(&pre), post.is_empty()) { + (true, true) => return, + (false, _) => ("pre", pre.join("")), + (true, false) => { + post.reverse(); + ("post", post.join("")) + }, + }; span_lint_and_help( cx, - STRUCT_FIELD_NAMES, + ENUM_VARIANT_NAMES, item.span, - format!("all fields have the same {what}fix: `{value}`"), + format!("all variants have the same {what}fix: `{value}`"), None, - format!("remove the {what}fixes"), + format!( + "remove the {what}fixes and use full paths to \ + the variants instead of glob imports" + ), ); } -} -fn check_struct_name_repetition(cx: &LateContext<'_>, item: &Item<'_>, fields: &[FieldDef<'_>]) { - let snake_name = to_snake_case(item.ident.name.as_str()); - let item_name_words: Vec<&str> = snake_name.split('_').collect(); - for field in fields { - if field.ident.span.eq_ctxt(item.ident.span) { - //consider linting only if the field identifier has the same SyntaxContext as the item(struct) + fn check_struct_common_affix(&self, cx: &LateContext<'_>, item: &Item<'_>, fields: &[FieldDef<'_>]) { + // if the SyntaxContext of the identifiers of the fields and struct differ dont lint them. + // this prevents linting in macros in which the location of the field identifier names differ + if !fields + .iter() + .all(|field| item.kind.ident().is_some_and(|i| i.span.eq_ctxt(field.ident.span))) + { + return; + } + + if self.avoid_breaking_exported_api + && fields + .iter() + .any(|field| cx.effective_visibilities.is_exported(field.def_id)) + { + return; + } + + let mut pre: Vec<&str> = match fields.first() { + Some(first_field) => first_field.ident.name.as_str().split('_').collect(), + None => return, + }; + let mut post = pre.clone(); + post.reverse(); + for field in fields { + let field_split: Vec<&str> = field.ident.name.as_str().split('_').collect(); + if field_split.len() == 1 { + return; + } + + pre = pre + .into_iter() + .zip(field_split.iter()) + .take_while(|(a, b)| &a == b) + .map(|e| e.0) + .collect(); + post = post + .into_iter() + .zip(field_split.iter().rev()) + .take_while(|(a, b)| &a == b) + .map(|e| e.0) + .collect(); + } + let prefix = pre.join("_"); + post.reverse(); + let postfix = match post.last() { + Some(&"") => post.join("_") + "_", + Some(_) | None => post.join("_"), + }; + if fields.len() > 1 { + let (what, value) = match ( + prefix.is_empty() || prefix.chars().all(|c| c == '_'), + postfix.is_empty(), + ) { + (true, true) => return, + (false, _) => ("pre", prefix), + (true, false) => ("post", postfix), + }; + if fields.iter().all(|field| is_bool(field.ty)) { + // If all fields are booleans, we don't want to emit this lint. + return; + } + span_lint_and_help( + cx, + STRUCT_FIELD_NAMES, + item.span, + format!("all fields have the same {what}fix: `{value}`"), + None, + format!("remove the {what}fixes"), + ); + } + } + + fn check_struct_name_repetition(&self, cx: &LateContext<'_>, item: &Item<'_>, fields: &[FieldDef<'_>]) { + let Some(ident) = item.kind.ident() else { return }; + let snake_name = to_snake_case(ident.name.as_str()); + let item_name_words: Vec<&str> = snake_name.split('_').collect(); + for field in fields { + if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(field.def_id) { + continue; + } + + if !field.ident.span.eq_ctxt(ident.span) { + // consider linting only if the field identifier has the same SyntaxContext as the item(struct) + continue; + } + let field_words: Vec<&str> = field.ident.name.as_str().split('_').collect(); if field_words.len() >= item_name_words.len() { // if the field name is shorter than the struct name it cannot contain it @@ -337,79 +432,24 @@ fn check_enum_end(cx: &LateContext<'_>, item_name: &str, variant: &Variant<'_>) } } -fn check_variant(cx: &LateContext<'_>, threshold: u64, def: &EnumDef<'_>, item_name: &str, span: Span) { - if (def.variants.len() as u64) < threshold { - return; - } - - for var in def.variants { - check_enum_start(cx, item_name, var); - check_enum_end(cx, item_name, var); - } - - let first = match def.variants.first() { - Some(variant) => variant.ident.name.as_str(), - None => return, - }; - let mut pre = camel_case_split(first); - let mut post = pre.clone(); - post.reverse(); - for var in def.variants { - let name = var.ident.name.as_str(); - - let variant_split = camel_case_split(name); - if variant_split.len() == 1 { - return; - } - - pre = pre - .iter() - .zip(variant_split.iter()) - .take_while(|(a, b)| a == b) - .map(|e| *e.0) - .collect(); - post = post - .iter() - .zip(variant_split.iter().rev()) - .take_while(|(a, b)| a == b) - .map(|e| *e.0) - .collect(); - } - let (what, value) = match (have_no_extra_prefix(&pre), post.is_empty()) { - (true, true) => return, - (false, _) => ("pre", pre.join("")), - (true, false) => { - post.reverse(); - ("post", post.join("")) - }, - }; - span_lint_and_help( - cx, - ENUM_VARIANT_NAMES, - span, - format!("all variants have the same {what}fix: `{value}`"), - None, - format!( - "remove the {what}fixes and use full paths to \ - the variants instead of glob imports" - ), - ); -} - impl LateLintPass<'_> for ItemNameRepetitions { - fn check_item_post(&mut self, _cx: &LateContext<'_>, _item: &Item<'_>) { + fn check_item_post(&mut self, _cx: &LateContext<'_>, item: &Item<'_>) { + let Some(_ident) = item.kind.ident() else { return }; + let last = self.modules.pop(); assert!(last.is_some()); } fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { - let item_name = item.ident.name.as_str(); + let Some(ident) = item.kind.ident() else { return }; + + let item_name = ident.name.as_str(); let item_camel = to_camel_case(item_name); if !item.span.from_expansion() && is_present_in_source(cx, item.span) { if let [.., (mod_name, mod_camel, mod_owner_id)] = &*self.modules { // constants don't have surrounding modules if !mod_camel.is_empty() { - if mod_name == &item.ident.name + if mod_name == &ident.name && let ItemKind::Mod(..) = item.kind && (!self.allow_private_module_inception || cx.tcx.visibility(mod_owner_id.def_id).is_public()) { @@ -438,7 +478,7 @@ impl LateLintPass<'_> for ItemNameRepetitions { Some(c) if is_word_beginning(c) => span_lint( cx, MODULE_NAME_REPETITIONS, - item.ident.span, + ident.span, "item name starts with its containing module's name", ), _ => (), @@ -450,7 +490,7 @@ impl LateLintPass<'_> for ItemNameRepetitions { span_lint( cx, MODULE_NAME_REPETITIONS, - item.ident.span, + ident.span, "item name ends with its containing module's name", ); } @@ -458,17 +498,18 @@ impl LateLintPass<'_> for ItemNameRepetitions { } } } - if !(self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(item.owner_id.def_id)) - && span_is_local(item.span) - { + + if span_is_local(item.span) { match item.kind { - ItemKind::Enum(def, _) => check_variant(cx, self.enum_threshold, &def, item_name, item.span), - ItemKind::Struct(VariantData::Struct { fields, .. }, _) => { - check_fields(cx, self.struct_threshold, item, fields); + ItemKind::Enum(_, def, _) => { + self.check_variants(cx, item, &def); + }, + ItemKind::Struct(_, VariantData::Struct { fields, .. }, _) => { + self.check_fields(cx, item, fields); }, _ => (), } } - self.modules.push((item.ident.name, item_camel, item.owner_id)); + self.modules.push((ident.name, item_camel, item.owner_id)); } } diff --git a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs index 9df044f25eb..dd63de288b8 100644 --- a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs +++ b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs @@ -44,7 +44,7 @@ declare_clippy_lint! { declare_lint_pass!(ItemsAfterTestModule => [ITEMS_AFTER_TEST_MODULE]); fn cfg_test_module<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool { - if let ItemKind::Mod(test_mod) = item.kind + if let ItemKind::Mod(_, test_mod) = item.kind && item.span.hi() == test_mod.spans.inner_span.hi() && is_cfg_test(cx.tcx, item.hir_id()) && !item.span.from_expansion() @@ -67,14 +67,20 @@ impl LateLintPass<'_> for ItemsAfterTestModule { let after: Vec<_> = items .filter(|item| { // Ignore the generated test main function - !(item.ident.name == sym::main - && item.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::TestHarness)) + if let ItemKind::Fn { ident, .. } = item.kind + && ident.name == sym::main + && item.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::TestHarness) + { + false + } else { + true + } }) .collect(); if let Some(last) = after.last() && after.iter().all(|&item| { - !matches!(item.kind, ItemKind::Mod(_)) && !item.span.from_expansion() && !is_from_proc_macro(cx, item) + !matches!(item.kind, ItemKind::Mod(..)) && !item.span.from_expansion() && !is_from_proc_macro(cx, item) }) && !fulfill_or_allowed(cx, ITEMS_AFTER_TEST_MODULE, after.iter().map(|item| item.hir_id())) { diff --git a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs index 4bc6ad0798c..753360906d6 100644 --- a/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs +++ b/src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs @@ -28,9 +28,9 @@ declare_clippy_lint! { /// use std::str::Chars; /// struct Data {} /// impl Data { - /// fn iter(&self) -> Chars<'static> { - /// todo!() - /// } + /// fn iter(&self) -> Chars<'static> { + /// todo!() + /// } /// } /// ``` #[clippy::version = "1.57.0"] diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs index cabf10b7e0e..394005e9912 100644 --- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs @@ -48,7 +48,7 @@ impl_lint_pass!(LargeConstArrays => [LARGE_CONST_ARRAYS]); impl<'tcx> LateLintPass<'tcx> for LargeConstArrays { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if let ItemKind::Const(_, generics, _) = &item.kind + if let ItemKind::Const(ident, _, generics, _) = &item.kind // Since static items may not have generics, skip generic const items. // FIXME(generic_const_items): I don't think checking `generics.hwcp` suffices as it // doesn't account for empty where-clauses that only consist of keyword `where` IINM. @@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays { && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes()) && u128::from(self.maximum_allowed_size) < u128::from(element_count) * u128::from(element_size) { - let hi_pos = item.ident.span.lo() - BytePos::from_usize(1); + let hi_pos = ident.span.lo() - BytePos::from_usize(1); let sugg_span = Span::new( hi_pos - BytePos::from_usize("const".len()), hi_pos, diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs index d9953dbc261..d08efa0ec9c 100644 --- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs +++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs @@ -73,7 +73,7 @@ impl_lint_pass!(LargeEnumVariant => [LARGE_ENUM_VARIANT]); impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &Item<'tcx>) { - if let ItemKind::Enum(ref def, _) = item.kind + if let ItemKind::Enum(ident, ref def, _) = item.kind && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() && let ty::Adt(adt, subst) = ty.kind() && adt.variants().len() > 1 @@ -114,7 +114,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant { let mut applicability = Applicability::MaybeIncorrect; if is_copy(cx, ty) || maybe_copy(cx, ty) { diag.span_note( - item.ident.span, + ident.span, "boxing a variant would require the type no longer be `Copy`", ); } else { diff --git a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs index 3939318bee6..01b49403cac 100644 --- a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs +++ b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs @@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { // Integer modules are "TBD" deprecated, and the contents are too, // so lint on the `use` statement directly. - if let ItemKind::Use(path, kind @ (UseKind::Single | UseKind::Glob)) = item.kind + if let ItemKind::Use(path, kind @ (UseKind::Single(_) | UseKind::Glob)) = item.kind && !item.span.in_external_macro(cx.sess().source_map()) && let Some(def_id) = path.res[0].opt_def_id() && self.msrv.meets(cx, msrvs::NUMERIC_ASSOCIATED_CONSTANTS) @@ -72,7 +72,9 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { "importing a legacy numeric constant" }, |diag| { - if item.ident.name == kw::Underscore { + if let UseKind::Single(ident) = kind + && ident.name == kw::Underscore + { diag.help("remove this import"); return; } diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 98ba52f1270..72e22ae59d8 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -17,7 +17,7 @@ use rustc_middle::ty::{self, AssocKind, FnSig, Ty}; use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; -use rustc_span::{Span, Symbol}; +use rustc_span::{Ident, Span, Symbol}; use rustc_trait_selection::traits::supertrait_def_ids; declare_clippy_lint! { @@ -123,10 +123,10 @@ declare_lint_pass!(LenZero => [LEN_ZERO, LEN_WITHOUT_IS_EMPTY, COMPARISON_TO_EMP impl<'tcx> LateLintPass<'tcx> for LenZero { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { - if let ItemKind::Trait(_, _, _, _, trait_items) = item.kind + if let ItemKind::Trait(_, _, ident, _, _, trait_items) = item.kind && !item.span.from_expansion() { - check_trait_items(cx, item, trait_items); + check_trait_items(cx, item, ident, trait_items); } } @@ -150,10 +150,10 @@ impl<'tcx> LateLintPass<'tcx> for LenZero { let (name, kind) = match cx.tcx.hir_node(ty_hir_id) { Node::ForeignItem(x) => (x.ident.name, "extern type"), Node::Item(x) => match x.kind { - ItemKind::Struct(..) => (x.ident.name, "struct"), - ItemKind::Enum(..) => (x.ident.name, "enum"), - ItemKind::Union(..) => (x.ident.name, "union"), - _ => (x.ident.name, "type"), + ItemKind::Struct(ident, ..) => (ident.name, "struct"), + ItemKind::Enum(ident, ..) => (ident.name, "enum"), + ItemKind::Union(ident, ..) => (ident.name, "union"), + _ => (x.kind.ident().unwrap().name, "type"), }, _ => return, }; @@ -250,7 +250,7 @@ fn span_without_enclosing_paren(cx: &LateContext<'_>, span: Span) -> Span { } } -fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items: &[TraitItemRef]) { +fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, ident: Ident, trait_items: &[TraitItemRef]) { fn is_named_self(cx: &LateContext<'_>, item: &TraitItemRef, name: Symbol) -> bool { item.ident.name == name && if let AssocItemKind::Fn { has_self } = item.kind { @@ -300,7 +300,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items visited_trait.span, format!( "trait `{}` has a `len` method but no (possibly inherited) `is_empty` method", - visited_trait.ident.name + ident.name ), ); } diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 3dd2de1fafc..8d47c756fc5 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -189,7 +189,7 @@ fn check_fn_inner<'tcx>( cx: &LateContext<'tcx>, sig: &'tcx FnSig<'_>, body: Option<BodyId>, - trait_sig: Option<&[Ident]>, + trait_sig: Option<&[Option<Ident>]>, generics: &'tcx Generics<'_>, span: Span, report_extra_lifetimes: bool, @@ -264,7 +264,7 @@ fn could_use_elision<'tcx>( cx: &LateContext<'tcx>, func: &'tcx FnDecl<'_>, body: Option<BodyId>, - trait_sig: Option<&[Ident]>, + trait_sig: Option<&[Option<Ident>]>, named_generics: &'tcx [GenericParam<'_>], msrv: Msrv, ) -> Option<(Vec<LocalDefId>, Vec<Lifetime>)> { @@ -310,7 +310,7 @@ fn could_use_elision<'tcx>( let body = cx.tcx.hir_body(body_id); let first_ident = body.params.first().and_then(|param| param.pat.simple_ident()); - if non_elidable_self_type(cx, func, first_ident, msrv) { + if non_elidable_self_type(cx, func, Some(first_ident), msrv) { return None; } @@ -384,8 +384,8 @@ fn allowed_lts_from(named_generics: &[GenericParam<'_>]) -> FxIndexSet<LocalDefI } // elision doesn't work for explicit self types before Rust 1.81, see rust-lang/rust#69064 -fn non_elidable_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident: Option<Ident>, msrv: Msrv) -> bool { - if let Some(ident) = ident +fn non_elidable_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident: Option<Option<Ident>>, msrv: Msrv) -> bool { + if let Some(Some(ident)) = ident && ident.name == kw::SelfLower && !func.implicit_self.has_implicit_self() && let Some(self_ty) = func.inputs.first() diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs index ed725a03989..4b0bf5a4b3c 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mod.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs @@ -469,7 +469,7 @@ declare_clippy_lint! { /// let item2 = 3; /// let mut vec: Vec<u8> = Vec::new(); /// for _ in 0..20 { - /// vec.push(item1); + /// vec.push(item1); /// } /// for _ in 0..30 { /// vec.push(item2); diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs index fb5d49a1004..5afcf51167d 100644 --- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs +++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs @@ -129,7 +129,7 @@ impl BreakAfterExprVisitor { }; get_enclosing_block(cx, hir_id).is_some_and(|block| { - visitor.visit_block(block); + let _ = visitor.visit_block(block); visitor.break_after_expr }) } diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs index dd7a6f77acf..c3a2a38b5ec 100644 --- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs @@ -4,11 +4,13 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::higher::ForLoop; use clippy_utils::macros::root_macro_call_first_node; use clippy_utils::source::snippet; +use clippy_utils::visitors::{Descend, for_each_expr_without_closures}; use rustc_errors::Applicability; use rustc_hir::{Block, Destination, Expr, ExprKind, HirId, InlineAsmOperand, Pat, Stmt, StmtKind, StructTailExpr}; use rustc_lint::LateContext; use rustc_span::{Span, sym}; use std::iter::once; +use std::ops::ControlFlow; pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, @@ -24,17 +26,23 @@ pub(super) fn check<'tcx>( arg: iterator, pat, span: for_span, + label, .. }) = for_loop { - // Suggests using an `if let` instead. This is `Unspecified` because the - // loop may (probably) contain `break` statements which would be invalid - // in an `if let`. + // If the block contains a break or continue, or if the loop has a label, `MachineApplicable` is not + // appropriate. + let app = if !contains_any_break_or_continue(block) && label.is_none() { + Applicability::MachineApplicable + } else { + Applicability::Unspecified + }; + diag.span_suggestion_verbose( for_span.with_hi(iterator.span.hi()), "if you need the first element of the iterator, try writing", for_to_if_let_sugg(cx, iterator, pat), - Applicability::Unspecified, + app, ); } }); @@ -43,6 +51,15 @@ pub(super) fn check<'tcx>( } } +fn contains_any_break_or_continue(block: &Block<'_>) -> bool { + for_each_expr_without_closures(block, |e| match e.kind { + ExprKind::Break(..) | ExprKind::Continue(..) => ControlFlow::Break(()), + ExprKind::Loop(..) => ControlFlow::Continue(Descend::No), + _ => ControlFlow::Continue(Descend::Yes), + }) + .is_some() +} + /// The `never_loop` analysis keeps track of three things: /// /// * Has any (reachable) code path hit a `continue` of the main loop? diff --git a/src/tools/clippy/clippy_lints/src/manual_bits.rs b/src/tools/clippy/clippy_lints/src/manual_bits.rs index 39c4857b3e8..40fe8853272 100644 --- a/src/tools/clippy/clippy_lints/src/manual_bits.rs +++ b/src/tools/clippy/clippy_lints/src/manual_bits.rs @@ -14,7 +14,7 @@ use rustc_span::{Span, sym}; declare_clippy_lint! { /// ### What it does - /// Checks for usage of `std::mem::size_of::<T>() * 8` when + /// Checks for usage of `size_of::<T>() * 8` when /// `T::BITS` is available. /// /// ### Why is this bad? @@ -22,7 +22,7 @@ declare_clippy_lint! { /// /// ### Example /// ```no_run - /// std::mem::size_of::<usize>() * 8; + /// size_of::<usize>() * 8; /// ``` /// Use instead: /// ```no_run @@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualBits { cx, MANUAL_BITS, expr.span, - "usage of `mem::size_of::<T>()` to obtain the size of `T` in bits", + "usage of `size_of::<T>()` to obtain the size of `T` in bits", "consider using", sugg, app, diff --git a/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs b/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs index 9c1419175d5..9944c4f8804 100644 --- a/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs +++ b/src/tools/clippy/clippy_lints/src/manual_div_ceil.rs @@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualDivCeil { && check_int_ty_and_feature(cx, div_lhs) && check_int_ty_and_feature(cx, div_rhs) && let ExprKind::Binary(inner_op, inner_lhs, inner_rhs) = div_lhs.kind - && self.msrv.meets(cx, msrvs::MANUAL_DIV_CEIL) + && self.msrv.meets(cx, msrvs::DIV_CEIL) { // (x + (y - 1)) / y if let ExprKind::Binary(sub_op, sub_lhs, sub_rhs) = inner_rhs.kind diff --git a/src/tools/clippy/clippy_lints/src/manual_ignore_case_cmp.rs b/src/tools/clippy/clippy_lints/src/manual_ignore_case_cmp.rs index 506f4f6d9de..d92069edb6d 100644 --- a/src/tools/clippy/clippy_lints/src/manual_ignore_case_cmp.rs +++ b/src/tools/clippy/clippy_lints/src/manual_ignore_case_cmp.rs @@ -29,7 +29,7 @@ declare_clippy_lint! { /// Use instead: /// ```no_run /// fn compare(a: &str, b: &str) -> bool { - /// a.eq_ignore_ascii_case(b) || a.eq_ignore_ascii_case("abc") + /// a.eq_ignore_ascii_case(b) || a.eq_ignore_ascii_case("abc") /// } /// ``` #[clippy::version = "1.84.0"] diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs index 47939767212..d6ac6e106b4 100644 --- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs @@ -5,7 +5,8 @@ use clippy_utils::higher::IfLetOrMatch; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{is_lint_allowed, is_never_expr, msrvs, pat_and_expr_can_be_question_mark, peel_blocks}; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_ast::BindingMode; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatExpr, PatExprKind, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LintContext}; @@ -113,7 +114,7 @@ fn emit_manual_let_else( cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, - ident_map: &FxHashMap<Symbol, &Pat<'_>>, + ident_map: &FxHashMap<Symbol, (&Pat<'_>, BindingMode)>, pat: &Pat<'_>, else_body: &Expr<'_>, ) { @@ -167,7 +168,7 @@ fn emit_manual_let_else( fn replace_in_pattern( cx: &LateContext<'_>, span: Span, - ident_map: &FxHashMap<Symbol, &Pat<'_>>, + ident_map: &FxHashMap<Symbol, (&Pat<'_>, BindingMode)>, pat: &Pat<'_>, app: &mut Applicability, top_level: bool, @@ -185,15 +186,16 @@ fn replace_in_pattern( match pat.kind { PatKind::Binding(_ann, _id, binding_name, opt_subpt) => { - let Some(pat_to_put) = ident_map.get(&binding_name.name) else { + let Some((pat_to_put, binding_mode)) = ident_map.get(&binding_name.name) else { break 'a; }; + let sn_pfx = binding_mode.prefix_str(); let (sn_ptp, _) = snippet_with_context(cx, pat_to_put.span, span.ctxt(), "", app); if let Some(subpt) = opt_subpt { let subpt = replace_in_pattern(cx, span, ident_map, subpt, app, false); - return format!("{sn_ptp} @ {subpt}"); + return format!("{sn_pfx}{sn_ptp} @ {subpt}"); } - return sn_ptp.to_string(); + return format!("{sn_pfx}{sn_ptp}"); }, PatKind::Or(pats) => { let patterns = pats @@ -211,17 +213,18 @@ fn replace_in_pattern( .iter() .map(|fld| { if let PatKind::Binding(_, _, name, None) = fld.pat.kind - && let Some(pat_to_put) = ident_map.get(&name.name) + && let Some((pat_to_put, binding_mode)) = ident_map.get(&name.name) { + let sn_pfx = binding_mode.prefix_str(); let (sn_fld_name, _) = snippet_with_context(cx, fld.ident.span, span.ctxt(), "", app); let (sn_ptp, _) = snippet_with_context(cx, pat_to_put.span, span.ctxt(), "", app); // TODO: this is a bit of a hack, but it does its job. Ideally, we'd check if pat_to_put is // a PatKind::Binding but that is also hard to get right. if sn_fld_name == sn_ptp { // Field init shorthand - return format!("{sn_fld_name}"); + return format!("{sn_pfx}{sn_fld_name}"); } - return format!("{sn_fld_name}: {sn_ptp}"); + return format!("{sn_fld_name}: {sn_pfx}{sn_ptp}"); } let (sn_fld, _) = snippet_with_context(cx, fld.span, span.ctxt(), "", app); sn_fld.into_owned() @@ -334,7 +337,7 @@ fn expr_simple_identity_map<'a, 'hir>( local_pat: &'a Pat<'hir>, let_pat: &'_ Pat<'hir>, expr: &'_ Expr<'hir>, -) -> Option<FxHashMap<Symbol, &'a Pat<'hir>>> { +) -> Option<FxHashMap<Symbol, (&'a Pat<'hir>, BindingMode)>> { let peeled = peel_blocks(expr); let (sub_pats, paths) = match (local_pat.kind, peeled.kind) { (PatKind::Tuple(pats, _), ExprKind::Tup(exprs)) | (PatKind::Slice(pats, ..), ExprKind::Array(exprs)) => { @@ -351,9 +354,9 @@ fn expr_simple_identity_map<'a, 'hir>( return None; } - let mut pat_bindings = FxHashSet::default(); - let_pat.each_binding_or_first(&mut |_ann, _hir_id, _sp, ident| { - pat_bindings.insert(ident); + let mut pat_bindings = FxHashMap::default(); + let_pat.each_binding_or_first(&mut |binding_mode, _hir_id, _sp, ident| { + pat_bindings.insert(ident, binding_mode); }); if pat_bindings.len() < paths.len() { // This rebinds some bindings from the outer scope, or it repeats some copy-able bindings multiple @@ -366,12 +369,10 @@ fn expr_simple_identity_map<'a, 'hir>( for (sub_pat, path) in sub_pats.iter().zip(paths.iter()) { if let ExprKind::Path(QPath::Resolved(_ty, path)) = path.kind && let [path_seg] = path.segments + && let ident = path_seg.ident + && let Some(let_binding_mode) = pat_bindings.remove(&ident) { - let ident = path_seg.ident; - if !pat_bindings.remove(&ident) { - return None; - } - ident_map.insert(ident.name, sub_pat); + ident_map.insert(ident.name, (sub_pat, let_binding_mode)); } else { return None; } diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs index 64b07a5536b..067b92cd46e 100644 --- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs +++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs @@ -87,7 +87,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive { } match item.kind { - ItemKind::Enum(def, _) if def.variants.len() > 1 => { + ItemKind::Enum(_, def, _) if def.variants.len() > 1 => { let iter = def.variants.iter().filter_map(|v| { (matches!(v.data, VariantData::Unit(_, _)) && is_doc_hidden(cx.tcx.hir_attrs(v.hir_id))) .then_some((v.def_id, v.span)) @@ -98,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive { self.potential_enums.push((item.owner_id.def_id, id, item.span, span)); } }, - ItemKind::Struct(variant_data, _) => { + ItemKind::Struct(_, variant_data, _) => { let fields = variant_data.fields(); let private_fields = fields .iter() diff --git a/src/tools/clippy/clippy_lints/src/manual_slice_size_calculation.rs b/src/tools/clippy/clippy_lints/src/manual_slice_size_calculation.rs index 18901f7399d..2dad0fa4925 100644 --- a/src/tools/clippy/clippy_lints/src/manual_slice_size_calculation.rs +++ b/src/tools/clippy/clippy_lints/src/manual_slice_size_calculation.rs @@ -24,12 +24,12 @@ declare_clippy_lint! { /// ### Example /// ```no_run /// # let data : &[i32] = &[1, 2, 3]; - /// let newlen = data.len() * std::mem::size_of::<i32>(); + /// let newlen = data.len() * size_of::<i32>(); /// ``` /// Use instead: /// ```no_run /// # let data : &[i32] = &[1, 2, 3]; - /// let newlen = std::mem::size_of_val(data); + /// let newlen = size_of_val(data); /// ``` #[clippy::version = "1.70.0"] pub MANUAL_SLICE_SIZE_CALCULATION, diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs index 35caa7d1f3a..2b9173e6f41 100644 --- a/src/tools/clippy/clippy_lints/src/matches/mod.rs +++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs @@ -1110,11 +1110,9 @@ impl<'tcx> LateLintPass<'tcx> for Matches { } } } - // If there are still comments, it means they are outside of the arms, therefore - // we should not lint. - if match_comments.is_empty() { - single_match::check(cx, ex, arms, expr); - } + // If there are still comments, it means they are outside of the arms. Tell the lint + // code about it. + single_match::check(cx, ex, arms, expr, !match_comments.is_empty()); match_bool::check(cx, ex, arms, expr); overlapping_arms::check(cx, ex, arms); match_wild_enum::check(cx, ex, arms); diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs index 2f46eaaabb3..56fbd626eef 100644 --- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::{SpanRangeExt, expr_block, snippet, snippet_block_with_context}; use clippy_utils::ty::implements_trait; use clippy_utils::{ @@ -6,7 +6,7 @@ use clippy_utils::{ }; use core::ops::ControlFlow; use rustc_arena::DroplessArena; -use rustc_errors::Applicability; +use rustc_errors::{Applicability, Diag}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{Visitor, walk_pat}; use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatExpr, PatExprKind, PatKind, QPath, StmtKind}; @@ -32,7 +32,7 @@ fn empty_arm_has_comment(cx: &LateContext<'_>, span: Span) -> bool { } #[rustfmt::skip] -pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>], expr: &'tcx Expr<'_>) { +pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>], expr: &'tcx Expr<'_>, contains_comments: bool) { if let [arm1, arm2] = arms && arm1.guard.is_none() && arm2.guard.is_none() @@ -77,15 +77,31 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'_>, arms: &'tc } } - report_single_pattern(cx, ex, arm1, expr, els); + report_single_pattern(cx, ex, arm1, expr, els, contains_comments); } } } -fn report_single_pattern(cx: &LateContext<'_>, ex: &Expr<'_>, arm: &Arm<'_>, expr: &Expr<'_>, els: Option<&Expr<'_>>) { +fn report_single_pattern( + cx: &LateContext<'_>, + ex: &Expr<'_>, + arm: &Arm<'_>, + expr: &Expr<'_>, + els: Option<&Expr<'_>>, + contains_comments: bool, +) { let lint = if els.is_some() { SINGLE_MATCH_ELSE } else { SINGLE_MATCH }; let ctxt = expr.span.ctxt(); - let mut app = Applicability::MachineApplicable; + let note = |diag: &mut Diag<'_, ()>| { + if contains_comments { + diag.note("you might want to preserve the comments from inside the `match`"); + } + }; + let mut app = if contains_comments { + Applicability::MaybeIncorrect + } else { + Applicability::MachineApplicable + }; let els_str = els.map_or(String::new(), |els| { format!(" else {}", expr_block(cx, els, ctxt, "..", Some(expr.span), &mut app)) }); @@ -109,7 +125,10 @@ fn report_single_pattern(cx: &LateContext<'_>, ex: &Expr<'_>, arm: &Arm<'_>, exp } (sugg, "try") }; - span_lint_and_sugg(cx, lint, expr.span, msg, help, sugg.to_string(), app); + span_lint_and_then(cx, lint, expr.span, msg, |diag| { + diag.span_suggestion(expr.span, help, sugg.to_string(), app); + note(diag); + }); return; } @@ -162,7 +181,10 @@ fn report_single_pattern(cx: &LateContext<'_>, ex: &Expr<'_>, arm: &Arm<'_>, exp (msg, sugg) }; - span_lint_and_sugg(cx, lint, expr.span, msg, "try", sugg, app); + span_lint_and_then(cx, lint, expr.span, msg, |diag| { + diag.span_suggestion(expr.span, "try", sugg.to_string(), app); + note(diag); + }); } struct PatVisitor<'tcx> { diff --git a/src/tools/clippy/clippy_lints/src/methods/io_other_error.rs b/src/tools/clippy/clippy_lints/src/methods/io_other_error.rs index 4659e9e163f..bdc834bd47a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/io_other_error.rs +++ b/src/tools/clippy/clippy_lints/src/methods/io_other_error.rs @@ -27,7 +27,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, path: &Expr<'_>, args "use `std::io::Error::other`", vec![ (new_segment.ident.span, "other".to_owned()), - (error_kind.span.until(error.span), String::new()), + (error_kind.span.until(error.span.source_callsite()), String::new()), ], Applicability::MachineApplicable, ); diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 7dde21d3edb..1d9296016e2 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -4447,13 +4447,13 @@ declare_clippy_lint! { /// ### Example /// ```no_run /// fn foo(values: &[u8]) -> bool { - /// values.iter().any(|&v| v == 10) + /// values.iter().any(|&v| v == 10) /// } /// ``` /// Use instead: /// ```no_run /// fn foo(values: &[u8]) -> bool { - /// values.contains(&10) + /// values.contains(&10) /// } /// ``` #[clippy::version = "1.86.0"] diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index 45f79dd44f2..56ff7e2c61b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -1,3 +1,5 @@ +use std::ops::ControlFlow; + use super::NEEDLESS_COLLECT; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then}; use clippy_utils::source::{snippet, snippet_with_applicability}; @@ -9,9 +11,9 @@ use clippy_utils::{ }; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, MultiSpan}; -use rustc_hir::intravisit::{Visitor, walk_block, walk_expr}; +use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_stmt}; use rustc_hir::{ - BindingMode, Block, Expr, ExprKind, HirId, HirIdSet, LetStmt, Mutability, Node, PatKind, Stmt, StmtKind, + BindingMode, Block, Expr, ExprKind, HirId, HirIdSet, LetStmt, Mutability, Node, Pat, PatKind, Stmt, StmtKind, }; use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; @@ -103,6 +105,12 @@ pub(super) fn check<'tcx>( return; } + if let IterFunctionKind::IntoIter(hir_id) = iter_call.func + && !check_iter_expr_used_only_as_iterator(cx, hir_id, block) + { + return; + } + // Suggest replacing iter_call with iter_replacement, and removing stmt let mut span = MultiSpan::from_span(name_span); span.push_span_label(iter_call.span, "the iterator could be used here instead"); @@ -253,7 +261,7 @@ struct IterFunction { impl IterFunction { fn get_iter_method(&self, cx: &LateContext<'_>) -> String { match &self.func { - IterFunctionKind::IntoIter => String::new(), + IterFunctionKind::IntoIter(_) => String::new(), IterFunctionKind::Len => String::from(".count()"), IterFunctionKind::IsEmpty => String::from(".next().is_none()"), IterFunctionKind::Contains(span) => { @@ -268,7 +276,7 @@ impl IterFunction { } fn get_suggestion_text(&self) -> &'static str { match &self.func { - IterFunctionKind::IntoIter => { + IterFunctionKind::IntoIter(_) => { "use the original Iterator instead of collecting it and then producing a new one" }, IterFunctionKind::Len => { @@ -284,7 +292,7 @@ impl IterFunction { } } enum IterFunctionKind { - IntoIter, + IntoIter(HirId), Len, IsEmpty, Contains(Span), @@ -343,7 +351,7 @@ impl<'tcx> Visitor<'tcx> for IterFunctionVisitor<'_, 'tcx> { } match method_name.ident.name.as_str() { "into_iter" => self.uses.push(Some(IterFunction { - func: IterFunctionKind::IntoIter, + func: IterFunctionKind::IntoIter(expr.hir_id), span: expr.span, })), "len" => self.uses.push(Some(IterFunction { @@ -520,3 +528,61 @@ fn get_captured_ids(cx: &LateContext<'_>, ty: Ty<'_>) -> HirIdSet { set } + +struct IteratorMethodCheckVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + hir_id_of_expr: HirId, + hir_id_of_let_binding: Option<HirId>, +} + +impl<'tcx> Visitor<'tcx> for IteratorMethodCheckVisitor<'_, 'tcx> { + type Result = ControlFlow<()>; + fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) -> ControlFlow<()> { + if let ExprKind::MethodCall(_method_name, recv, _args, _) = &expr.kind + && (recv.hir_id == self.hir_id_of_expr + || self + .hir_id_of_let_binding + .is_some_and(|hid| path_to_local_id(recv, hid))) + && !is_trait_method(self.cx, expr, sym::Iterator) + { + return ControlFlow::Break(()); + } else if let ExprKind::Assign(place, value, _span) = &expr.kind + && value.hir_id == self.hir_id_of_expr + && let Some(id) = path_to_local(place) + { + // our iterator was directly assigned to a variable + self.hir_id_of_let_binding = Some(id); + } + walk_expr(self, expr) + } + fn visit_stmt(&mut self, stmt: &'tcx Stmt<'tcx>) -> ControlFlow<()> { + if let StmtKind::Let(LetStmt { + init: Some(expr), + pat: + Pat { + kind: PatKind::Binding(BindingMode::NONE | BindingMode::MUT, id, _, None), + .. + }, + .. + }) = &stmt.kind + && expr.hir_id == self.hir_id_of_expr + { + // our iterator was directly assigned to a variable + self.hir_id_of_let_binding = Some(*id); + } + walk_stmt(self, stmt) + } +} + +fn check_iter_expr_used_only_as_iterator<'tcx>( + cx: &LateContext<'tcx>, + hir_id_of_expr: HirId, + block: &'tcx Block<'tcx>, +) -> bool { + let mut visitor = IteratorMethodCheckVisitor { + cx, + hir_id_of_expr, + hir_id_of_let_binding: None, + }; + visitor.visit_block(block).is_continue() +} diff --git a/src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs b/src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs index c9251c1b849..fe999a3b5f8 100644 --- a/src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs +++ b/src/tools/clippy/clippy_lints/src/methods/read_line_without_trim.rs @@ -40,7 +40,7 @@ pub fn check(cx: &LateContext<'_>, call: &Expr<'_>, recv: &Expr<'_>, arg: &Expr< // We've checked that `call` is a call to `Stdin::read_line()` with the right receiver, // now let's check if the first use of the string passed to `::read_line()` // is used for operations that will always fail (e.g. parsing "6\n" into a number) - for_each_local_use_after_expr(cx, local_id, call.hir_id, |expr| { + let _ = for_each_local_use_after_expr(cx, local_id, call.hir_id, |expr| { if let Some(parent) = get_parent_expr(cx, expr) { let data = if let ExprKind::MethodCall(segment, recv, args, span) = parent.kind { if args.is_empty() diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index a71b3659fd2..62ba3012643 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -6,7 +6,8 @@ use clippy_utils::source::{SpanRangeExt, snippet}; use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item}; use clippy_utils::visitors::find_all_ret_expressions; use clippy_utils::{ - fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, peel_middle_ty_refs, return_ty, + fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, is_expr_temporary_value, peel_middle_ty_refs, + return_ty, }; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -219,6 +220,8 @@ fn check_into_iter_call_arg( && let Some(receiver_snippet) = receiver.span.get_source_text(cx) // If the receiver is a `Cow`, we can't remove the `into_owned` generally, see https://github.com/rust-lang/rust-clippy/issues/13624. && !is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(receiver), sym::Cow) + // Calling `iter()` on a temporary object can lead to false positives. #14242 + && !is_expr_temporary_value(cx, receiver) { if unnecessary_iter_cloned::check_for_loop_iter(cx, parent, method_name, receiver, true) { return true; diff --git a/src/tools/clippy/clippy_lints/src/misc_early/mixed_case_hex_literals.rs b/src/tools/clippy/clippy_lints/src/misc_early/mixed_case_hex_literals.rs index 9151cc63320..4fbd3c9874d 100644 --- a/src/tools/clippy/clippy_lints/src/misc_early/mixed_case_hex_literals.rs +++ b/src/tools/clippy/clippy_lints/src/misc_early/mixed_case_hex_literals.rs @@ -1,32 +1,51 @@ -use clippy_utils::diagnostics::span_lint; +use clippy_utils::diagnostics::span_lint_and_help; use rustc_lint::EarlyContext; use rustc_span::Span; use super::MIXED_CASE_HEX_LITERALS; pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, suffix: &str, lit_snip: &str) { - let Some(maybe_last_sep_idx) = lit_snip.len().checked_sub(suffix.len() + 1) else { - return; // It's useless so shouldn't lint. + let num_end_idx = match lit_snip.strip_suffix(suffix) { + Some(p) if p.ends_with('_') => lit_snip.len() - (suffix.len() + 1), + Some(_) => lit_snip.len() - suffix.len(), + None => lit_snip.len(), }; - if maybe_last_sep_idx <= 2 { + + if num_end_idx <= 2 { // It's meaningless or causes range error. return; } + let mut seen = (false, false); - for ch in &lit_snip.as_bytes()[2..=maybe_last_sep_idx] { + for ch in &lit_snip.as_bytes()[2..num_end_idx] { match ch { b'a'..=b'f' => seen.0 = true, b'A'..=b'F' => seen.1 = true, _ => {}, } if seen.0 && seen.1 { - span_lint( + let raw_digits = &lit_snip[2..num_end_idx]; + let (sugg_lower, sugg_upper) = if suffix.is_empty() { + ( + format!("0x{}", raw_digits.to_lowercase()), + format!("0x{}", raw_digits.to_uppercase()), + ) + } else { + ( + format!("0x{}_{}", raw_digits.to_lowercase(), suffix), + format!("0x{}_{}", raw_digits.to_uppercase(), suffix), + ) + }; + + span_lint_and_help( cx, MIXED_CASE_HEX_LITERALS, lit_span, "inconsistent casing in hexadecimal literal", + None, + format!("consider using `{sugg_lower}` or `{sugg_upper}`"), ); - break; + return; } } } diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index 3470c266c49..b234b190153 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -192,17 +192,17 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc { fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) { match it.kind { - hir::ItemKind::Fn { .. } => { + hir::ItemKind::Fn { ident, .. } => { // ignore main() - if it.ident.name == sym::main { + if ident.name == sym::main { let at_root = cx.tcx.local_parent(it.owner_id.def_id) == CRATE_DEF_ID; if at_root { note_prev_span_then_ret!(self.prev_span, it.span); } } }, - hir::ItemKind::Const(..) => { - if it.ident.name == kw::Underscore { + hir::ItemKind::Const(ident, ..) => { + if ident.name == kw::Underscore { note_prev_span_then_ret!(self.prev_span, it.span); } }, diff --git a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs index 59f29d242ab..66631a69206 100644 --- a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs +++ b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs @@ -67,7 +67,7 @@ impl_lint_pass!(ImportRename => [MISSING_ENFORCED_IMPORT_RENAMES]); impl LateLintPass<'_> for ImportRename { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { - if let ItemKind::Use(path, UseKind::Single) = &item.kind { + if let ItemKind::Use(path, UseKind::Single(_)) = &item.kind { for &res in &path.res { if let Res::Def(_, id) = res && let Some(name) = self.renames.get(&id) diff --git a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs index 675989156ca..28dc2427428 100644 --- a/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs +++ b/src/tools/clippy/clippy_lints/src/missing_fields_in_debug.rs @@ -226,7 +226,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingFieldsInDebug { && should_lint(cx, typeck_results, block) { // we intentionally only lint structs, see lint description - if let ItemKind::Struct(data, _) = &self_item.kind { + if let ItemKind::Struct(_, data, _) = &self_item.kind { check_struct(cx, typeck_results, block, self_ty, item, data); } } diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs index 2c578d81602..f49e03ea765 100644 --- a/src/tools/clippy/clippy_lints/src/missing_inline.rs +++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs @@ -37,7 +37,7 @@ declare_clippy_lint! { /// /// struct Baz; /// impl Baz { - /// fn private() {} // ok + /// fn private() {} // ok /// } /// /// impl Bar for Baz { @@ -46,13 +46,13 @@ declare_clippy_lint! { /// /// pub struct PubBaz; /// impl PubBaz { - /// fn private() {} // ok - /// pub fn not_private() {} // missing #[inline] + /// fn private() {} // ok + /// pub fn not_private() {} // missing #[inline] /// } /// /// impl Bar for PubBaz { - /// fn bar() {} // missing #[inline] - /// fn def_bar() {} // missing #[inline] + /// fn bar() {} // missing #[inline] + /// fn def_bar() {} // missing #[inline] /// } /// ``` /// @@ -101,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline { let attrs = cx.tcx.hir_attrs(it.hir_id()); check_missing_inline_attrs(cx, attrs, it.span, desc); }, - hir::ItemKind::Trait(ref _is_auto, ref _unsafe, _generics, _bounds, trait_items) => { + hir::ItemKind::Trait(ref _is_auto, ref _unsafe, _ident, _generics, _bounds, trait_items) => { // note: we need to check if the trait is exported so we can't use // `LateLintPass::check_trait_item` here. for tit in trait_items { diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs index 3efbed0c236..a914267cf50 100644 --- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs +++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::path_to_local; -use clippy_utils::source::{SourceText, SpanRangeExt}; +use clippy_utils::source::{SourceText, SpanRangeExt, snippet}; use clippy_utils::ty::needs_ordered_drop; use clippy_utils::visitors::{for_each_expr, for_each_expr_without_closures, is_local_used}; use core::ops::ControlFlow; @@ -100,7 +100,6 @@ fn stmt_needs_ordered_drop(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool { #[derive(Debug)] struct LocalAssign { lhs_id: HirId, - lhs_span: Span, rhs_span: Span, span: Span, } @@ -118,7 +117,6 @@ impl LocalAssign { Some(Self { lhs_id: path_to_local(lhs)?, - lhs_span: lhs.span, rhs_span: rhs.span.source_callsite(), span, }) @@ -281,7 +279,10 @@ fn check<'tcx>( format!("move the declaration `{binding_name}` here"), vec![ (local_stmt.span, String::new()), - (assign.lhs_span, let_snippet.to_owned()), + ( + assign.span, + let_snippet.to_owned() + " = " + &snippet(cx, assign.rhs_span, ".."), + ), ], Applicability::MachineApplicable, ); diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 7bee89086b8..55ca875edce 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -1,10 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_then; -use clippy_utils::is_self; use clippy_utils::ptr::get_spans; use clippy_utils::source::{SpanRangeExt, snippet}; use clippy_utils::ty::{ implements_trait, implements_trait_with_env_from_iter, is_copy, is_type_diagnostic_item, is_type_lang_item, }; +use clippy_utils::{is_self, peel_hir_ty_options}; use rustc_abi::ExternAbi; use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::FnKind; @@ -279,10 +279,10 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { } } - diag.span_suggestion( - input.span, + diag.span_suggestion_verbose( + peel_hir_ty_options(cx, input).span.shrink_to_lo(), "consider taking a reference instead", - format!("&{}", snippet(cx, input.span, "_")), + '&', Applicability::MaybeIncorrect, ); }; diff --git a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs index 37463cfec9a..72b0a80260e 100644 --- a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs @@ -40,7 +40,7 @@ declare_clippy_lint! { /// } /// /// fn f(to: TO) -> Option<usize> { - /// to.magic + /// to.magic /// } /// /// struct TR { diff --git a/src/tools/clippy/clippy_lints/src/needless_update.rs b/src/tools/clippy/clippy_lints/src/needless_update.rs index 0cba72bd2c6..cce0617ba39 100644 --- a/src/tools/clippy/clippy_lints/src/needless_update.rs +++ b/src/tools/clippy/clippy_lints/src/needless_update.rs @@ -54,8 +54,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessUpdate { if let ExprKind::Struct(_, fields, StructTailExpr::Base(base)) = expr.kind { let ty = cx.typeck_results().expr_ty(expr); if let ty::Adt(def, _) = ty.kind() { - if fields.len() == def.non_enum_variant().fields.len() - && !def.variant(0_usize.into()).is_field_list_non_exhaustive() + let variant = def.non_enum_variant(); + if fields.len() == variant.fields.len() + && !variant.is_field_list_non_exhaustive() { span_lint( cx, diff --git a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs index fe8a02c64c6..b71dde90691 100644 --- a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs +++ b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs @@ -37,12 +37,12 @@ declare_lint_pass!(NoMangleWithRustAbi => [NO_MANGLE_WITH_RUST_ABI]); impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { - if let ItemKind::Fn { sig: fn_sig, .. } = &item.kind + if let ItemKind::Fn { ident, sig: fn_sig, .. } = &item.kind && !item.span.from_expansion() { let attrs = cx.tcx.hir_attrs(item.hir_id()); let mut app = Applicability::MaybeIncorrect; - let fn_snippet = snippet_with_applicability(cx, fn_sig.span.with_hi(item.ident.span.lo()), "..", &mut app); + let fn_snippet = snippet_with_applicability(cx, fn_sig.span.with_hi(ident.span.lo()), "..", &mut app); for attr in attrs { if let Some(ident) = attr.ident() && ident.name == rustc_span::sym::no_mangle diff --git a/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs b/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs index a82365f9431..8305bf345ef 100644 --- a/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs +++ b/src/tools/clippy/clippy_lints/src/non_std_lazy_statics.rs @@ -192,7 +192,7 @@ struct LazyInfo { impl LazyInfo { fn from_item(state: &NonStdLazyStatic, cx: &LateContext<'_>, item: &Item<'_>) -> Option<Self> { // Check if item is a `once_cell:sync::Lazy` static. - if let ItemKind::Static(ty, _, body_id) = item.kind + if let ItemKind::Static(_, ty, _, body_id) = item.kind && let Some(path_def_id) = path_def_id(cx, ty) && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind && state.once_cell_sync_lazy.contains(&path_def_id) diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs index 80459945094..f758d08d366 100644 --- a/src/tools/clippy/clippy_lints/src/operators/mod.rs +++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs @@ -18,7 +18,6 @@ mod modulo_one; mod needless_bitwise_bool; mod numeric_arithmetic; mod op_ref; -mod ptr_eq; mod self_assignment; mod verbose_bit_mask; @@ -770,35 +769,6 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Use `std::ptr::eq` when applicable - /// - /// ### Why is this bad? - /// `ptr::eq` can be used to compare `&T` references - /// (which coerce to `*const T` implicitly) by their address rather than - /// comparing the values they point to. - /// - /// ### Example - /// ```no_run - /// let a = &[1, 2, 3]; - /// let b = &[1, 2, 3]; - /// - /// assert!(a as *const _ as usize == b as *const _ as usize); - /// ``` - /// Use instead: - /// ```no_run - /// let a = &[1, 2, 3]; - /// let b = &[1, 2, 3]; - /// - /// assert!(std::ptr::eq(a, b)); - /// ``` - #[clippy::version = "1.49.0"] - pub PTR_EQ, - style, - "use `std::ptr::eq` when comparing raw pointers" -} - -declare_clippy_lint! { - /// ### What it does /// Checks for explicit self-assignments. /// /// ### Why is this bad? @@ -902,7 +872,6 @@ impl_lint_pass!(Operators => [ MODULO_ONE, MODULO_ARITHMETIC, NEEDLESS_BITWISE_BOOL, - PTR_EQ, SELF_ASSIGNMENT, MANUAL_MIDPOINT, ]); @@ -921,7 +890,6 @@ impl<'tcx> LateLintPass<'tcx> for Operators { erasing_op::check(cx, e, op.node, lhs, rhs); identity_op::check(cx, e, op.node, lhs, rhs); needless_bitwise_bool::check(cx, e, op.node, lhs, rhs); - ptr_eq::check(cx, e, op.node, lhs, rhs); manual_midpoint::check(cx, e, op.node, lhs, rhs, self.msrv); } self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs); diff --git a/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs b/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs deleted file mode 100644 index 8118ad59bb7..00000000000 --- a/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs +++ /dev/null @@ -1,62 +0,0 @@ -use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::source::SpanRangeExt; -use clippy_utils::std_or_core; -use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Expr, ExprKind}; -use rustc_lint::LateContext; - -use super::PTR_EQ; - -pub(super) fn check<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx Expr<'_>, - op: BinOpKind, - left: &'tcx Expr<'_>, - right: &'tcx Expr<'_>, -) { - if BinOpKind::Eq == op { - let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) { - (Some(lhs), Some(rhs)) => (lhs, rhs), - _ => (left, right), - }; - - if let Some(left_var) = expr_as_cast_to_raw_pointer(cx, left) - && let Some(right_var) = expr_as_cast_to_raw_pointer(cx, right) - && let Some(left_snip) = left_var.span.get_source_text(cx) - && let Some(right_snip) = right_var.span.get_source_text(cx) - { - let Some(top_crate) = std_or_core(cx) else { return }; - span_lint_and_sugg( - cx, - PTR_EQ, - expr.span, - format!("use `{top_crate}::ptr::eq` when comparing raw pointers"), - "try", - format!("{top_crate}::ptr::eq({left_snip}, {right_snip})"), - Applicability::MachineApplicable, - ); - } - } -} - -// If the given expression is a cast to a usize, return the lhs of the cast -// E.g., `foo as *const _ as usize` returns `foo as *const _`. -fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { - if cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize { - if let ExprKind::Cast(expr, _) = cast_expr.kind { - return Some(expr); - } - } - None -} - -// If the given expression is a cast to a `*const` pointer, return the lhs of the cast -// E.g., `foo as *const _` returns `foo`. -fn expr_as_cast_to_raw_pointer<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { - if cx.typeck_results().expr_ty(cast_expr).is_raw_ptr() { - if let ExprKind::Cast(expr, _) = cast_expr.kind { - return Some(expr); - } - } - None -} diff --git a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs index 75b18bc651e..6f302ea1962 100644 --- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs @@ -1,16 +1,23 @@ +use std::ops::ControlFlow; + use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::sugg::Sugg; +use clippy_utils::ty::is_copy; use clippy_utils::{ CaptureKind, can_move_expr_to_closure, eager_or_lazy, higher, is_else_clause, is_in_const_context, is_res_lang_ctor, peel_blocks, peel_hir_expr_while, }; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::def::Res; +use rustc_hir::intravisit::{Visitor, walk_expr, walk_path}; use rustc_hir::{ - Arm, BindingMode, Expr, ExprKind, MatchSource, Mutability, Pat, PatExpr, PatExprKind, PatKind, Path, QPath, UnOp, + Arm, BindingMode, Expr, ExprKind, HirId, MatchSource, Mutability, Node, Pat, PatExpr, PatExprKind, PatKind, Path, + QPath, UnOp, }; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::nested_filter; use rustc_session::declare_lint_pass; use rustc_span::SyntaxContext; @@ -110,11 +117,12 @@ fn format_option_in_sugg(cond_sugg: Sugg<'_>, as_ref: bool, as_mut: bool) -> Str ) } +#[expect(clippy::too_many_lines)] fn try_get_option_occurrence<'tcx>( cx: &LateContext<'tcx>, ctxt: SyntaxContext, pat: &Pat<'tcx>, - expr: &Expr<'_>, + expr: &'tcx Expr<'_>, if_then: &'tcx Expr<'_>, if_else: &'tcx Expr<'_>, ) -> Option<OptionOccurrence> { @@ -182,6 +190,26 @@ fn try_get_option_occurrence<'tcx>( Some(CaptureKind::Ref(Mutability::Not)) | None => (), } } + } else if !is_copy(cx, cx.typeck_results().expr_ty(expr)) + // TODO: Cover more match cases + && matches!( + expr.kind, + ExprKind::Field(_, _) | ExprKind::Path(_) | ExprKind::Index(_, _, _) + ) + { + let mut condition_visitor = ConditionVisitor { + cx, + identifiers: FxHashSet::default(), + }; + condition_visitor.visit_expr(cond_expr); + + let mut reference_visitor = ReferenceVisitor { + cx, + identifiers: condition_visitor.identifiers, + }; + if reference_visitor.visit_expr(none_body).is_break() { + return None; + } } let mut app = Applicability::Unspecified; @@ -219,6 +247,60 @@ fn try_get_option_occurrence<'tcx>( None } +/// This visitor looks for bindings in the <then> block that mention a local variable. Then gets the +/// identifiers. The list of identifiers will then be used to check if the <none> block mentions the +/// same local. See [`ReferenceVisitor`] for more. +struct ConditionVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + identifiers: FxHashSet<HirId>, +} + +impl<'tcx> Visitor<'tcx> for ConditionVisitor<'_, 'tcx> { + type NestedFilter = nested_filter::All; + + fn visit_path(&mut self, path: &Path<'tcx>, _: HirId) { + if let Res::Local(local_id) = path.res + && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id) + && let PatKind::Binding(_, local_id, ..) = pat.kind + { + self.identifiers.insert(local_id); + } + walk_path(self, path); + } + + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.cx.tcx + } +} + +/// This visitor checks if the <none> block contains references to the local variables that are +/// used in the <then> block. See [`ConditionVisitor`] for more. +struct ReferenceVisitor<'a, 'tcx> { + cx: &'a LateContext<'tcx>, + identifiers: FxHashSet<HirId>, +} + +impl<'tcx> Visitor<'tcx> for ReferenceVisitor<'_, 'tcx> { + type NestedFilter = nested_filter::All; + type Result = ControlFlow<()>; + fn visit_expr(&mut self, expr: &'tcx Expr<'_>) -> ControlFlow<()> { + if let ExprKind::Path(ref path) = expr.kind + && let QPath::Resolved(_, path) = path + && let Res::Local(local_id) = path.res + && let Node::Pat(pat) = self.cx.tcx.hir_node(local_id) + && let PatKind::Binding(_, local_id, ..) = pat.kind + && self.identifiers.contains(&local_id) + { + return ControlFlow::Break(()); + } + walk_expr(self, expr) + } + + fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + self.cx.tcx + } +} + fn try_get_inner_pat_and_is_result<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<(&'tcx Pat<'tcx>, bool)> { if let PatKind::TupleStruct(ref qpath, [inner_pat], ..) = pat.kind { let res = cx.qpath_res(qpath, pat.hir_id); diff --git a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs index 55676522419..65671b478ba 100644 --- a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs +++ b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs @@ -19,8 +19,8 @@ declare_clippy_lint! { /// struct Foo; /// /// impl PartialEq for Foo { - /// fn eq(&self, other: &Foo) -> bool { true } - /// fn ne(&self, other: &Foo) -> bool { !(self == other) } + /// fn eq(&self, other: &Foo) -> bool { true } + /// fn ne(&self, other: &Foo) -> bool { !(self == other) } /// } /// ``` #[clippy::version = "pre 1.29.0"] diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index 320c0286bb7..0a8e2885648 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -141,7 +141,7 @@ impl PassByRefOrValue { // Gather all the lifetimes found in the output type which may affect whether // `TRIVIALLY_COPY_PASS_BY_REF` should be linted. let mut output_regions = FxHashSet::default(); - for_each_top_level_late_bound_region(fn_sig.skip_binder().output(), |region| -> ControlFlow<!> { + let _ = for_each_top_level_late_bound_region(fn_sig.skip_binder().output(), |region| -> ControlFlow<!> { output_regions.insert(region); ControlFlow::Continue(()) }); diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index dae0709a540..55f1ece0559 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -148,7 +148,36 @@ declare_clippy_lint! { "invalid usage of a null pointer, suggesting `NonNull::dangling()` instead" } -declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, INVALID_NULL_PTR_USAGE]); +declare_clippy_lint! { + /// ### What it does + /// Use `std::ptr::eq` when applicable + /// + /// ### Why is this bad? + /// `ptr::eq` can be used to compare `&T` references + /// (which coerce to `*const T` implicitly) by their address rather than + /// comparing the values they point to. + /// + /// ### Example + /// ```no_run + /// let a = &[1, 2, 3]; + /// let b = &[1, 2, 3]; + /// + /// assert!(a as *const _ as usize == b as *const _ as usize); + /// ``` + /// Use instead: + /// ```no_run + /// let a = &[1, 2, 3]; + /// let b = &[1, 2, 3]; + /// + /// assert!(std::ptr::eq(a, b)); + /// ``` + #[clippy::version = "1.49.0"] + pub PTR_EQ, + style, + "use `std::ptr::eq` when comparing raw pointers" +} + +declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, INVALID_NULL_PTR_USAGE, PTR_EQ]); impl<'tcx> LateLintPass<'tcx> for Ptr { fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) { @@ -253,10 +282,14 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { if let ExprKind::Binary(op, l, r) = expr.kind && (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne) { - let non_null_path_snippet = match (is_null_path(cx, l), is_null_path(cx, r)) { - (true, false) if let Some(sugg) = Sugg::hir_opt(cx, r) => sugg.maybe_par(), - (false, true) if let Some(sugg) = Sugg::hir_opt(cx, l) => sugg.maybe_par(), - _ => return, + let non_null_path_snippet = match ( + is_lint_allowed(cx, CMP_NULL, expr.hir_id), + is_null_path(cx, l), + is_null_path(cx, r), + ) { + (false, true, false) if let Some(sugg) = Sugg::hir_opt(cx, r) => sugg.maybe_par(), + (false, false, true) if let Some(sugg) = Sugg::hir_opt(cx, l) => sugg.maybe_par(), + _ => return check_ptr_eq(cx, expr, op.node, l, r), }; span_lint_and_sugg( @@ -740,3 +773,71 @@ fn is_null_path(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { false } } + +fn check_ptr_eq<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'_>, + op: BinOpKind, + left: &'tcx Expr<'_>, + right: &'tcx Expr<'_>, +) { + if expr.span.from_expansion() { + return; + } + + // Remove one level of usize conversion if any + let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) { + (Some(lhs), Some(rhs)) => (lhs, rhs), + _ => (left, right), + }; + + // This lint concerns raw pointers + let (left_ty, right_ty) = (cx.typeck_results().expr_ty(left), cx.typeck_results().expr_ty(right)); + if !left_ty.is_raw_ptr() || !right_ty.is_raw_ptr() { + return; + } + + let (left_var, right_var) = (peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty)); + + if let Some(left_snip) = left_var.span.get_source_text(cx) + && let Some(right_snip) = right_var.span.get_source_text(cx) + { + let Some(top_crate) = std_or_core(cx) else { return }; + let invert = if op == BinOpKind::Eq { "" } else { "!" }; + span_lint_and_sugg( + cx, + PTR_EQ, + expr.span, + format!("use `{top_crate}::ptr::eq` when comparing raw pointers"), + "try", + format!("{invert}{top_crate}::ptr::eq({left_snip}, {right_snip})"), + Applicability::MachineApplicable, + ); + } +} + +// If the given expression is a cast to a usize, return the lhs of the cast +// E.g., `foo as *const _ as usize` returns `foo as *const _`. +fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> { + if cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize + && let ExprKind::Cast(expr, _) = cast_expr.kind + { + Some(expr) + } else { + None + } +} + +// Peel raw casts if the remaining expression can be coerced to it +fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> &'tcx Expr<'tcx> { + if let ExprKind::Cast(inner, _) = expr.kind + && let ty::RawPtr(target_ty, _) = expr_ty.kind() + && let inner_ty = cx.typeck_results().expr_ty(inner) + && let ty::RawPtr(inner_target_ty, _) | ty::Ref(_, inner_target_ty, _) = inner_ty.kind() + && target_ty == inner_target_ty + { + peel_raw_casts(cx, inner, inner_ty) + } else { + expr + } +} diff --git a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs index fd21893232d..e4a9bf7a848 100644 --- a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs +++ b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs @@ -58,7 +58,7 @@ impl PubUnderscoreFields { impl<'tcx> LateLintPass<'tcx> for PubUnderscoreFields { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { // This lint only pertains to structs. - let ItemKind::Struct(variant_data, _) = &item.kind else { + let ItemKind::Struct(_, variant_data, _) = &item.kind else { return; }; diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index 4f5f3eb6c15..a80e1f79bbc 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -3,7 +3,7 @@ use crate::question_mark_used::QUESTION_MARK_USED; use clippy_config::Conf; use clippy_config::types::MatchLintBehaviour; use clippy_utils::diagnostics::span_lint_and_sugg; -use clippy_utils::msrvs::Msrv; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{implements_trait, is_type_diagnostic_item}; use clippy_utils::{ @@ -145,8 +145,47 @@ fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) { { let mut applicability = Applicability::MaybeIncorrect; let init_expr_str = snippet_with_applicability(cx, init_expr.span, "..", &mut applicability); - let receiver_str = snippet_with_applicability(cx, inner_pat.span, "..", &mut applicability); - let sugg = format!("let {receiver_str} = {init_expr_str}?;",); + // Take care when binding is `ref` + let sugg = if let PatKind::Binding( + BindingMode(ByRef::Yes(ref_mutability), binding_mutability), + _hir_id, + ident, + subpattern, + ) = inner_pat.kind + { + let (from_method, replace_to) = match ref_mutability { + Mutability::Mut => (".as_mut()", "&mut "), + Mutability::Not => (".as_ref()", "&"), + }; + + let mutability_str = match binding_mutability { + Mutability::Mut => "mut ", + Mutability::Not => "", + }; + + // Handle subpattern (@ subpattern) + let maybe_subpattern = match subpattern { + Some(Pat { + kind: PatKind::Binding(BindingMode(ByRef::Yes(_), _), _, subident, None), + .. + }) => { + // avoid `&ref` + // note that, because you can't have aliased, mutable references, we don't have to worry about + // the outer and inner mutability being different + format!(" @ {subident}") + }, + Some(subpattern) => { + let substr = snippet_with_applicability(cx, subpattern.span, "..", &mut applicability); + format!(" @ {replace_to}{substr}") + }, + None => String::new(), + }; + + format!("let {mutability_str}{ident}{maybe_subpattern} = {init_expr_str}{from_method}?;") + } else { + let receiver_str = snippet_with_applicability(cx, inner_pat.span, "..", &mut applicability); + format!("let {receiver_str} = {init_expr_str}?;") + }; span_lint_and_sugg( cx, QUESTION_MARK, @@ -230,7 +269,7 @@ fn expr_return_none_or_err( /// /// ```ignore /// if option.is_none() { -/// return None; +/// return None; /// } /// ``` /// @@ -485,7 +524,8 @@ fn is_inferred_ret_closure(expr: &Expr<'_>) -> bool { impl<'tcx> LateLintPass<'tcx> for QuestionMark { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { - if !is_lint_allowed(cx, QUESTION_MARK_USED, stmt.hir_id) { + if !is_lint_allowed(cx, QUESTION_MARK_USED, stmt.hir_id) || !self.msrv.meets(cx, msrvs::QUESTION_MARK_OPERATOR) + { return; } @@ -501,7 +541,10 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark { return; } - if !self.inside_try_block() && !is_in_const_context(cx) && is_lint_allowed(cx, QUESTION_MARK_USED, expr.hir_id) + if !self.inside_try_block() + && !is_in_const_context(cx) + && is_lint_allowed(cx, QUESTION_MARK_USED, expr.hir_id) + && self.msrv.meets(cx, msrvs::QUESTION_MARK_OPERATOR) { check_is_none_or_err_and_early_return(cx, expr); check_if_let_some_or_err_and_early_return(cx, expr); diff --git a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs index bc5e8fd2c25..8289ec47bc7 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs @@ -23,7 +23,7 @@ declare_clippy_lint! { /// ### Example /// ```no_run /// let f = async { - /// 1 + 2 + /// 1 + 2 /// }; /// let fut = async { /// f.await @@ -32,7 +32,7 @@ declare_clippy_lint! { /// Use instead: /// ```no_run /// let f = async { - /// 1 + 2 + /// 1 + 2 /// }; /// let fut = f; /// ``` diff --git a/src/tools/clippy/clippy_lints/src/redundant_locals.rs b/src/tools/clippy/clippy_lints/src/redundant_locals.rs index defb6684cff..8f33a47e290 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_locals.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_locals.rs @@ -26,7 +26,7 @@ declare_clippy_lint! { /// let a = a; /// /// fn foo(b: i32) { - /// let b = b; + /// let b = b; /// } /// ``` /// Use instead: diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs index 6a17b83b3d0..f2fdac5a8af 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs @@ -52,7 +52,13 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { && is_not_macro_export(item) && !item.span.in_external_macro(cx.sess().source_map()) { - let span = item.span.with_hi(item.ident.span.hi()); + // FIXME: `DUMMY_SP` isn't right here, because it causes the + // resulting span to begin at the start of the file. + let span = item.span.with_hi( + item.kind + .ident() + .map_or(rustc_span::DUMMY_SP.hi(), |ident| ident.span.hi()), + ); let descr = cx.tcx.def_kind(item.owner_id).descr(item.owner_id.to_def_id()); span_lint_and_then( cx, diff --git a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs index 8b2d597b9e3..534ba3a50c6 100644 --- a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs +++ b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs @@ -73,7 +73,8 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors { if let Some(self_def) = self_ty.ty_adt_def() && let Some(self_local_did) = self_def.did().as_local() && let Node::Item(x) = cx.tcx.hir_node_by_def_id(self_local_did) - && let type_name = x.ident.name.as_str().to_lowercase() + && let Some(type_ident) = x.kind.ident() + && let type_name = type_ident.name.as_str().to_lowercase() && (impl_item.ident.name.as_str() == type_name || impl_item.ident.name.as_str().replace('_', "") == type_name) { diff --git a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs index dc19236011b..835ec1e4ca1 100644 --- a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs +++ b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs @@ -18,7 +18,6 @@ declare_clippy_lint! { /// ### Example /// ```rust,no_run /// # use std::ptr::copy_nonoverlapping; - /// # use std::mem::size_of; /// const SIZE: usize = 128; /// let x = [2u8; SIZE]; /// let mut y = [2u8; SIZE]; diff --git a/src/tools/clippy/clippy_lints/src/size_of_ref.rs b/src/tools/clippy/clippy_lints/src/size_of_ref.rs index b3d32a6d7d8..60d923bcd77 100644 --- a/src/tools/clippy/clippy_lints/src/size_of_ref.rs +++ b/src/tools/clippy/clippy_lints/src/size_of_ref.rs @@ -8,7 +8,7 @@ use rustc_span::sym; declare_clippy_lint! { /// ### What it does /// - /// Checks for calls to `std::mem::size_of_val()` where the argument is + /// Checks for calls to `size_of_val()` where the argument is /// a reference to a reference. /// /// ### Why is this bad? @@ -29,7 +29,7 @@ declare_clippy_lint! { /// // is already a reference, `&self` is a double-reference. /// // The return value of `size_of_val()` therefore is the /// // size of the reference-type, not the size of `self`. - /// std::mem::size_of_val(&self) + /// size_of_val(&self) /// } /// } /// ``` @@ -42,14 +42,14 @@ declare_clippy_lint! { /// impl Foo { /// fn size(&self) -> usize { /// // Correct - /// std::mem::size_of_val(self) + /// size_of_val(self) /// } /// } /// ``` #[clippy::version = "1.68.0"] pub SIZE_OF_REF, suspicious, - "Argument to `std::mem::size_of_val()` is a double-reference, which is almost certainly unintended" + "Argument to `size_of_val()` is a double-reference, which is almost certainly unintended" } declare_lint_pass!(SizeOfRef => [SIZE_OF_REF]); @@ -65,9 +65,9 @@ impl LateLintPass<'_> for SizeOfRef { cx, SIZE_OF_REF, expr.span, - "argument to `std::mem::size_of_val()` is a reference to a reference", + "argument to `size_of_val()` is a reference to a reference", None, - "dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type", + "dereference the argument to `size_of_val()` to get the size of the value instead of the size of the reference-type", ); } } diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs index 4a5f143a2d3..27c548bed9f 100644 --- a/src/tools/clippy/clippy_lints/src/strings.rs +++ b/src/tools/clippy/clippy_lints/src/strings.rs @@ -14,6 +14,8 @@ use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::sym; +use std::ops::ControlFlow; + declare_clippy_lint! { /// ### What it does /// Checks for string appends of the form `x = x + y` (without @@ -438,27 +440,94 @@ declare_clippy_lint! { declare_lint_pass!(StringToString => [STRING_TO_STRING]); +fn is_parent_map_like(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<rustc_span::Span> { + if let Some(parent_expr) = get_parent_expr(cx, expr) + && let ExprKind::MethodCall(name, _, _, parent_span) = parent_expr.kind + && name.ident.name == sym::map + && let Some(caller_def_id) = cx.typeck_results().type_dependent_def_id(parent_expr.hir_id) + && (clippy_utils::is_diag_item_method(cx, caller_def_id, sym::Result) + || clippy_utils::is_diag_item_method(cx, caller_def_id, sym::Option) + || clippy_utils::is_diag_trait_item(cx, caller_def_id, sym::Iterator)) + { + Some(parent_span) + } else { + None + } +} + +fn is_called_from_map_like(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<rustc_span::Span> { + // Look for a closure as parent of `expr`, discarding simple blocks + let parent_closure = cx + .tcx + .hir_parent_iter(expr.hir_id) + .try_fold(expr.hir_id, |child_hir_id, (_, node)| match node { + // Check that the child expression is the only expression in the block + Node::Block(block) if block.stmts.is_empty() && block.expr.map(|e| e.hir_id) == Some(child_hir_id) => { + ControlFlow::Continue(block.hir_id) + }, + Node::Expr(expr) if matches!(expr.kind, ExprKind::Block(..)) => ControlFlow::Continue(expr.hir_id), + Node::Expr(expr) if matches!(expr.kind, ExprKind::Closure(_)) => ControlFlow::Break(Some(expr)), + _ => ControlFlow::Break(None), + }) + .break_value()?; + is_parent_map_like(cx, parent_closure?) +} + +fn suggest_cloned_string_to_string(cx: &LateContext<'_>, span: rustc_span::Span) { + span_lint_and_sugg( + cx, + STRING_TO_STRING, + span, + "`to_string()` called on a `String`", + "try", + "cloned()".to_string(), + Applicability::MachineApplicable, + ); +} + impl<'tcx> LateLintPass<'tcx> for StringToString { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { if expr.span.from_expansion() { return; } - if let ExprKind::MethodCall(path, self_arg, [], _) = &expr.kind - && path.ident.name == sym::to_string - && let ty = cx.typeck_results().expr_ty(self_arg) - && is_type_lang_item(cx, ty, LangItem::String) - { - #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] - span_lint_and_then( - cx, - STRING_TO_STRING, - expr.span, - "`to_string()` called on a `String`", - |diag| { - diag.help("consider using `.clone()`"); - }, - ); + match &expr.kind { + ExprKind::MethodCall(path, self_arg, [], _) => { + if path.ident.name == sym::to_string + && let ty = cx.typeck_results().expr_ty(self_arg) + && is_type_lang_item(cx, ty.peel_refs(), LangItem::String) + { + if let Some(parent_span) = is_called_from_map_like(cx, expr) { + suggest_cloned_string_to_string(cx, parent_span); + } else { + #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] + span_lint_and_then( + cx, + STRING_TO_STRING, + expr.span, + "`to_string()` called on a `String`", + |diag| { + diag.help("consider using `.clone()`"); + }, + ); + } + } + }, + ExprKind::Path(QPath::TypeRelative(ty, segment)) => { + if segment.ident.name == sym::to_string + && let rustc_hir::TyKind::Path(QPath::Resolved(_, path)) = ty.peel_refs().kind + && let rustc_hir::def::Res::Def(_, def_id) = path.res + && cx + .tcx + .lang_items() + .get(LangItem::String) + .is_some_and(|lang_id| lang_id == def_id) + && let Some(parent_span) = is_parent_map_like(cx, expr) + { + suggest_cloned_string_to_string(cx, parent_span); + } + }, + _ => {}, } } } diff --git a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs index 82cc5155380..20bf3a0bff1 100644 --- a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs +++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs @@ -57,7 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray { } fn is_struct_with_trailing_zero_sized_array<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool { - if let ItemKind::Struct(data, _) = &item.kind + if let ItemKind::Struct(_, data, _) = &item.kind && let Some(last_field) = data.fields().last() && let field_ty = cx.tcx.normalize_erasing_regions( cx.typing_env(), diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index f961e1c4d1a..fa36c9a21f6 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -112,7 +112,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { // special handling for self trait bounds as these are not considered generics // ie. trait Foo: Display {} if let Item { - kind: ItemKind::Trait(_, _, _, bounds, ..), + kind: ItemKind::Trait(_, _, _, _, bounds, ..), .. } = item { @@ -133,7 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { .. }) = segments.first() && let Some(Node::Item(Item { - kind: ItemKind::Trait(_, _, _, self_bounds, _), + kind: ItemKind::Trait(_, _, _, _, self_bounds, _), .. })) = cx.tcx.hir_get_if_local(*def_id) { diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 151a6f67437..b6f4c4d7f0a 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -61,10 +61,6 @@ declare_clippy_lint! { /// `Vec` already keeps its contents in a separate area on /// the heap. So if you `Box` its contents, you just add another level of indirection. /// - /// ### Known problems - /// Vec<Box<T: Sized>> makes sense if T is a large type (see [#3530](https://github.com/rust-lang/rust-clippy/issues/3530), - /// 1st comment). - /// /// ### Example /// ```no_run /// struct X { @@ -451,7 +447,7 @@ impl<'tcx> LateLintPass<'tcx> for Types { let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id); match item.kind { - ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _, _) => self.check_ty( + ItemKind::Static(_, ty, _, _) | ItemKind::Const(_, ty, _, _) => self.check_ty( cx, ty, CheckTyContext { diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs index a443043bef9..51c7d6fce31 100644 --- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs @@ -381,7 +381,7 @@ impl UnconditionalRecursion { implemented_ty_id, method_span, }; - walk_body(&mut c, body); + let _ = walk_body(&mut c, body); } } } diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index be533ca915e..a2938c86c76 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -312,6 +312,25 @@ fn expr_has_unnecessary_safety_comment<'tcx>( }, _, ) => ControlFlow::Break(()), + // `_ = foo()` is desugared to `{ let _ = foo(); }` + hir::ExprKind::Block( + Block { + rules: BlockCheckMode::DefaultBlock, + stmts: + [ + hir::Stmt { + kind: + hir::StmtKind::Let(hir::LetStmt { + source: hir::LocalSource::AssignDesugar(_), + .. + }), + .. + }, + ], + .. + }, + _, + ) => ControlFlow::Continue(Descend::Yes), // statements will be handled by check_stmt itself again hir::ExprKind::Block(..) => ControlFlow::Continue(Descend::No), _ => ControlFlow::Continue(Descend::Yes), @@ -339,6 +358,33 @@ fn is_unsafe_from_proc_macro(cx: &LateContext<'_>, span: Span) -> bool { .is_none_or(|src| !src.starts_with("unsafe")) } +fn find_unsafe_block_parent_in_expr<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'tcx>, +) -> Option<(Span, HirId)> { + match cx.tcx.parent_hir_node(expr.hir_id) { + Node::LetStmt(hir::LetStmt { span, hir_id, .. }) + | Node::Expr(hir::Expr { + hir_id, + kind: hir::ExprKind::Assign(_, _, span), + .. + }) => Some((*span, *hir_id)), + Node::Expr(expr) => find_unsafe_block_parent_in_expr(cx, expr), + node if let Some((span, hir_id)) = span_and_hid_of_item_alike_node(&node) + && is_const_or_static(&node) => + { + Some((span, hir_id)) + }, + + _ => { + if is_branchy(expr) { + return None; + } + Some((expr.span, expr.hir_id)) + }, + } +} + // Checks if any parent {expression, statement, block, local, const, static} // has a safety comment fn block_parents_have_safety_comment( @@ -348,21 +394,7 @@ fn block_parents_have_safety_comment( id: HirId, ) -> bool { let (span, hir_id) = match cx.tcx.parent_hir_node(id) { - Node::Expr(expr) => match cx.tcx.parent_hir_node(expr.hir_id) { - Node::LetStmt(hir::LetStmt { span, hir_id, .. }) => (*span, *hir_id), - Node::Item(hir::Item { - kind: ItemKind::Const(..) | ItemKind::Static(..), - span, - owner_id, - .. - }) => (*span, cx.tcx.local_def_id_to_hir_id(owner_id.def_id)), - _ => { - if is_branchy(expr) { - return false; - } - (expr.span, expr.hir_id) - }, - }, + Node::Expr(expr) if let Some(inner) = find_unsafe_block_parent_in_expr(cx, expr) => inner, Node::Stmt(hir::Stmt { kind: hir::StmtKind::Let(hir::LetStmt { span, hir_id, .. }) @@ -371,12 +403,13 @@ fn block_parents_have_safety_comment( .. }) | Node::LetStmt(hir::LetStmt { span, hir_id, .. }) => (*span, *hir_id), - Node::Item(hir::Item { - kind: ItemKind::Const(..) | ItemKind::Static(..), - span, - owner_id, - .. - }) => (*span, cx.tcx.local_def_id_to_hir_id(owner_id.def_id)), + + node if let Some((span, hir_id)) = span_and_hid_of_item_alike_node(&node) + && is_const_or_static(&node) => + { + (span, hir_id) + }, + _ => return false, }; // if unsafe block is part of a let/const/static statement, @@ -427,11 +460,12 @@ fn block_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool { } fn include_attrs_in_span(cx: &LateContext<'_>, hir_id: HirId, span: Span) -> Span { - span.to(cx - .tcx - .hir_attrs(hir_id) - .iter() - .fold(span, |acc, attr| acc.to(attr.span()))) + span.to(cx.tcx.hir_attrs(hir_id).iter().fold(span, |acc, attr| { + if attr.is_doc_comment() { + return acc; + } + acc.to(attr.span()) + })) } enum HasSafetyComment { @@ -454,7 +488,7 @@ fn item_has_safety_comment(cx: &LateContext<'_>, item: &hir::Item<'_>) -> HasSaf let comment_start = match cx.tcx.parent_hir_node(item.hir_id()) { Node::Crate(parent_mod) => comment_start_before_item_in_mod(cx, parent_mod, parent_mod.spans.inner_span, item), Node::Item(parent_item) => { - if let ItemKind::Mod(parent_mod) = &parent_item.kind { + if let ItemKind::Mod(_, parent_mod) = &parent_item.kind { comment_start_before_item_in_mod(cx, parent_mod, parent_item.span, item) } else { // Doesn't support impls in this position. Pretend a comment was found. @@ -603,31 +637,35 @@ fn span_from_macro_expansion_has_safety_comment(cx: &LateContext<'_>, span: Span fn get_body_search_span(cx: &LateContext<'_>) -> Option<Span> { let body = cx.enclosing_body?; - let mut span = cx.tcx.hir_body(body).value.span; - let mut maybe_global_var = false; - for (_, node) in cx.tcx.hir_parent_iter(body.hir_id) { - match node { - Node::Expr(e) => span = e.span, - Node::Block(_) | Node::Arm(_) | Node::Stmt(_) | Node::LetStmt(_) => (), - Node::Item(hir::Item { - kind: ItemKind::Const(..) | ItemKind::Static(..), - .. - }) => maybe_global_var = true, + let mut maybe_mod_item = None; + + for (_, parent_node) in cx.tcx.hir_parent_iter(body.hir_id) { + match parent_node { + Node::Crate(mod_) => return Some(mod_.spans.inner_span), Node::Item(hir::Item { - kind: ItemKind::Mod(_), - span: item_span, + kind: ItemKind::Mod(_, mod_), + span, .. }) => { - span = *item_span; - break; + return maybe_mod_item + .and_then(|item| comment_start_before_item_in_mod(cx, mod_, *span, &item)) + .map(|comment_start| mod_.spans.inner_span.with_lo(comment_start)) + .or(Some(*span)); }, - Node::Crate(mod_) if maybe_global_var => { - span = mod_.spans.inner_span; + node if let Some((span, _)) = span_and_hid_of_item_alike_node(&node) + && !is_const_or_static(&node) => + { + return Some(span); + }, + Node::Item(item) => { + maybe_mod_item = Some(*item); + }, + _ => { + maybe_mod_item = None; }, - _ => break, } } - Some(span) + None } fn span_has_safety_comment(cx: &LateContext<'_>, span: Span) -> bool { @@ -716,3 +754,28 @@ fn text_has_safety_comment(src: &str, line_starts: &[RelativeBytePos], start_pos } } } + +fn span_and_hid_of_item_alike_node(node: &Node<'_>) -> Option<(Span, HirId)> { + match node { + Node::Item(item) => Some((item.span, item.owner_id.into())), + Node::TraitItem(ti) => Some((ti.span, ti.owner_id.into())), + Node::ImplItem(ii) => Some((ii.span, ii.owner_id.into())), + _ => None, + } +} + +fn is_const_or_static(node: &Node<'_>) -> bool { + matches!( + node, + Node::Item(hir::Item { + kind: ItemKind::Const(..) | ItemKind::Static(..), + .. + }) | Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Const(..), + .. + }) | Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Const(..), + .. + }) + ) +} diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs index 4158050f969..2b7d3dc0c90 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs @@ -130,9 +130,9 @@ impl LateLintPass<'_> for UnnecessaryBoxReturns { } fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { - let ItemKind::Fn { sig, .. } = &item.kind else { + let ItemKind::Fn { ident, sig, .. } = &item.kind else { return; }; - self.check_fn_item(cx, sig.decl, item.owner_id.def_id, item.ident.name); + self.check_fn_item(cx, sig.decl, item.owner_id.def_id, ident.name); } } diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_semicolon.rs b/src/tools/clippy/clippy_lints/src/unnecessary_semicolon.rs index e5267620c4f..f1d1a76d0c2 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_semicolon.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_semicolon.rs @@ -26,7 +26,7 @@ declare_clippy_lint! { /// ```no_run /// # let a: u32 = 42; /// if a > 10 { - /// println!("a is greater than 10"); + /// println!("a is greater than 10"); /// } /// ``` #[clippy::version = "1.86.0"] diff --git a/src/tools/clippy/clippy_lints/src/unneeded_struct_pattern.rs b/src/tools/clippy/clippy_lints/src/unneeded_struct_pattern.rs index a74eab8b6ae..3326dea8c5d 100644 --- a/src/tools/clippy/clippy_lints/src/unneeded_struct_pattern.rs +++ b/src/tools/clippy/clippy_lints/src/unneeded_struct_pattern.rs @@ -51,7 +51,7 @@ impl LateLintPass<'_> for UnneededStructPattern { let variant = cx.tcx.adt_def(enum_did).variant_with_id(did); let has_only_fields_brackets = variant.ctor.is_some() && variant.fields.is_empty(); - let non_exhaustive_activated = !variant.def_id.is_local() && variant.is_field_list_non_exhaustive(); + let non_exhaustive_activated = variant.field_list_has_applicable_non_exhaustive(); if !has_only_fields_brackets || non_exhaustive_activated { return; } diff --git a/src/tools/clippy/clippy_lints/src/unused_trait_names.rs b/src/tools/clippy/clippy_lints/src/unused_trait_names.rs index 2577f1ceaa2..14ac65cf4df 100644 --- a/src/tools/clippy/clippy_lints/src/unused_trait_names.rs +++ b/src/tools/clippy/clippy_lints/src/unused_trait_names.rs @@ -60,9 +60,9 @@ impl_lint_pass!(UnusedTraitNames => [UNUSED_TRAIT_NAMES]); impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { if !item.span.in_external_macro(cx.sess().source_map()) - && let ItemKind::Use(path, UseKind::Single) = item.kind + && let ItemKind::Use(path, UseKind::Single(ident)) = item.kind // Ignore imports that already use Underscore - && item.ident.name != kw::Underscore + && ident.name != kw::Underscore // Only check traits && let Some(Res::Def(DefKind::Trait, _)) = path.res.first() && cx.tcx.maybe_unused_trait_imports(()).contains(&item.owner_id.def_id) @@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames { && self.msrv.meets(cx, msrvs::UNDERSCORE_IMPORTS) && !is_from_proc_macro(cx, &last_segment.ident) { - let complete_span = last_segment.ident.span.to(item.ident.span); + let complete_span = last_segment.ident.span.to(ident.span); span_lint_and_sugg( cx, UNUSED_TRAIT_NAMES, diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs index 3449468ef48..8922478e718 100644 --- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs +++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs @@ -131,11 +131,11 @@ impl LateLintPass<'_> for UpperCaseAcronyms { return; } match it.kind { - ItemKind::TyAlias(..) | ItemKind::Struct(..) | ItemKind::Trait(..) => { - check_ident(cx, &it.ident, it.hir_id(), self.upper_case_acronyms_aggressive); + ItemKind::TyAlias(ident, ..) | ItemKind::Struct(ident, ..) | ItemKind::Trait(_, _, ident, ..) => { + check_ident(cx, &ident, it.hir_id(), self.upper_case_acronyms_aggressive); }, - ItemKind::Enum(ref enumdef, _) => { - check_ident(cx, &it.ident, it.hir_id(), self.upper_case_acronyms_aggressive); + ItemKind::Enum(ident, ref enumdef, _) => { + check_ident(cx, &ident, it.hir_id(), self.upper_case_acronyms_aggressive); // check enum variants separately because again we only want to lint on private enums and // the fn check_variant does not know about the vis of the enum of its variants enumdef.variants.iter().for_each(|variant| { diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs index 5e452c6d2ac..57bb2fc27f1 100644 --- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs +++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::{snippet, snippet_with_context}; use clippy_utils::sugg::{DiagExt as _, Sugg}; -use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts}; +use clippy_utils::ty::{get_type_diagnostic_name, is_copy, is_type_diagnostic_item, same_type_and_consts}; use clippy_utils::{ get_parent_expr, is_inherent_method_call, is_trait_item, is_trait_method, is_ty_alias, path_to_local, }; @@ -13,7 +13,7 @@ use rustc_infer::traits::Obligation; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::adjustment::{Adjust, AutoBorrow, AutoBorrowMutability}; -use rustc_middle::ty::{self, AdtDef, EarlyBinder, GenericArg, GenericArgsRef, Ty, TypeVisitableExt}; +use rustc_middle::ty::{self, EarlyBinder, GenericArg, GenericArgsRef, Ty, TypeVisitableExt}; use rustc_session::impl_lint_pass; use rustc_span::{Span, sym}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; @@ -412,24 +412,14 @@ pub fn check_function_application(cx: &LateContext<'_>, expr: &Expr<'_>, recv: & } fn has_eligible_receiver(cx: &LateContext<'_>, recv: &Expr<'_>, expr: &Expr<'_>) -> bool { - let recv_ty = cx.typeck_results().expr_ty(recv); - if is_inherent_method_call(cx, expr) - && let Some(recv_ty_defid) = recv_ty.ty_adt_def().map(AdtDef::did) - { - if let Some(diag_name) = cx.tcx.get_diagnostic_name(recv_ty_defid) - && matches!(diag_name, sym::Option | sym::Result) - { - return true; - } - - if cx.tcx.is_diagnostic_item(sym::ControlFlow, recv_ty_defid) { - return true; - } - } - if is_trait_method(cx, expr, sym::Iterator) { - return true; + if is_inherent_method_call(cx, expr) { + matches!( + get_type_diagnostic_name(cx, cx.typeck_results().expr_ty(recv)), + Some(sym::Option | sym::Result | sym::ControlFlow) + ) + } else { + is_trait_method(cx, expr, sym::Iterator) } - false } fn adjustments(cx: &LateContext<'_>, expr: &Expr<'_>) -> String { diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs index bfcce81c498..0a01a364a75 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs @@ -44,11 +44,10 @@ impl AlmostStandardFormulation { impl<'tcx> LateLintPass<'tcx> for AlmostStandardFormulation { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { let mut check_next = false; - if let ItemKind::Static(ty, Mutability::Not, _) = item.kind { + if let ItemKind::Static(_, ty, Mutability::Not, _) = item.kind { let lines = cx .tcx - .hir() - .attrs(item.hir_id()) + .hir_attrs(item.hir_id()) .iter() .filter_map(|attr| Attribute::doc_str(attr).map(|sym| (sym, attr))); if is_lint_ref_type(cx, ty) { diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs index 16d51fa0902..94a2e598522 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs @@ -104,7 +104,7 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { return; } - if let hir::ItemKind::Static(ty, Mutability::Not, body_id) = item.kind { + if let hir::ItemKind::Static(ident, ty, Mutability::Not, body_id) = item.kind { if is_lint_ref_type(cx, ty) { check_invalid_clippy_version_attribute(cx, item); @@ -133,10 +133,10 @@ impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass { cx, DEFAULT_LINT, item.span, - format!("the lint `{}` has the default lint description", item.ident.name), + format!("the lint `{}` has the default lint description", ident.name), ); } - self.declared_lints.insert(item.ident.name, item.span); + self.declared_lints.insert(ident.name, item.span); } } } else if let Some(macro_call) = root_macro_call_first_node(cx, item) { diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/produce_ice.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/produce_ice.rs index 9169e2968eb..0a07919d659 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/produce_ice.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/produce_ice.rs @@ -1,6 +1,6 @@ use rustc_ast::ast::NodeId; use rustc_ast::visit::FnKind; -use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::declare_lint_pass; use rustc_span::Span; @@ -24,8 +24,12 @@ declare_clippy_lint! { declare_lint_pass!(ProduceIce => [PRODUCE_ICE]); impl EarlyLintPass for ProduceIce { - fn check_fn(&mut self, _: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: Span, _: NodeId) { - assert!(!is_trigger_fn(fn_kind), "Would you like some help with that?"); + fn check_fn(&mut self, ctx: &EarlyContext<'_>, fn_kind: FnKind<'_>, span: Span, _: NodeId) { + if is_trigger_fn(fn_kind) { + ctx.sess() + .dcx() + .span_delayed_bug(span, "Would you like some help with that?"); + } } } diff --git a/src/tools/clippy/clippy_utils/README.md b/src/tools/clippy/clippy_utils/README.md index 5dd31b52f88..7c665b42497 100644 --- a/src/tools/clippy/clippy_utils/README.md +++ b/src/tools/clippy/clippy_utils/README.md @@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain: <!-- begin autogenerated nightly --> ``` -nightly-2025-02-27 +nightly-2025-03-20 ``` <!-- end autogenerated nightly --> @@ -30,7 +30,7 @@ Function signatures can change or be removed without replacement without any pri <!-- REUSE-IgnoreStart --> -Copyright 2014-2024 The Rust Project Developers +Copyright 2014-2025 The Rust Project Developers Licensed under the Apache License, Version 2.0 <[https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)> or the MIT license diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index 707312a97f3..54261079fca 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -201,7 +201,8 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool { (Loop(lt, ll, _), Loop(rt, rl, _)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_block(lt, rt), (Block(lb, ll), Block(rb, rl)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_block(lb, rb), (TryBlock(l), TryBlock(r)) => eq_block(l, r), - (Yield(l), Yield(r)) | (Ret(l), Ret(r)) => eq_expr_opt(l.as_ref(), r.as_ref()), + (Yield(l), Yield(r)) => eq_expr_opt(l.expr(), r.expr()) && l.same_kind(r), + (Ret(l), Ret(r)) => eq_expr_opt(l.as_ref(), r.as_ref()), (Break(ll, le), Break(rl, re)) => eq_label(ll.as_ref(), rl.as_ref()) && eq_expr_opt(le.as_ref(), re.as_ref()), (Continue(ll), Continue(rl)) => eq_label(ll.as_ref(), rl.as_ref()), (Assign(l1, l2, _), Assign(r1, r2, _)) | (Index(l1, l2, _), Index(r1, r2, _)) => { @@ -688,7 +689,7 @@ pub fn eq_generics(l: &Generics, r: &Generics) -> bool { pub fn eq_where_predicate(l: &WherePredicate, r: &WherePredicate) -> bool { use WherePredicateKind::*; - over(&l.attrs, &r.attrs, eq_attr) + over(&l.attrs, &r.attrs, eq_attr) && match (&l.kind, &r.kind) { (BoundPredicate(l), BoundPredicate(r)) => { over(&l.bound_generic_params, &r.bound_generic_params, |l, r| { diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index 4f48fb3b8a9..004c840c331 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -242,14 +242,14 @@ fn fn_header_search_pat(header: FnHeader) -> Pat { fn item_search_pat(item: &Item<'_>) -> (Pat, Pat) { let (start_pat, end_pat) = match &item.kind { - ItemKind::ExternCrate(_) => (Pat::Str("extern"), Pat::Str(";")), + ItemKind::ExternCrate(..) => (Pat::Str("extern"), Pat::Str(";")), ItemKind::Static(..) => (Pat::Str("static"), Pat::Str(";")), ItemKind::Const(..) => (Pat::Str("const"), Pat::Str(";")), ItemKind::Fn { sig, .. } => (fn_header_search_pat(sig.header), Pat::Str("")), ItemKind::ForeignMod { .. } => (Pat::Str("extern"), Pat::Str("}")), ItemKind::TyAlias(..) => (Pat::Str("type"), Pat::Str(";")), ItemKind::Enum(..) => (Pat::Str("enum"), Pat::Str("}")), - ItemKind::Struct(VariantData::Struct { .. }, _) => (Pat::Str("struct"), Pat::Str("}")), + ItemKind::Struct(_, VariantData::Struct { .. }, _) => (Pat::Str("struct"), Pat::Str("}")), ItemKind::Struct(..) => (Pat::Str("struct"), Pat::Str(";")), ItemKind::Union(..) => (Pat::Str("union"), Pat::Str("}")), ItemKind::Trait(_, Safety::Unsafe, ..) diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index ddb7a6635e0..292792408c6 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -85,7 +85,7 @@ fn validate_diag(diag: &Diag<'_, impl EmissionGuarantee>) { /// This is needed for `#[allow]` and `#[expect]` attributes to work on the node /// highlighted in the displayed warning. /// -/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works +/// If you're unsure which function you should use, you can test if the `#[expect]` attribute works /// where you would expect it to. /// If it doesn't, you likely need to use [`span_lint_hir`] instead. /// @@ -128,7 +128,7 @@ pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<Mult /// This is needed for `#[allow]` and `#[expect]` attributes to work on the node /// highlighted in the displayed warning. /// -/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works +/// If you're unsure which function you should use, you can test if the `#[expect]` attribute works /// where you would expect it to. /// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead. /// @@ -183,7 +183,7 @@ pub fn span_lint_and_help<T: LintContext>( /// This is needed for `#[allow]` and `#[expect]` attributes to work on the node /// highlighted in the displayed warning. /// -/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works +/// If you're unsure which function you should use, you can test if the `#[expect]` attribute works /// where you would expect it to. /// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead. /// @@ -241,7 +241,7 @@ pub fn span_lint_and_note<T: LintContext>( /// This is needed for `#[allow]` and `#[expect]` attributes to work on the node /// highlighted in the displayed warning. /// -/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works +/// If you're unsure which function you should use, you can test if the `#[expect]` attribute works /// where you would expect it to. /// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead. pub fn span_lint_and_then<C, S, M, F>(cx: &C, lint: &'static Lint, sp: S, msg: M, f: F) @@ -358,7 +358,7 @@ pub fn span_lint_hir_and_then( /// This is needed for `#[allow]` and `#[expect]` attributes to work on the node /// highlighted in the displayed warning. /// -/// If you're unsure which function you should use, you can test if the `#[allow]` attribute works +/// If you're unsure which function you should use, you can test if the `#[expect]` attribute works /// where you would expect it to. /// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead. /// diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 80613a51c14..1307ff79bc5 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -106,10 +106,10 @@ use rustc_hir::hir_id::{HirIdMap, HirIdSet}; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr}; use rustc_hir::{ self as hir, Arm, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext, - Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, - ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat, - PatExpr, PatExprKind, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitFn, TraitItem, TraitItemKind, - TraitItemRef, TraitRef, TyKind, UnOp, def, + Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArg, GenericArgs, HirId, Impl, ImplItem, + ImplItemKind, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, + Param, Pat, PatExpr, PatExprKind, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitFn, TraitItem, + TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp, def, }; use rustc_lexer::{TokenKind, tokenize}; use rustc_lint::{LateContext, Level, Lint, LintContext}; @@ -434,7 +434,7 @@ pub fn qpath_generic_tys<'tcx>(qpath: &QPath<'tcx>) -> impl Iterator<Item = &'tc .map_or(&[][..], |a| a.args) .iter() .filter_map(|a| match a { - hir::GenericArg::Type(ty) => Some(ty.as_unambig_ty()), + GenericArg::Type(ty) => Some(ty.as_unambig_ty()), _ => None, }) } @@ -644,7 +644,7 @@ fn local_item_children_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, name: Symb let root_mod; let item_kind = match tcx.hir_node_by_def_id(local_id) { Node::Crate(r#mod) => { - root_mod = ItemKind::Mod(r#mod); + root_mod = ItemKind::Mod(Ident::dummy(), r#mod); &root_mod }, Node::Item(item) => &item.kind, @@ -661,10 +661,13 @@ fn local_item_children_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, name: Symb }; match item_kind { - ItemKind::Mod(r#mod) => r#mod + ItemKind::Mod(_, r#mod) => r#mod .item_ids .iter() - .filter_map(|&item_id| res(tcx.hir_item(item_id).ident, item_id.owner_id)) + .filter_map(|&item_id| { + let ident = tcx.hir_item(item_id).kind.ident()?; + res(ident, item_id.owner_id) + }) .collect(), ItemKind::Impl(r#impl) => r#impl .items @@ -1416,9 +1419,8 @@ pub fn is_in_panic_handler(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> { let parent_id = cx.tcx.hir_get_parent_item(expr.hir_id).def_id; match cx.tcx.hir_node_by_def_id(parent_id) { - Node::Item(Item { ident, .. }) - | Node::TraitItem(TraitItem { ident, .. }) - | Node::ImplItem(ImplItem { ident, .. }) => Some(ident.name), + Node::Item(item) => item.kind.ident().map(|ident| ident.name), + Node::TraitItem(TraitItem { ident, .. }) | Node::ImplItem(ImplItem { ident, .. }) => Some(ident.name), _ => None, } } @@ -2331,6 +2333,18 @@ pub fn is_expr_final_block_expr(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { matches!(tcx.parent_hir_node(expr.hir_id), Node::Block(..)) } +/// Checks if the expression is a temporary value. +// This logic is the same as the one used in rustc's `check_named_place_expr function`. +// https://github.com/rust-lang/rust/blob/3ed2a10d173d6c2e0232776af338ca7d080b1cd4/compiler/rustc_hir_typeck/src/expr.rs#L482-L499 +pub fn is_expr_temporary_value(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { + !expr.is_place_expr(|base| { + cx.typeck_results() + .adjustments() + .get(base.hir_id) + .is_some_and(|x| x.iter().any(|adj| matches!(adj.kind, Adjust::Deref(_)))) + }) +} + pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> { if !is_no_std_crate(cx) { Some("std") @@ -2634,7 +2648,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Sym for id in tcx.hir_module_free_items(module) { if matches!(tcx.def_kind(id.owner_id), DefKind::Const) && let item = tcx.hir_item(id) - && let ItemKind::Const(ty, _generics, _body) = item.kind + && let ItemKind::Const(ident, ty, _generics, _body) = item.kind { if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind { // We could also check for the type name `test::TestDescAndFn` @@ -2644,7 +2658,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Sym .iter() .any(|a| a.has_name(sym::rustc_test_marker)); if has_test_marker { - names.push(item.ident.name); + names.push(ident.name); } } } @@ -2668,10 +2682,10 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool { // function scope .any(|(_id, node)| { if let Node::Item(item) = node { - if let ItemKind::Fn { .. } = item.kind { + if let ItemKind::Fn { ident, .. } = item.kind { // Note that we have sorted the item names in the visitor, // so the binary_search gets the same as `contains`, but faster. - return names.binary_search(&item.ident.name).is_ok(); + return names.binary_search(&ident.name).is_ok(); } } false @@ -3545,7 +3559,7 @@ pub fn is_block_like(expr: &Expr<'_>) -> bool { pub fn binary_expr_needs_parentheses(expr: &Expr<'_>) -> bool { fn contains_block(expr: &Expr<'_>, is_operand: bool) -> bool { match expr.kind { - ExprKind::Binary(_, lhs, _) => contains_block(lhs, true), + ExprKind::Binary(_, lhs, _) | ExprKind::Cast(lhs, _) => contains_block(lhs, true), _ if is_block_like(expr) => is_operand, _ => false, } @@ -3692,3 +3706,21 @@ pub fn is_mutable(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { true } } + +/// Peel `Option<…>` from `hir_ty` as long as the HIR name is `Option` and it corresponds to the +/// `core::Option<_>` type. +pub fn peel_hir_ty_options<'tcx>(cx: &LateContext<'tcx>, mut hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> { + let Some(option_def_id) = cx.tcx.get_diagnostic_item(sym::Option) else { + return hir_ty; + }; + while let TyKind::Path(QPath::Resolved(None, path)) = hir_ty.kind + && let Some(segment) = path.segments.last() + && segment.ident.name == sym::Option + && let Res::Def(DefKind::Enum, def_id) = segment.res + && def_id == option_def_id + && let [GenericArg::Type(arg_ty)] = segment.args().args + { + hir_ty = arg_ty.as_unambig_ty(); + } + hir_ty +} diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs index 605764cef89..152b4272c26 100644 --- a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs +++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs @@ -6,8 +6,7 @@ use rustc_index::bit_set::DenseBitSet; use rustc_lint::LateContext; use rustc_middle::mir::visit::Visitor as _; use rustc_middle::mir::{self, Mutability}; -use rustc_middle::ty::visit::TypeVisitor; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt, TypeVisitor}; use rustc_mir_dataflow::impls::MaybeStorageLive; use rustc_mir_dataflow::{Analysis, ResultsCursor}; use std::borrow::Cow; diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs index 0316de172de..86f4f190b95 100644 --- a/src/tools/clippy/clippy_utils/src/msrvs.rs +++ b/src/tools/clippy/clippy_utils/src/msrvs.rs @@ -33,7 +33,7 @@ msrv_aliases! { 1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT } 1,75,0 { OPTION_AS_SLICE } 1,74,0 { REPR_RUST, IO_ERROR_OTHER } - 1,73,0 { MANUAL_DIV_CEIL } + 1,73,0 { DIV_CEIL } 1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE } 1,70,0 { OPTION_RESULT_IS_VARIANT_AND, BINARY_HEAP_RETAIN } 1,68,0 { PATH_MAIN_SEPARATOR_STR } @@ -74,6 +74,7 @@ msrv_aliases! { 1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST, EXPECT_ERR } 1,16,0 { STR_REPEAT } 1,15,0 { MAYBE_BOUND_IN_WHERE } + 1,13,0 { QUESTION_MARK_OPERATOR } } /// `#[clippy::msrv]` attributes are rarely used outside of Clippy's test suite, as a basic diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 8e6f4d4a317..5d0401010db 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -395,24 +395,32 @@ fn check_terminator<'tcx>( fn is_stable_const_fn(cx: &LateContext<'_>, def_id: DefId, msrv: Msrv) -> bool { cx.tcx.is_const_fn(def_id) - && cx.tcx.lookup_const_stability(def_id).is_none_or(|const_stab| { - if let rustc_attr_parsing::StabilityLevel::Stable { since, .. } = const_stab.level { - // Checking MSRV is manually necessary because `rustc` has no such concept. This entire - // function could be removed if `rustc` provided a MSRV-aware version of `is_stable_const_fn`. - // as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262. + && cx + .tcx + .lookup_const_stability(def_id) + .or_else(|| { + cx.tcx + .trait_of_item(def_id) + .and_then(|trait_def_id| cx.tcx.lookup_const_stability(trait_def_id)) + }) + .is_none_or(|const_stab| { + if let rustc_attr_parsing::StabilityLevel::Stable { since, .. } = const_stab.level { + // Checking MSRV is manually necessary because `rustc` has no such concept. This entire + // function could be removed if `rustc` provided a MSRV-aware version of `is_stable_const_fn`. + // as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262. - let const_stab_rust_version = match since { - StableSince::Version(version) => version, - StableSince::Current => RustcVersion::CURRENT, - StableSince::Err => return false, - }; + let const_stab_rust_version = match since { + StableSince::Version(version) => version, + StableSince::Current => RustcVersion::CURRENT, + StableSince::Err => return false, + }; - msrv.meets(cx, const_stab_rust_version) - } else { - // Unstable const fn, check if the feature is enabled. - cx.tcx.features().enabled(const_stab.feature) && msrv.current(cx).is_none() - } - }) + msrv.meets(cx, const_stab_rust_version) + } else { + // Unstable const fn, check if the feature is enabled. + cx.tcx.features().enabled(const_stab.feature) && msrv.current(cx).is_none() + } + }) } fn is_ty_const_destruct<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, body: &Body<'tcx>) -> bool { diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index 9cc66593dcc..68a1de96a35 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -4,8 +4,8 @@ use crate::source::{snippet, snippet_opt, snippet_with_applicability, snippet_with_context}; use crate::ty::expr_sig; use crate::{get_parent_expr_for_hir, higher}; -use rustc_ast::util::parser::AssocOp; use rustc_ast::ast; +use rustc_ast::util::parser::AssocOp; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::{Closure, ExprKind, HirId, MutTy, TyKind}; @@ -444,7 +444,7 @@ impl<'a> Not for Sugg<'a> { type Output = Sugg<'a>; fn not(self) -> Sugg<'a> { use AssocOp::Binary; - use ast::BinOpKind::{Eq, Gt, Ge, Lt, Le, Ne}; + use ast::BinOpKind::{Eq, Ge, Gt, Le, Lt, Ne}; if let Sugg::BinOp(op, lhs, rhs) = self { let to_op = match op { @@ -515,10 +515,10 @@ pub fn make_assoc(op: AssocOp, lhs: &Sugg<'_>, rhs: &Sugg<'_>) -> Sugg<'static> op, AssocOp::Binary( ast::BinOpKind::Add - | ast::BinOpKind::Sub - | ast::BinOpKind::Mul - | ast::BinOpKind::Div - | ast::BinOpKind::Rem + | ast::BinOpKind::Sub + | ast::BinOpKind::Mul + | ast::BinOpKind::Div + | ast::BinOpKind::Rem ) ) } @@ -578,10 +578,8 @@ enum Associativity { /// associative. #[must_use] fn associativity(op: AssocOp) -> Associativity { + use ast::BinOpKind::{Add, And, BitAnd, BitOr, BitXor, Div, Eq, Ge, Gt, Le, Lt, Mul, Ne, Or, Rem, Shl, Shr, Sub}; use rustc_ast::util::parser::AssocOp::{Assign, AssignOp, Binary, Cast, Range}; - use ast::BinOpKind::{ - Add, BitAnd, BitOr, BitXor, Div, Eq, Gt, Ge, And, Or, Lt, Le, Rem, Mul, Ne, Shl, Shr, Sub, - }; match op { Assign | AssignOp(_) => Associativity::Right, @@ -994,6 +992,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> { mod test { use super::Sugg; + use rustc_ast as ast; use rustc_ast::util::parser::AssocOp; use std::borrow::Cow; @@ -1011,15 +1010,15 @@ mod test { #[test] fn binop_maybe_par() { - let sugg = Sugg::BinOp(AssocOp::Add, "1".into(), "1".into()); + let sugg = Sugg::BinOp(AssocOp::Binary(ast::BinOpKind::Add), "1".into(), "1".into()); assert_eq!("(1 + 1)", sugg.maybe_par().to_string()); - let sugg = Sugg::BinOp(AssocOp::Add, "(1 + 1)".into(), "(1 + 1)".into()); + let sugg = Sugg::BinOp(AssocOp::Binary(ast::BinOpKind::Add), "(1 + 1)".into(), "(1 + 1)".into()); assert_eq!("((1 + 1) + (1 + 1))", sugg.maybe_par().to_string()); } #[test] fn not_op() { - use AssocOp::{Add, Equal, Greater, GreaterEqual, LAnd, LOr, Less, LessEqual, NotEqual}; + use ast::BinOpKind::{Add, And, Eq, Ge, Gt, Le, Lt, Ne, Or}; fn test_not(op: AssocOp, correct: &str) { let sugg = Sugg::BinOp(op, "x".into(), "y".into()); @@ -1027,16 +1026,16 @@ mod test { } // Invert the comparison operator. - test_not(Equal, "x != y"); - test_not(NotEqual, "x == y"); - test_not(Less, "x >= y"); - test_not(LessEqual, "x > y"); - test_not(Greater, "x <= y"); - test_not(GreaterEqual, "x < y"); + test_not(AssocOp::Binary(Eq), "x != y"); + test_not(AssocOp::Binary(Ne), "x == y"); + test_not(AssocOp::Binary(Lt), "x >= y"); + test_not(AssocOp::Binary(Le), "x > y"); + test_not(AssocOp::Binary(Gt), "x <= y"); + test_not(AssocOp::Binary(Ge), "x < y"); // Other operators are inverted like !(..). - test_not(Add, "!(x + y)"); - test_not(LAnd, "!(x && y)"); - test_not(LOr, "!(x || y)"); + test_not(AssocOp::Binary(Add), "!(x + y)"); + test_not(AssocOp::Binary(And), "!(x && y)"); + test_not(AssocOp::Binary(Or), "!(x || y)"); } } diff --git a/src/tools/clippy/lintcheck/src/json.rs b/src/tools/clippy/lintcheck/src/json.rs index 3a68f2c9243..8ea0a41ed36 100644 --- a/src/tools/clippy/lintcheck/src/json.rs +++ b/src/tools/clippy/lintcheck/src/json.rs @@ -1,3 +1,9 @@ +//! JSON output and comparison functionality for Clippy warnings. +//! +//! This module handles serialization of Clippy warnings to JSON format, +//! loading warnings from JSON files, and generating human-readable diffs +//! between different linting runs. + use std::fs; use std::path::Path; @@ -8,8 +14,10 @@ use crate::ClippyWarning; /// This is the total number. 300 warnings results in 100 messages per section. const DEFAULT_LIMIT_PER_LINT: usize = 300; +/// Target for total warnings to display across all lints when truncating output. const TRUNCATION_TOTAL_TARGET: usize = 1000; +/// Representation of a single Clippy warning for JSON serialization. #[derive(Debug, Deserialize, Serialize)] struct LintJson { /// The lint name e.g. `clippy::bytes_nth` @@ -21,10 +29,12 @@ struct LintJson { } impl LintJson { + /// Returns a tuple of name and `file_line` for sorting and comparison. fn key(&self) -> impl Ord + '_ { (self.name.as_str(), self.file_line.as_str()) } + /// Formats the warning information with an action verb for display. fn info_text(&self, action: &str) -> String { format!("{action} `{}` at [`{}`]({})", self.name, self.file_line, self.file_url) } @@ -53,12 +63,17 @@ pub(crate) fn output(clippy_warnings: Vec<ClippyWarning>) -> String { serde_json::to_string(&lints).unwrap() } +/// Loads lint warnings from a JSON file at the given path. fn load_warnings(path: &Path) -> Vec<LintJson> { let file = fs::read(path).unwrap_or_else(|e| panic!("failed to read {}: {e}", path.display())); serde_json::from_slice(&file).unwrap_or_else(|e| panic!("failed to deserialize {}: {e}", path.display())) } +/// Generates and prints a diff between two sets of lint warnings. +/// +/// Compares warnings from `old_path` and `new_path`, then displays a summary table +/// and detailed information about added, removed, and changed warnings. pub(crate) fn diff(old_path: &Path, new_path: &Path, truncate: bool) { let old_warnings = load_warnings(old_path); let new_warnings = load_warnings(new_path); @@ -116,6 +131,7 @@ pub(crate) fn diff(old_path: &Path, new_path: &Path, truncate: bool) { } } +/// Container for grouped lint warnings organized by status (added/removed/changed). #[derive(Debug)] struct LintWarnings { name: String, @@ -124,6 +140,7 @@ struct LintWarnings { changed: Vec<(LintJson, LintJson)>, } +/// Prints a formatted report for a single lint type with its warnings. fn print_lint_warnings(lint: &LintWarnings, truncate_after: usize) { let name = &lint.name; let html_id = to_html_id(name); @@ -145,6 +162,7 @@ fn print_lint_warnings(lint: &LintWarnings, truncate_after: usize) { print_changed_diff(&lint.changed, truncate_after / 3); } +/// Prints a summary table of all lints with counts of added, removed, and changed warnings. fn print_summary_table(lints: &[LintWarnings]) { println!("| Lint | Added | Removed | Changed |"); println!("| ------------------------------------------ | ------: | ------: | ------: |"); @@ -160,6 +178,7 @@ fn print_summary_table(lints: &[LintWarnings]) { } } +/// Prints a section of warnings with a header and formatted code blocks. fn print_warnings(title: &str, warnings: &[LintJson], truncate_after: usize) { if warnings.is_empty() { return; @@ -180,6 +199,7 @@ fn print_warnings(title: &str, warnings: &[LintJson], truncate_after: usize) { } } +/// Prints a section of changed warnings with unified diff format. fn print_changed_diff(changed: &[(LintJson, LintJson)], truncate_after: usize) { if changed.is_empty() { return; @@ -213,6 +233,7 @@ fn print_changed_diff(changed: &[(LintJson, LintJson)], truncate_after: usize) { } } +/// Truncates a list to a maximum number of items and prints a message about truncation. fn truncate<T>(list: &[T], truncate_after: usize) -> &[T] { if list.len() > truncate_after { println!( @@ -227,6 +248,7 @@ fn truncate<T>(list: &[T], truncate_after: usize) -> &[T] { } } +/// Prints a level 3 heading with an appropriate HTML ID for linking. fn print_h3(lint: &str, title: &str) { let html_id = to_html_id(lint); // We have to use HTML here to be able to manually add an id. diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain index a4931499c80..fcaeedc9a66 100644 --- a/src/tools/clippy/rust-toolchain +++ b/src/tools/clippy/rust-toolchain @@ -1,6 +1,6 @@ [toolchain] # begin autogenerated nightly -channel = "nightly-2025-02-27" +channel = "nightly-2025-03-20" # end autogenerated nightly components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" diff --git a/src/tools/clippy/rustc_tools_util/README.md b/src/tools/clippy/rustc_tools_util/README.md index ff4ca6f830e..f47a4c69c2c 100644 --- a/src/tools/clippy/rustc_tools_util/README.md +++ b/src/tools/clippy/rustc_tools_util/README.md @@ -51,7 +51,7 @@ The changelog for `rustc_tools_util` is available under: <!-- REUSE-IgnoreStart --> -Copyright 2014-2024 The Rust Project Developers +Copyright 2014-2025 The Rust Project Developers Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs index f44cf7a7c25..956a05288f3 100644 --- a/src/tools/clippy/tests/compile-test.rs +++ b/src/tools/clippy/tests/compile-test.rs @@ -16,7 +16,7 @@ use test_utils::IS_RUSTC_TEST_SUITE; use ui_test::custom_flags::Flag; use ui_test::custom_flags::rustfix::RustfixMode; use ui_test::spanned::Spanned; -use ui_test::{Args, CommandBuilder, Config, Match, OutputConflictHandling, status_emitter}; +use ui_test::{Args, CommandBuilder, Config, Match, error_on_output_conflict, status_emitter}; use std::collections::{BTreeMap, HashMap}; use std::env::{self, set_var, var_os}; @@ -142,7 +142,7 @@ impl TestContext { fn base_config(&self, test_dir: &str, mandatory_annotations: bool) -> Config { let target_dir = PathBuf::from(var_os("CARGO_TARGET_DIR").unwrap_or_else(|| "target".into())); let mut config = Config { - output_conflict_handling: OutputConflictHandling::Error, + output_conflict_handling: error_on_output_conflict, filter_files: env::var("TESTNAME") .map(|filters| filters.split(',').map(str::to_string).collect()) .unwrap_or_default(), @@ -220,7 +220,7 @@ fn run_internal_tests(cx: &TestContext) { if !RUN_INTERNAL_TESTS { return; } - let mut config = cx.base_config("ui-internal", false); + let mut config = cx.base_config("ui-internal", true); config.bless_command = Some("cargo uitest --features internal -- -- --bless".into()); ui_test::run_tests_generic( diff --git a/src/tools/clippy/tests/lint_message_convention.rs b/src/tools/clippy/tests/lint_message_convention.rs index 7ed1f485c1c..9229e2e8c49 100644 --- a/src/tools/clippy/tests/lint_message_convention.rs +++ b/src/tools/clippy/tests/lint_message_convention.rs @@ -44,6 +44,7 @@ impl Message { ".*AT&T x86 assembly syntax used", "note: Clippy version: .*", "the compiler unexpectedly panicked. this is a bug.", + "internal compiler error:", ]) .unwrap() }); diff --git a/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.rs b/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.rs index 31acac89cc6..e5f6001b74d 100644 --- a/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.rs +++ b/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.rs @@ -38,6 +38,7 @@ declare_tool_lint! { // Invalid attributes /////////////////////// declare_tool_lint! { +//~^ invalid_clippy_version_attribute #[clippy::version = "1.2.3.4.5.6"] pub clippy::INVALID_ONE, Warn, @@ -46,6 +47,7 @@ declare_tool_lint! { } declare_tool_lint! { +//~^ invalid_clippy_version_attribute #[clippy::version = "I'm a string"] pub clippy::INVALID_TWO, Warn, @@ -57,6 +59,7 @@ declare_tool_lint! { // Missing attribute test /////////////////////// declare_tool_lint! { +//~^ missing_clippy_version_attribute #[clippy::version] pub clippy::MISSING_ATTRIBUTE_ONE, Warn, @@ -65,6 +68,7 @@ declare_tool_lint! { } declare_tool_lint! { +//~^ missing_clippy_version_attribute pub clippy::MISSING_ATTRIBUTE_TWO, Warn, "Two", diff --git a/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr b/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr index 631c292f524..1129c35d1d0 100644 --- a/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr +++ b/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr @@ -2,10 +2,10 @@ error: this item has an invalid `clippy::version` attribute --> tests/ui-internal/check_clippy_version_attribute.rs:40:1 | LL | / declare_tool_lint! { +LL | | LL | | #[clippy::version = "1.2.3.4.5.6"] LL | | pub clippy::INVALID_ONE, -LL | | Warn, -LL | | "One", +... | LL | | report_in_external_macro: true LL | | } | |_^ @@ -20,13 +20,13 @@ LL | #![deny(clippy::internal)] = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info) error: this item has an invalid `clippy::version` attribute - --> tests/ui-internal/check_clippy_version_attribute.rs:48:1 + --> tests/ui-internal/check_clippy_version_attribute.rs:49:1 | LL | / declare_tool_lint! { +LL | | LL | | #[clippy::version = "I'm a string"] LL | | pub clippy::INVALID_TWO, -LL | | Warn, -LL | | "Two", +... | LL | | report_in_external_macro: true LL | | } | |_^ @@ -35,13 +35,13 @@ LL | | } = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info) error: this lint is missing the `clippy::version` attribute or version value - --> tests/ui-internal/check_clippy_version_attribute.rs:59:1 + --> tests/ui-internal/check_clippy_version_attribute.rs:61:1 | LL | / declare_tool_lint! { +LL | | LL | | #[clippy::version] LL | | pub clippy::MISSING_ATTRIBUTE_ONE, -LL | | Warn, -LL | | "Two", +... | LL | | report_in_external_macro: true LL | | } | |_^ @@ -51,9 +51,10 @@ LL | | } = note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info) error: this lint is missing the `clippy::version` attribute or version value - --> tests/ui-internal/check_clippy_version_attribute.rs:67:1 + --> tests/ui-internal/check_clippy_version_attribute.rs:70:1 | LL | / declare_tool_lint! { +LL | | LL | | pub clippy::MISSING_ATTRIBUTE_TWO, LL | | Warn, LL | | "Two", diff --git a/src/tools/clippy/tests/ui-internal/check_formulation.rs b/src/tools/clippy/tests/ui-internal/check_formulation.rs index 43fc996033e..8265a78769d 100644 --- a/src/tools/clippy/tests/ui-internal/check_formulation.rs +++ b/src/tools/clippy/tests/ui-internal/check_formulation.rs @@ -21,6 +21,7 @@ declare_tool_lint! { declare_tool_lint! { /// # What it does /// Check for lint formulations that are correct + //~^ almost_standard_lint_formulation #[clippy::version = "pre 1.29.0"] pub clippy::INVALID1, Warn, @@ -31,6 +32,7 @@ declare_tool_lint! { declare_tool_lint! { /// # What it does /// Detects uses of incorrect formulations + //~^ almost_standard_lint_formulation #[clippy::version = "pre 1.29.0"] pub clippy::INVALID2, Warn, diff --git a/src/tools/clippy/tests/ui-internal/check_formulation.stderr b/src/tools/clippy/tests/ui-internal/check_formulation.stderr index 12514370e6d..b16e1bf8687 100644 --- a/src/tools/clippy/tests/ui-internal/check_formulation.stderr +++ b/src/tools/clippy/tests/ui-internal/check_formulation.stderr @@ -9,7 +9,7 @@ LL | /// Check for lint formulations that are correct = help: to override `-D warnings` add `#[allow(clippy::almost_standard_lint_formulation)]` error: non-standard lint formulation - --> tests/ui-internal/check_formulation.rs:33:5 + --> tests/ui-internal/check_formulation.rs:34:5 | LL | /// Detects uses of incorrect formulations | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs index 1baf6142b34..2f289ae2b48 100644 --- a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs +++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs @@ -33,18 +33,23 @@ impl EarlyLintPass for Pass { let predicate = true; span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls db.span_suggestion(expr.span, help_msg, sugg.to_string(), Applicability::MachineApplicable); }); span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls db.span_help(expr.span, help_msg); }); span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls db.help(help_msg); }); span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls db.span_note(expr.span, note_msg); }); span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { + //~^ collapsible_span_lint_calls db.note(note_msg); }); diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr index 104995918de..a2be1f1cd36 100644 --- a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr +++ b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr @@ -2,6 +2,7 @@ error: this call is collapsible --> tests/ui-internal/collapsible_span_lint_calls.rs:35:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | LL | | db.span_suggestion(expr.span, help_msg, sugg.to_string(), Applicability::MachineApplicable); LL | | }); | |__________^ help: collapse into: `span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, help_msg, sugg.to_string(), Applicability::MachineApplicable)` @@ -14,33 +15,37 @@ LL | #![deny(clippy::internal)] = note: `#[deny(clippy::collapsible_span_lint_calls)]` implied by `#[deny(clippy::internal)]` error: this call is collapsible - --> tests/ui-internal/collapsible_span_lint_calls.rs:38:9 + --> tests/ui-internal/collapsible_span_lint_calls.rs:39:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | LL | | db.span_help(expr.span, help_msg); LL | | }); | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), help_msg)` error: this call is collapsible - --> tests/ui-internal/collapsible_span_lint_calls.rs:41:9 + --> tests/ui-internal/collapsible_span_lint_calls.rs:43:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | LL | | db.help(help_msg); LL | | }); | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, help_msg)` error: this call is collapsible - --> tests/ui-internal/collapsible_span_lint_calls.rs:44:9 + --> tests/ui-internal/collapsible_span_lint_calls.rs:47:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | LL | | db.span_note(expr.span, note_msg); LL | | }); | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg)` error: this call is collapsible - --> tests/ui-internal/collapsible_span_lint_calls.rs:47:9 + --> tests/ui-internal/collapsible_span_lint_calls.rs:51:9 | LL | / span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| { +LL | | LL | | db.note(note_msg); LL | | }); | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg)` diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs index 9b0db660c99..71819fe3707 100644 --- a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs +++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs @@ -10,5 +10,6 @@ #![allow(clippy::missing_clippy_version_attribute)] fn it_looks_like_you_are_trying_to_kill_clippy() {} +//~^ ice: Would you like some help with that? fn main() {} diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr index 801b0f340de..589e1190a90 100644 --- a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr +++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr @@ -1,9 +1,18 @@ - -thread '<unnamed>' panicked at clippy_lints/src/utils/internal_lints/produce_ice.rs: -Would you like some help with that? -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace - -error: the compiler unexpectedly panicked. this is a bug. +note: no errors encountered even though delayed bugs were created + +note: those delayed bugs will now be shown as internal compiler errors + +error: internal compiler error: Would you like some help with that? + --> tests/ui-internal/custom_ice_message.rs:12:1 + | +LL | fn it_looks_like_you_are_trying_to_kill_clippy() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: delayed at clippy_lints/src/utils/internal_lints/produce_ice.rs - disabled backtrace + --> tests/ui-internal/custom_ice_message.rs:12:1 + | +LL | fn it_looks_like_you_are_trying_to_kill_clippy() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml @@ -13,9 +22,5 @@ note: rustc <version> running on <target> note: compiler flags: -Z ui-testing -Z deduplicate-diagnostics=no -query stack during panic: -#0 [early_lint_checks] perform lints prior to AST lowering -#1 [hir_crate] getting the crate HIR -... and 3 other queries... use `env RUST_BACKTRACE=1` to see the full query stack note: Clippy version: foo diff --git a/src/tools/clippy/tests/ui-internal/default_lint.rs b/src/tools/clippy/tests/ui-internal/default_lint.rs index da29aedb2a3..959bfd27e38 100644 --- a/src/tools/clippy/tests/ui-internal/default_lint.rs +++ b/src/tools/clippy/tests/ui-internal/default_lint.rs @@ -16,6 +16,7 @@ declare_tool_lint! { } declare_tool_lint! { +//~^ default_lint pub clippy::TEST_LINT_DEFAULT, Warn, "default lint description", diff --git a/src/tools/clippy/tests/ui-internal/default_lint.stderr b/src/tools/clippy/tests/ui-internal/default_lint.stderr index c939125e875..9d4c2e15349 100644 --- a/src/tools/clippy/tests/ui-internal/default_lint.stderr +++ b/src/tools/clippy/tests/ui-internal/default_lint.stderr @@ -2,6 +2,7 @@ error: the lint `TEST_LINT_DEFAULT` has the default lint description --> tests/ui-internal/default_lint.rs:18:1 | LL | / declare_tool_lint! { +LL | | LL | | pub clippy::TEST_LINT_DEFAULT, LL | | Warn, LL | | "default lint description", diff --git a/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs b/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs index ca71dddcc24..3fed38cab64 100644 --- a/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs +++ b/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs @@ -12,12 +12,14 @@ use rustc_middle::ty::TyCtxt; pub fn a(cx: impl LintContext, lint: &'static Lint, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) { cx.span_lint(lint, span, |lint| { + //~^ disallowed_methods lint.primary_message(msg); }); } pub fn b(tcx: TyCtxt<'_>, lint: &'static Lint, hir_id: HirId, span: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) { tcx.node_span_lint(lint, hir_id, span, |lint| { + //~^ disallowed_methods lint.primary_message(msg); }); } diff --git a/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr index 16e1487f2bb..9a7a7ecbbff 100644 --- a/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr +++ b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr @@ -9,7 +9,7 @@ LL | cx.span_lint(lint, span, |lint| { = help: to override `-D warnings` add `#[allow(clippy::disallowed_methods)]` error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::node_span_lint` - --> tests/ui-internal/disallow_span_lint.rs:20:9 + --> tests/ui-internal/disallow_span_lint.rs:21:9 | LL | tcx.node_span_lint(lint, hir_id, span, |lint| { | ^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui-internal/interning_defined_symbol.fixed b/src/tools/clippy/tests/ui-internal/interning_defined_symbol.fixed index 3bcabb4ab2d..92d3b1537e0 100644 --- a/src/tools/clippy/tests/ui-internal/interning_defined_symbol.fixed +++ b/src/tools/clippy/tests/ui-internal/interning_defined_symbol.fixed @@ -15,15 +15,19 @@ macro_rules! sym { fn main() { // Direct use of Symbol::intern let _ = rustc_span::sym::f32; + //~^ interning_defined_symbol // Using a sym macro let _ = rustc_span::sym::f32; + //~^ interning_defined_symbol // Correct suggestion when symbol isn't stringified constant name let _ = rustc_span::sym::proc_dash_macro; + //~^ interning_defined_symbol // interning a keyword let _ = rustc_span::kw::SelfLower; + //~^ interning_defined_symbol // Interning a symbol that is not defined let _ = Symbol::intern("xyz123"); diff --git a/src/tools/clippy/tests/ui-internal/interning_defined_symbol.rs b/src/tools/clippy/tests/ui-internal/interning_defined_symbol.rs index 92e92d4fbc1..d1e6f9cb1c4 100644 --- a/src/tools/clippy/tests/ui-internal/interning_defined_symbol.rs +++ b/src/tools/clippy/tests/ui-internal/interning_defined_symbol.rs @@ -15,15 +15,19 @@ macro_rules! sym { fn main() { // Direct use of Symbol::intern let _ = Symbol::intern("f32"); + //~^ interning_defined_symbol // Using a sym macro let _ = sym!(f32); + //~^ interning_defined_symbol // Correct suggestion when symbol isn't stringified constant name let _ = Symbol::intern("proc-macro"); + //~^ interning_defined_symbol // interning a keyword let _ = Symbol::intern("self"); + //~^ interning_defined_symbol // Interning a symbol that is not defined let _ = Symbol::intern("xyz123"); diff --git a/src/tools/clippy/tests/ui-internal/interning_defined_symbol.stderr b/src/tools/clippy/tests/ui-internal/interning_defined_symbol.stderr index c4d0308979f..c84a566436a 100644 --- a/src/tools/clippy/tests/ui-internal/interning_defined_symbol.stderr +++ b/src/tools/clippy/tests/ui-internal/interning_defined_symbol.stderr @@ -12,19 +12,19 @@ LL | #![deny(clippy::internal)] = note: `#[deny(clippy::interning_defined_symbol)]` implied by `#[deny(clippy::internal)]` error: interning a defined symbol - --> tests/ui-internal/interning_defined_symbol.rs:20:13 + --> tests/ui-internal/interning_defined_symbol.rs:21:13 | LL | let _ = sym!(f32); | ^^^^^^^^^ help: try: `rustc_span::sym::f32` error: interning a defined symbol - --> tests/ui-internal/interning_defined_symbol.rs:23:13 + --> tests/ui-internal/interning_defined_symbol.rs:25:13 | LL | let _ = Symbol::intern("proc-macro"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `rustc_span::sym::proc_dash_macro` error: interning a defined symbol - --> tests/ui-internal/interning_defined_symbol.rs:26:13 + --> tests/ui-internal/interning_defined_symbol.rs:29:13 | LL | let _ = Symbol::intern("self"); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `rustc_span::kw::SelfLower` diff --git a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed index 7011ef518f2..6804e2bbae8 100644 --- a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed +++ b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.fixed @@ -27,6 +27,7 @@ impl_lint_pass!(Pass => [TEST_LINT]); impl EarlyLintPass for Pass { extract_msrv_attr!(); + //~^ missing_msrv_attr_impl fn check_expr(&mut self, _: &EarlyContext<'_>, _: &rustc_ast::Expr) {} } diff --git a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs index 323061decd2..c625a5d9a45 100644 --- a/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs +++ b/src/tools/clippy/tests/ui-internal/invalid_msrv_attr_impl.rs @@ -26,6 +26,7 @@ struct Pass { impl_lint_pass!(Pass => [TEST_LINT]); impl EarlyLintPass for Pass { + //~^ missing_msrv_attr_impl fn check_expr(&mut self, _: &EarlyContext<'_>, _: &rustc_ast::Expr) {} } diff --git a/src/tools/clippy/tests/ui-internal/invalid_paths.rs b/src/tools/clippy/tests/ui-internal/invalid_paths.rs index 9a9790a4bae..abfb111f938 100644 --- a/src/tools/clippy/tests/ui-internal/invalid_paths.rs +++ b/src/tools/clippy/tests/ui-internal/invalid_paths.rs @@ -13,12 +13,15 @@ mod paths { // Path with empty segment pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"]; + //~^ invalid_paths // Path with bad crate pub const BAD_CRATE_PATH: [&str; 2] = ["bad", "path"]; + //~^ invalid_paths // Path with bad module pub const BAD_MOD_PATH: [&str; 2] = ["std", "xxx"]; + //~^ invalid_paths // Path to method on an enum inherent impl pub const OPTION_IS_SOME: [&str; 4] = ["core", "option", "Option", "is_some"]; diff --git a/src/tools/clippy/tests/ui-internal/invalid_paths.stderr b/src/tools/clippy/tests/ui-internal/invalid_paths.stderr index fc530a2efa3..7bde37667be 100644 --- a/src/tools/clippy/tests/ui-internal/invalid_paths.stderr +++ b/src/tools/clippy/tests/ui-internal/invalid_paths.stderr @@ -8,13 +8,13 @@ LL | pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute" = help: to override `-D warnings` add `#[allow(clippy::invalid_paths)]` error: invalid path - --> tests/ui-internal/invalid_paths.rs:18:5 + --> tests/ui-internal/invalid_paths.rs:19:5 | LL | pub const BAD_CRATE_PATH: [&str; 2] = ["bad", "path"]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid path - --> tests/ui-internal/invalid_paths.rs:21:5 + --> tests/ui-internal/invalid_paths.rs:23:5 | LL | pub const BAD_MOD_PATH: [&str; 2] = ["std", "xxx"]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs index d59e9cbbb61..69591523432 100644 --- a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs +++ b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs @@ -10,6 +10,7 @@ extern crate rustc_lint; use rustc_lint::{LintPass, LintVec}; declare_tool_lint! { +//~^ lint_without_lint_pass pub clippy::TEST_LINT, Warn, "", diff --git a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr index 187bba97fd4..9cca96ca160 100644 --- a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr +++ b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr @@ -2,6 +2,7 @@ error: the lint `TEST_LINT` is not added to any `LintPass` --> tests/ui-internal/lint_without_lint_pass.rs:12:1 | LL | / declare_tool_lint! { +LL | | LL | | pub clippy::TEST_LINT, LL | | Warn, LL | | "", diff --git a/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed b/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed index cef16cf6ca5..cb7680b8bb1 100644 --- a/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed +++ b/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed @@ -21,6 +21,7 @@ declare_lint_pass!(Pass => [TEST_LINT]); impl<'tcx> LateLintPass<'tcx> for Pass { fn check_expr(&mut self, _cx: &LateContext<'tcx>, expr: &'tcx Expr) { let _ = expr.span.ctxt().outer_expn_data(); + //~^ outer_expn_expn_data } } diff --git a/src/tools/clippy/tests/ui-internal/outer_expn_data.rs b/src/tools/clippy/tests/ui-internal/outer_expn_data.rs index fb453be661c..41d735110b5 100644 --- a/src/tools/clippy/tests/ui-internal/outer_expn_data.rs +++ b/src/tools/clippy/tests/ui-internal/outer_expn_data.rs @@ -21,6 +21,7 @@ declare_lint_pass!(Pass => [TEST_LINT]); impl<'tcx> LateLintPass<'tcx> for Pass { fn check_expr(&mut self, _cx: &LateContext<'tcx>, expr: &'tcx Expr) { let _ = expr.span.ctxt().outer_expn().expn_data(); + //~^ outer_expn_expn_data } } diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed index d3fab60f9e3..577fad9341b 100644 --- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed +++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed @@ -35,28 +35,43 @@ const RESULT: &[&str] = &["core", "result", "Result"]; fn _f<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, did: DefId, expr: &Expr<'_>) { let _ = is_type_diagnostic_item(cx, ty, sym::Option); + //~^ unnecessary_def_path let _ = is_type_diagnostic_item(cx, ty, sym::Result); + //~^ unnecessary_def_path let _ = is_type_diagnostic_item(cx, ty, sym::Result); + //~^ unnecessary_def_path #[allow(unused, clippy::unnecessary_def_path)] let rc_path = &["alloc", "rc", "Rc"]; let _ = is_type_diagnostic_item(cx, ty, sym::Rc); + //~^ unnecessary_def_path let _ = is_type_diagnostic_item(cx, ty, sym::Option); + //~^ unnecessary_def_path let _ = is_type_diagnostic_item(cx, ty, sym::Result); + //~^ unnecessary_def_path let _ = is_type_lang_item(cx, ty, LangItem::OwnedBox); + //~^ unnecessary_def_path let _ = is_type_diagnostic_item(cx, ty, sym::maybe_uninit_uninit); + //~^ unnecessary_def_path let _ = cx.tcx.lang_items().get(LangItem::OwnedBox) == Some(did); + //~^ unnecessary_def_path let _ = cx.tcx.is_diagnostic_item(sym::Option, did); + //~^ unnecessary_def_path let _ = cx.tcx.lang_items().get(LangItem::OptionSome) == Some(did); + //~^ unnecessary_def_path let _ = is_trait_method(cx, expr, sym::AsRef); + //~^ unnecessary_def_path let _ = is_path_diagnostic_item(cx, expr, sym::Option); + //~^ unnecessary_def_path let _ = path_res(cx, expr).opt_def_id().map_or(false, |id| cx.tcx.lang_items().get(LangItem::IteratorNext) == Some(id)); + //~^ unnecessary_def_path let _ = is_res_lang_ctor(cx, path_res(cx, expr), LangItem::OptionSome); + //~^ unnecessary_def_path } fn main() {} diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs index 1b36f6b09e9..d4deb3626d0 100644 --- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs +++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs @@ -35,28 +35,43 @@ const RESULT: &[&str] = &["core", "result", "Result"]; fn _f<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, did: DefId, expr: &Expr<'_>) { let _ = match_type(cx, ty, &OPTION); + //~^ unnecessary_def_path let _ = match_type(cx, ty, RESULT); + //~^ unnecessary_def_path let _ = match_type(cx, ty, &["core", "result", "Result"]); + //~^ unnecessary_def_path #[allow(unused, clippy::unnecessary_def_path)] let rc_path = &["alloc", "rc", "Rc"]; let _ = clippy_utils::ty::match_type(cx, ty, rc_path); + //~^ unnecessary_def_path let _ = match_type(cx, ty, &paths::OPTION); + //~^ unnecessary_def_path let _ = match_type(cx, ty, paths::RESULT); + //~^ unnecessary_def_path let _ = match_type(cx, ty, &["alloc", "boxed", "Box"]); + //~^ unnecessary_def_path let _ = match_type(cx, ty, &["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"]); + //~^ unnecessary_def_path let _ = match_def_path(cx, did, &["alloc", "boxed", "Box"]); + //~^ unnecessary_def_path let _ = match_def_path(cx, did, &["core", "option", "Option"]); + //~^ unnecessary_def_path let _ = match_def_path(cx, did, &["core", "option", "Option", "Some"]); + //~^ unnecessary_def_path let _ = match_trait_method(cx, expr, &["core", "convert", "AsRef"]); + //~^ unnecessary_def_path let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option"]); + //~^ unnecessary_def_path let _ = is_expr_path_def_path(cx, expr, &["core", "iter", "traits", "Iterator", "next"]); + //~^ unnecessary_def_path let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option", "Some"]); + //~^ unnecessary_def_path } fn main() {} diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr index 79521c5037a..0053ba321bb 100644 --- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr +++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr @@ -12,61 +12,61 @@ LL | #![deny(clippy::internal)] = note: `#[deny(clippy::unnecessary_def_path)]` implied by `#[deny(clippy::internal)]` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:38:13 + --> tests/ui-internal/unnecessary_def_path.rs:39:13 | LL | let _ = match_type(cx, ty, RESULT); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:39:13 + --> tests/ui-internal/unnecessary_def_path.rs:41:13 | LL | let _ = match_type(cx, ty, &["core", "result", "Result"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:43:13 + --> tests/ui-internal/unnecessary_def_path.rs:46:13 | LL | let _ = clippy_utils::ty::match_type(cx, ty, rc_path); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Rc)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:45:13 + --> tests/ui-internal/unnecessary_def_path.rs:49:13 | LL | let _ = match_type(cx, ty, &paths::OPTION); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Option)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:46:13 + --> tests/ui-internal/unnecessary_def_path.rs:51:13 | LL | let _ = match_type(cx, ty, paths::RESULT); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)` error: use of a def path to a `LangItem` - --> tests/ui-internal/unnecessary_def_path.rs:48:13 + --> tests/ui-internal/unnecessary_def_path.rs:54:13 | LL | let _ = match_type(cx, ty, &["alloc", "boxed", "Box"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_lang_item(cx, ty, LangItem::OwnedBox)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:49:13 + --> tests/ui-internal/unnecessary_def_path.rs:56:13 | LL | let _ = match_type(cx, ty, &["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::maybe_uninit_uninit)` error: use of a def path to a `LangItem` - --> tests/ui-internal/unnecessary_def_path.rs:51:13 + --> tests/ui-internal/unnecessary_def_path.rs:59:13 | LL | let _ = match_def_path(cx, did, &["alloc", "boxed", "Box"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().get(LangItem::OwnedBox) == Some(did)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:52:13 + --> tests/ui-internal/unnecessary_def_path.rs:61:13 | LL | let _ = match_def_path(cx, did, &["core", "option", "Option"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.is_diagnostic_item(sym::Option, did)` error: use of a def path to a `LangItem` - --> tests/ui-internal/unnecessary_def_path.rs:53:13 + --> tests/ui-internal/unnecessary_def_path.rs:63:13 | LL | let _ = match_def_path(cx, did, &["core", "option", "Option", "Some"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().get(LangItem::OptionSome) == Some(did)` @@ -74,25 +74,25 @@ LL | let _ = match_def_path(cx, did, &["core", "option", "Option", "Some"]); = help: if this `DefId` came from a constructor expression or pattern then the parent `DefId` should be used instead error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:55:13 + --> tests/ui-internal/unnecessary_def_path.rs:66:13 | LL | let _ = match_trait_method(cx, expr, &["core", "convert", "AsRef"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_trait_method(cx, expr, sym::AsRef)` error: use of a def path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path.rs:57:13 + --> tests/ui-internal/unnecessary_def_path.rs:69:13 | LL | let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_path_diagnostic_item(cx, expr, sym::Option)` error: use of a def path to a `LangItem` - --> tests/ui-internal/unnecessary_def_path.rs:58:13 + --> tests/ui-internal/unnecessary_def_path.rs:71:13 | LL | let _ = is_expr_path_def_path(cx, expr, &["core", "iter", "traits", "Iterator", "next"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `path_res(cx, expr).opt_def_id().map_or(false, |id| cx.tcx.lang_items().get(LangItem::IteratorNext) == Some(id))` error: use of a def path to a `LangItem` - --> tests/ui-internal/unnecessary_def_path.rs:59:13 + --> tests/ui-internal/unnecessary_def_path.rs:73:13 | LL | let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option", "Some"]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_res_lang_ctor(cx, path_res(cx, expr), LangItem::OptionSome)` diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs index f6abb3cc3d7..4801d76bd26 100644 --- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs +++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs @@ -8,8 +8,11 @@ use rustc_hir::LangItem; fn main() { const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"]; + //~^ unnecessary_def_path const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"]; + //~^ unnecessary_def_path const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"]; + //~^ unnecessary_def_path // Don't lint, not a diagnostic or language item const OPS_MOD: [&str; 2] = ["core", "ops"]; diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr index 9d7c00088fe..b9383951932 100644 --- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr +++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr @@ -9,7 +9,7 @@ LL | const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"]; = help: to override `-D warnings` add `#[allow(clippy::unnecessary_def_path)]` error: hardcoded path to a language item - --> tests/ui-internal/unnecessary_def_path_hardcoded_path.rs:11:40 + --> tests/ui-internal/unnecessary_def_path_hardcoded_path.rs:12:40 | LL | const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"] = help: convert all references to use `LangItem::DerefMut` error: hardcoded path to a diagnostic item - --> tests/ui-internal/unnecessary_def_path_hardcoded_path.rs:12:43 + --> tests/ui-internal/unnecessary_def_path_hardcoded_path.rs:14:43 | LL | const OPS_MOD: [&str; 5] = ["core", "ops"]; | ^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed index 3d9deb705ac..dc564daef82 100644 --- a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed +++ b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.fixed @@ -14,8 +14,13 @@ use rustc_span::symbol::{Ident, Symbol}; fn main() { Symbol::intern("foo") == rustc_span::sym::clippy; + //~^ unnecessary_symbol_str Symbol::intern("foo") == rustc_span::kw::SelfLower; + //~^ unnecessary_symbol_str Symbol::intern("foo") != rustc_span::kw::SelfUpper; + //~^ unnecessary_symbol_str Ident::empty().name == rustc_span::sym::clippy; + //~^ unnecessary_symbol_str rustc_span::sym::clippy == Ident::empty().name; + //~^ unnecessary_symbol_str } diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs index 9aeeb9aaf3a..d74262d1294 100644 --- a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs +++ b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.rs @@ -14,8 +14,13 @@ use rustc_span::symbol::{Ident, Symbol}; fn main() { Symbol::intern("foo").as_str() == "clippy"; + //~^ unnecessary_symbol_str Symbol::intern("foo").to_string() == "self"; + //~^ unnecessary_symbol_str Symbol::intern("foo").to_ident_string() != "Self"; + //~^ unnecessary_symbol_str &*Ident::empty().as_str() == "clippy"; + //~^ unnecessary_symbol_str "clippy" == Ident::empty().to_string(); + //~^ unnecessary_symbol_str } diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.stderr index 1742603eff6..517a395e93f 100644 --- a/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.stderr +++ b/src/tools/clippy/tests/ui-internal/unnecessary_symbol_str.stderr @@ -12,25 +12,25 @@ LL | #![deny(clippy::internal)] = note: `#[deny(clippy::unnecessary_symbol_str)]` implied by `#[deny(clippy::internal)]` error: unnecessary `Symbol` to string conversion - --> tests/ui-internal/unnecessary_symbol_str.rs:17:5 + --> tests/ui-internal/unnecessary_symbol_str.rs:18:5 | LL | Symbol::intern("foo").to_string() == "self"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Symbol::intern("foo") == rustc_span::kw::SelfLower` error: unnecessary `Symbol` to string conversion - --> tests/ui-internal/unnecessary_symbol_str.rs:18:5 + --> tests/ui-internal/unnecessary_symbol_str.rs:20:5 | LL | Symbol::intern("foo").to_ident_string() != "Self"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Symbol::intern("foo") != rustc_span::kw::SelfUpper` error: unnecessary `Symbol` to string conversion - --> tests/ui-internal/unnecessary_symbol_str.rs:19:5 + --> tests/ui-internal/unnecessary_symbol_str.rs:22:5 | LL | &*Ident::empty().as_str() == "clippy"; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Ident::empty().name == rustc_span::sym::clippy` error: unnecessary `Symbol` to string conversion - --> tests/ui-internal/unnecessary_symbol_str.rs:20:5 + --> tests/ui-internal/unnecessary_symbol_str.rs:24:5 | LL | "clippy" == Ident::empty().to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `rustc_span::sym::clippy == Ident::empty().name` diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_4/clippy.toml b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_4/clippy.toml new file mode 100644 index 00000000000..baf7041138f --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_4/clippy.toml @@ -0,0 +1 @@ +module-items-ordered-within-groupings = true diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_5/clippy.toml b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_5/clippy.toml new file mode 100644 index 00000000000..1fa80c73012 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_5/clippy.toml @@ -0,0 +1 @@ +module-items-ordered-within-groupings = ["madules"] diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_6/clippy.toml b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_6/clippy.toml new file mode 100644 index 00000000000..cee857a155b --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_6/clippy.toml @@ -0,0 +1 @@ +module-items-ordered-within-groupings = ["entirely garbled"] diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/default_exp/clippy.toml b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/default_exp/clippy.toml index ddca5cfa577..af3aa1cc62a 100644 --- a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/default_exp/clippy.toml +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/default_exp/clippy.toml @@ -9,4 +9,4 @@ module-item-order-groupings = [ ["PascalCase", ["ty_alias", "enum", "struct", "union", "trait", "trait_alias", "impl"]], ["lower_snake_case", ["fn"]] ] - +module-items-ordered-within-groupings = "none" diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ord_in_2/clippy.toml b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ord_in_2/clippy.toml new file mode 100644 index 00000000000..fd961c82d6f --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ord_in_2/clippy.toml @@ -0,0 +1 @@ +module-items-ordered-within-groupings = ["PascalCase"] diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ord_in_3/clippy.toml b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ord_in_3/clippy.toml new file mode 100644 index 00000000000..de2a7307eca --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ord_in_3/clippy.toml @@ -0,0 +1,2 @@ +source-item-ordering = ["module"] +module-items-ordered-within-groupings = ["PascalCase"] diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ord_within/clippy.toml b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ord_within/clippy.toml new file mode 100644 index 00000000000..e7640efde10 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ord_within/clippy.toml @@ -0,0 +1 @@ +module-items-ordered-within-groupings = "all" diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_4.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_4.stderr new file mode 100644 index 00000000000..c38c54ffeb0 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_4.stderr @@ -0,0 +1,8 @@ +error: error reading Clippy's configuration file: data did not match any variant of untagged enum StringOrVecOfString The available options for configuring an ordering within module item groups are: "all", "none", or a list of module item group names (as configured with the `module-item-order-groupings` configuration option). + --> $DIR/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_4/clippy.toml:1:41 + | +LL | module-items-ordered-within-groupings = true + | ^^^^ + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_5.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_5.stderr new file mode 100644 index 00000000000..7b1dafb6d0d --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_5.stderr @@ -0,0 +1,4 @@ +error: error reading Clippy's configuration file: unknown ordering group: `madules` was not specified in `module-items-ordered-within-groupings`, perhaps you meant `modules`? expected one of: `modules`, `use`, `macros`, `global_asm`, `UPPER_SNAKE_CASE`, `PascalCase`, `lower_snake_case` + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_6.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_6.stderr new file mode 100644 index 00000000000..996cabeeed4 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_6.stderr @@ -0,0 +1,4 @@ +error: error reading Clippy's configuration file: unknown ordering group: `entirely garbled` was not specified in `module-items-ordered-within-groupings`, expected one of: `modules`, `use`, `macros`, `global_asm`, `UPPER_SNAKE_CASE`, `PascalCase`, `lower_snake_case` + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs index 05eb40506db..b43791521cb 100644 --- a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs @@ -1,15 +1,21 @@ //@aux-build:../../ui/auxiliary/proc_macros.rs -//@revisions: default default_exp bad_conf_1 bad_conf_2 bad_conf_3 +//@revisions: default default_exp bad_conf_1 bad_conf_2 bad_conf_3 bad_conf_4 bad_conf_5 bad_conf_6 //@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default //@[default_exp] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default_exp //@[bad_conf_1] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_1 //@[bad_conf_2] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_2 //@[bad_conf_3] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_3 +//@[bad_conf_4] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_4 +//@[bad_conf_5] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_5 +//@[bad_conf_6] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_6 //@[default] check-pass //@[default_exp] check-pass //@[bad_conf_1] error-in-other-file: //@[bad_conf_2] error-in-other-file: //@[bad_conf_3] error-in-other-file: +//@[bad_conf_4] error-in-other-file: +//@[bad_conf_5] error-in-other-file: +//@[bad_conf_6] error-in-other-file: #![allow(dead_code)] #![warn(clippy::arbitrary_source_item_ordering)] diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr index 3605952bddc..50567e32b1b 100644 --- a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr @@ -1,223 +1,160 @@ -error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:22:14 +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:26:14 | LL | use std::rc::Weak; | ^^^^ | note: should be placed before `SNAKE_CASE` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:20:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:23:7 | LL | const SNAKE_CASE: &str = "zzzzzzzz"; | ^^^^^^^^^^ = note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` -error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:67:1 - | -LL | / impl CloneSelf for StructOrdered { -LL | | -LL | | fn clone_self(&self) -> Self { -LL | | Self { -... | -LL | | } - | |_^ - | -note: should be placed before the following item - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:57:1 - | -LL | / impl Default for StructOrdered { -LL | | fn default() -> Self { -LL | | Self { -LL | | a: true, -... | -LL | | } - | |_^ - -error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:145:7 +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:149:7 | LL | const ZIS_SHOULD_BE_REALLY_EARLY: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `TraitUnorderedItemKinds` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:132:7 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:136:7 | LL | trait TraitUnorderedItemKinds { | ^^^^^^^^^^^^^^^^^^^^^^^ -error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:163:1 - | -LL | impl BasicEmptyTrait for StructOrdered {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: should be placed before the following item - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:148:1 - | -LL | / impl TraitUnordered for StructUnordered { -LL | | const A: bool = false; -LL | | const C: bool = false; -LL | | const B: bool = false; -... | -LL | | } - | |_^ - -error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:184:5 +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:188:5 | LL | mod this_is_in_the_wrong_position { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `main` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:179:4 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:183:4 | LL | fn main() { | ^^^^ -error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:194:7 +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:198:7 | LL | const ZIS_SHOULD_BE_EVEN_EARLIER: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `ZisShouldBeBeforeZeMainFn` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:192:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:196:8 | LL | struct ZisShouldBeBeforeZeMainFn; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:12:11 - | -LL | const AFTER: i8 = 0; - | ^^^^^ - | -note: should be placed before `BEFORE` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:10:11 - | -LL | const BEFORE: i8 = 0; - | ^^^^^^ - -error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:40:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:44:5 | LL | B, | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:39:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:43:5 | LL | C, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:92:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:96:5 | LL | b: bool, | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:91:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:95:5 | LL | c: bool, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:101:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:105:5 | LL | b: bool, | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:100:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:104:5 | LL | c: bool, | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:121:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:125:11 | LL | const B: bool; | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:120:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:124:11 | LL | const C: bool; | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:128:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:132:8 | LL | fn b(); | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:127:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:131:8 | LL | fn c(); | ^ error: incorrect ordering of trait items (defined order: [Const, Type, Fn]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:135:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:139:5 | LL | const A: bool; | ^^^^^^^^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:133:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:137:5 | LL | type SomeType; | ^^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:151:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:155:11 | LL | const B: bool = false; | ^ | note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:150:11 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:154:11 | LL | const C: bool = false; | ^ error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:158:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:162:8 | LL | fn b() {} | ^ | note: should be placed before `c` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:157:8 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:161:8 | LL | fn c() {} | ^ error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:169:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:173:5 | LL | const A: bool = false; | ^^^^^^^^^^^^^^^^^^^^^^ | note: should be placed before `SomeType` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:167:5 + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:171:5 | LL | type SomeType = (); | ^^^^^^^^^^^^^^^^^^^ -error: incorrect ordering of items (must be alphabetically ordered) - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:187:11 - | -LL | const A: i8 = 1; - | ^ - | -note: should be placed before `C` - --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:186:11 - | -LL | const C: i8 = 0; - | ^ - -error: aborting due to 17 previous errors +error: aborting due to 13 previous errors diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default_exp.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default_exp.stderr new file mode 100644 index 00000000000..50567e32b1b --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default_exp.stderr @@ -0,0 +1,160 @@ +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:26:14 + | +LL | use std::rc::Weak; + | ^^^^ + | +note: should be placed before `SNAKE_CASE` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:23:7 + | +LL | const SNAKE_CASE: &str = "zzzzzzzz"; + | ^^^^^^^^^^ + = note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` + +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:149:7 + | +LL | const ZIS_SHOULD_BE_REALLY_EARLY: () = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `TraitUnorderedItemKinds` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:136:7 + | +LL | trait TraitUnorderedItemKinds { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:188:5 + | +LL | mod this_is_in_the_wrong_position { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `main` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:183:4 + | +LL | fn main() { + | ^^^^ + +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:198:7 + | +LL | const ZIS_SHOULD_BE_EVEN_EARLIER: () = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `ZisShouldBeBeforeZeMainFn` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:196:8 + | +LL | struct ZisShouldBeBeforeZeMainFn; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:44:5 + | +LL | B, + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:43:5 + | +LL | C, + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:96:5 + | +LL | b: bool, + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:95:5 + | +LL | c: bool, + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:105:5 + | +LL | b: bool, + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:104:5 + | +LL | c: bool, + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:125:11 + | +LL | const B: bool; + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:124:11 + | +LL | const C: bool; + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:132:8 + | +LL | fn b(); + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:131:8 + | +LL | fn c(); + | ^ + +error: incorrect ordering of trait items (defined order: [Const, Type, Fn]) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:139:5 + | +LL | const A: bool; + | ^^^^^^^^^^^^^^ + | +note: should be placed before `SomeType` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:137:5 + | +LL | type SomeType; + | ^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:155:11 + | +LL | const B: bool = false; + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:154:11 + | +LL | const C: bool = false; + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:162:8 + | +LL | fn b() {} + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:161:8 + | +LL | fn c() {} + | ^ + +error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:173:5 + | +LL | const A: bool = false; + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `SomeType` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:171:5 + | +LL | type SomeType = (); + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 13 previous errors + diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.ord_within.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.ord_within.stderr new file mode 100644 index 00000000000..ae5261dcc6d --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.ord_within.stderr @@ -0,0 +1,235 @@ +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:23:7 + | +LL | const SNAKE_CASE: &str = "zzzzzzzz"; + | ^^^^^^^^^^ + | +note: should be placed before `ZNAKE_CASE` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:22:7 + | +LL | const ZNAKE_CASE: &str = "123"; + | ^^^^^^^^^^ + = note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]` + +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:26:14 + | +LL | use std::rc::Weak; + | ^^^^ + | +note: should be placed before `SNAKE_CASE` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:23:7 + | +LL | const SNAKE_CASE: &str = "zzzzzzzz"; + | ^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:71:1 + | +LL | / impl CloneSelf for StructOrdered { +LL | | +LL | | fn clone_self(&self) -> Self { +LL | | Self { +... | +LL | | } + | |_^ + | +note: should be placed before the following item + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:61:1 + | +LL | / impl Default for StructOrdered { +LL | | fn default() -> Self { +LL | | Self { +LL | | a: true, +... | +LL | | } + | |_^ + +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:149:7 + | +LL | const ZIS_SHOULD_BE_REALLY_EARLY: () = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `TraitUnorderedItemKinds` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:136:7 + | +LL | trait TraitUnorderedItemKinds { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:167:1 + | +LL | impl BasicEmptyTrait for StructOrdered {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before the following item + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:152:1 + | +LL | / impl TraitUnordered for StructUnordered { +LL | | const A: bool = false; +LL | | const C: bool = false; +LL | | const B: bool = false; +... | +LL | | } + | |_^ + +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:188:5 + | +LL | mod this_is_in_the_wrong_position { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `main` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:183:4 + | +LL | fn main() { + | ^^^^ + +error: incorrect ordering of items (module item groupings specify another order) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:198:7 + | +LL | const ZIS_SHOULD_BE_EVEN_EARLIER: () = (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `ZisShouldBeBeforeZeMainFn` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:196:8 + | +LL | struct ZisShouldBeBeforeZeMainFn; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:14:11 + | +LL | const AFTER: i8 = 0; + | ^^^^^ + | +note: should be placed before `BEFORE` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:12:11 + | +LL | const BEFORE: i8 = 0; + | ^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:44:5 + | +LL | B, + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:43:5 + | +LL | C, + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:96:5 + | +LL | b: bool, + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:95:5 + | +LL | c: bool, + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:105:5 + | +LL | b: bool, + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:104:5 + | +LL | c: bool, + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:125:11 + | +LL | const B: bool; + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:124:11 + | +LL | const C: bool; + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:132:8 + | +LL | fn b(); + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:131:8 + | +LL | fn c(); + | ^ + +error: incorrect ordering of trait items (defined order: [Const, Type, Fn]) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:139:5 + | +LL | const A: bool; + | ^^^^^^^^^^^^^^ + | +note: should be placed before `SomeType` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:137:5 + | +LL | type SomeType; + | ^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:155:11 + | +LL | const B: bool = false; + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:154:11 + | +LL | const C: bool = false; + | ^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:162:8 + | +LL | fn b() {} + | ^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:161:8 + | +LL | fn c() {} + | ^ + +error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:173:5 + | +LL | const A: bool = false; + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `SomeType` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:171:5 + | +LL | type SomeType = (); + | ^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:191:11 + | +LL | const A: i8 = 1; + | ^ + | +note: should be placed before `C` + --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:190:11 + | +LL | const C: i8 = 0; + | ^ + +error: aborting due to 18 previous errors + diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs index 9e65a9cca0d..90399470d4c 100644 --- a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs @@ -1,6 +1,8 @@ //@aux-build:../../ui/auxiliary/proc_macros.rs -//@revisions: default +//@revisions: default default_exp ord_within //@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default +//@[default_exp] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default_exp +//@[ord_within] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/ord_within #![allow(dead_code)] #![warn(clippy::arbitrary_source_item_ordering)] @@ -10,14 +12,16 @@ mod i_am_just_right { const BEFORE: i8 = 0; const AFTER: i8 = 0; - //~^ arbitrary_source_item_ordering + //~[ord_within]^ arbitrary_source_item_ordering } // Use statements should not be linted internally - this is normally auto-sorted using rustfmt. use std::rc::Rc; use std::sync::{Arc, Barrier, RwLock}; +const ZNAKE_CASE: &str = "123"; const SNAKE_CASE: &str = "zzzzzzzz"; +//~[ord_within]^ arbitrary_source_item_ordering use std::rc::Weak; //~^ arbitrary_source_item_ordering @@ -65,7 +69,7 @@ impl Default for StructOrdered { } impl CloneSelf for StructOrdered { - //~^ arbitrary_source_item_ordering + //~[ord_within]^ arbitrary_source_item_ordering fn clone_self(&self) -> Self { Self { a: true, @@ -161,7 +165,7 @@ impl TraitUnordered for StructUnordered { // Trait impls should be located just after the type they implement it for. impl BasicEmptyTrait for StructOrdered {} -//~^ arbitrary_source_item_ordering +//~[ord_within]^ arbitrary_source_item_ordering impl TraitUnorderedItemKinds for StructUnordered { type SomeType = (); @@ -185,7 +189,7 @@ mod this_is_in_the_wrong_position { //~^ arbitrary_source_item_ordering const C: i8 = 0; const A: i8 = 1; - //~^ arbitrary_source_item_ordering + //~[ord_within]^ arbitrary_source_item_ordering } #[derive(Default, std::clone::Clone)] diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.default.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.default.stderr new file mode 100644 index 00000000000..7fc216b30d5 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.default.stderr @@ -0,0 +1,19 @@ +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:35:5 + | +LL | a: bool, + | ^ + | +note: should be placed before `b` + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:34:5 + | +LL | b: bool, + | ^ +note: the lint level is defined here + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:32:8 + | +LL | #[deny(clippy::arbitrary_source_item_ordering)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_2.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_2.stderr new file mode 100644 index 00000000000..1f75f5099ec --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_2.stderr @@ -0,0 +1,36 @@ +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:24:8 + | +LL | struct OrderedChecked { + | ^^^^^^^^^^^^^^ + | +note: should be placed before `Unordered` + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:18:8 + | +LL | struct Unordered { + | ^^^^^^^^^ +note: the lint level is defined here + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:9:9 + | +LL | #![deny(clippy::arbitrary_source_item_ordering)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:35:5 + | +LL | a: bool, + | ^ + | +note: should be placed before `b` + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:34:5 + | +LL | b: bool, + | ^ +note: the lint level is defined here + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:32:8 + | +LL | #[deny(clippy::arbitrary_source_item_ordering)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_3.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_3.stderr new file mode 100644 index 00000000000..8027f55add6 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_in_3.stderr @@ -0,0 +1,19 @@ +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:24:8 + | +LL | struct OrderedChecked { + | ^^^^^^^^^^^^^^ + | +note: should be placed before `Unordered` + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:18:8 + | +LL | struct Unordered { + | ^^^^^^^^^ +note: the lint level is defined here + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:9:9 + | +LL | #![deny(clippy::arbitrary_source_item_ordering)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_within.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_within.stderr new file mode 100644 index 00000000000..333a601f6a9 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.ord_within.stderr @@ -0,0 +1,48 @@ +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:24:8 + | +LL | struct OrderedChecked { + | ^^^^^^^^^^^^^^ + | +note: should be placed before `Unordered` + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:18:8 + | +LL | struct Unordered { + | ^^^^^^^^^ +note: the lint level is defined here + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:9:9 + | +LL | #![deny(clippy::arbitrary_source_item_ordering)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:45:4 + | +LL | fn before_main() {} + | ^^^^^^^^^^^ + | +note: should be placed before `main` + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:41:4 + | +LL | fn main() { + | ^^^^ + +error: incorrect ordering of items (must be alphabetically ordered) + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:35:5 + | +LL | a: bool, + | ^ + | +note: should be placed before `b` + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:34:5 + | +LL | b: bool, + | ^ +note: the lint level is defined here + --> tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs:32:8 + | +LL | #[deny(clippy::arbitrary_source_item_ordering)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs new file mode 100644 index 00000000000..e32b921dd96 --- /dev/null +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/selective_ordering.rs @@ -0,0 +1,46 @@ +//@aux-build:../../ui/auxiliary/proc_macros.rs +//@revisions: default ord_within ord_in_2 ord_in_3 +//@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default +//@[ord_within] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/ord_within +//@[ord_in_2] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/ord_in_2 +//@[ord_in_3] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/ord_in_3 + +#![allow(dead_code)] +#![deny(clippy::arbitrary_source_item_ordering)] + +#[allow(clippy::arbitrary_source_item_ordering)] +struct Ordered { + a: bool, + b: bool, +} + +#[allow(clippy::arbitrary_source_item_ordering)] +struct Unordered { + b: bool, + a: bool, +} + +#[deny(clippy::arbitrary_source_item_ordering)] +struct OrderedChecked { + //~[ord_within]^ arbitrary_source_item_ordering + //~[ord_in_2]| arbitrary_source_item_ordering + //~[ord_in_3]| arbitrary_source_item_ordering + a: bool, + b: bool, +} + +#[deny(clippy::arbitrary_source_item_ordering)] +struct UnorderedChecked { + b: bool, + a: bool, + //~[ord_within]^ arbitrary_source_item_ordering + //~[default]| arbitrary_source_item_ordering + //~[ord_in_2]| arbitrary_source_item_ordering +} + +fn main() { + // test code goes here +} + +fn before_main() {} +//~[ord_within]^ arbitrary_source_item_ordering diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index acfe739277c..fee5b01b689 100644 --- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -60,6 +60,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect min-ident-chars-threshold missing-docs-in-crate-items module-item-order-groupings + module-items-ordered-within-groupings msrv pass-by-value-size-limit pub-underscore-fields-behavior @@ -152,6 +153,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect min-ident-chars-threshold missing-docs-in-crate-items module-item-order-groupings + module-items-ordered-within-groupings msrv pass-by-value-size-limit pub-underscore-fields-behavior @@ -244,6 +246,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni min-ident-chars-threshold missing-docs-in-crate-items module-item-order-groupings + module-items-ordered-within-groupings msrv pass-by-value-size-limit pub-underscore-fields-behavior diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr index 32ed78151d2..8a2f201009a 100644 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr @@ -310,5 +310,49 @@ LL | let bar = unsafe {}; | = help: consider adding a safety comment on the preceding line -error: aborting due to 35 previous errors +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:638:52 + | +LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; + | ^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:647:41 + | +LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; + | ^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:657:42 + | +LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; + | ^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:662:40 + | +LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; + | ^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: statement has unnecessary safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:719:5 + | +LL | _ = bar(); + | ^^^^^^^^^^ + | +help: consider removing the safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:718:5 + | +LL | // SAFETY: unnecessary_safety_comment triggers here + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 40 previous errors diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr index 83a6986addf..e9c5e5f9f11 100644 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr @@ -390,5 +390,65 @@ LL | unsafe {} | = help: consider adding a safety comment on the preceding line -error: aborting due to 45 previous errors +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:638:52 + | +LL | const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; + | ^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:647:41 + | +LL | const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; + | ^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:657:42 + | +LL | const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; + | ^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:662:40 + | +LL | const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; + | ^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:673:9 + | +LL | unsafe { here_is_another_variable_with_long_name }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:702:9 + | +LL | unsafe { Date::__from_ordinal_date_unchecked(1970, 1) }.into_julian_day_just_make_this_line_longer(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: statement has unnecessary safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:719:5 + | +LL | _ = bar(); + | ^^^^^^^^^^ + | +help: consider removing the safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:718:5 + | +LL | // SAFETY: unnecessary_safety_comment triggers here + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 52 previous errors diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index 6a3fda3df5c..91a02bc3d7c 100644 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -632,4 +632,95 @@ mod issue_11246 { // Safety: Another safety comment const FOO: () = unsafe {}; +// trait items and impl items +mod issue_11709 { + trait MyTrait { + const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 0 }; + //~^ ERROR: unsafe block missing a safety comment + + // SAFETY: safe + const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; + + // SAFETY: unrelated + unsafe fn unsafe_fn() {} + + const NO_SAFETY_IN_TRAIT: i32 = unsafe { 1 }; + //~^ ERROR: unsafe block missing a safety comment + } + + struct UnsafeStruct; + + impl MyTrait for UnsafeStruct { + // SAFETY: safe in this impl + const NO_SAFETY_IN_TRAIT_BUT_IN_IMPL: u8 = unsafe { 2 }; + + const HAS_SAFETY_IN_TRAIT: i32 = unsafe { 3 }; + //~^ ERROR: unsafe block missing a safety comment + } + + impl UnsafeStruct { + const NO_SAFETY_IN_IMPL: i32 = unsafe { 1 }; + //~^ ERROR: unsafe block missing a safety comment + } +} + +fn issue_13024() { + let mut just_a_simple_variable_with_a_very_long_name_that_has_seventy_eight_characters = 0; + let here_is_another_variable_with_long_name = 100; + + // SAFETY: fail ONLY if `accept-comment-above-statement = false` + just_a_simple_variable_with_a_very_long_name_that_has_seventy_eight_characters = + unsafe { here_is_another_variable_with_long_name }; + //~[disabled]^ undocumented_unsafe_blocks +} + +// https://docs.rs/time/0.3.36/src/time/offset_date_time.rs.html#35 +mod issue_11709_regression { + use std::num::NonZeroI32; + + struct Date { + value: NonZeroI32, + } + + impl Date { + const unsafe fn __from_ordinal_date_unchecked(year: i32, ordinal: u16) -> Self { + Self { + // Safety: The caller must guarantee that `ordinal` is not zero. + value: unsafe { NonZeroI32::new_unchecked((year << 9) | ordinal as i32) }, + } + } + + const fn into_julian_day_just_make_this_line_longer(self) -> i32 { + 42 + } + } + + /// The Julian day of the Unix epoch. + // SAFETY: fail ONLY if `accept-comment-above-attribute = false` + #[allow(unsafe_code)] + const UNIX_EPOCH_JULIAN_DAY: i32 = + unsafe { Date::__from_ordinal_date_unchecked(1970, 1) }.into_julian_day_just_make_this_line_longer(); + //~[disabled]^ undocumented_unsafe_blocks +} + +fn issue_13039() { + unsafe fn foo() -> usize { + 1234 + } + + fn bar() -> usize { + 1234 + } + + // SAFETY: unnecessary_safety_comment should not trigger here + _ = unsafe { foo() }; + + // SAFETY: unnecessary_safety_comment triggers here + _ = bar(); + //~^ unnecessary_safety_comment + + // SAFETY: unnecessary_safety_comment should not trigger here + _ = unsafe { foo() } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions.fixed b/src/tools/clippy/tests/ui/blocks_in_conditions.fixed index df375e37057..cd307e803d0 100644 --- a/src/tools/clippy/tests/ui/blocks_in_conditions.fixed +++ b/src/tools/clippy/tests/ui/blocks_in_conditions.fixed @@ -118,6 +118,13 @@ mod issue_12016 { } } +fn issue_9911() { + if { return } {} + + let a = 1; + if { if a == 1 { return } else { true } } {} +} + fn in_closure() { let v = vec![1, 2, 3]; if v.into_iter() diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions.rs b/src/tools/clippy/tests/ui/blocks_in_conditions.rs index 1d9c9dd4246..6a211c8edfd 100644 --- a/src/tools/clippy/tests/ui/blocks_in_conditions.rs +++ b/src/tools/clippy/tests/ui/blocks_in_conditions.rs @@ -118,6 +118,13 @@ mod issue_12016 { } } +fn issue_9911() { + if { return } {} + + let a = 1; + if { if a == 1 { return } else { true } } {} +} + fn in_closure() { let v = vec![1, 2, 3]; if v.into_iter() diff --git a/src/tools/clippy/tests/ui/crashes/if_same_then_else.rs b/src/tools/clippy/tests/ui/crashes/if_same_then_else.rs index 58ee751948b..8a27b3c6d47 100644 --- a/src/tools/clippy/tests/ui/crashes/if_same_then_else.rs +++ b/src/tools/clippy/tests/ui/crashes/if_same_then_else.rs @@ -1,6 +1,5 @@ //@ check-pass -#![allow(clippy::comparison_chain)] #![deny(clippy::if_same_then_else)] // Test for https://github.com/rust-lang/rust-clippy/issues/2426 diff --git a/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr b/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr index 28479570006..b4fb1222539 100644 --- a/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr +++ b/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr @@ -2,7 +2,7 @@ error: this argument is passed by value, but not consumed in the function body --> tests/ui/crashes/needless_pass_by_value-w-late-bound.rs:7:12 | LL | fn test(x: Foo<'_>) {} - | ^^^^^^^ help: consider taking a reference instead: `&Foo<'_>` + | ^^^^^^^ | help: or consider marking this type as `Copy` --> tests/ui/crashes/needless_pass_by_value-w-late-bound.rs:5:1 @@ -11,6 +11,10 @@ LL | struct Foo<'a>(&'a [(); 100]); | ^^^^^^^^^^^^^^ = note: `-D clippy::needless-pass-by-value` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::needless_pass_by_value)]` +help: consider taking a reference instead + | +LL | fn test(x: &Foo<'_>) {} + | + error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/derive_ord_xor_partial_ord.stderr b/src/tools/clippy/tests/ui/derive_ord_xor_partial_ord.stderr index 6bbe54eeaa6..76dca3c7947 100644 --- a/src/tools/clippy/tests/ui/derive_ord_xor_partial_ord.stderr +++ b/src/tools/clippy/tests/ui/derive_ord_xor_partial_ord.stderr @@ -11,7 +11,6 @@ LL | impl PartialOrd for DeriveOrd { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: `-D clippy::derive-ord-xor-partial-ord` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::derive_ord_xor_partial_ord)]` - = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are deriving `Ord` but have implemented `PartialOrd` explicitly --> tests/ui/derive_ord_xor_partial_ord.rs:33:10 @@ -24,7 +23,6 @@ note: `PartialOrd` implemented here | LL | impl PartialOrd<DeriveOrdWithExplicitTypeVariable> for DeriveOrdWithExplicitTypeVariable { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are implementing `Ord` explicitly but have derived `PartialOrd` --> tests/ui/derive_ord_xor_partial_ord.rs:47:1 @@ -42,7 +40,6 @@ note: `PartialOrd` implemented here | LL | #[derive(PartialOrd, PartialEq, Eq)] | ^^^^^^^^^^ - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are implementing `Ord` explicitly but have derived `PartialOrd` --> tests/ui/derive_ord_xor_partial_ord.rs:69:5 @@ -60,7 +57,6 @@ note: `PartialOrd` implemented here | LL | #[derive(PartialOrd, PartialEq, Eq)] | ^^^^^^^^^^ - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/derived_hash_with_manual_eq.stderr b/src/tools/clippy/tests/ui/derived_hash_with_manual_eq.stderr index 19a24e75281..55740780c8a 100644 --- a/src/tools/clippy/tests/ui/derived_hash_with_manual_eq.stderr +++ b/src/tools/clippy/tests/ui/derived_hash_with_manual_eq.stderr @@ -10,7 +10,6 @@ note: `PartialEq` implemented here LL | impl PartialEq for Bar { | ^^^^^^^^^^^^^^^^^^^^^^ = note: `#[deny(clippy::derived_hash_with_manual_eq)]` on by default - = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) error: you are deriving `Hash` but have implemented `PartialEq` explicitly --> tests/ui/derived_hash_with_manual_eq.rs:23:10 @@ -23,7 +22,6 @@ note: `PartialEq` implemented here | LL | impl PartialEq<Baz> for Baz { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/tools/clippy/tests/ui/diverging_sub_expression.stderr b/src/tools/clippy/tests/ui/diverging_sub_expression.stderr index 3e417aa39cd..ba08eb4e5f4 100644 --- a/src/tools/clippy/tests/ui/diverging_sub_expression.stderr +++ b/src/tools/clippy/tests/ui/diverging_sub_expression.stderr @@ -36,8 +36,6 @@ error: sub-expression diverges | LL | _ => true || panic!("boo"), | ^^^^^^^^^^^^^ - | - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: sub-expression diverges --> tests/ui/diverging_sub_expression.rs:52:29 diff --git a/src/tools/clippy/tests/ui/doc/doc_comment_double_space_linebreaks.fixed b/src/tools/clippy/tests/ui/doc/doc_comment_double_space_linebreaks.fixed new file mode 100644 index 00000000000..6a616b2c7e1 --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/doc_comment_double_space_linebreaks.fixed @@ -0,0 +1,98 @@ +#![feature(custom_inner_attributes)] +#![rustfmt::skip] + +#![warn(clippy::doc_comment_double_space_linebreaks)] +#![allow(unused, clippy::empty_docs)] + +//~v doc_comment_double_space_linebreaks +//! Should warn on double space linebreaks\ +//! in file/module doc comment + +/// Should not warn on single-line doc comments +fn single_line() {} + +/// Should not warn on single-line doc comments +/// split across multiple lines +fn single_line_split() {} + +// Should not warn on normal comments + +// note: cargo fmt can remove double spaces from normal and block comments +// Should not warn on normal comments +// with double spaces at the end of a line + +#[doc = "This is a doc attribute, which should not be linted"] +fn normal_comment() { + /* + Should not warn on block comments + */ + + /* + Should not warn on block comments + with double space at the end of a line + */ +} + +//~v doc_comment_double_space_linebreaks +/// Should warn when doc comment uses double space\ +/// as a line-break, even when there are multiple\ +/// in a row +fn double_space_doc_comment() {} + +/// Should not warn when back-slash is used \ +/// as a line-break +fn back_slash_doc_comment() {} + +//~v doc_comment_double_space_linebreaks +/// 🌹 are 🟥\ +/// 🌷 are 🟦\ +/// 📎 is 😎\ +/// and so are 🫵\ +/// (hopefully no formatting weirdness linting this) +fn multi_byte_chars_tada() {} + +macro_rules! macro_that_makes_function { + () => { + /// Shouldn't lint on this! + /// (hopefully) + fn my_macro_created_function() {} + } +} + +macro_that_makes_function!(); + +// dont lint when its alone on a line +/// +fn alone() {} + +/// | First column | Second column | +/// | ------------ | ------------- | +/// | Not a line | break when | +/// | after a line | in a table | +fn table() {} + +/// ```text +/// It's also not a hard line break if +/// there's two spaces at the end of a +/// line in a block code. +/// ``` +fn codeblock() {} + +/// It's also not a hard line break `if +/// there's` two spaces in the middle of inline code. +fn inline() {} + +/// It's also not a hard line break [when]( +/// https://example.com) in a URL. +fn url() {} + +//~v doc_comment_double_space_linebreaks +/// here we mix\ +/// double spaces\ +/// and also\ +/// adding backslash\ +/// to some of them\ +/// to see how that looks +fn mixed() {} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/doc/doc_comment_double_space_linebreaks.rs b/src/tools/clippy/tests/ui/doc/doc_comment_double_space_linebreaks.rs new file mode 100644 index 00000000000..e36cf7dea23 --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/doc_comment_double_space_linebreaks.rs @@ -0,0 +1,98 @@ +#![feature(custom_inner_attributes)] +#![rustfmt::skip] + +#![warn(clippy::doc_comment_double_space_linebreaks)] +#![allow(unused, clippy::empty_docs)] + +//~v doc_comment_double_space_linebreaks +//! Should warn on double space linebreaks +//! in file/module doc comment + +/// Should not warn on single-line doc comments +fn single_line() {} + +/// Should not warn on single-line doc comments +/// split across multiple lines +fn single_line_split() {} + +// Should not warn on normal comments + +// note: cargo fmt can remove double spaces from normal and block comments +// Should not warn on normal comments +// with double spaces at the end of a line + +#[doc = "This is a doc attribute, which should not be linted"] +fn normal_comment() { + /* + Should not warn on block comments + */ + + /* + Should not warn on block comments + with double space at the end of a line + */ +} + +//~v doc_comment_double_space_linebreaks +/// Should warn when doc comment uses double space +/// as a line-break, even when there are multiple +/// in a row +fn double_space_doc_comment() {} + +/// Should not warn when back-slash is used \ +/// as a line-break +fn back_slash_doc_comment() {} + +//~v doc_comment_double_space_linebreaks +/// 🌹 are 🟥 +/// 🌷 are 🟦 +/// 📎 is 😎 +/// and so are 🫵 +/// (hopefully no formatting weirdness linting this) +fn multi_byte_chars_tada() {} + +macro_rules! macro_that_makes_function { + () => { + /// Shouldn't lint on this! + /// (hopefully) + fn my_macro_created_function() {} + } +} + +macro_that_makes_function!(); + +// dont lint when its alone on a line +/// +fn alone() {} + +/// | First column | Second column | +/// | ------------ | ------------- | +/// | Not a line | break when | +/// | after a line | in a table | +fn table() {} + +/// ```text +/// It's also not a hard line break if +/// there's two spaces at the end of a +/// line in a block code. +/// ``` +fn codeblock() {} + +/// It's also not a hard line break `if +/// there's` two spaces in the middle of inline code. +fn inline() {} + +/// It's also not a hard line break [when]( +/// https://example.com) in a URL. +fn url() {} + +//~v doc_comment_double_space_linebreaks +/// here we mix +/// double spaces\ +/// and also +/// adding backslash\ +/// to some of them +/// to see how that looks +fn mixed() {} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/doc/doc_comment_double_space_linebreaks.stderr b/src/tools/clippy/tests/ui/doc/doc_comment_double_space_linebreaks.stderr new file mode 100644 index 00000000000..08c6956c3d0 --- /dev/null +++ b/src/tools/clippy/tests/ui/doc/doc_comment_double_space_linebreaks.stderr @@ -0,0 +1,50 @@ +error: doc comment uses two spaces for a hard line break + --> tests/ui/doc/doc_comment_double_space_linebreaks.rs:8:43 + | +LL | //! Should warn on double space linebreaks + | ^^ + | + = help: replace this double space with a backslash: `\` + = note: `-D clippy::doc-comment-double-space-linebreaks` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::doc_comment_double_space_linebreaks)]` + +error: doc comment uses two spaces for a hard line break + --> tests/ui/doc/doc_comment_double_space_linebreaks.rs:37:51 + | +LL | /// Should warn when doc comment uses double space + | ^^ +LL | /// as a line-break, even when there are multiple + | ^^ + | + = help: replace this double space with a backslash: `\` + +error: doc comment uses two spaces for a hard line break + --> tests/ui/doc/doc_comment_double_space_linebreaks.rs:47:12 + | +LL | /// 🌹 are 🟥 + | ^^ +LL | /// 🌷 are 🟦 + | ^^ +LL | /// 📎 is 😎 + | ^^ +LL | /// and so are 🫵 + | ^^ + | + = help: replace this double space with a backslash: `\` + +error: doc comment uses two spaces for a hard line break + --> tests/ui/doc/doc_comment_double_space_linebreaks.rs:90:16 + | +LL | /// here we mix + | ^^ +LL | /// double spaces\ +LL | /// and also + | ^^ +LL | /// adding backslash\ +LL | /// to some of them + | ^^ + | + = help: replace this double space with a backslash: `\` + +error: aborting due to 4 previous errors + diff --git a/src/tools/clippy/tests/ui/entry_unfixable.rs b/src/tools/clippy/tests/ui/entry_unfixable.rs new file mode 100644 index 00000000000..dbdacf95056 --- /dev/null +++ b/src/tools/clippy/tests/ui/entry_unfixable.rs @@ -0,0 +1,94 @@ +#![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)] +#![warn(clippy::map_entry)] +//@no-rustfix + +use std::collections::HashMap; +use std::hash::Hash; + +macro_rules! m { + ($e:expr) => {{ $e }}; +} + +macro_rules! insert { + ($map:expr, $key:expr, $val:expr) => { + $map.insert($key, $val) + }; +} + +mod issue13306 { + use std::collections::HashMap; + + struct Env { + enclosing: Option<Box<Env>>, + values: HashMap<String, usize>, + } + + impl Env { + fn assign(&mut self, name: String, value: usize) -> bool { + if !self.values.contains_key(&name) { + //~^ map_entry + self.values.insert(name, value); + true + } else if let Some(enclosing) = &mut self.enclosing { + enclosing.assign(name, value) + } else { + false + } + } + } +} + +fn issue9925(mut hm: HashMap<String, bool>) { + let key = "hello".to_string(); + if hm.contains_key(&key) { + //~^ map_entry + let bval = hm.get_mut(&key).unwrap(); + *bval = false; + } else { + hm.insert(key, true); + } +} + +mod issue9470 { + use std::collections::HashMap; + use std::sync::Mutex; + + struct Interner(i32); + + impl Interner { + const fn new() -> Self { + Interner(0) + } + + fn resolve(&self, name: String) -> Option<String> { + todo!() + } + } + + static INTERNER: Mutex<Interner> = Mutex::new(Interner::new()); + + struct VM { + stack: Vec<i32>, + globals: HashMap<String, i32>, + } + + impl VM { + fn stack_top(&self) -> &i32 { + self.stack.last().unwrap() + } + + fn resolve(&mut self, name: String, value: i32) -> Result<(), String> { + if self.globals.contains_key(&name) { + //~^ map_entry + self.globals.insert(name, value); + } else { + let interner = INTERNER.lock().unwrap(); + return Err(interner.resolve(name).unwrap().to_owned()); + } + + Ok(()) + } + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/entry_unfixable.stderr b/src/tools/clippy/tests/ui/entry_unfixable.stderr new file mode 100644 index 00000000000..9f9956d351b --- /dev/null +++ b/src/tools/clippy/tests/ui/entry_unfixable.stderr @@ -0,0 +1,41 @@ +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> tests/ui/entry_unfixable.rs:28:13 + | +LL | / if !self.values.contains_key(&name) { +LL | | +LL | | self.values.insert(name, value); +LL | | true +... | +LL | | false +LL | | } + | |_____________^ + | + = note: `-D clippy::map-entry` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::map_entry)]` + +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> tests/ui/entry_unfixable.rs:43:5 + | +LL | / if hm.contains_key(&key) { +LL | | +LL | | let bval = hm.get_mut(&key).unwrap(); +LL | | *bval = false; +LL | | } else { +LL | | hm.insert(key, true); +LL | | } + | |_____^ + +error: usage of `contains_key` followed by `insert` on a `HashMap` + --> tests/ui/entry_unfixable.rs:81:13 + | +LL | / if self.globals.contains_key(&name) { +LL | | +LL | | self.globals.insert(name, value); +LL | | } else { +LL | | let interner = INTERNER.lock().unwrap(); +LL | | return Err(interner.resolve(name).unwrap().to_owned()); +LL | | } + | |_____________^ + +error: aborting due to 3 previous errors + diff --git a/src/tools/clippy/tests/ui/fallible_impl_from.stderr b/src/tools/clippy/tests/ui/fallible_impl_from.stderr index d773fc3a6d7..402494b39f3 100644 --- a/src/tools/clippy/tests/ui/fallible_impl_from.stderr +++ b/src/tools/clippy/tests/ui/fallible_impl_from.stderr @@ -38,7 +38,6 @@ note: potential failure(s) | LL | panic!(); | ^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: consider implementing `TryFrom` instead --> tests/ui/fallible_impl_from.rs:40:1 @@ -64,7 +63,6 @@ LL | } else if s.parse::<u32>().unwrap() != 42 { | ^^^^^^^^^^^^^^^^^^^^^^^^^ LL | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: consider implementing `TryFrom` instead --> tests/ui/fallible_impl_from.rs:60:1 @@ -85,7 +83,6 @@ LL | if s.parse::<u32>().ok().unwrap() != 42 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | panic!("{:?}", s); | ^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/tools/clippy/tests/ui/from_over_into.fixed b/src/tools/clippy/tests/ui/from_over_into.fixed index 7d6780a0e02..7229e5a2d35 100644 --- a/src/tools/clippy/tests/ui/from_over_into.fixed +++ b/src/tools/clippy/tests/ui/from_over_into.fixed @@ -105,4 +105,15 @@ fn issue_12138() { } } +fn issue_112502() { + struct MyInt(i64); + + impl From<MyInt> for i64 { + //~^ from_over_into + fn from(val: MyInt) -> Self { + val.0 + } + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/from_over_into.rs b/src/tools/clippy/tests/ui/from_over_into.rs index 387ddde359c..9c75969c5c1 100644 --- a/src/tools/clippy/tests/ui/from_over_into.rs +++ b/src/tools/clippy/tests/ui/from_over_into.rs @@ -105,4 +105,15 @@ fn issue_12138() { } } +fn issue_112502() { + struct MyInt(i64); + + impl Into<i64> for MyInt { + //~^ from_over_into + fn into(self: MyInt) -> i64 { + self.0 + } + } +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/from_over_into.stderr b/src/tools/clippy/tests/ui/from_over_into.stderr index a564bccbaf7..fe779544dd5 100644 --- a/src/tools/clippy/tests/ui/from_over_into.stderr +++ b/src/tools/clippy/tests/ui/from_over_into.stderr @@ -107,5 +107,21 @@ LL | LL ~ fn from(val: Hello) {} | -error: aborting due to 7 previous errors +error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true + --> tests/ui/from_over_into.rs:111:5 + | +LL | impl Into<i64> for MyInt { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `impl From<Local> for Foreign` is allowed by the orphan rules, for more information see + https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence +help: replace the `Into` implementation with `From<issue_112502::MyInt>` + | +LL ~ impl From<MyInt> for i64 { +LL | +LL ~ fn from(val: MyInt) -> Self { +LL ~ val.0 + | + +error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/ifs_same_cond.rs b/src/tools/clippy/tests/ui/ifs_same_cond.rs index 6ecb7cb1eba..ebc3acb1b77 100644 --- a/src/tools/clippy/tests/ui/ifs_same_cond.rs +++ b/src/tools/clippy/tests/ui/ifs_same_cond.rs @@ -1,10 +1,5 @@ #![warn(clippy::ifs_same_cond)] -#![allow( - clippy::if_same_then_else, - clippy::comparison_chain, - clippy::needless_if, - clippy::needless_else -)] // all empty blocks +#![allow(clippy::if_same_then_else, clippy::needless_if, clippy::needless_else)] // all empty blocks fn ifs_same_cond() { let a = 0; diff --git a/src/tools/clippy/tests/ui/ifs_same_cond.stderr b/src/tools/clippy/tests/ui/ifs_same_cond.stderr index 81fbb921e84..df21e6f1b82 100644 --- a/src/tools/clippy/tests/ui/ifs_same_cond.stderr +++ b/src/tools/clippy/tests/ui/ifs_same_cond.stderr @@ -1,11 +1,11 @@ error: this `if` has the same condition as a previous `if` - --> tests/ui/ifs_same_cond.rs:14:15 + --> tests/ui/ifs_same_cond.rs:9:15 | LL | } else if b { | ^ | note: same as this - --> tests/ui/ifs_same_cond.rs:13:8 + --> tests/ui/ifs_same_cond.rs:8:8 | LL | if b { | ^ @@ -13,37 +13,37 @@ LL | if b { = help: to override `-D warnings` add `#[allow(clippy::ifs_same_cond)]` error: this `if` has the same condition as a previous `if` - --> tests/ui/ifs_same_cond.rs:19:15 + --> tests/ui/ifs_same_cond.rs:14:15 | LL | } else if a == 1 { | ^^^^^^ | note: same as this - --> tests/ui/ifs_same_cond.rs:18:8 + --> tests/ui/ifs_same_cond.rs:13:8 | LL | if a == 1 { | ^^^^^^ error: this `if` has the same condition as a previous `if` - --> tests/ui/ifs_same_cond.rs:25:15 + --> tests/ui/ifs_same_cond.rs:20:15 | LL | } else if 2 * a == 1 { | ^^^^^^^^^^ | note: same as this - --> tests/ui/ifs_same_cond.rs:23:8 + --> tests/ui/ifs_same_cond.rs:18:8 | LL | if 2 * a == 1 { | ^^^^^^^^^^ error: this `if` has the same condition as a previous `if` - --> tests/ui/ifs_same_cond.rs:58:15 + --> tests/ui/ifs_same_cond.rs:53:15 | LL | } else if a.contains("ah") { | ^^^^^^^^^^^^^^^^ | note: same as this - --> tests/ui/ifs_same_cond.rs:57:8 + --> tests/ui/ifs_same_cond.rs:52:8 | LL | if a.contains("ah") { | ^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/impl_hash_with_borrow_str_and_bytes.stderr b/src/tools/clippy/tests/ui/impl_hash_with_borrow_str_and_bytes.stderr index 7328f563ce1..c327ce3f7ca 100644 --- a/src/tools/clippy/tests/ui/impl_hash_with_borrow_str_and_bytes.stderr +++ b/src/tools/clippy/tests/ui/impl_hash_with_borrow_str_and_bytes.stderr @@ -23,7 +23,6 @@ LL | #[derive(Hash)] = note: ... as (`hash("abc") != hash("abc".as_bytes())` = help: consider either removing one of the `Borrow` implementations (`Borrow<str>` or `Borrow<[u8]>`) ... = help: ... or not implementing `Hash` for this type - = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) error: the semantics of `Borrow<T>` around `Hash` can't be satisfied when both `Borrow<str>` and `Borrow<[u8]>` are implemented --> tests/ui/impl_hash_with_borrow_str_and_bytes.rs:117:6 diff --git a/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed b/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed index 136238f9eca..1aab6c54407 100644 --- a/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed +++ b/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed @@ -228,3 +228,27 @@ fn regression_13524(a: usize, b: usize, c: bool) -> usize { 123 } else { b.saturating_sub(a) } } + +fn with_side_effect(a: u64) -> u64 { + println!("a = {a}"); + a +} + +fn arbitrary_expression() { + let (a, b) = (15u64, 20u64); + + let _ = (a * 2).saturating_sub(b); + //~^ implicit_saturating_sub + + let _ = a.saturating_sub(b * 2); + //~^ implicit_saturating_sub + + let _ = a.saturating_sub(b * 2); + //~^ implicit_saturating_sub + + let _ = if with_side_effect(a) > a { + with_side_effect(a) - a + } else { + 0 + }; +} diff --git a/src/tools/clippy/tests/ui/implicit_saturating_sub.rs b/src/tools/clippy/tests/ui/implicit_saturating_sub.rs index 140cf033860..7ca57a2902d 100644 --- a/src/tools/clippy/tests/ui/implicit_saturating_sub.rs +++ b/src/tools/clippy/tests/ui/implicit_saturating_sub.rs @@ -302,3 +302,27 @@ fn regression_13524(a: usize, b: usize, c: bool) -> usize { b - a } } + +fn with_side_effect(a: u64) -> u64 { + println!("a = {a}"); + a +} + +fn arbitrary_expression() { + let (a, b) = (15u64, 20u64); + + let _ = if a * 2 > b { a * 2 - b } else { 0 }; + //~^ implicit_saturating_sub + + let _ = if a > b * 2 { a - b * 2 } else { 0 }; + //~^ implicit_saturating_sub + + let _ = if a < b * 2 { 0 } else { a - b * 2 }; + //~^ implicit_saturating_sub + + let _ = if with_side_effect(a) > a { + with_side_effect(a) - a + } else { + 0 + }; +} diff --git a/src/tools/clippy/tests/ui/implicit_saturating_sub.stderr b/src/tools/clippy/tests/ui/implicit_saturating_sub.stderr index f9c94d3ad84..0c225856fd0 100644 --- a/src/tools/clippy/tests/ui/implicit_saturating_sub.stderr +++ b/src/tools/clippy/tests/ui/implicit_saturating_sub.stderr @@ -220,5 +220,23 @@ LL | | b - a LL | | } | |_____^ help: replace it with: `{ b.saturating_sub(a) }` -error: aborting due to 24 previous errors +error: manual arithmetic check found + --> tests/ui/implicit_saturating_sub.rs:314:13 + | +LL | let _ = if a * 2 > b { a * 2 - b } else { 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `(a * 2).saturating_sub(b)` + +error: manual arithmetic check found + --> tests/ui/implicit_saturating_sub.rs:317:13 + | +LL | let _ = if a > b * 2 { a - b * 2 } else { 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b * 2)` + +error: manual arithmetic check found + --> tests/ui/implicit_saturating_sub.rs:320:13 + | +LL | let _ = if a < b * 2 { 0 } else { a - b * 2 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a.saturating_sub(b * 2)` + +error: aborting due to 27 previous errors diff --git a/src/tools/clippy/tests/ui/incompatible_msrv.rs b/src/tools/clippy/tests/ui/incompatible_msrv.rs index b4fea4cae5e..99101b2bb8f 100644 --- a/src/tools/clippy/tests/ui/incompatible_msrv.rs +++ b/src/tools/clippy/tests/ui/incompatible_msrv.rs @@ -1,5 +1,6 @@ #![warn(clippy::incompatible_msrv)] #![feature(custom_inner_attributes)] +#![feature(panic_internals)] #![clippy::msrv = "1.3.0"] use std::collections::HashMap; @@ -34,4 +35,42 @@ async fn issue12273(v: impl Future<Output = ()>) { v.await; } +fn core_special_treatment(p: bool) { + // Do not lint code coming from `core` macros expanding into `core` function calls + if p { + panic!("foo"); // Do not lint + } + + // But still lint code calling `core` functions directly + if p { + core::panicking::panic("foo"); + //~^ ERROR: is `1.3.0` but this item is stable since `1.6.0` + } + + // Lint code calling `core` from non-`core` macros + macro_rules! my_panic { + ($msg:expr) => { + core::panicking::panic($msg) + }; //~^ ERROR: is `1.3.0` but this item is stable since `1.6.0` + } + my_panic!("foo"); + + // Lint even when the macro comes from `core` and calls `core` functions + assert!(core::panicking::panic("out of luck")); + //~^ ERROR: is `1.3.0` but this item is stable since `1.6.0` +} + +#[clippy::msrv = "1.26.0"] +fn lang_items() { + // Do not lint lang items. `..=` will expand into `RangeInclusive::new()`, which was introduced + // in Rust 1.27.0. + let _ = 1..=3; +} + +#[clippy::msrv = "1.80.0"] +fn issue14212() { + let _ = std::iter::repeat_n((), 5); + //~^ ERROR: is `1.80.0` but this item is stable since `1.82.0` +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/incompatible_msrv.stderr b/src/tools/clippy/tests/ui/incompatible_msrv.stderr index 56c9eae5aaf..5ea2bb9cc58 100644 --- a/src/tools/clippy/tests/ui/incompatible_msrv.stderr +++ b/src/tools/clippy/tests/ui/incompatible_msrv.stderr @@ -1,5 +1,5 @@ error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.10.0` - --> tests/ui/incompatible_msrv.rs:13:39 + --> tests/ui/incompatible_msrv.rs:14:39 | LL | assert_eq!(map.entry("poneyland").key(), &"poneyland"); | ^^^^^ @@ -8,16 +8,45 @@ LL | assert_eq!(map.entry("poneyland").key(), &"poneyland"); = help: to override `-D warnings` add `#[allow(clippy::incompatible_msrv)]` error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.12.0` - --> tests/ui/incompatible_msrv.rs:17:11 + --> tests/ui/incompatible_msrv.rs:18:11 | LL | v.into_key(); | ^^^^^^^^^^ error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.4.0` - --> tests/ui/incompatible_msrv.rs:21:5 + --> tests/ui/incompatible_msrv.rs:22:5 | LL | sleep(Duration::new(1, 0)); | ^^^^^ -error: aborting due to 3 previous errors +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.6.0` + --> tests/ui/incompatible_msrv.rs:46:9 + | +LL | core::panicking::panic("foo"); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.6.0` + --> tests/ui/incompatible_msrv.rs:53:13 + | +LL | core::panicking::panic($msg) + | ^^^^^^^^^^^^^^^^^^^^^^ +... +LL | my_panic!("foo"); + | ---------------- in this macro invocation + | + = note: this error originates in the macro `my_panic` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.6.0` + --> tests/ui/incompatible_msrv.rs:59:13 + | +LL | assert!(core::panicking::panic("out of luck")); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: current MSRV (Minimum Supported Rust Version) is `1.80.0` but this item is stable since `1.82.0` + --> tests/ui/incompatible_msrv.rs:72:13 + | +LL | let _ = std::iter::repeat_n((), 5); + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors diff --git a/src/tools/clippy/tests/ui/io_other_error.fixed b/src/tools/clippy/tests/ui/io_other_error.fixed index 0054c56fb62..ce7e8ef281f 100644 --- a/src/tools/clippy/tests/ui/io_other_error.fixed +++ b/src/tools/clippy/tests/ui/io_other_error.fixed @@ -53,3 +53,8 @@ mod paths { fn under_msrv() { let _err = std::io::Error::new(std::io::ErrorKind::Other, E); } + +pub fn issue14346(x: i32) -> std::io::Error { + std::io::Error::other(format!("{x}")) + //~^ ERROR: this can be `std::io::Error::other(_)` +} diff --git a/src/tools/clippy/tests/ui/io_other_error.rs b/src/tools/clippy/tests/ui/io_other_error.rs index 8529fb9a77f..b66e7f88ab1 100644 --- a/src/tools/clippy/tests/ui/io_other_error.rs +++ b/src/tools/clippy/tests/ui/io_other_error.rs @@ -53,3 +53,8 @@ mod paths { fn under_msrv() { let _err = std::io::Error::new(std::io::ErrorKind::Other, E); } + +pub fn issue14346(x: i32) -> std::io::Error { + std::io::Error::new(std::io::ErrorKind::Other, format!("{x}")) + //~^ ERROR: this can be `std::io::Error::other(_)` +} diff --git a/src/tools/clippy/tests/ui/io_other_error.stderr b/src/tools/clippy/tests/ui/io_other_error.stderr index e79e05ecd40..b37e3d15064 100644 --- a/src/tools/clippy/tests/ui/io_other_error.stderr +++ b/src/tools/clippy/tests/ui/io_other_error.stderr @@ -48,5 +48,17 @@ LL - let _err = io::Error::new(io::ErrorKind::Other, super::E); LL + let _err = io::Error::other(super::E); | -error: aborting due to 4 previous errors +error: this can be `std::io::Error::other(_)` + --> tests/ui/io_other_error.rs:58:5 + | +LL | std::io::Error::new(std::io::ErrorKind::Other, format!("{x}")) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `std::io::Error::other` + | +LL - std::io::Error::new(std::io::ErrorKind::Other, format!("{x}")) +LL + std::io::Error::other(format!("{x}")) + | + +error: aborting due to 5 previous errors diff --git a/src/tools/clippy/tests/ui/issue-7447.stderr b/src/tools/clippy/tests/ui/issue-7447.stderr index 5e28c142384..09a75c6b8d2 100644 --- a/src/tools/clippy/tests/ui/issue-7447.stderr +++ b/src/tools/clippy/tests/ui/issue-7447.stderr @@ -6,15 +6,12 @@ LL | byte_view(panic!()); | = note: `-D clippy::diverging-sub-expression` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::diverging_sub_expression)]` - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: sub-expression diverges --> tests/ui/issue-7447.rs:29:19 | LL | group_entries(panic!()); | ^^^^^^^^ - | - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/tools/clippy/tests/ui/literals.rs b/src/tools/clippy/tests/ui/literals.rs index d21d49310a0..ba343a8f62f 100644 --- a/src/tools/clippy/tests/ui/literals.rs +++ b/src/tools/clippy/tests/ui/literals.rs @@ -30,6 +30,10 @@ fn main() { //~^ separated_literal_suffix //~| mixed_case_hex_literals + let fail2 = 0xab_CD_isize; + //~^ separated_literal_suffix + //~| mixed_case_hex_literals + let fail_multi_zero = 000_123usize; //~^ unseparated_literal_suffix //~| zero_prefixed_literal diff --git a/src/tools/clippy/tests/ui/literals.stderr b/src/tools/clippy/tests/ui/literals.stderr index d65cd3c89eb..6bfeb91625b 100644 --- a/src/tools/clippy/tests/ui/literals.stderr +++ b/src/tools/clippy/tests/ui/literals.stderr @@ -25,6 +25,7 @@ error: inconsistent casing in hexadecimal literal LL | let fail1 = 0xabCD; | ^^^^^^ | + = help: consider using `0xabcd` or `0xABCD` = note: `-D clippy::mixed-case-hex-literals` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::mixed_case_hex_literals)]` @@ -39,6 +40,8 @@ error: inconsistent casing in hexadecimal literal | LL | let fail2 = 0xabCD_u32; | ^^^^^^^^^^ + | + = help: consider using `0xabcd_u32` or `0xABCD_u32` error: integer type suffix should not be separated by an underscore --> tests/ui/literals.rs:29:17 @@ -51,9 +54,25 @@ error: inconsistent casing in hexadecimal literal | LL | let fail2 = 0xabCD_isize; | ^^^^^^^^^^^^ + | + = help: consider using `0xabcd_isize` or `0xABCD_isize` + +error: integer type suffix should not be separated by an underscore + --> tests/ui/literals.rs:33:17 + | +LL | let fail2 = 0xab_CD_isize; + | ^^^^^^^^^^^^^ help: remove the underscore: `0xab_CDisize` + +error: inconsistent casing in hexadecimal literal + --> tests/ui/literals.rs:33:17 + | +LL | let fail2 = 0xab_CD_isize; + | ^^^^^^^^^^^^^ + | + = help: consider using `0xab_cd_isize` or `0xAB_CD_isize` error: integer type suffix should be separated by an underscore - --> tests/ui/literals.rs:33:27 + --> tests/ui/literals.rs:37:27 | LL | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ help: add an underscore: `000_123_usize` @@ -62,7 +81,7 @@ LL | let fail_multi_zero = 000_123usize; = help: to override `-D warnings` add `#[allow(clippy::unseparated_literal_suffix)]` error: this is a decimal constant - --> tests/ui/literals.rs:33:27 + --> tests/ui/literals.rs:37:27 | LL | let fail_multi_zero = 000_123usize; | ^^^^^^^^^^^^ @@ -81,13 +100,13 @@ LL + let fail_multi_zero = 0o123usize; | error: integer type suffix should not be separated by an underscore - --> tests/ui/literals.rs:38:16 + --> tests/ui/literals.rs:42:16 | LL | let ok10 = 0_i64; | ^^^^^ help: remove the underscore: `0i64` error: this is a decimal constant - --> tests/ui/literals.rs:41:17 + --> tests/ui/literals.rs:45:17 | LL | let fail8 = 0123; | ^^^^ @@ -103,13 +122,13 @@ LL | let fail8 = 0o123; | + error: integer type suffix should not be separated by an underscore - --> tests/ui/literals.rs:51:16 + --> tests/ui/literals.rs:55:16 | LL | let ok17 = 0x123_4567_8901_usize; | ^^^^^^^^^^^^^^^^^^^^^ help: remove the underscore: `0x123_4567_8901usize` error: digits grouped inconsistently by underscores - --> tests/ui/literals.rs:56:18 + --> tests/ui/literals.rs:60:18 | LL | let fail19 = 12_3456_21; | ^^^^^^^^^^ help: consider: `12_345_621` @@ -118,19 +137,19 @@ LL | let fail19 = 12_3456_21; = help: to override `-D warnings` add `#[allow(clippy::inconsistent_digit_grouping)]` error: digits grouped inconsistently by underscores - --> tests/ui/literals.rs:59:18 + --> tests/ui/literals.rs:63:18 | LL | let fail22 = 3__4___23; | ^^^^^^^^^ help: consider: `3_423` error: digits grouped inconsistently by underscores - --> tests/ui/literals.rs:62:18 + --> tests/ui/literals.rs:66:18 | LL | let fail23 = 3__16___23; | ^^^^^^^^^^ help: consider: `31_623` error: digits of hex, binary or octal literal not in groups of equal size - --> tests/ui/literals.rs:65:18 + --> tests/ui/literals.rs:69:18 | LL | let fail24 = 0xAB_ABC_AB; | ^^^^^^^^^^^ help: consider: `0x0ABA_BCAB` @@ -139,7 +158,7 @@ LL | let fail24 = 0xAB_ABC_AB; = help: to override `-D warnings` add `#[allow(clippy::unusual_byte_groupings)]` error: this is a decimal constant - --> tests/ui/literals.rs:75:13 + --> tests/ui/literals.rs:79:13 | LL | let _ = 08; | ^^ @@ -151,7 +170,7 @@ LL + let _ = 8; | error: this is a decimal constant - --> tests/ui/literals.rs:78:13 + --> tests/ui/literals.rs:82:13 | LL | let _ = 09; | ^^ @@ -163,7 +182,7 @@ LL + let _ = 9; | error: this is a decimal constant - --> tests/ui/literals.rs:81:13 + --> tests/ui/literals.rs:85:13 | LL | let _ = 089; | ^^^ @@ -174,5 +193,5 @@ LL - let _ = 089; LL + let _ = 89; | -error: aborting due to 20 previous errors +error: aborting due to 22 previous errors diff --git a/src/tools/clippy/tests/ui/manual_arithmetic_check-2.rs b/src/tools/clippy/tests/ui/manual_arithmetic_check-2.rs index 749d15f1cbd..b094b2021b3 100644 --- a/src/tools/clippy/tests/ui/manual_arithmetic_check-2.rs +++ b/src/tools/clippy/tests/ui/manual_arithmetic_check-2.rs @@ -24,6 +24,15 @@ fn main() { let result = if b <= a { 0 } else { a - b }; //~^ inverted_saturating_sub + let result = if b * 2 <= a { 0 } else { a - b * 2 }; + //~^ inverted_saturating_sub + + let result = if b <= a * 2 { 0 } else { a * 2 - b }; + //~^ inverted_saturating_sub + + let result = if b + 3 <= a + 2 { 0 } else { (a + 2) - (b + 3) }; + //~^ inverted_saturating_sub + let af = 12f32; let bf = 13f32; // Should not lint! diff --git a/src/tools/clippy/tests/ui/manual_arithmetic_check-2.stderr b/src/tools/clippy/tests/ui/manual_arithmetic_check-2.stderr index 8841210befd..fb0f0da772c 100644 --- a/src/tools/clippy/tests/ui/manual_arithmetic_check-2.stderr +++ b/src/tools/clippy/tests/ui/manual_arithmetic_check-2.stderr @@ -71,5 +71,41 @@ note: this subtraction underflows when `a < b` LL | let result = if b <= a { 0 } else { a - b }; | ^^^^^ -error: aborting due to 6 previous errors +error: inverted arithmetic check before subtraction + --> tests/ui/manual_arithmetic_check-2.rs:27:27 + | +LL | let result = if b * 2 <= a { 0 } else { a - b * 2 }; + | ^^ --------- help: try replacing it with: `b * 2 - a` + | +note: this subtraction underflows when `a < b * 2` + --> tests/ui/manual_arithmetic_check-2.rs:27:45 + | +LL | let result = if b * 2 <= a { 0 } else { a - b * 2 }; + | ^^^^^^^^^ + +error: inverted arithmetic check before subtraction + --> tests/ui/manual_arithmetic_check-2.rs:30:23 + | +LL | let result = if b <= a * 2 { 0 } else { a * 2 - b }; + | ^^ --------- help: try replacing it with: `b - a * 2` + | +note: this subtraction underflows when `a * 2 < b` + --> tests/ui/manual_arithmetic_check-2.rs:30:45 + | +LL | let result = if b <= a * 2 { 0 } else { a * 2 - b }; + | ^^^^^^^^^ + +error: inverted arithmetic check before subtraction + --> tests/ui/manual_arithmetic_check-2.rs:33:27 + | +LL | let result = if b + 3 <= a + 2 { 0 } else { (a + 2) - (b + 3) }; + | ^^ ----------------- help: try replacing it with: `b + 3 - (a + 2)` + | +note: this subtraction underflows when `a + 2 < b + 3` + --> tests/ui/manual_arithmetic_check-2.rs:33:49 + | +LL | let result = if b + 3 <= a + 2 { 0 } else { (a + 2) - (b + 3) }; + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors diff --git a/src/tools/clippy/tests/ui/manual_bits.stderr b/src/tools/clippy/tests/ui/manual_bits.stderr index a50975ed474..44c4cf9239c 100644 --- a/src/tools/clippy/tests/ui/manual_bits.stderr +++ b/src/tools/clippy/tests/ui/manual_bits.stderr @@ -1,4 +1,4 @@ -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:14:5 | LL | size_of::<i8>() * 8; @@ -7,169 +7,169 @@ LL | size_of::<i8>() * 8; = note: `-D clippy::manual-bits` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::manual_bits)]` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:16:5 | LL | size_of::<i16>() * 8; | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i16::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:18:5 | LL | size_of::<i32>() * 8; | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i32::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:20:5 | LL | size_of::<i64>() * 8; | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i64::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:22:5 | LL | size_of::<i128>() * 8; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `i128::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:24:5 | LL | size_of::<isize>() * 8; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `isize::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:27:5 | LL | size_of::<u8>() * 8; | ^^^^^^^^^^^^^^^^^^^ help: consider using: `u8::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:29:5 | LL | size_of::<u16>() * 8; | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u16::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:31:5 | LL | size_of::<u32>() * 8; | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u32::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:33:5 | LL | size_of::<u64>() * 8; | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u64::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:35:5 | LL | size_of::<u128>() * 8; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:37:5 | LL | size_of::<usize>() * 8; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `usize::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:40:5 | LL | 8 * size_of::<i8>(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `i8::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:42:5 | LL | 8 * size_of::<i16>(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i16::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:44:5 | LL | 8 * size_of::<i32>(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i32::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:46:5 | LL | 8 * size_of::<i64>(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i64::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:48:5 | LL | 8 * size_of::<i128>(); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `i128::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:50:5 | LL | 8 * size_of::<isize>(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `isize::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:53:5 | LL | 8 * size_of::<u8>(); | ^^^^^^^^^^^^^^^^^^^ help: consider using: `u8::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:55:5 | LL | 8 * size_of::<u16>(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u16::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:57:5 | LL | 8 * size_of::<u32>(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u32::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:59:5 | LL | 8 * size_of::<u64>(); | ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u64::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:61:5 | LL | 8 * size_of::<u128>(); | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:63:5 | LL | 8 * size_of::<usize>(); | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `usize::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:74:5 | LL | size_of::<Word>() * 8; | ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `Word::BITS as usize` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:79:18 | LL | let _: u32 = (size_of::<u128>() * 8) as u32; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:81:18 | LL | let _: u32 = (size_of::<u128>() * 8).try_into().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:83:13 | LL | let _ = (size_of::<u128>() * 8).pow(5); | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(u128::BITS as usize)` -error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits +error: usage of `size_of::<T>()` to obtain the size of `T` in bits --> tests/ui/manual_bits.rs:85:14 | LL | let _ = &(size_of::<u128>() * 8); diff --git a/src/tools/clippy/tests/ui/manual_let_else.rs b/src/tools/clippy/tests/ui/manual_let_else.rs index d2350d97ed0..a753566b34c 100644 --- a/src/tools/clippy/tests/ui/manual_let_else.rs +++ b/src/tools/clippy/tests/ui/manual_let_else.rs @@ -480,3 +480,37 @@ fn issue12337() { //~^ manual_let_else }; } + +mod issue13768 { + enum Foo { + Str(String), + None, + } + + fn foo(value: Foo) { + let signature = match value { + //~^ manual_let_else + Foo::Str(ref val) => val, + _ => { + println!("No signature found"); + return; + }, + }; + } + + enum Bar { + Str { inner: String }, + None, + } + + fn bar(mut value: Bar) { + let signature = match value { + //~^ manual_let_else + Bar::Str { ref mut inner } => inner, + _ => { + println!("No signature found"); + return; + }, + }; + } +} diff --git a/src/tools/clippy/tests/ui/manual_let_else.stderr b/src/tools/clippy/tests/ui/manual_let_else.stderr index 8f5cba64d54..ef042192114 100644 --- a/src/tools/clippy/tests/ui/manual_let_else.stderr +++ b/src/tools/clippy/tests/ui/manual_let_else.stderr @@ -489,5 +489,45 @@ error: this could be rewritten as `let...else` LL | let v = if let Some(v_some) = g() { v_some } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };` -error: aborting due to 31 previous errors +error: this could be rewritten as `let...else` + --> tests/ui/manual_let_else.rs:491:9 + | +LL | / let signature = match value { +LL | | +LL | | Foo::Str(ref val) => val, +LL | | _ => { +... | +LL | | }, +LL | | }; + | |__________^ + | +help: consider writing + | +LL ~ let Foo::Str(ref signature) = value else { +LL + println!("No signature found"); +LL + return; +LL + }; + | + +error: this could be rewritten as `let...else` + --> tests/ui/manual_let_else.rs:507:9 + | +LL | / let signature = match value { +LL | | +LL | | Bar::Str { ref mut inner } => inner, +LL | | _ => { +... | +LL | | }, +LL | | }; + | |__________^ + | +help: consider writing + | +LL ~ let Bar::Str { inner: ref mut signature } = value else { +LL + println!("No signature found"); +LL + return; +LL + }; + | + +error: aborting due to 33 previous errors diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs index bd6339b7870..40e7a5d745c 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -218,3 +218,91 @@ mod with_ty_alias { fn mut_add(x: &mut i32) { *x += 1; } + +#[clippy::msrv = "1.87"] +mod issue14020 { + use std::ops::Add; + + fn f<T: Add>(a: T, b: T) -> <T as Add>::Output { + a + b + } +} + +#[clippy::msrv = "1.87"] +mod issue14290 { + use std::ops::{Deref, DerefMut}; + + struct Wrapper<T> { + t: T, + } + + impl<T> Deref for Wrapper<T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.t + } + } + impl<T> DerefMut for Wrapper<T> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.t + } + } + + struct Example(bool); + + fn do_something(mut a: Wrapper<Example>) { + a.0 = !a.0; + } + + pub struct Stream(Vec<u8>); + + impl Stream { + pub fn bytes(&self) -> &[u8] { + &self.0 + } + } +} + +#[clippy::msrv = "1.87"] +mod issue14091 { + use std::mem::ManuallyDrop; + + struct BucketSlotGuard<'a> { + id: u32, + free_list: &'a mut Vec<u32>, + } + + impl BucketSlotGuard<'_> { + fn into_inner(self) -> u32 { + let this = ManuallyDrop::new(self); + this.id + } + } + + use std::ops::{Deref, DerefMut}; + + struct Wrap<T>(T); + + impl<T> Deref for Wrap<T> { + type Target = T; + fn deref(&self) -> &T { + &self.0 + } + } + + impl<T> DerefMut for Wrap<T> { + fn deref_mut(&mut self) -> &mut T { + &mut self.0 + } + } + + fn smart_two_field(v: &mut Wrap<(i32, i32)>) { + let _a = &mut v.0; + let _b = &mut v.1; + } + + fn smart_destructure(v: &mut Wrap<(i32, i32)>) { + let (ref mut _head, ref mut _tail) = **v; + } +} diff --git a/src/tools/clippy/tests/ui/needless_collect.fixed b/src/tools/clippy/tests/ui/needless_collect.fixed index bad8c307586..6551fa56b42 100644 --- a/src/tools/clippy/tests/ui/needless_collect.fixed +++ b/src/tools/clippy/tests/ui/needless_collect.fixed @@ -98,6 +98,29 @@ fn main() { let mut out = vec![]; values.iter().cloned().map(|x| out.push(x)).collect::<Vec<_>>(); let _y = values.iter().cloned().map(|x| out.push(x)).collect::<Vec<_>>(); // this is fine + + // Don't write a warning if we call `clone()` on the iterator + // https://github.com/rust-lang/rust-clippy/issues/13430 + let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + let _cloned = my_collection.into_iter().clone(); + let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + let my_iter = my_collection.into_iter(); + let _cloned = my_iter.clone(); + // Same for `as_slice()`, for same reason. + let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + let _sliced = my_collection.into_iter().as_slice(); + let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + let my_iter = my_collection.into_iter(); + let _sliced = my_iter.as_slice(); + // Assignment outside of main scope + { + let x; + { + let xxx: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + x = xxx.into_iter(); + for i in x.as_slice() {} + } + } } fn foo(_: impl IntoIterator<Item = usize>) {} diff --git a/src/tools/clippy/tests/ui/needless_collect.rs b/src/tools/clippy/tests/ui/needless_collect.rs index 3dfb5194f40..973c41c6875 100644 --- a/src/tools/clippy/tests/ui/needless_collect.rs +++ b/src/tools/clippy/tests/ui/needless_collect.rs @@ -98,6 +98,29 @@ fn main() { let mut out = vec![]; values.iter().cloned().map(|x| out.push(x)).collect::<Vec<_>>(); let _y = values.iter().cloned().map(|x| out.push(x)).collect::<Vec<_>>(); // this is fine + + // Don't write a warning if we call `clone()` on the iterator + // https://github.com/rust-lang/rust-clippy/issues/13430 + let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + let _cloned = my_collection.into_iter().clone(); + let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + let my_iter = my_collection.into_iter(); + let _cloned = my_iter.clone(); + // Same for `as_slice()`, for same reason. + let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + let _sliced = my_collection.into_iter().as_slice(); + let my_collection: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + let my_iter = my_collection.into_iter(); + let _sliced = my_iter.as_slice(); + // Assignment outside of main scope + { + let x; + { + let xxx: Vec<()> = vec![()].into_iter().map(|()| {}).collect(); + x = xxx.into_iter(); + for i in x.as_slice() {} + } + } } fn foo(_: impl IntoIterator<Item = usize>) {} diff --git a/src/tools/clippy/tests/ui/needless_late_init.fixed b/src/tools/clippy/tests/ui/needless_late_init.fixed index eb67e6cc828..391d4bc3fcc 100644 --- a/src/tools/clippy/tests/ui/needless_late_init.fixed +++ b/src/tools/clippy/tests/ui/needless_late_init.fixed @@ -297,3 +297,9 @@ fn issue13776() { let x; issue13776_mac!(x, 10); // should not lint } + +fn issue9895() { + + //~^ needless_late_init + let r = 5; +} diff --git a/src/tools/clippy/tests/ui/needless_late_init.rs b/src/tools/clippy/tests/ui/needless_late_init.rs index 7de2202dc32..6096e8300e1 100644 --- a/src/tools/clippy/tests/ui/needless_late_init.rs +++ b/src/tools/clippy/tests/ui/needless_late_init.rs @@ -297,3 +297,9 @@ fn issue13776() { let x; issue13776_mac!(x, 10); // should not lint } + +fn issue9895() { + let r; + //~^ needless_late_init + (r = 5); +} diff --git a/src/tools/clippy/tests/ui/needless_late_init.stderr b/src/tools/clippy/tests/ui/needless_late_init.stderr index 02fd2811da5..e7c36136847 100644 --- a/src/tools/clippy/tests/ui/needless_late_init.stderr +++ b/src/tools/clippy/tests/ui/needless_late_init.stderr @@ -275,5 +275,21 @@ LL | }, LL ~ }; | -error: aborting due to 16 previous errors +error: unneeded late initialization + --> tests/ui/needless_late_init.rs:302:5 + | +LL | let r; + | ^^^^^^ created here +LL | +LL | (r = 5); + | ^^^^^^^ initialised here + | +help: move the declaration `r` here + | +LL ~ +LL | +LL ~ let r = 5; + | + +error: aborting due to 17 previous errors diff --git a/src/tools/clippy/tests/ui/needless_pass_by_value.rs b/src/tools/clippy/tests/ui/needless_pass_by_value.rs index 885fb409417..aef7fff2870 100644 --- a/src/tools/clippy/tests/ui/needless_pass_by_value.rs +++ b/src/tools/clippy/tests/ui/needless_pass_by_value.rs @@ -189,6 +189,42 @@ struct Obj(String); fn prefix_test(_unused_with_prefix: Obj) {} +// Regression test for <https://github.com/rust-lang/rust-clippy/issues/13744>. +// It's more idiomatic to write `Option<&T>` rather than `&Option<T>`. +fn option_inner_ref(x: Option<String>) { + //~^ ERROR: this argument is passed by value, but not consumed in the function body + assert!(x.is_some()); +} + +mod non_standard { + #[derive(Debug)] + pub struct Option<T>(T); +} + +fn non_standard_option(x: non_standard::Option<String>) { + //~^ needless_pass_by_value + dbg!(&x); +} + +fn option_by_name(x: Option<std::option::Option<core::option::Option<non_standard::Option<String>>>>) { + //~^ needless_pass_by_value + dbg!(&x); +} + +type OptStr = Option<String>; + +fn non_option(x: OptStr) { + //~^ needless_pass_by_value + dbg!(&x); +} + +type Opt<T> = Option<T>; + +fn non_option_either(x: Opt<String>) { + //~^ needless_pass_by_value + dbg!(&x); +} + fn main() { // This should not cause an ICE either // https://github.com/rust-lang/rust-clippy/issues/3144 diff --git a/src/tools/clippy/tests/ui/needless_pass_by_value.stderr b/src/tools/clippy/tests/ui/needless_pass_by_value.stderr index 4ac4fdce972..e4381d1db53 100644 --- a/src/tools/clippy/tests/ui/needless_pass_by_value.stderr +++ b/src/tools/clippy/tests/ui/needless_pass_by_value.stderr @@ -17,43 +17,78 @@ error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:35:22 | LL | fn bar(x: String, y: Wrapper) { - | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` + | ^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn bar(x: String, y: &Wrapper) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:44:71 | LL | fn test_borrow_trait<T: Borrow<str>, U: AsRef<str>, V>(t: T, u: U, v: V) { - | ^ help: consider taking a reference instead: `&V` + | ^ + | +help: consider taking a reference instead + | +LL | fn test_borrow_trait<T: Borrow<str>, U: AsRef<str>, V>(t: T, u: U, v: &V) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:58:18 | LL | fn test_match(x: Option<Option<String>>, y: Option<Option<String>>) { - | ^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&Option<Option<String>>` + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn test_match(x: Option<Option<&String>>, y: Option<Option<String>>) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:73:24 | LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { - | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` + | ^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn test_destructure(x: &Wrapper, y: Wrapper, z: Wrapper) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:73:36 | LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) { - | ^^^^^^^ help: consider taking a reference instead: `&Wrapper` + | ^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn test_destructure(x: Wrapper, y: &Wrapper, z: Wrapper) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:92:49 | LL | fn test_blanket_ref<T: Foo, S: Serialize>(vals: T, serializable: S) {} - | ^ help: consider taking a reference instead: `&T` + | ^ + | +help: consider taking a reference instead + | +LL | fn test_blanket_ref<T: Foo, S: Serialize>(vals: &T, serializable: S) {} + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:95:18 | LL | fn issue_2114(s: String, t: String, u: Vec<i32>, v: Vec<i32>) { - | ^^^^^^ help: consider taking a reference instead: `&String` + | ^^^^^^ + | +help: consider taking a reference instead + | +LL | fn issue_2114(s: &String, t: String, u: Vec<i32>, v: Vec<i32>) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:95:29 @@ -76,7 +111,12 @@ error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:95:40 | LL | fn issue_2114(s: String, t: String, u: Vec<i32>, v: Vec<i32>) { - | ^^^^^^^^ help: consider taking a reference instead: `&Vec<i32>` + | ^^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn issue_2114(s: String, t: String, u: &Vec<i32>, v: Vec<i32>) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:95:53 @@ -105,79 +145,175 @@ error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:115:12 | LL | t: String, - | ^^^^^^ help: consider taking a reference instead: `&String` + | ^^^^^^ + | +help: consider taking a reference instead + | +LL | t: &String, + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:125:23 | LL | fn baz(&self, uu: U, ss: Self) {} - | ^ help: consider taking a reference instead: `&U` + | ^ + | +help: consider taking a reference instead + | +LL | fn baz(&self, uu: &U, ss: Self) {} + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:125:30 | LL | fn baz(&self, uu: U, ss: Self) {} - | ^^^^ help: consider taking a reference instead: `&Self` + | ^^^^ + | +help: consider taking a reference instead + | +LL | fn baz(&self, uu: U, ss: &Self) {} + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:149:24 | LL | fn bar_copy(x: u32, y: CopyWrapper) { - | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` + | ^^^^^^^^^^^ | help: or consider marking this type as `Copy` --> tests/ui/needless_pass_by_value.rs:147:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^ +help: consider taking a reference instead + | +LL | fn bar_copy(x: u32, y: &CopyWrapper) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:157:29 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { - | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` + | ^^^^^^^^^^^ | help: or consider marking this type as `Copy` --> tests/ui/needless_pass_by_value.rs:147:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^ +help: consider taking a reference instead + | +LL | fn test_destructure_copy(x: &CopyWrapper, y: CopyWrapper, z: CopyWrapper) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:157:45 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { - | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` + | ^^^^^^^^^^^ | help: or consider marking this type as `Copy` --> tests/ui/needless_pass_by_value.rs:147:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^ +help: consider taking a reference instead + | +LL | fn test_destructure_copy(x: CopyWrapper, y: &CopyWrapper, z: CopyWrapper) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:157:61 | LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) { - | ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper` + | ^^^^^^^^^^^ | help: or consider marking this type as `Copy` --> tests/ui/needless_pass_by_value.rs:147:1 | LL | struct CopyWrapper(u32); | ^^^^^^^^^^^^^^^^^^ +help: consider taking a reference instead + | +LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: &CopyWrapper) { + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:173:40 | LL | fn some_fun<'b, S: Bar<'b, ()>>(items: S) {} - | ^ help: consider taking a reference instead: `&S` + | ^ + | +help: consider taking a reference instead + | +LL | fn some_fun<'b, S: Bar<'b, ()>>(items: &S) {} + | + error: this argument is passed by value, but not consumed in the function body --> tests/ui/needless_pass_by_value.rs:179:20 | LL | fn more_fun(items: impl Club<'static, i32>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&impl Club<'static, i32>` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn more_fun(items: &impl Club<'static, i32>) {} + | + + +error: this argument is passed by value, but not consumed in the function body + --> tests/ui/needless_pass_by_value.rs:194:24 + | +LL | fn option_inner_ref(x: Option<String>) { + | ^^^^^^^^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn option_inner_ref(x: Option<&String>) { + | + + +error: this argument is passed by value, but not consumed in the function body + --> tests/ui/needless_pass_by_value.rs:204:27 + | +LL | fn non_standard_option(x: non_standard::Option<String>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn non_standard_option(x: &non_standard::Option<String>) { + | + + +error: this argument is passed by value, but not consumed in the function body + --> tests/ui/needless_pass_by_value.rs:209:22 + | +LL | fn option_by_name(x: Option<std::option::Option<core::option::Option<non_standard::Option<String>>>>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn option_by_name(x: Option<std::option::Option<core::option::Option<&non_standard::Option<String>>>>) { + | + + +error: this argument is passed by value, but not consumed in the function body + --> tests/ui/needless_pass_by_value.rs:216:18 + | +LL | fn non_option(x: OptStr) { + | ^^^^^^ + | +help: consider taking a reference instead + | +LL | fn non_option(x: &OptStr) { + | + + +error: this argument is passed by value, but not consumed in the function body + --> tests/ui/needless_pass_by_value.rs:223:25 + | +LL | fn non_option_either(x: Opt<String>) { + | ^^^^^^^^^^^ + | +help: consider taking a reference instead + | +LL | fn non_option_either(x: &Opt<String>) { + | + -error: aborting due to 22 previous errors +error: aborting due to 27 previous errors diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed index efc073ebe87..ad625ad6d50 100644 --- a/src/tools/clippy/tests/ui/needless_return.fixed +++ b/src/tools/clippy/tests/ui/needless_return.fixed @@ -6,7 +6,8 @@ clippy::single_match, clippy::needless_bool, clippy::equatable_if_let, - clippy::needless_else + clippy::needless_else, + clippy::missing_safety_doc )] #![warn(clippy::needless_return)] @@ -442,3 +443,12 @@ fn b(x: Option<u8>) -> Option<u8> { }, } } + +unsafe fn todo() -> *const u8 { + todo!() +} + +pub unsafe fn issue_12157() -> *const i32 { + (unsafe { todo() } as *const i32) + //~^ needless_return +} diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs index 283d86f25fe..41d7e5bdd50 100644 --- a/src/tools/clippy/tests/ui/needless_return.rs +++ b/src/tools/clippy/tests/ui/needless_return.rs @@ -6,7 +6,8 @@ clippy::single_match, clippy::needless_bool, clippy::equatable_if_let, - clippy::needless_else + clippy::needless_else, + clippy::missing_safety_doc )] #![warn(clippy::needless_return)] @@ -451,3 +452,12 @@ fn b(x: Option<u8>) -> Option<u8> { }, } } + +unsafe fn todo() -> *const u8 { + todo!() +} + +pub unsafe fn issue_12157() -> *const i32 { + return unsafe { todo() } as *const i32; + //~^ needless_return +} diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr index 04c97a41d67..80863b9b62b 100644 --- a/src/tools/clippy/tests/ui/needless_return.stderr +++ b/src/tools/clippy/tests/ui/needless_return.stderr @@ -1,5 +1,5 @@ error: unneeded `return` statement - --> tests/ui/needless_return.rs:29:5 + --> tests/ui/needless_return.rs:30:5 | LL | return true; | ^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:34:5 + --> tests/ui/needless_return.rs:35:5 | LL | return true; | ^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:40:5 + --> tests/ui/needless_return.rs:41:5 | LL | return true;;; | ^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:46:5 + --> tests/ui/needless_return.rs:47:5 | LL | return true;; ; ; | ^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:52:9 + --> tests/ui/needless_return.rs:53:9 | LL | return true; | ^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:55:9 + --> tests/ui/needless_return.rs:56:9 | LL | return false; | ^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + false | error: unneeded `return` statement - --> tests/ui/needless_return.rs:62:17 + --> tests/ui/needless_return.rs:63:17 | LL | true => return false, | ^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + true => false, | error: unneeded `return` statement - --> tests/ui/needless_return.rs:65:13 + --> tests/ui/needless_return.rs:66:13 | LL | return true; | ^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:73:9 + --> tests/ui/needless_return.rs:74:9 | LL | return true; | ^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:76:16 + --> tests/ui/needless_return.rs:77:16 | LL | let _ = || return true; | ^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + let _ = || true; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:81:5 + --> tests/ui/needless_return.rs:82:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL + the_answer!() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:85:21 + --> tests/ui/needless_return.rs:86:21 | LL | fn test_void_fun() { | _____________________^ @@ -148,7 +148,7 @@ LL + fn test_void_fun() { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:91:11 + --> tests/ui/needless_return.rs:92:11 | LL | if b { | ___________^ @@ -163,7 +163,7 @@ LL + if b { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:94:13 + --> tests/ui/needless_return.rs:95:13 | LL | } else { | _____________^ @@ -178,7 +178,7 @@ LL + } else { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:103:14 + --> tests/ui/needless_return.rs:104:14 | LL | _ => return, | ^^^^^^ @@ -190,7 +190,7 @@ LL + _ => (), | error: unneeded `return` statement - --> tests/ui/needless_return.rs:112:24 + --> tests/ui/needless_return.rs:113:24 | LL | let _ = 42; | ________________________^ @@ -205,7 +205,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:116:14 + --> tests/ui/needless_return.rs:117:14 | LL | _ => return, | ^^^^^^ @@ -217,7 +217,7 @@ LL + _ => (), | error: unneeded `return` statement - --> tests/ui/needless_return.rs:130:9 + --> tests/ui/needless_return.rs:131:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -229,7 +229,7 @@ LL + String::from("test") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:133:9 + --> tests/ui/needless_return.rs:134:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -241,7 +241,7 @@ LL + String::new() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:156:32 + --> tests/ui/needless_return.rs:157:32 | LL | bar.unwrap_or_else(|_| return) | ^^^^^^ @@ -253,7 +253,7 @@ LL + bar.unwrap_or_else(|_| {}) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:161:21 + --> tests/ui/needless_return.rs:162:21 | LL | let _ = || { | _____________________^ @@ -268,7 +268,7 @@ LL + let _ = || { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:165:20 + --> tests/ui/needless_return.rs:166:20 | LL | let _ = || return; | ^^^^^^ @@ -280,7 +280,7 @@ LL + let _ = || {}; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:172:32 + --> tests/ui/needless_return.rs:173:32 | LL | res.unwrap_or_else(|_| return Foo) | ^^^^^^^^^^ @@ -292,7 +292,7 @@ LL + res.unwrap_or_else(|_| Foo) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:182:5 + --> tests/ui/needless_return.rs:183:5 | LL | return true; | ^^^^^^^^^^^ @@ -304,7 +304,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:187:5 + --> tests/ui/needless_return.rs:188:5 | LL | return true; | ^^^^^^^^^^^ @@ -316,7 +316,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:193:9 + --> tests/ui/needless_return.rs:194:9 | LL | return true; | ^^^^^^^^^^^ @@ -328,7 +328,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:196:9 + --> tests/ui/needless_return.rs:197:9 | LL | return false; | ^^^^^^^^^^^^ @@ -340,7 +340,7 @@ LL + false | error: unneeded `return` statement - --> tests/ui/needless_return.rs:203:17 + --> tests/ui/needless_return.rs:204:17 | LL | true => return false, | ^^^^^^^^^^^^ @@ -352,7 +352,7 @@ LL + true => false, | error: unneeded `return` statement - --> tests/ui/needless_return.rs:206:13 + --> tests/ui/needless_return.rs:207:13 | LL | return true; | ^^^^^^^^^^^ @@ -364,7 +364,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:214:9 + --> tests/ui/needless_return.rs:215:9 | LL | return true; | ^^^^^^^^^^^ @@ -376,7 +376,7 @@ LL + true | error: unneeded `return` statement - --> tests/ui/needless_return.rs:217:16 + --> tests/ui/needless_return.rs:218:16 | LL | let _ = || return true; | ^^^^^^^^^^^ @@ -388,7 +388,7 @@ LL + let _ = || true; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:222:5 + --> tests/ui/needless_return.rs:223:5 | LL | return the_answer!(); | ^^^^^^^^^^^^^^^^^^^^ @@ -400,7 +400,7 @@ LL + the_answer!() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:226:33 + --> tests/ui/needless_return.rs:227:33 | LL | async fn async_test_void_fun() { | _________________________________^ @@ -415,7 +415,7 @@ LL + async fn async_test_void_fun() { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:232:11 + --> tests/ui/needless_return.rs:233:11 | LL | if b { | ___________^ @@ -430,7 +430,7 @@ LL + if b { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:235:13 + --> tests/ui/needless_return.rs:236:13 | LL | } else { | _____________^ @@ -445,7 +445,7 @@ LL + } else { | error: unneeded `return` statement - --> tests/ui/needless_return.rs:244:14 + --> tests/ui/needless_return.rs:245:14 | LL | _ => return, | ^^^^^^ @@ -457,7 +457,7 @@ LL + _ => (), | error: unneeded `return` statement - --> tests/ui/needless_return.rs:258:9 + --> tests/ui/needless_return.rs:259:9 | LL | return String::from("test"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -469,7 +469,7 @@ LL + String::from("test") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:261:9 + --> tests/ui/needless_return.rs:262:9 | LL | return String::new(); | ^^^^^^^^^^^^^^^^^^^^ @@ -481,7 +481,7 @@ LL + String::new() | error: unneeded `return` statement - --> tests/ui/needless_return.rs:278:5 + --> tests/ui/needless_return.rs:279:5 | LL | return format!("Hello {}", "world!"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -493,7 +493,7 @@ LL + format!("Hello {}", "world!") | error: unneeded `return` statement - --> tests/ui/needless_return.rs:320:9 + --> tests/ui/needless_return.rs:321:9 | LL | return true; | ^^^^^^^^^^^ @@ -508,7 +508,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:323:9 + --> tests/ui/needless_return.rs:324:9 | LL | return false; | ^^^^^^^^^^^^ @@ -521,7 +521,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:331:13 + --> tests/ui/needless_return.rs:332:13 | LL | return 10; | ^^^^^^^^^ @@ -536,7 +536,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:335:13 + --> tests/ui/needless_return.rs:336:13 | LL | return 100; | ^^^^^^^^^^ @@ -550,7 +550,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:344:9 + --> tests/ui/needless_return.rs:345:9 | LL | return 0; | ^^^^^^^^ @@ -563,7 +563,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:352:13 + --> tests/ui/needless_return.rs:353:13 | LL | return *(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -579,7 +579,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:355:13 + --> tests/ui/needless_return.rs:356:13 | LL | return !*(x as *const isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -593,7 +593,7 @@ LL ~ } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:363:20 + --> tests/ui/needless_return.rs:364:20 | LL | let _ = 42; | ____________________^ @@ -608,7 +608,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:370:20 + --> tests/ui/needless_return.rs:371:20 | LL | let _ = 42; return; | ^^^^^^^ @@ -620,7 +620,7 @@ LL + let _ = 42; | error: unneeded `return` statement - --> tests/ui/needless_return.rs:383:9 + --> tests/ui/needless_return.rs:384:9 | LL | return Ok(format!("ok!")); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -632,7 +632,7 @@ LL + Ok(format!("ok!")) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:386:9 + --> tests/ui/needless_return.rs:387:9 | LL | return Err(format!("err!")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -644,7 +644,7 @@ LL + Err(format!("err!")) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:393:9 + --> tests/ui/needless_return.rs:394:9 | LL | return if true { 1 } else { 2 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -656,7 +656,7 @@ LL + if true { 1 } else { 2 } | error: unneeded `return` statement - --> tests/ui/needless_return.rs:398:9 + --> tests/ui/needless_return.rs:399:9 | LL | return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -668,7 +668,7 @@ LL + (if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else | error: unneeded `return` statement - --> tests/ui/needless_return.rs:420:5 + --> tests/ui/needless_return.rs:421:5 | LL | return { "a".to_string() } + "b" + { "c" }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -680,7 +680,7 @@ LL + ({ "a".to_string() } + "b" + { "c" }) | error: unneeded `return` statement - --> tests/ui/needless_return.rs:425:5 + --> tests/ui/needless_return.rs:426:5 | LL | return "".split("").next().unwrap().to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -691,5 +691,17 @@ LL - return "".split("").next().unwrap().to_string(); LL + "".split("").next().unwrap().to_string() | -error: aborting due to 54 previous errors +error: unneeded `return` statement + --> tests/ui/needless_return.rs:461:5 + | +LL | return unsafe { todo() } as *const i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove `return` and wrap the sequence with parentheses + | +LL - return unsafe { todo() } as *const i32; +LL + (unsafe { todo() } as *const i32) + | + +error: aborting due to 55 previous errors diff --git a/src/tools/clippy/tests/ui/never_loop.rs b/src/tools/clippy/tests/ui/never_loop.rs index 2d8e04c192e..e0f54ef899b 100644 --- a/src/tools/clippy/tests/ui/never_loop.rs +++ b/src/tools/clippy/tests/ui/never_loop.rs @@ -422,6 +422,34 @@ pub fn issue12205() -> Option<()> { } } +fn stmt_after_return() { + for v in 0..10 { + //~^ never_loop + break; + println!("{v}"); + } +} + +fn loop_label() { + 'outer: for v in 0..10 { + //~^ never_loop + loop { + //~^ never_loop + break 'outer; + } + return; + } + + for v in 0..10 { + //~^ never_loop + 'inner: loop { + //~^ never_loop + break 'inner; + } + return; + } +} + fn main() { test1(); test2(); diff --git a/src/tools/clippy/tests/ui/never_loop.stderr b/src/tools/clippy/tests/ui/never_loop.stderr index f6d6d109542..bc9a7ec48b4 100644 --- a/src/tools/clippy/tests/ui/never_loop.stderr +++ b/src/tools/clippy/tests/ui/never_loop.stderr @@ -164,5 +164,73 @@ LL | | unimplemented!("not yet"); LL | | } | |_____^ -error: aborting due to 16 previous errors +error: this loop never actually loops + --> tests/ui/never_loop.rs:426:5 + | +LL | / for v in 0..10 { +LL | | +LL | | break; +LL | | println!("{v}"); +LL | | } + | |_____^ + | +help: if you need the first element of the iterator, try writing + | +LL - for v in 0..10 { +LL + if let Some(v) = (0..10).next() { + | + +error: this loop never actually loops + --> tests/ui/never_loop.rs:434:5 + | +LL | / 'outer: for v in 0..10 { +LL | | +LL | | loop { +... | +LL | | return; +LL | | } + | |_____^ + | +help: if you need the first element of the iterator, try writing + | +LL - 'outer: for v in 0..10 { +LL + if let Some(v) = (0..10).next() { + | + +error: this loop never actually loops + --> tests/ui/never_loop.rs:436:9 + | +LL | / loop { +LL | | +LL | | break 'outer; +LL | | } + | |_________^ + +error: this loop never actually loops + --> tests/ui/never_loop.rs:443:5 + | +LL | / for v in 0..10 { +LL | | +LL | | 'inner: loop { +... | +LL | | return; +LL | | } + | |_____^ + | +help: if you need the first element of the iterator, try writing + | +LL - for v in 0..10 { +LL + if let Some(v) = (0..10).next() { + | + +error: this loop never actually loops + --> tests/ui/never_loop.rs:445:9 + | +LL | / 'inner: loop { +LL | | +LL | | break 'inner; +LL | | } + | |_________^ + +error: aborting due to 21 previous errors diff --git a/src/tools/clippy/tests/ui/never_loop_fixable.fixed b/src/tools/clippy/tests/ui/never_loop_fixable.fixed new file mode 100644 index 00000000000..5bc9ff1bb4d --- /dev/null +++ b/src/tools/clippy/tests/ui/never_loop_fixable.fixed @@ -0,0 +1,20 @@ +#![allow(clippy::iter_next_slice, clippy::needless_return)] + +fn no_break_or_continue_loop() { + if let Some(i) = [1, 2, 3].iter().next() { + //~^ never_loop + return; + } +} + +fn no_break_or_continue_loop_outer() { + if let Some(i) = [1, 2, 3].iter().next() { + //~^ never_loop + return; + loop { + if true { + continue; + } + } + } +} diff --git a/src/tools/clippy/tests/ui/never_loop_fixable.rs b/src/tools/clippy/tests/ui/never_loop_fixable.rs new file mode 100644 index 00000000000..9782bc107e9 --- /dev/null +++ b/src/tools/clippy/tests/ui/never_loop_fixable.rs @@ -0,0 +1,20 @@ +#![allow(clippy::iter_next_slice, clippy::needless_return)] + +fn no_break_or_continue_loop() { + for i in [1, 2, 3].iter() { + //~^ never_loop + return; + } +} + +fn no_break_or_continue_loop_outer() { + for i in [1, 2, 3].iter() { + //~^ never_loop + return; + loop { + if true { + continue; + } + } + } +} diff --git a/src/tools/clippy/tests/ui/never_loop_fixable.stderr b/src/tools/clippy/tests/ui/never_loop_fixable.stderr new file mode 100644 index 00000000000..ee02d9a4297 --- /dev/null +++ b/src/tools/clippy/tests/ui/never_loop_fixable.stderr @@ -0,0 +1,35 @@ +error: this loop never actually loops + --> tests/ui/never_loop_fixable.rs:4:5 + | +LL | / for i in [1, 2, 3].iter() { +LL | | +LL | | return; +LL | | } + | |_____^ + | + = note: `#[deny(clippy::never_loop)]` on by default +help: if you need the first element of the iterator, try writing + | +LL - for i in [1, 2, 3].iter() { +LL + if let Some(i) = [1, 2, 3].iter().next() { + | + +error: this loop never actually loops + --> tests/ui/never_loop_fixable.rs:11:5 + | +LL | / for i in [1, 2, 3].iter() { +LL | | +LL | | return; +LL | | loop { +... | +LL | | } + | |_____^ + | +help: if you need the first element of the iterator, try writing + | +LL - for i in [1, 2, 3].iter() { +LL + if let Some(i) = [1, 2, 3].iter().next() { + | + +error: aborting due to 2 previous errors + diff --git a/src/tools/clippy/tests/ui/option_if_let_else.fixed b/src/tools/clippy/tests/ui/option_if_let_else.fixed index f5a869cf283..ee309889601 100644 --- a/src/tools/clippy/tests/ui/option_if_let_else.fixed +++ b/src/tools/clippy/tests/ui/option_if_let_else.fixed @@ -268,3 +268,23 @@ fn issue11893() { panic!("Haven't thought about this condition."); } } + +mod issue13964 { + #[derive(Debug)] + struct A(Option<String>); + + fn foo(a: A) { + let _ = match a.0 { + Some(x) => x, + None => panic!("{a:?} is invalid."), + }; + } + + fn bar(a: A) { + let _ = if let Some(x) = a.0 { + x + } else { + panic!("{a:?} is invalid.") + }; + } +} diff --git a/src/tools/clippy/tests/ui/option_if_let_else.rs b/src/tools/clippy/tests/ui/option_if_let_else.rs index d48272e618a..525a5df4371 100644 --- a/src/tools/clippy/tests/ui/option_if_let_else.rs +++ b/src/tools/clippy/tests/ui/option_if_let_else.rs @@ -331,3 +331,23 @@ fn issue11893() { panic!("Haven't thought about this condition."); } } + +mod issue13964 { + #[derive(Debug)] + struct A(Option<String>); + + fn foo(a: A) { + let _ = match a.0 { + Some(x) => x, + None => panic!("{a:?} is invalid."), + }; + } + + fn bar(a: A) { + let _ = if let Some(x) = a.0 { + x + } else { + panic!("{a:?} is invalid.") + }; + } +} diff --git a/src/tools/clippy/tests/ui/ptr_eq.fixed b/src/tools/clippy/tests/ui/ptr_eq.fixed index 1ccd2c2237d..df6305ed497 100644 --- a/src/tools/clippy/tests/ui/ptr_eq.fixed +++ b/src/tools/clippy/tests/ui/ptr_eq.fixed @@ -20,8 +20,10 @@ fn main() { //~^ ptr_eq let _ = std::ptr::eq(a, b); //~^ ptr_eq - let _ = a.as_ptr() == b as *const _; - let _ = a.as_ptr() == b.as_ptr(); + let _ = std::ptr::eq(a.as_ptr(), b as *const _); + //~^ ptr_eq + let _ = std::ptr::eq(a.as_ptr(), b.as_ptr()); + //~^ ptr_eq // Do not lint @@ -31,9 +33,22 @@ fn main() { let a = &mut [1, 2, 3]; let b = &mut [1, 2, 3]; - let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _; - let _ = a.as_mut_ptr() == b.as_mut_ptr(); + let _ = std::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _); + //~^ ptr_eq + let _ = std::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr()); + //~^ ptr_eq let _ = a == b; let _ = core::ptr::eq(a, b); + + let (x, y) = (&0u32, &mut 1u32); + let _ = std::ptr::eq(x, y); + //~^ ptr_eq + + let _ = !std::ptr::eq(x, y); + //~^ ptr_eq + + #[allow(clippy::eq_op)] + let _issue14337 = std::ptr::eq(main as *const (), main as *const ()); + //~^ ptr_eq } diff --git a/src/tools/clippy/tests/ui/ptr_eq.rs b/src/tools/clippy/tests/ui/ptr_eq.rs index 0bc58a57fa5..0ed0ff0d137 100644 --- a/src/tools/clippy/tests/ui/ptr_eq.rs +++ b/src/tools/clippy/tests/ui/ptr_eq.rs @@ -21,7 +21,9 @@ fn main() { let _ = a as *const _ == b as *const _; //~^ ptr_eq let _ = a.as_ptr() == b as *const _; + //~^ ptr_eq let _ = a.as_ptr() == b.as_ptr(); + //~^ ptr_eq // Do not lint @@ -32,8 +34,21 @@ fn main() { let b = &mut [1, 2, 3]; let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _; + //~^ ptr_eq let _ = a.as_mut_ptr() == b.as_mut_ptr(); + //~^ ptr_eq let _ = a == b; let _ = core::ptr::eq(a, b); + + let (x, y) = (&0u32, &mut 1u32); + let _ = x as *const u32 == y as *mut u32 as *const u32; + //~^ ptr_eq + + let _ = x as *const u32 != y as *mut u32 as *const u32; + //~^ ptr_eq + + #[allow(clippy::eq_op)] + let _issue14337 = main as *const () == main as *const (); + //~^ ptr_eq } diff --git a/src/tools/clippy/tests/ui/ptr_eq.stderr b/src/tools/clippy/tests/ui/ptr_eq.stderr index 8e8b34f26ff..33190df284a 100644 --- a/src/tools/clippy/tests/ui/ptr_eq.stderr +++ b/src/tools/clippy/tests/ui/ptr_eq.stderr @@ -13,5 +13,47 @@ error: use `std::ptr::eq` when comparing raw pointers LL | let _ = a as *const _ == b as *const _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a, b)` -error: aborting due to 2 previous errors +error: use `std::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq.rs:23:13 + | +LL | let _ = a.as_ptr() == b as *const _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_ptr(), b as *const _)` + +error: use `std::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq.rs:25:13 + | +LL | let _ = a.as_ptr() == b.as_ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_ptr(), b.as_ptr())` + +error: use `std::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq.rs:36:13 + | +LL | let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _)` + +error: use `std::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq.rs:38:13 + | +LL | let _ = a.as_mut_ptr() == b.as_mut_ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr())` + +error: use `std::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq.rs:45:13 + | +LL | let _ = x as *const u32 == y as *mut u32 as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(x, y)` + +error: use `std::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq.rs:48:13 + | +LL | let _ = x as *const u32 != y as *mut u32 as *const u32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!std::ptr::eq(x, y)` + +error: use `std::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq.rs:52:23 + | +LL | let _issue14337 = main as *const () == main as *const (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(main as *const (), main as *const ())` + +error: aborting due to 9 previous errors diff --git a/src/tools/clippy/tests/ui/ptr_eq_no_std.fixed b/src/tools/clippy/tests/ui/ptr_eq_no_std.fixed index b3e82fae38f..d8ee4ea88f8 100644 --- a/src/tools/clippy/tests/ui/ptr_eq_no_std.fixed +++ b/src/tools/clippy/tests/ui/ptr_eq_no_std.fixed @@ -32,8 +32,10 @@ fn main() { //~^ ptr_eq let _ = core::ptr::eq(a, b); //~^ ptr_eq - let _ = a.as_ptr() == b as *const _; - let _ = a.as_ptr() == b.as_ptr(); + let _ = core::ptr::eq(a.as_ptr(), b as *const _); + //~^ ptr_eq + let _ = core::ptr::eq(a.as_ptr(), b.as_ptr()); + //~^ ptr_eq // Do not lint @@ -43,8 +45,10 @@ fn main() { let a = &mut [1, 2, 3]; let b = &mut [1, 2, 3]; - let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _; - let _ = a.as_mut_ptr() == b.as_mut_ptr(); + let _ = core::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _); + //~^ ptr_eq + let _ = core::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr()); + //~^ ptr_eq let _ = a == b; let _ = core::ptr::eq(a, b); diff --git a/src/tools/clippy/tests/ui/ptr_eq_no_std.rs b/src/tools/clippy/tests/ui/ptr_eq_no_std.rs index ba78f5ee5f8..a236314c29b 100644 --- a/src/tools/clippy/tests/ui/ptr_eq_no_std.rs +++ b/src/tools/clippy/tests/ui/ptr_eq_no_std.rs @@ -33,7 +33,9 @@ fn main() { let _ = a as *const _ == b as *const _; //~^ ptr_eq let _ = a.as_ptr() == b as *const _; + //~^ ptr_eq let _ = a.as_ptr() == b.as_ptr(); + //~^ ptr_eq // Do not lint @@ -44,7 +46,9 @@ fn main() { let b = &mut [1, 2, 3]; let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _; + //~^ ptr_eq let _ = a.as_mut_ptr() == b.as_mut_ptr(); + //~^ ptr_eq let _ = a == b; let _ = core::ptr::eq(a, b); diff --git a/src/tools/clippy/tests/ui/ptr_eq_no_std.stderr b/src/tools/clippy/tests/ui/ptr_eq_no_std.stderr index 8c7b1ff7666..5b8135dc8e8 100644 --- a/src/tools/clippy/tests/ui/ptr_eq_no_std.stderr +++ b/src/tools/clippy/tests/ui/ptr_eq_no_std.stderr @@ -13,5 +13,29 @@ error: use `core::ptr::eq` when comparing raw pointers LL | let _ = a as *const _ == b as *const _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a, b)` -error: aborting due to 2 previous errors +error: use `core::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq_no_std.rs:35:13 + | +LL | let _ = a.as_ptr() == b as *const _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_ptr(), b as *const _)` + +error: use `core::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq_no_std.rs:37:13 + | +LL | let _ = a.as_ptr() == b.as_ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_ptr(), b.as_ptr())` + +error: use `core::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq_no_std.rs:48:13 + | +LL | let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _)` + +error: use `core::ptr::eq` when comparing raw pointers + --> tests/ui/ptr_eq_no_std.rs:50:13 + | +LL | let _ = a.as_mut_ptr() == b.as_mut_ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr())` + +error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/question_mark.fixed b/src/tools/clippy/tests/ui/question_mark.fixed index 8dfef3202be..fff41f57828 100644 --- a/src/tools/clippy/tests/ui/question_mark.fixed +++ b/src/tools/clippy/tests/ui/question_mark.fixed @@ -375,3 +375,58 @@ fn issue12412(foo: &Foo, bar: &Bar) -> Option<()> { //~^^^ question_mark Some(()) } + +struct StructWithOptionString { + opt_x: Option<String>, +} + +struct WrapperStructWithString(String); + +#[allow(clippy::disallowed_names)] +fn issue_13417(foo: &mut StructWithOptionString) -> Option<String> { + let x = foo.opt_x.as_ref()?; + //~^^^ question_mark + let opt_y = Some(x.clone()); + std::mem::replace(&mut foo.opt_x, opt_y) +} + +#[allow(clippy::disallowed_names)] +fn issue_13417_mut(foo: &mut StructWithOptionString) -> Option<String> { + let x = foo.opt_x.as_mut()?; + //~^^^ question_mark + let opt_y = Some(x.clone()); + std::mem::replace(&mut foo.opt_x, opt_y) +} + +#[allow(clippy::disallowed_names)] +#[allow(unused)] +fn issue_13417_weirder(foo: &mut StructWithOptionString, mut bar: Option<WrapperStructWithString>) -> Option<()> { + let x @ y = foo.opt_x.as_ref()?; + //~^^^ question_mark + let x @ &WrapperStructWithString(_) = bar.as_ref()?; + //~^^^ question_mark + let x @ &mut WrapperStructWithString(_) = bar.as_mut()?; + //~^^^ question_mark + Some(()) +} + +#[clippy::msrv = "1.12"] +fn msrv_1_12(arg: Option<i32>) -> Option<i32> { + if arg.is_none() { + return None; + } + let val = match arg { + Some(val) => val, + None => return None, + }; + println!("{}", val); + Some(val) +} + +#[clippy::msrv = "1.13"] +fn msrv_1_13(arg: Option<i32>) -> Option<i32> { + arg?; + let val = arg?; + println!("{}", val); + Some(val) +} diff --git a/src/tools/clippy/tests/ui/question_mark.rs b/src/tools/clippy/tests/ui/question_mark.rs index fffaa803f39..c71c8ee984e 100644 --- a/src/tools/clippy/tests/ui/question_mark.rs +++ b/src/tools/clippy/tests/ui/question_mark.rs @@ -452,3 +452,75 @@ fn issue12412(foo: &Foo, bar: &Bar) -> Option<()> { //~^^^ question_mark Some(()) } + +struct StructWithOptionString { + opt_x: Option<String>, +} + +struct WrapperStructWithString(String); + +#[allow(clippy::disallowed_names)] +fn issue_13417(foo: &mut StructWithOptionString) -> Option<String> { + let Some(ref x) = foo.opt_x else { + return None; + }; + //~^^^ question_mark + let opt_y = Some(x.clone()); + std::mem::replace(&mut foo.opt_x, opt_y) +} + +#[allow(clippy::disallowed_names)] +fn issue_13417_mut(foo: &mut StructWithOptionString) -> Option<String> { + let Some(ref mut x) = foo.opt_x else { + return None; + }; + //~^^^ question_mark + let opt_y = Some(x.clone()); + std::mem::replace(&mut foo.opt_x, opt_y) +} + +#[allow(clippy::disallowed_names)] +#[allow(unused)] +fn issue_13417_weirder(foo: &mut StructWithOptionString, mut bar: Option<WrapperStructWithString>) -> Option<()> { + let Some(ref x @ ref y) = foo.opt_x else { + return None; + }; + //~^^^ question_mark + let Some(ref x @ WrapperStructWithString(_)) = bar else { + return None; + }; + //~^^^ question_mark + let Some(ref mut x @ WrapperStructWithString(_)) = bar else { + return None; + }; + //~^^^ question_mark + Some(()) +} + +#[clippy::msrv = "1.12"] +fn msrv_1_12(arg: Option<i32>) -> Option<i32> { + if arg.is_none() { + return None; + } + let val = match arg { + Some(val) => val, + None => return None, + }; + println!("{}", val); + Some(val) +} + +#[clippy::msrv = "1.13"] +fn msrv_1_13(arg: Option<i32>) -> Option<i32> { + if arg.is_none() { + //~^ question_mark + return None; + } + let val = match arg { + //~^ question_mark + Some(val) => val, + None => return None, + }; + println!("{}", val); + Some(val) +} diff --git a/src/tools/clippy/tests/ui/question_mark.stderr b/src/tools/clippy/tests/ui/question_mark.stderr index c4db0fbc302..183b8866a74 100644 --- a/src/tools/clippy/tests/ui/question_mark.stderr +++ b/src/tools/clippy/tests/ui/question_mark.stderr @@ -215,5 +215,65 @@ LL | | return None; LL | | }; | |______^ help: replace it with: `let v = bar.foo.owned.clone()?;` -error: aborting due to 22 previous errors +error: this `let...else` may be rewritten with the `?` operator + --> tests/ui/question_mark.rs:464:5 + | +LL | / let Some(ref x) = foo.opt_x else { +LL | | return None; +LL | | }; + | |______^ help: replace it with: `let x = foo.opt_x.as_ref()?;` + +error: this `let...else` may be rewritten with the `?` operator + --> tests/ui/question_mark.rs:474:5 + | +LL | / let Some(ref mut x) = foo.opt_x else { +LL | | return None; +LL | | }; + | |______^ help: replace it with: `let x = foo.opt_x.as_mut()?;` + +error: this `let...else` may be rewritten with the `?` operator + --> tests/ui/question_mark.rs:485:5 + | +LL | / let Some(ref x @ ref y) = foo.opt_x else { +LL | | return None; +LL | | }; + | |______^ help: replace it with: `let x @ y = foo.opt_x.as_ref()?;` + +error: this `let...else` may be rewritten with the `?` operator + --> tests/ui/question_mark.rs:489:5 + | +LL | / let Some(ref x @ WrapperStructWithString(_)) = bar else { +LL | | return None; +LL | | }; + | |______^ help: replace it with: `let x @ &WrapperStructWithString(_) = bar.as_ref()?;` + +error: this `let...else` may be rewritten with the `?` operator + --> tests/ui/question_mark.rs:493:5 + | +LL | / let Some(ref mut x @ WrapperStructWithString(_)) = bar else { +LL | | return None; +LL | | }; + | |______^ help: replace it with: `let x @ &mut WrapperStructWithString(_) = bar.as_mut()?;` + +error: this block may be rewritten with the `?` operator + --> tests/ui/question_mark.rs:515:5 + | +LL | / if arg.is_none() { +LL | | +LL | | return None; +LL | | } + | |_____^ help: replace it with: `arg?;` + +error: this `match` expression can be replaced with `?` + --> tests/ui/question_mark.rs:519:15 + | +LL | let val = match arg { + | _______________^ +LL | | +LL | | Some(val) => val, +LL | | None => return None, +LL | | }; + | |_____^ help: try instead: `arg?` + +error: aborting due to 29 previous errors diff --git a/src/tools/clippy/tests/ui/same_functions_in_if_condition.rs b/src/tools/clippy/tests/ui/same_functions_in_if_condition.rs index b7ed3aab004..a98b73c9e1c 100644 --- a/src/tools/clippy/tests/ui/same_functions_in_if_condition.rs +++ b/src/tools/clippy/tests/ui/same_functions_in_if_condition.rs @@ -3,12 +3,7 @@ // ifs_same_cond warning is different from `ifs_same_cond`. // clippy::if_same_then_else, clippy::comparison_chain -- all empty blocks #![allow(incomplete_features)] -#![allow( - clippy::comparison_chain, - clippy::if_same_then_else, - clippy::ifs_same_cond, - clippy::uninlined_format_args -)] +#![allow(clippy::if_same_then_else, clippy::ifs_same_cond, clippy::uninlined_format_args)] use std::marker::ConstParamTy; diff --git a/src/tools/clippy/tests/ui/same_functions_in_if_condition.stderr b/src/tools/clippy/tests/ui/same_functions_in_if_condition.stderr index 6cd4f96c13e..35dcbadce59 100644 --- a/src/tools/clippy/tests/ui/same_functions_in_if_condition.stderr +++ b/src/tools/clippy/tests/ui/same_functions_in_if_condition.stderr @@ -1,11 +1,11 @@ error: this `if` has the same function call as a previous `if` - --> tests/ui/same_functions_in_if_condition.rs:39:15 + --> tests/ui/same_functions_in_if_condition.rs:34:15 | LL | } else if function() { | ^^^^^^^^^^ | note: same as this - --> tests/ui/same_functions_in_if_condition.rs:38:8 + --> tests/ui/same_functions_in_if_condition.rs:33:8 | LL | if function() { | ^^^^^^^^^^ @@ -16,61 +16,61 @@ LL | #![deny(clippy::same_functions_in_if_condition)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this `if` has the same function call as a previous `if` - --> tests/ui/same_functions_in_if_condition.rs:44:15 + --> tests/ui/same_functions_in_if_condition.rs:39:15 | LL | } else if fn_arg(a) { | ^^^^^^^^^ | note: same as this - --> tests/ui/same_functions_in_if_condition.rs:43:8 + --> tests/ui/same_functions_in_if_condition.rs:38:8 | LL | if fn_arg(a) { | ^^^^^^^^^ error: this `if` has the same function call as a previous `if` - --> tests/ui/same_functions_in_if_condition.rs:49:15 + --> tests/ui/same_functions_in_if_condition.rs:44:15 | LL | } else if obj.method() { | ^^^^^^^^^^^^ | note: same as this - --> tests/ui/same_functions_in_if_condition.rs:48:8 + --> tests/ui/same_functions_in_if_condition.rs:43:8 | LL | if obj.method() { | ^^^^^^^^^^^^ error: this `if` has the same function call as a previous `if` - --> tests/ui/same_functions_in_if_condition.rs:54:15 + --> tests/ui/same_functions_in_if_condition.rs:49:15 | LL | } else if obj.method_arg(a) { | ^^^^^^^^^^^^^^^^^ | note: same as this - --> tests/ui/same_functions_in_if_condition.rs:53:8 + --> tests/ui/same_functions_in_if_condition.rs:48:8 | LL | if obj.method_arg(a) { | ^^^^^^^^^^^^^^^^^ error: this `if` has the same function call as a previous `if` - --> tests/ui/same_functions_in_if_condition.rs:60:15 + --> tests/ui/same_functions_in_if_condition.rs:55:15 | LL | } else if v.pop().is_none() { | ^^^^^^^^^^^^^^^^^ | note: same as this - --> tests/ui/same_functions_in_if_condition.rs:59:8 + --> tests/ui/same_functions_in_if_condition.rs:54:8 | LL | if v.pop().is_none() { | ^^^^^^^^^^^^^^^^^ error: this `if` has the same function call as a previous `if` - --> tests/ui/same_functions_in_if_condition.rs:65:15 + --> tests/ui/same_functions_in_if_condition.rs:60:15 | LL | } else if v.len() == 42 { | ^^^^^^^^^^^^^ | note: same as this - --> tests/ui/same_functions_in_if_condition.rs:64:8 + --> tests/ui/same_functions_in_if_condition.rs:59:8 | LL | if v.len() == 42 { | ^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/same_name_method.stderr b/src/tools/clippy/tests/ui/same_name_method.stderr index fefdb5c9c23..b2624ac4d26 100644 --- a/src/tools/clippy/tests/ui/same_name_method.stderr +++ b/src/tools/clippy/tests/ui/same_name_method.stderr @@ -23,7 +23,6 @@ note: existing `clone` defined here | LL | #[derive(Clone)] | ^^^^^ - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: method's name is the same as an existing method in a trait --> tests/ui/same_name_method.rs:46:13 diff --git a/src/tools/clippy/tests/ui/single_match.fixed b/src/tools/clippy/tests/ui/single_match.fixed index c6ffe93eb7a..0e198ec7934 100644 --- a/src/tools/clippy/tests/ui/single_match.fixed +++ b/src/tools/clippy/tests/ui/single_match.fixed @@ -1,3 +1,4 @@ +//@require-annotations-for-level: WARN #![warn(clippy::single_match)] #![allow( unused, @@ -18,13 +19,9 @@ fn single_match() { //~^^^^^^ single_match let x = Some(1u8); - match x { - // Note the missing block braces. - // We suggest `if let Some(y) = x { .. }` because the macro - // is expanded before we can do anything. - Some(y) => println!("{:?}", y), - _ => (), - } + if let Some(y) = x { println!("{:?}", y) } + //~^^^^^^^ single_match + //~| NOTE: you might want to preserve the comments from inside the `match` let z = (1u8, 1u8); if let (2..=3, 7..=9) = z { dummy() }; @@ -358,21 +355,14 @@ fn irrefutable_match() { let mut x = vec![1i8]; - // Should not lint. - match x.pop() { - // bla - Some(u) => println!("{u}"), - // more comments! - None => {}, - } - // Should not lint. - match x.pop() { - // bla - Some(u) => { - // bla - println!("{u}"); - }, + if let Some(u) = x.pop() { println!("{u}") } + //~^^^^^^ single_match + //~| NOTE: you might want to preserve the comments from inside the `match` + + if let Some(u) = x.pop() { // bla - None => {}, + println!("{u}"); } + //~^^^^^^^^^ single_match + //~| NOTE: you might want to preserve the comments from inside the `match` } diff --git a/src/tools/clippy/tests/ui/single_match.rs b/src/tools/clippy/tests/ui/single_match.rs index dc758fa4281..fcac65f8aaf 100644 --- a/src/tools/clippy/tests/ui/single_match.rs +++ b/src/tools/clippy/tests/ui/single_match.rs @@ -1,3 +1,4 @@ +//@require-annotations-for-level: WARN #![warn(clippy::single_match)] #![allow( unused, @@ -28,6 +29,8 @@ fn single_match() { Some(y) => println!("{:?}", y), _ => (), } + //~^^^^^^^ single_match + //~| NOTE: you might want to preserve the comments from inside the `match` let z = (1u8, 1u8); match z { @@ -437,14 +440,15 @@ fn irrefutable_match() { let mut x = vec![1i8]; - // Should not lint. match x.pop() { // bla Some(u) => println!("{u}"), // more comments! None => {}, } - // Should not lint. + //~^^^^^^ single_match + //~| NOTE: you might want to preserve the comments from inside the `match` + match x.pop() { // bla Some(u) => { @@ -454,4 +458,6 @@ fn irrefutable_match() { // bla None => {}, } + //~^^^^^^^^^ single_match + //~| NOTE: you might want to preserve the comments from inside the `match` } diff --git a/src/tools/clippy/tests/ui/single_match.stderr b/src/tools/clippy/tests/ui/single_match.stderr index c8829695948..2467423b9c1 100644 --- a/src/tools/clippy/tests/ui/single_match.stderr +++ b/src/tools/clippy/tests/ui/single_match.stderr @@ -1,5 +1,5 @@ error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:15:5 + --> tests/ui/single_match.rs:16:5 | LL | / match x { LL | | Some(y) => { @@ -19,7 +19,18 @@ LL ~ }; | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:33:5 + --> tests/ui/single_match.rs:25:5 + | +LL | / match x { +... | +LL | | _ => (), +LL | | } + | |_____^ help: try: `if let Some(y) = x { println!("{:?}", y) }` + | + = note: you might want to preserve the comments from inside the `match` + +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> tests/ui/single_match.rs:36:5 | LL | / match z { LL | | (2..=3, 7..=9) => dummy(), @@ -28,7 +39,7 @@ LL | | }; | |_____^ help: try: `if let (2..=3, 7..=9) = z { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:63:5 + --> tests/ui/single_match.rs:66:5 | LL | / match x { LL | | Some(y) => dummy(), @@ -37,7 +48,7 @@ LL | | }; | |_____^ help: try: `if let Some(y) = x { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:69:5 + --> tests/ui/single_match.rs:72:5 | LL | / match y { LL | | Ok(y) => dummy(), @@ -46,7 +57,7 @@ LL | | }; | |_____^ help: try: `if let Ok(y) = y { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:77:5 + --> tests/ui/single_match.rs:80:5 | LL | / match c { LL | | Cow::Borrowed(..) => dummy(), @@ -55,7 +66,7 @@ LL | | }; | |_____^ help: try: `if let Cow::Borrowed(..) = c { dummy() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:99:5 + --> tests/ui/single_match.rs:102:5 | LL | / match x { LL | | "test" => println!(), @@ -64,7 +75,7 @@ LL | | } | |_____^ help: try: `if x == "test" { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:113:5 + --> tests/ui/single_match.rs:116:5 | LL | / match x { LL | | Foo::A => println!(), @@ -73,7 +84,7 @@ LL | | } | |_____^ help: try: `if x == Foo::A { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:120:5 + --> tests/ui/single_match.rs:123:5 | LL | / match x { LL | | FOO_C => println!(), @@ -82,7 +93,7 @@ LL | | } | |_____^ help: try: `if x == FOO_C { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:126:5 + --> tests/ui/single_match.rs:129:5 | LL | / match &&x { LL | | Foo::A => println!(), @@ -91,7 +102,7 @@ LL | | } | |_____^ help: try: `if x == Foo::A { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:133:5 + --> tests/ui/single_match.rs:136:5 | LL | / match &x { LL | | Foo::A => println!(), @@ -100,7 +111,7 @@ LL | | } | |_____^ help: try: `if x == &Foo::A { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:151:5 + --> tests/ui/single_match.rs:154:5 | LL | / match x { LL | | Bar::A => println!(), @@ -109,7 +120,7 @@ LL | | } | |_____^ help: try: `if let Bar::A = x { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:160:5 + --> tests/ui/single_match.rs:163:5 | LL | / match x { LL | | None => println!(), @@ -118,7 +129,7 @@ LL | | }; | |_____^ help: try: `if let None = x { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:183:5 + --> tests/ui/single_match.rs:186:5 | LL | / match x { LL | | (Some(_), _) => {}, @@ -127,7 +138,7 @@ LL | | } | |_____^ help: try: `if let (Some(_), _) = x {}` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:190:5 + --> tests/ui/single_match.rs:193:5 | LL | / match x { LL | | (Some(E::V), _) => todo!(), @@ -136,7 +147,7 @@ LL | | } | |_____^ help: try: `if let (Some(E::V), _) = x { todo!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:197:5 + --> tests/ui/single_match.rs:200:5 | LL | / match (Some(42), Some(E::V), Some(42)) { LL | | (.., Some(E::V), _) => {}, @@ -145,7 +156,7 @@ LL | | } | |_____^ help: try: `if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {}` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:270:5 + --> tests/ui/single_match.rs:273:5 | LL | / match bar { LL | | Some(v) => unsafe { @@ -165,7 +176,7 @@ LL + } } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:279:5 + --> tests/ui/single_match.rs:282:5 | LL | / match bar { LL | | #[rustfmt::skip] @@ -187,7 +198,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:360:5 + --> tests/ui/single_match.rs:363:5 | LL | / match Ok::<_, u32>(Some(A)) { LL | | Ok(Some(A)) => println!(), @@ -196,7 +207,7 @@ LL | | } | |_____^ help: try: `if let Ok(Some(A)) = Ok::<_, u32>(Some(A)) { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:376:5 + --> tests/ui/single_match.rs:379:5 | LL | / match &Some(A) { LL | | Some(A | B) => println!(), @@ -205,7 +216,7 @@ LL | | } | |_____^ help: try: `if let Some(A | B) = &Some(A) { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:384:5 + --> tests/ui/single_match.rs:387:5 | LL | / match &s[0..3] { LL | | b"foo" => println!(), @@ -214,7 +225,7 @@ LL | | } | |_____^ help: try: `if &s[0..3] == b"foo" { println!() }` error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match.rs:398:5 + --> tests/ui/single_match.rs:401:5 | LL | / match DATA { LL | | DATA => println!(), @@ -223,7 +234,7 @@ LL | | } | |_____^ help: try: `println!();` error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match.rs:404:5 + --> tests/ui/single_match.rs:407:5 | LL | / match CONST_I32 { LL | | CONST_I32 => println!(), @@ -232,7 +243,7 @@ LL | | } | |_____^ help: try: `println!();` error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match.rs:411:5 + --> tests/ui/single_match.rs:414:5 | LL | / match i { LL | | i => { @@ -252,7 +263,7 @@ LL + } | error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match.rs:420:5 + --> tests/ui/single_match.rs:423:5 | LL | / match i { LL | | i => {}, @@ -261,7 +272,7 @@ LL | | } | |_____^ help: `match` expression can be removed error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match.rs:426:5 + --> tests/ui/single_match.rs:429:5 | LL | / match i { LL | | i => (), @@ -270,7 +281,7 @@ LL | | } | |_____^ help: `match` expression can be removed error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match.rs:432:5 + --> tests/ui/single_match.rs:435:5 | LL | / match CONST_I32 { LL | | CONST_I32 => println!(), @@ -278,5 +289,37 @@ LL | | _ => {}, LL | | } | |_____^ help: try: `println!();` -error: aborting due to 26 previous errors +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> tests/ui/single_match.rs:443:5 + | +LL | / match x.pop() { +LL | | // bla +LL | | Some(u) => println!("{u}"), +... | +LL | | } + | |_____^ help: try: `if let Some(u) = x.pop() { println!("{u}") }` + | + = note: you might want to preserve the comments from inside the `match` + +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> tests/ui/single_match.rs:452:5 + | +LL | / match x.pop() { +LL | | // bla +LL | | Some(u) => { +... | +LL | | None => {}, +LL | | } + | |_____^ + | + = note: you might want to preserve the comments from inside the `match` +help: try + | +LL ~ if let Some(u) = x.pop() { +LL + // bla +LL + println!("{u}"); +LL + } + | + +error: aborting due to 29 previous errors diff --git a/src/tools/clippy/tests/ui/single_match_else.fixed b/src/tools/clippy/tests/ui/single_match_else.fixed index 64782bf62a7..fde13fb90db 100644 --- a/src/tools/clippy/tests/ui/single_match_else.fixed +++ b/src/tools/clippy/tests/ui/single_match_else.fixed @@ -1,4 +1,5 @@ //@aux-build: proc_macros.rs +//@require-annotations-for-level: WARN #![warn(clippy::single_match_else)] #![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)] @@ -90,6 +91,13 @@ fn main() { } //~^^^^^^^ single_match_else + if let Some(a) = Some(1) { println!("${:?}", a) } else { + println!("else block"); + return; + } + //~^^^^^^^^ single_match_else + //~| NOTE: you might want to preserve the comments from inside the `match` + // lint here use std::convert::Infallible; if let Ok(a) = Result::<i32, &Infallible>::Ok(1) { println!("${:?}", a) } else { diff --git a/src/tools/clippy/tests/ui/single_match_else.rs b/src/tools/clippy/tests/ui/single_match_else.rs index 3f86f4d5180..ca282200067 100644 --- a/src/tools/clippy/tests/ui/single_match_else.rs +++ b/src/tools/clippy/tests/ui/single_match_else.rs @@ -1,4 +1,5 @@ //@aux-build: proc_macros.rs +//@require-annotations-for-level: WARN #![warn(clippy::single_match_else)] #![allow(unused, clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)] @@ -99,6 +100,17 @@ fn main() { } //~^^^^^^^ single_match_else + match Some(1) { + Some(a) => println!("${:?}", a), + // This is an inner comment + None => { + println!("else block"); + return; + }, + } + //~^^^^^^^^ single_match_else + //~| NOTE: you might want to preserve the comments from inside the `match` + // lint here use std::convert::Infallible; match Result::<i32, &Infallible>::Ok(1) { diff --git a/src/tools/clippy/tests/ui/single_match_else.stderr b/src/tools/clippy/tests/ui/single_match_else.stderr index 7d4ba5fb75e..570480f9a3f 100644 --- a/src/tools/clippy/tests/ui/single_match_else.stderr +++ b/src/tools/clippy/tests/ui/single_match_else.stderr @@ -1,5 +1,5 @@ error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:17:13 + --> tests/ui/single_match_else.rs:18:13 | LL | let _ = match ExprNode::Butterflies { | _____________^ @@ -22,7 +22,7 @@ LL ~ }; | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:83:5 + --> tests/ui/single_match_else.rs:84:5 | LL | / match Some(1) { LL | | Some(a) => println!("${:?}", a), @@ -42,7 +42,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:93:5 + --> tests/ui/single_match_else.rs:94:5 | LL | / match Some(1) { LL | | Some(a) => println!("${:?}", a), @@ -62,7 +62,28 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:104:5 + --> tests/ui/single_match_else.rs:103:5 + | +LL | / match Some(1) { +LL | | Some(a) => println!("${:?}", a), +LL | | // This is an inner comment +LL | | None => { +... | +LL | | }, +LL | | } + | |_____^ + | + = note: you might want to preserve the comments from inside the `match` +help: try + | +LL ~ if let Some(a) = Some(1) { println!("${:?}", a) } else { +LL + println!("else block"); +LL + return; +LL + } + | + +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> tests/ui/single_match_else.rs:116:5 | LL | / match Result::<i32, &Infallible>::Ok(1) { LL | | Ok(a) => println!("${:?}", a), @@ -81,7 +102,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:114:5 + --> tests/ui/single_match_else.rs:126:5 | LL | / match Cow::from("moo") { LL | | Cow::Owned(a) => println!("${:?}", a), @@ -100,7 +121,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:125:5 + --> tests/ui/single_match_else.rs:137:5 | LL | / match bar { LL | | Some(v) => unsafe { @@ -123,7 +144,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:137:5 + --> tests/ui/single_match_else.rs:149:5 | LL | / match bar { LL | | Some(v) => { @@ -147,7 +168,7 @@ LL + } } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:150:5 + --> tests/ui/single_match_else.rs:162:5 | LL | / match bar { LL | | Some(v) => unsafe { @@ -171,7 +192,7 @@ LL + } } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match_else.rs:163:5 + --> tests/ui/single_match_else.rs:175:5 | LL | / match bar { LL | | #[rustfmt::skip] @@ -196,7 +217,7 @@ LL + } | error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match_else.rs:213:5 + --> tests/ui/single_match_else.rs:225:5 | LL | / match ExprNode::Butterflies { LL | | ExprNode::Butterflies => Some(&NODE), @@ -207,5 +228,5 @@ LL | | }, LL | | } | |_____^ help: try: `Some(&NODE)` -error: aborting due to 10 previous errors +error: aborting due to 11 previous errors diff --git a/src/tools/clippy/tests/ui/size_of_ref.stderr b/src/tools/clippy/tests/ui/size_of_ref.stderr index 6ac0b0dd2f0..46af9f55dea 100644 --- a/src/tools/clippy/tests/ui/size_of_ref.stderr +++ b/src/tools/clippy/tests/ui/size_of_ref.stderr @@ -1,28 +1,28 @@ -error: argument to `std::mem::size_of_val()` is a reference to a reference +error: argument to `size_of_val()` is a reference to a reference --> tests/ui/size_of_ref.rs:13:5 | LL | size_of_val(&&x); | ^^^^^^^^^^^^^^^^ | - = help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type + = help: dereference the argument to `size_of_val()` to get the size of the value instead of the size of the reference-type = note: `-D clippy::size-of-ref` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::size_of_ref)]` -error: argument to `std::mem::size_of_val()` is a reference to a reference +error: argument to `size_of_val()` is a reference to a reference --> tests/ui/size_of_ref.rs:16:5 | LL | size_of_val(&y); | ^^^^^^^^^^^^^^^ | - = help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type + = help: dereference the argument to `size_of_val()` to get the size of the value instead of the size of the reference-type -error: argument to `std::mem::size_of_val()` is a reference to a reference +error: argument to `size_of_val()` is a reference to a reference --> tests/ui/size_of_ref.rs:28:9 | LL | std::mem::size_of_val(&self) + (std::mem::size_of::<u8>() * self.data.capacity()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: dereference the argument to `std::mem::size_of_val()` to get the size of the value instead of the size of the reference-type + = help: dereference the argument to `size_of_val()` to get the size of the value instead of the size of the reference-type error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/string_to_string.rs b/src/tools/clippy/tests/ui/string_to_string.rs index 94174e1253b..7c5bd8a897b 100644 --- a/src/tools/clippy/tests/ui/string_to_string.rs +++ b/src/tools/clippy/tests/ui/string_to_string.rs @@ -1,8 +1,21 @@ #![warn(clippy::string_to_string)] -#![allow(clippy::redundant_clone)] +#![allow(clippy::redundant_clone, clippy::unnecessary_literal_unwrap)] fn main() { let mut message = String::from("Hello"); let mut v = message.to_string(); //~^ string_to_string + + let variable1 = String::new(); + let v = &variable1; + let variable2 = Some(v); + let _ = variable2.map(|x| { + println!(); + x.to_string() + }); + //~^^ string_to_string + + let x = Some(String::new()); + let _ = x.unwrap_or_else(|| v.to_string()); + //~^ string_to_string } diff --git a/src/tools/clippy/tests/ui/string_to_string.stderr b/src/tools/clippy/tests/ui/string_to_string.stderr index ae80597d1f8..99eea06f18e 100644 --- a/src/tools/clippy/tests/ui/string_to_string.stderr +++ b/src/tools/clippy/tests/ui/string_to_string.stderr @@ -8,5 +8,21 @@ LL | let mut v = message.to_string(); = note: `-D clippy::string-to-string` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::string_to_string)]` -error: aborting due to 1 previous error +error: `to_string()` called on a `String` + --> tests/ui/string_to_string.rs:14:9 + | +LL | x.to_string() + | ^^^^^^^^^^^^^ + | + = help: consider using `.clone()` + +error: `to_string()` called on a `String` + --> tests/ui/string_to_string.rs:19:33 + | +LL | let _ = x.unwrap_or_else(|| v.to_string()); + | ^^^^^^^^^^^^^ + | + = help: consider using `.clone()` + +error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/string_to_string_in_map.fixed b/src/tools/clippy/tests/ui/string_to_string_in_map.fixed new file mode 100644 index 00000000000..efc085539f1 --- /dev/null +++ b/src/tools/clippy/tests/ui/string_to_string_in_map.fixed @@ -0,0 +1,20 @@ +#![deny(clippy::string_to_string)] +#![allow(clippy::unnecessary_literal_unwrap, clippy::useless_vec, clippy::iter_cloned_collect)] + +fn main() { + let variable1 = String::new(); + let v = &variable1; + let variable2 = Some(v); + let _ = variable2.cloned(); + //~^ string_to_string + let _ = variable2.cloned(); + //~^ string_to_string + #[rustfmt::skip] + let _ = variable2.cloned(); + //~^ string_to_string + + let _ = vec![String::new()].iter().cloned().collect::<Vec<_>>(); + //~^ string_to_string + let _ = vec![String::new()].iter().cloned().collect::<Vec<_>>(); + //~^ string_to_string +} diff --git a/src/tools/clippy/tests/ui/string_to_string_in_map.rs b/src/tools/clippy/tests/ui/string_to_string_in_map.rs new file mode 100644 index 00000000000..5bf1d7ba5a2 --- /dev/null +++ b/src/tools/clippy/tests/ui/string_to_string_in_map.rs @@ -0,0 +1,20 @@ +#![deny(clippy::string_to_string)] +#![allow(clippy::unnecessary_literal_unwrap, clippy::useless_vec, clippy::iter_cloned_collect)] + +fn main() { + let variable1 = String::new(); + let v = &variable1; + let variable2 = Some(v); + let _ = variable2.map(String::to_string); + //~^ string_to_string + let _ = variable2.map(|x| x.to_string()); + //~^ string_to_string + #[rustfmt::skip] + let _ = variable2.map(|x| { x.to_string() }); + //~^ string_to_string + + let _ = vec![String::new()].iter().map(String::to_string).collect::<Vec<_>>(); + //~^ string_to_string + let _ = vec![String::new()].iter().map(|x| x.to_string()).collect::<Vec<_>>(); + //~^ string_to_string +} diff --git a/src/tools/clippy/tests/ui/string_to_string_in_map.stderr b/src/tools/clippy/tests/ui/string_to_string_in_map.stderr new file mode 100644 index 00000000000..35aeed656ee --- /dev/null +++ b/src/tools/clippy/tests/ui/string_to_string_in_map.stderr @@ -0,0 +1,38 @@ +error: `to_string()` called on a `String` + --> tests/ui/string_to_string_in_map.rs:8:23 + | +LL | let _ = variable2.map(String::to_string); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()` + | +note: the lint level is defined here + --> tests/ui/string_to_string_in_map.rs:1:9 + | +LL | #![deny(clippy::string_to_string)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `to_string()` called on a `String` + --> tests/ui/string_to_string_in_map.rs:10:23 + | +LL | let _ = variable2.map(|x| x.to_string()); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()` + +error: `to_string()` called on a `String` + --> tests/ui/string_to_string_in_map.rs:13:23 + | +LL | let _ = variable2.map(|x| { x.to_string() }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()` + +error: `to_string()` called on a `String` + --> tests/ui/string_to_string_in_map.rs:16:40 + | +LL | let _ = vec![String::new()].iter().map(String::to_string).collect::<Vec<_>>(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()` + +error: `to_string()` called on a `String` + --> tests/ui/string_to_string_in_map.rs:18:40 + | +LL | let _ = vec![String::new()].iter().map(|x| x.to_string()).collect::<Vec<_>>(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()` + +error: aborting due to 5 previous errors + diff --git a/src/tools/clippy/tests/ui/struct_fields.rs b/src/tools/clippy/tests/ui/struct_fields.rs index 3dce530efff..e7ff2e6573b 100644 --- a/src/tools/clippy/tests/ui/struct_fields.rs +++ b/src/tools/clippy/tests/ui/struct_fields.rs @@ -344,4 +344,31 @@ struct Use { //~^ struct_field_names } +// should lint on private fields of public structs (renaming them is not breaking-exported-api) +pub struct PubStructFieldNamedAfterStruct { + pub_struct_field_named_after_struct: bool, + //~^ ERROR: field name starts with the struct's name + other1: bool, + other2: bool, +} +pub struct PubStructFieldPrefix { + //~^ ERROR: all fields have the same prefix: `field` + field_foo: u8, + field_bar: u8, + field_baz: u8, +} +// ...but should not lint on structs with public fields. +pub struct PubStructPubAndPrivateFields { + /// One could argue that this field should be linted, but currently, any public field stops all + /// checking. + pub_struct_pub_and_private_fields_1: bool, + pub pub_struct_pub_and_private_fields_2: bool, +} +// nor on common prefixes if one of the involved fields is public +pub struct PubStructPubAndPrivateFieldPrefix { + pub field_foo: u8, + field_bar: u8, + field_baz: u8, +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/struct_fields.stderr b/src/tools/clippy/tests/ui/struct_fields.stderr index 79186cc1cfd..a5ff1b12590 100644 --- a/src/tools/clippy/tests/ui/struct_fields.stderr +++ b/src/tools/clippy/tests/ui/struct_fields.stderr @@ -281,5 +281,24 @@ error: field name starts with the struct's name LL | use_baz: bool, | ^^^^^^^^^^^^^ -error: aborting due to 24 previous errors +error: field name starts with the struct's name + --> tests/ui/struct_fields.rs:349:5 + | +LL | pub_struct_field_named_after_struct: bool, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: all fields have the same prefix: `field` + --> tests/ui/struct_fields.rs:354:1 + | +LL | / pub struct PubStructFieldPrefix { +LL | | +LL | | field_foo: u8, +LL | | field_bar: u8, +LL | | field_baz: u8, +LL | | } + | |_^ + | + = help: remove the prefixes + +error: aborting due to 26 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_path_debug_formatting.rs b/src/tools/clippy/tests/ui/unnecessary_path_debug_formatting.rs index 02adeece280..f14f6085c9a 100644 --- a/src/tools/clippy/tests/ui/unnecessary_path_debug_formatting.rs +++ b/src/tools/clippy/tests/ui/unnecessary_path_debug_formatting.rs @@ -41,3 +41,9 @@ fn main() { let deref_path = DerefPath { path }; println!("{:?}", &*deref_path); //~ unnecessary_debug_formatting } + +#[test] +fn issue_14345() { + let input = std::path::Path::new("/foo/bar"); + assert!(input.ends_with("baz"), "{input:?}"); +} diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed index bf271aef763..5410033dbd8 100644 --- a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed +++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed @@ -195,19 +195,11 @@ fn main() { //~^ unnecessary_to_owned let _ = slice.iter().copied(); //~^ unnecessary_to_owned - let _ = [std::path::PathBuf::new()][..].iter().cloned(); - //~^ unnecessary_to_owned - let _ = [std::path::PathBuf::new()][..].iter().cloned(); - //~^ unnecessary_to_owned let _ = slice.iter().copied(); //~^ unnecessary_to_owned let _ = slice.iter().copied(); //~^ unnecessary_to_owned - let _ = [std::path::PathBuf::new()][..].iter().cloned(); - //~^ unnecessary_to_owned - let _ = [std::path::PathBuf::new()][..].iter().cloned(); - //~^ unnecessary_to_owned let _ = check_files(&[FileType::Account]); @@ -317,19 +309,6 @@ fn get_file_path(_file_type: &FileType) -> Result<std::path::PathBuf, std::io::E fn require_string(_: &String) {} -#[clippy::msrv = "1.35"] -fn _msrv_1_35() { - // `copied` was stabilized in 1.36, so clippy should use `cloned`. - let _ = &["x"][..].iter().cloned(); - //~^ unnecessary_to_owned -} - -#[clippy::msrv = "1.36"] -fn _msrv_1_36() { - let _ = &["x"][..].iter().copied(); - //~^ unnecessary_to_owned -} - // https://github.com/rust-lang/rust-clippy/issues/8507 mod issue_8507 { #![allow(dead_code)] @@ -680,3 +659,18 @@ fn issue13624() -> impl IntoIterator { cow.into_owned().into_iter() } + +mod issue_14242 { + use std::rc::Rc; + + #[derive(Copy, Clone)] + struct Foo; + + fn rc_slice_provider() -> Rc<[Foo]> { + Rc::from([Foo]) + } + + fn iterator_provider() -> impl Iterator<Item = Foo> { + rc_slice_provider().to_vec().into_iter() + } +} diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs index 95b95ab6bd2..0619dd4ddec 100644 --- a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs +++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs @@ -195,19 +195,11 @@ fn main() { //~^ unnecessary_to_owned let _ = slice.to_owned().into_iter(); //~^ unnecessary_to_owned - let _ = [std::path::PathBuf::new()][..].to_vec().into_iter(); - //~^ unnecessary_to_owned - let _ = [std::path::PathBuf::new()][..].to_owned().into_iter(); - //~^ unnecessary_to_owned let _ = IntoIterator::into_iter(slice.to_vec()); //~^ unnecessary_to_owned let _ = IntoIterator::into_iter(slice.to_owned()); //~^ unnecessary_to_owned - let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_vec()); - //~^ unnecessary_to_owned - let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_owned()); - //~^ unnecessary_to_owned let _ = check_files(&[FileType::Account]); @@ -317,19 +309,6 @@ fn get_file_path(_file_type: &FileType) -> Result<std::path::PathBuf, std::io::E fn require_string(_: &String) {} -#[clippy::msrv = "1.35"] -fn _msrv_1_35() { - // `copied` was stabilized in 1.36, so clippy should use `cloned`. - let _ = &["x"][..].to_vec().into_iter(); - //~^ unnecessary_to_owned -} - -#[clippy::msrv = "1.36"] -fn _msrv_1_36() { - let _ = &["x"][..].to_vec().into_iter(); - //~^ unnecessary_to_owned -} - // https://github.com/rust-lang/rust-clippy/issues/8507 mod issue_8507 { #![allow(dead_code)] @@ -680,3 +659,18 @@ fn issue13624() -> impl IntoIterator { cow.into_owned().into_iter() } + +mod issue_14242 { + use std::rc::Rc; + + #[derive(Copy, Clone)] + struct Foo; + + fn rc_slice_provider() -> Rc<[Foo]> { + Rc::from([Foo]) + } + + fn iterator_provider() -> impl Iterator<Item = Foo> { + rc_slice_provider().to_vec().into_iter() + } +} diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr b/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr index 4daa3876e60..8926db34da8 100644 --- a/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr @@ -1,11 +1,11 @@ error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:225:64 + --> tests/ui/unnecessary_to_owned.rs:217:64 | LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:225:20 + --> tests/ui/unnecessary_to_owned.rs:217:20 | LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,49 +13,49 @@ LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned()) = help: to override `-D warnings` add `#[allow(clippy::redundant_clone)]` error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:227:40 + --> tests/ui/unnecessary_to_owned.rs:219:40 | LL | require_os_str(&OsString::from("x").to_os_string()); | ^^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:227:21 + --> tests/ui/unnecessary_to_owned.rs:219:21 | LL | require_os_str(&OsString::from("x").to_os_string()); | ^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:229:48 + --> tests/ui/unnecessary_to_owned.rs:221:48 | LL | require_path(&std::path::PathBuf::from("x").to_path_buf()); | ^^^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:229:19 + --> tests/ui/unnecessary_to_owned.rs:221:19 | LL | require_path(&std::path::PathBuf::from("x").to_path_buf()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:231:35 + --> tests/ui/unnecessary_to_owned.rs:223:35 | LL | require_str(&String::from("x").to_string()); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:231:18 + --> tests/ui/unnecessary_to_owned.rs:223:18 | LL | require_str(&String::from("x").to_string()); | ^^^^^^^^^^^^^^^^^ error: redundant clone - --> tests/ui/unnecessary_to_owned.rs:233:39 + --> tests/ui/unnecessary_to_owned.rs:225:39 | LL | require_slice(&[String::from("x")].to_owned()); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> tests/ui/unnecessary_to_owned.rs:233:20 + --> tests/ui/unnecessary_to_owned.rs:225:20 | LL | require_slice(&[String::from("x")].to_owned()); | ^^^^^^^^^^^^^^^^^^^ @@ -442,43 +442,19 @@ LL | let _ = slice.to_owned().into_iter(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:198:13 - | -LL | let _ = [std::path::PathBuf::new()][..].to_vec().into_iter(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` - -error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:200:13 - | -LL | let _ = [std::path::PathBuf::new()][..].to_owned().into_iter(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` - -error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:203:13 + --> tests/ui/unnecessary_to_owned.rs:199:13 | LL | let _ = IntoIterator::into_iter(slice.to_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:205:13 + --> tests/ui/unnecessary_to_owned.rs:201:13 | LL | let _ = IntoIterator::into_iter(slice.to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `slice.iter().copied()` -error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:207:13 - | -LL | let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_vec()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` - -error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:209:13 - | -LL | let _ = IntoIterator::into_iter([std::path::PathBuf::new()][..].to_owned()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[std::path::PathBuf::new()][..].iter().cloned()` - error: allocating a new `String` only to create a temporary `&str` from it - --> tests/ui/unnecessary_to_owned.rs:237:26 + --> tests/ui/unnecessary_to_owned.rs:229:26 | LL | let _ref_str: &str = &String::from_utf8(slice.to_vec()).expect("not UTF-8"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -490,7 +466,7 @@ LL + let _ref_str: &str = core::str::from_utf8(&slice).expect("not UTF-8"); | error: allocating a new `String` only to create a temporary `&str` from it - --> tests/ui/unnecessary_to_owned.rs:239:26 + --> tests/ui/unnecessary_to_owned.rs:231:26 | LL | let _ref_str: &str = &String::from_utf8(b"foo".to_vec()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -502,7 +478,7 @@ LL + let _ref_str: &str = core::str::from_utf8(b"foo").unwrap(); | error: allocating a new `String` only to create a temporary `&str` from it - --> tests/ui/unnecessary_to_owned.rs:241:26 + --> tests/ui/unnecessary_to_owned.rs:233:26 | LL | let _ref_str: &str = &String::from_utf8(b"foo".as_slice().to_owned()).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -514,7 +490,7 @@ LL + let _ref_str: &str = core::str::from_utf8(b"foo".as_slice()).unwrap(); | error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:299:14 + --> tests/ui/unnecessary_to_owned.rs:291:14 | LL | for t in file_types.to_vec() { | ^^^^^^^^^^^^^^^^^^^ @@ -526,65 +502,53 @@ LL | LL ~ let path = match get_file_path(t) { | -error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:323:14 - | -LL | let _ = &["x"][..].to_vec().into_iter(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `["x"][..].iter().cloned()` - -error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:329:14 - | -LL | let _ = &["x"][..].to_vec().into_iter(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `["x"][..].iter().copied()` - error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned.rs:378:24 + --> tests/ui/unnecessary_to_owned.rs:357:24 | LL | Box::new(build(y.to_string())) | ^^^^^^^^^^^^^ help: use: `y` error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned.rs:488:12 + --> tests/ui/unnecessary_to_owned.rs:467:12 | LL | id("abc".to_string()) | ^^^^^^^^^^^^^^^^^ help: use: `"abc"` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:632:37 + --> tests/ui/unnecessary_to_owned.rs:611:37 | LL | IntoFuture::into_future(foo([].to_vec(), &0)); | ^^^^^^^^^^^ help: use: `[]` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:643:18 + --> tests/ui/unnecessary_to_owned.rs:622:18 | LL | s.remove(&a.to_vec()); | ^^^^^^^^^^^ help: replace it with: `a` error: unnecessary use of `to_owned` - --> tests/ui/unnecessary_to_owned.rs:648:14 + --> tests/ui/unnecessary_to_owned.rs:627:14 | LL | s.remove(&"b".to_owned()); | ^^^^^^^^^^^^^^^ help: replace it with: `"b"` error: unnecessary use of `to_string` - --> tests/ui/unnecessary_to_owned.rs:650:14 + --> tests/ui/unnecessary_to_owned.rs:629:14 | LL | s.remove(&"b".to_string()); | ^^^^^^^^^^^^^^^^ help: replace it with: `"b"` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:656:14 + --> tests/ui/unnecessary_to_owned.rs:635:14 | LL | s.remove(&["b"].to_vec()); | ^^^^^^^^^^^^^^^ help: replace it with: `["b"].as_slice()` error: unnecessary use of `to_vec` - --> tests/ui/unnecessary_to_owned.rs:658:14 + --> tests/ui/unnecessary_to_owned.rs:637:14 | LL | s.remove(&(&["b"]).to_vec()); | ^^^^^^^^^^^^^^^^^^ help: replace it with: `(&["b"]).as_slice()` -error: aborting due to 88 previous errors +error: aborting due to 82 previous errors diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml index 3d35116ebc1..33d3b0728f3 100644 --- a/src/tools/clippy/triagebot.toml +++ b/src/tools/clippy/triagebot.toml @@ -34,5 +34,4 @@ users_on_vacation = [ "@Jarcho", "@blyxyas", "@y21", - "@Centri3", ] diff --git a/src/tools/clippy/util/gh-pages/index_template.html b/src/tools/clippy/util/gh-pages/index_template.html index a9b64628003..19dc1ec0b0c 100644 --- a/src/tools/clippy/util/gh-pages/index_template.html +++ b/src/tools/clippy/util/gh-pages/index_template.html @@ -19,10 +19,10 @@ Otherwise, have a great day =^.^= <link id="githubDarkHighlight" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/github-dark.min.css" disabled="true" /> {# #} <!-- The files are not copied over into the Clippy project since they use the MPL-2.0 License --> - <link rel="stylesheet" href="https://rust-lang.github.io/mdBook/css/variables.css"/> {# #} - <link id="styleHighlight" rel="stylesheet" href="https://rust-lang.github.io/mdBook/highlight.css"> {# #} - <link id="styleNight" rel="stylesheet" href="https://rust-lang.github.io/mdBook/tomorrow-night.css" disabled="true"> {# #} - <link id="styleAyu" rel="stylesheet" href="https://rust-lang.github.io/mdBook/ayu-highlight.css" disabled="true"> {# #} + <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/rust-lang/mdBook@0.4.46/src/theme/css/variables.css"/> {# #} + <link id="styleHighlight" rel="stylesheet" href="https://cdn.jsdelivr.net/gh/rust-lang/mdBook@0.4.46/src/theme/highlight.css"> {# #} + <link id="styleNight" rel="stylesheet" href="https://cdn.jsdelivr.net/gh/rust-lang/mdBook@0.4.46/src/theme/tomorrow-night.css" disabled="true"> {# #} + <link id="styleAyu" rel="stylesheet" href="https://cdn.jsdelivr.net/gh/rust-lang/mdBook@0.4.46/src/theme/ayu-highlight.css" disabled="true"> {# #} <link rel="stylesheet" href="style.css"> {# #} <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js" defer></script> {# #} <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/languages/rust.min.js" defer></script> {# #} diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index dd611b19a8d..3ec984edacb 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -747,8 +747,7 @@ fn modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> { } let files = - get_git_modified_files(&config.git_config(), Some(dir), &vec!["rs", "stderr", "fixed"])? - .unwrap_or(vec![]); + get_git_modified_files(&config.git_config(), Some(dir), &vec!["rs", "stderr", "fixed"])?; // Add new test cases to the list, it will be convenient in daily development. let untracked_files = get_git_untracked_files(&config.git_config(), None)?.unwrap_or(vec![]); diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 2f0c7d8ddc5..b9ae583581e 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -27,7 +27,7 @@ fn main() { eprintln!( r#" WARNING: profiler runtime is not available, so `.coverage` files won't be {actioned} -help: try setting `profiler = true` in the `[build]` section of `config.toml`"# +help: try setting `profiler = true` in the `[build]` section of `bootstrap.toml`"# ); } diff --git a/src/tools/jsondocck/Cargo.toml b/src/tools/jsondocck/Cargo.toml index e1eb6d05665..80fc26cbe66 100644 --- a/src/tools/jsondocck/Cargo.toml +++ b/src/tools/jsondocck/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -jsonpath_lib = "0.3" +jsonpath-rust = "1.0.0" getopts = "0.2" regex = "1.4" shlex = "1.0" diff --git a/src/tools/jsondocck/src/cache.rs b/src/tools/jsondocck/src/cache.rs index 47512039740..1369c8ded00 100644 --- a/src/tools/jsondocck/src/cache.rs +++ b/src/tools/jsondocck/src/cache.rs @@ -30,6 +30,6 @@ impl Cache { // FIXME: Make this failible, so jsonpath syntax error has line number. pub fn select(&self, path: &str) -> Vec<&Value> { - jsonpath_lib::select(&self.value, path).unwrap() + jsonpath_rust::query::js_path_vals(path, &self.value).unwrap() } } diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index 791b231c27a..8c9e4c8bb3a 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -326,6 +326,7 @@ impl<'a> Validator<'a> { self.check_type(o); } } + GenericArgs::ReturnTypeNotation => {} } } diff --git a/src/tools/linkchecker/Cargo.toml b/src/tools/linkchecker/Cargo.toml index f1be6e9e749..7123d43eb56 100644 --- a/src/tools/linkchecker/Cargo.toml +++ b/src/tools/linkchecker/Cargo.toml @@ -9,4 +9,4 @@ path = "main.rs" [dependencies] regex = "1" -html5ever = "0.27.0" +html5ever = "0.29.0" diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 19340b5d07a..84cba3f8c44 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -16,7 +16,7 @@ //! A few exceptions are allowed as there's known bugs in rustdoc, but this //! should catch the majority of "broken link" cases. -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use std::collections::{HashMap, HashSet}; use std::io::ErrorKind; use std::path::{Component, Path, PathBuf}; @@ -544,7 +544,7 @@ fn parse_html<Sink: TokenSink>(source: &str, sink: Sink) -> Sink { let mut input = BufferQueue::default(); input.push_back(tendril.try_reinterpret().unwrap()); - let mut tok = Tokenizer::new(sink, TokenizerOpts::default()); + let tok = Tokenizer::new(sink, TokenizerOpts::default()); let _ = tok.feed(&mut input); assert!(input.is_empty()); tok.end(); @@ -554,8 +554,8 @@ fn parse_html<Sink: TokenSink>(source: &str, sink: Sink) -> Sink { #[derive(Default)] struct AttrCollector { attr_name: &'static [u8], - base: Option<String>, - found_attrs: Vec<(u64, String)>, + base: Cell<Option<String>>, + found_attrs: RefCell<Vec<(u64, String)>>, /// Tracks whether or not it is inside a <script> tag. /// /// A lot of our sources have JSON script tags which have HTML embedded @@ -564,13 +564,13 @@ struct AttrCollector { /// `TokenSinkResult::Script(…)` (and then maybe switch parser?), but I /// don't fully understand the best way to use that, and this seems good /// enough for now. - in_script: bool, + in_script: Cell<bool>, } impl TokenSink for AttrCollector { type Handle = (); - fn process_token(&mut self, token: Token, line_number: u64) -> TokenSinkResult<()> { + fn process_token(&self, token: Token, line_number: u64) -> TokenSinkResult<()> { match token { TagToken(tag) => { let tag_name = tag.name.as_bytes(); @@ -578,20 +578,20 @@ impl TokenSink for AttrCollector { if let Some(href) = tag.attrs.iter().find(|attr| attr.name.local.as_bytes() == b"href") { - self.base = Some(href.value.to_string()); + self.base.set(Some(href.value.to_string())); } return TokenSinkResult::Continue; } else if tag_name == b"script" { - self.in_script = !self.in_script; + self.in_script.set(!self.in_script.get()); } - if self.in_script { + if self.in_script.get() { return TokenSinkResult::Continue; } for attr in tag.attrs.iter() { let name = attr.name.local.as_bytes(); if name == self.attr_name { let url = attr.value.to_string(); - self.found_attrs.push((line_number, url)); + self.found_attrs.borrow_mut().push((line_number, url)); } } } @@ -607,7 +607,7 @@ impl TokenSink for AttrCollector { fn get_urls(source: &str) -> (Option<String>, Vec<(u64, String)>) { let collector = AttrCollector { attr_name: b"href", ..AttrCollector::default() }; let sink = parse_html(source, collector); - (sink.base, sink.found_attrs) + (sink.base.into_inner(), sink.found_attrs.into_inner()) } /// Retrieves id="..." attributes from HTML elements. @@ -619,7 +619,7 @@ fn parse_ids(ids: &mut HashSet<String>, file: &str, source: &str, report: &mut R let collector = AttrCollector { attr_name: b"id", ..AttrCollector::default() }; let sink = parse_html(source, collector); - for (line_number, id) in sink.found_attrs { + for (line_number, id) in sink.found_attrs.into_inner() { let encoded = small_url_encode(&id); if let Some(id) = ids.replace(id) { report.errors += 1; diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md index 5a08ac9af60..0d77ca06e1b 100644 --- a/src/tools/miri/CONTRIBUTING.md +++ b/src/tools/miri/CONTRIBUTING.md @@ -153,7 +153,7 @@ MIRI_LOG=rustc_mir::interpret=info,miri::stacked_borrows ./miri run tests/pass/v Note that you will only get `info`, `warn` or `error` messages if you use a prebuilt compiler. In order to get `debug` and `trace` level messages, you need to build miri with a locally built -compiler that has `debug=true` set in `config.toml`. +compiler that has `debug=true` set in `bootstrap.toml`. #### Debugging error messages diff --git a/src/tools/miri/cargo-miri/src/setup.rs b/src/tools/miri/cargo-miri/src/setup.rs index 0cf6f1a375c..7afc8481009 100644 --- a/src/tools/miri/cargo-miri/src/setup.rs +++ b/src/tools/miri/cargo-miri/src/setup.rs @@ -115,7 +115,7 @@ pub fn setup( // https://github.com/rust-lang/miri/issues/1421, // https://github.com/rust-lang/miri/issues/2429). Looks like setting // `RUSTC_WRAPPER` to the empty string overwrites `build.rustc-wrapper` set via - // `config.toml`. + // `bootstrap.toml`. command.env("RUSTC_WRAPPER", ""); if show_setup { diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 0bf5ae87f38..03f76cfa652 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -71,6 +71,7 @@ extern crate rustc_index; extern crate rustc_middle; extern crate rustc_session; extern crate rustc_span; +extern crate rustc_symbol_mangling; extern crate rustc_target; // Linking `rustc_driver` pulls in the required object code as the rest of the rustc crates are // shipped only as rmeta files. diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 90beffbf830..9006190cbee 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1366,6 +1366,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { _tcx: TyCtxtAt<'tcx>, machine: &Self, alloc_extra: &AllocExtra<'tcx>, + _ptr: Pointer, (alloc_id, prov_extra): (AllocId, Self::ProvenanceExtra), range: AllocRange, ) -> InterpResult<'tcx> { @@ -1390,6 +1391,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { _tcx: TyCtxtAt<'tcx>, machine: &mut Self, alloc_extra: &mut AllocExtra<'tcx>, + _ptr: Pointer, (alloc_id, prov_extra): (AllocId, Self::ProvenanceExtra), range: AllocRange, ) -> InterpResult<'tcx> { @@ -1414,6 +1416,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> { _tcx: TyCtxtAt<'tcx>, machine: &mut Self, alloc_extra: &mut AllocExtra<'tcx>, + _ptr: Pointer, (alloc_id, prove_extra): (AllocId, Self::ProvenanceExtra), size: Size, align: Align, diff --git a/src/tools/miri/src/shims/extern_static.rs b/src/tools/miri/src/shims/extern_static.rs index 20dd3c8db2a..2feed5a8352 100644 --- a/src/tools/miri/src/shims/extern_static.rs +++ b/src/tools/miri/src/shims/extern_static.rs @@ -1,5 +1,7 @@ //! Provides the `extern static` that this platform expects. +use rustc_symbol_mangling::mangle_internal_symbol; + use crate::*; impl<'tcx> MiriMachine<'tcx> { @@ -50,7 +52,11 @@ impl<'tcx> MiriMachine<'tcx> { // "__rust_alloc_error_handler_should_panic" let val = ecx.tcx.sess.opts.unstable_opts.oom.should_panic(); let val = ImmTy::from_int(val, ecx.machine.layouts.u8); - Self::alloc_extern_static(ecx, "__rust_alloc_error_handler_should_panic", val)?; + Self::alloc_extern_static( + ecx, + &mangle_internal_symbol(*ecx.tcx, "__rust_alloc_error_handler_should_panic"), + val, + )?; if ecx.target_os_is_unix() { // "environ" is mandated by POSIX. diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 505c079143a..03c6081e992 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -12,6 +12,7 @@ use rustc_middle::mir::interpret::AllocInit; use rustc_middle::ty::Ty; use rustc_middle::{mir, ty}; use rustc_span::Symbol; +use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::callconv::{Conv, FnAbi}; use self::helpers::{ToHost, ToSoft}; @@ -51,7 +52,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Some shims forward to other MIR bodies. match link_name.as_str() { - "__rust_alloc_error_handler" => { + name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc_error_handler") => { // Forward to the right symbol that implements this function. let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else { // in real code, this symbol does not exist without an allocator @@ -59,9 +60,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { "`__rust_alloc_error_handler` cannot be called when no alloc error handler is set" ); }; - let name = alloc_error_handler_name(handler_kind); + let name = + mangle_internal_symbol(*this.tcx, alloc_error_handler_name(handler_kind)); let handler = this - .lookup_exported_symbol(Symbol::intern(name))? + .lookup_exported_symbol(Symbol::intern(&name))? .expect("missing alloc error handler symbol"); return interp_ok(Some(handler)); } @@ -136,15 +138,29 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Find it if it was not cached. let mut instance_and_crate: Option<(ty::Instance<'_>, CrateNum)> = None; helpers::iter_exported_symbols(tcx, |cnum, def_id| { + if tcx.is_foreign_item(def_id) { + // Skip over imports of items + return interp_ok(()); + } + let attrs = tcx.codegen_fn_attrs(def_id); + // FIXME use tcx.symbol_name(instance) instead let symbol_name = if let Some(export_name) = attrs.export_name { export_name - } else if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) { + } else if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) + || attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) + { tcx.item_name(def_id) } else { // Skip over items without an explicitly defined symbol name. return interp_ok(()); }; + let symbol_name = + if attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) { + Symbol::intern(&mangle_internal_symbol(tcx, symbol_name.as_str())) + } else { + symbol_name + }; if symbol_name == link_name { if let Some((original_instance, original_cnum)) = instance_and_crate { // Make sure we are consistent wrt what is 'first' and 'second'. @@ -489,7 +505,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } // Rust allocation - "__rust_alloc" | "miri_alloc" => { + name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc") + || name == "miri_alloc" => + { let default = |ecx: &mut MiriInterpCx<'tcx>| { // Only call `check_shim` when `#[global_allocator]` isn't used. When that // macro is used, we act like no shim exists, so that the exported function can run. @@ -500,9 +518,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { ecx.check_rustc_alloc_request(size, align)?; let memory_kind = match link_name.as_str() { - "__rust_alloc" => MiriMemoryKind::Rust, "miri_alloc" => MiriMemoryKind::Miri, - _ => unreachable!(), + _ => MiriMemoryKind::Rust, }; let ptr = ecx.allocate_ptr( @@ -516,15 +533,14 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { }; match link_name.as_str() { - "__rust_alloc" => return this.emulate_allocator(default), "miri_alloc" => { default(this)?; return interp_ok(EmulateItemResult::NeedsReturn); } - _ => unreachable!(), + _ => return this.emulate_allocator(default), } } - "__rust_alloc_zeroed" => { + name if name == mangle_internal_symbol(*this.tcx, "__rust_alloc_zeroed") => { return this.emulate_allocator(|this| { // See the comment for `__rust_alloc` why `check_shim` is only called in the // default case. @@ -543,7 +559,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_pointer(ptr, dest) }); } - "__rust_dealloc" | "miri_dealloc" => { + name if name == mangle_internal_symbol(*this.tcx, "__rust_dealloc") + || name == "miri_dealloc" => + { let default = |ecx: &mut MiriInterpCx<'tcx>| { // See the comment for `__rust_alloc` why `check_shim` is only called in the // default case. @@ -554,9 +572,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { let align = ecx.read_target_usize(align)?; let memory_kind = match link_name.as_str() { - "__rust_dealloc" => MiriMemoryKind::Rust, "miri_dealloc" => MiriMemoryKind::Miri, - _ => unreachable!(), + _ => MiriMemoryKind::Rust, }; // No need to check old_size/align; we anyway check that they match the allocation. @@ -568,17 +585,14 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { }; match link_name.as_str() { - "__rust_dealloc" => { - return this.emulate_allocator(default); - } "miri_dealloc" => { default(this)?; return interp_ok(EmulateItemResult::NeedsReturn); } - _ => unreachable!(), + _ => return this.emulate_allocator(default), } } - "__rust_realloc" => { + name if name == mangle_internal_symbol(*this.tcx, "__rust_realloc") => { return this.emulate_allocator(|this| { // See the comment for `__rust_alloc` why `check_shim` is only called in the // default case. diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr index 1a9e7574339..7e8c198b6a3 100644 --- a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr +++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr @@ -21,7 +21,6 @@ note: inside `miri_start` | LL | handle_alloc_error(Layout::for_value(&0)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/alloc/too_large.rs b/src/tools/miri/tests/fail/alloc/too_large.rs index 4e28d2401d7..c53318855ab 100644 --- a/src/tools/miri/tests/fail/alloc/too_large.rs +++ b/src/tools/miri/tests/fail/alloc/too_large.rs @@ -1,4 +1,7 @@ +#![feature(rustc_attrs)] + extern "Rust" { + #[rustc_std_internal_symbol] fn __rust_alloc(size: usize, align: usize) -> *mut u8; } diff --git a/src/tools/miri/tests/fail/alloc/unsupported_big_alignment.rs b/src/tools/miri/tests/fail/alloc/unsupported_big_alignment.rs index 08d84c461bf..34c6a6ce550 100644 --- a/src/tools/miri/tests/fail/alloc/unsupported_big_alignment.rs +++ b/src/tools/miri/tests/fail/alloc/unsupported_big_alignment.rs @@ -2,7 +2,10 @@ // because rustc does not support alignments that large. // https://github.com/rust-lang/miri/issues/3687 +#![feature(rustc_attrs)] + extern "Rust" { + #[rustc_std_internal_symbol] fn __rust_alloc(size: usize, align: usize) -> *mut u8; } diff --git a/src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.rs b/src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.rs index a4ab8094bf4..ce8861937f8 100644 --- a/src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.rs +++ b/src/tools/miri/tests/fail/alloc/unsupported_non_power_two_alignment.rs @@ -1,5 +1,9 @@ // Test non-power-of-two alignment. + +#![feature(rustc_attrs)] + extern "Rust" { + #[rustc_std_internal_symbol] fn __rust_alloc(size: usize, align: usize) -> *mut u8; } diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs index f174909e9d5..d0a28482054 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs +++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race1.rs @@ -3,6 +3,8 @@ // Avoid accidental synchronization via address reuse inside `thread::spawn`. //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0 +#![feature(rustc_attrs)] + use std::thread::spawn; #[derive(Copy, Clone)] @@ -12,6 +14,7 @@ unsafe impl<T> Send for EvilSend<T> {} unsafe impl<T> Sync for EvilSend<T> {} extern "Rust" { + #[rustc_std_internal_symbol] fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); } diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs index 1edfbf5e61c..f56c44cabc2 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs +++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.rs @@ -3,6 +3,8 @@ // Avoid accidental synchronization via address reuse inside `thread::spawn`. //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0 +#![feature(rustc_attrs)] + use std::thread::spawn; #[derive(Copy, Clone)] @@ -12,6 +14,7 @@ unsafe impl<T> Send for EvilSend<T> {} unsafe impl<T> Sync for EvilSend<T> {} extern "Rust" { + #[rustc_std_internal_symbol] fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); } diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs index 7605f1911db..a16ea25e11c 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs +++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race1.rs @@ -3,6 +3,8 @@ // Avoid accidental synchronization via address reuse inside `thread::spawn`. //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0 +#![feature(rustc_attrs)] + use std::thread::spawn; #[derive(Copy, Clone)] @@ -12,6 +14,7 @@ unsafe impl<T> Send for EvilSend<T> {} unsafe impl<T> Sync for EvilSend<T> {} extern "Rust" { + #[rustc_std_internal_symbol] fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); } pub fn main() { diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs index 4f3819bd636..f3855e33c98 100644 --- a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs +++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.rs @@ -3,6 +3,8 @@ // Avoid accidental synchronization via address reuse inside `thread::spawn`. //@compile-flags: -Zmiri-address-reuse-cross-thread-rate=0 +#![feature(rustc_attrs)] + use std::thread::spawn; #[derive(Copy, Clone)] @@ -12,6 +14,7 @@ unsafe impl<T> Send for EvilSend<T> {} unsafe impl<T> Sync for EvilSend<T> {} extern "Rust" { + #[rustc_std_internal_symbol] fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); } pub fn main() { diff --git a/src/tools/miri/tests/fail/erroneous_const.stderr b/src/tools/miri/tests/fail/erroneous_const.stderr index 2906ac6b20a..6f1e3529ccc 100644 --- a/src/tools/miri/tests/fail/erroneous_const.stderr +++ b/src/tools/miri/tests/fail/erroneous_const.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `PrintName::<i32>::VOID` failed | LL | const VOID: ! = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> tests/fail/erroneous_const.rs:LL:CC diff --git a/src/tools/miri/tests/fail/panic/no_std.stderr b/src/tools/miri/tests/fail/panic/no_std.stderr index d54f2a58776..b1d98ffc7a9 100644 --- a/src/tools/miri/tests/fail/panic/no_std.stderr +++ b/src/tools/miri/tests/fail/panic/no_std.stderr @@ -13,7 +13,6 @@ note: inside `miri_start` | LL | panic!("blarg I am dead") | ^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/panic/panic_abort1.stderr b/src/tools/miri/tests/fail/panic/panic_abort1.stderr index ca32722942f..c950b2b4ea6 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort1.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort1.stderr @@ -22,7 +22,6 @@ note: inside `main` | LL | std::panic!("panicking from libstd"); | ^ - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/panic/panic_abort2.stderr b/src/tools/miri/tests/fail/panic/panic_abort2.stderr index 8d113d80588..9a9266ec493 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort2.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort2.stderr @@ -22,7 +22,6 @@ note: inside `main` | LL | std::panic!("{}-panicking from libstd", 42); | ^ - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/panic/panic_abort3.stderr b/src/tools/miri/tests/fail/panic/panic_abort3.stderr index 2ce753ba689..f04a2b0f3f1 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort3.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort3.stderr @@ -22,7 +22,6 @@ note: inside `main` | LL | core::panic!("panicking from libcore"); | ^ - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/panic/panic_abort4.stderr b/src/tools/miri/tests/fail/panic/panic_abort4.stderr index c9c5ae107b7..e71c4879ea3 100644 --- a/src/tools/miri/tests/fail/panic/panic_abort4.stderr +++ b/src/tools/miri/tests/fail/panic/panic_abort4.stderr @@ -22,7 +22,6 @@ note: inside `main` | LL | core::panic!("{}-panicking from libcore", 42); | ^ - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/pass/function_calls/exported_symbol.rs b/src/tools/miri/tests/pass/function_calls/exported_symbol.rs index 27aee9c8835..d804f3642b1 100644 --- a/src/tools/miri/tests/pass/function_calls/exported_symbol.rs +++ b/src/tools/miri/tests/pass/function_calls/exported_symbol.rs @@ -40,6 +40,7 @@ fn main() { extern "Rust" { fn bar() -> i32; + #[rustc_std_internal_symbol] fn baz() -> i32; fn qux() -> i32; } @@ -63,6 +64,7 @@ fn main() { extern "C" { fn bar() -> i32; + #[rustc_std_internal_symbol] fn baz() -> i32; fn qux() -> i32; } diff --git a/src/tools/miri/tests/pass/shims/pipe.rs b/src/tools/miri/tests/pass/shims/pipe.rs index 1be29886d2d..c47feb8774a 100644 --- a/src/tools/miri/tests/pass/shims/pipe.rs +++ b/src/tools/miri/tests/pass/shims/pipe.rs @@ -1,7 +1,5 @@ //@ignore-target: windows -#![feature(anonymous_pipe)] - use std::io::{Read, Write, pipe}; fn main() { diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs index 3111149f2ae..ac5d294f07e 100644 --- a/src/tools/opt-dist/src/main.rs +++ b/src/tools/opt-dist/src/main.rs @@ -369,9 +369,17 @@ fn main() -> anyhow::Result<()> { println!("Environment values\n{}", format_env_variables()); }); - with_log_group("Printing config.toml", || { - if let Ok(config) = std::fs::read_to_string("config.toml") { - println!("Contents of `config.toml`:\n{config}"); + with_log_group("Printing bootstrap.toml", || { + let config_file = if std::path::Path::new("bootstrap.toml").exists() { + "bootstrap.toml" + } else { + "config.toml" // Fall back for backward compatibility + }; + + if let Ok(config) = std::fs::read_to_string(config_file) { + println!("Contents of `bootstrap.toml`:\n{config}"); + } else { + eprintln!("Failed to read `{}`", config_file); } }); diff --git a/src/tools/opt-dist/src/tests.rs b/src/tools/opt-dist/src/tests.rs index 8b3bd77141b..53ce772fa77 100644 --- a/src/tools/opt-dist/src/tests.rs +++ b/src/tools/opt-dist/src/tests.rs @@ -1,3 +1,5 @@ +use std::path::Path; + use anyhow::Context; use camino::{Utf8Path, Utf8PathBuf}; @@ -83,39 +85,60 @@ llvm-config = "{llvm_config}" cargo = cargo_path.to_string().replace('\\', "/"), llvm_config = llvm_config.to_string().replace('\\', "/") ); - log::info!("Using following `config.toml` for running tests:\n{config_content}"); + log::info!("Using following `bootstrap.toml` for running tests:\n{config_content}"); // Simulate a stage 0 compiler with the extracted optimized dist artifacts. - std::fs::write("config.toml", config_content)?; - - let x_py = env.checkout_path().join("x.py"); - let mut args = vec![ - env.python_binary(), - x_py.as_str(), - "test", - "--build", - env.host_tuple(), - "--stage", - "0", - "tests/assembly", - "tests/codegen", - "tests/codegen-units", - "tests/incremental", - "tests/mir-opt", - "tests/pretty", - "tests/run-make/glibc-symbols-x86_64-unknown-linux-gnu", - "tests/ui", - "tests/crashes", - ]; - for test_path in env.skipped_tests() { - args.extend(["--skip", test_path]); + with_backed_up_file(Path::new("bootstrap.toml"), &config_content, || { + let x_py = env.checkout_path().join("x.py"); + let mut args = vec![ + env.python_binary(), + x_py.as_str(), + "test", + "--build", + env.host_tuple(), + "--stage", + "0", + "tests/assembly", + "tests/codegen", + "tests/codegen-units", + "tests/incremental", + "tests/mir-opt", + "tests/pretty", + "tests/run-make/glibc-symbols-x86_64-unknown-linux-gnu", + "tests/ui", + "tests/crashes", + ]; + for test_path in env.skipped_tests() { + args.extend(["--skip", test_path]); + } + cmd(&args) + .env("COMPILETEST_FORCE_STAGE0", "1") + // Also run dist-only tests + .env("COMPILETEST_ENABLE_DIST_TESTS", "1") + .run() + .context("Cannot execute tests") + }) +} + +/// Backup `path` (if it exists), then write `contents` into it, and then restore the original +/// contents of the file. +fn with_backed_up_file<F>(path: &Path, contents: &str, func: F) -> anyhow::Result<()> +where + F: FnOnce() -> anyhow::Result<()>, +{ + let original_contents = + if path.is_file() { Some(std::fs::read_to_string(path)?) } else { None }; + + // Overwrite it with new contents + std::fs::write(path, contents)?; + + let ret = func(); + + if let Some(original_contents) = original_contents { + std::fs::write(path, original_contents)?; } - cmd(&args) - .env("COMPILETEST_FORCE_STAGE0", "1") - // Also run dist-only tests - .env("COMPILETEST_ENABLE_DIST_TESTS", "1") - .run() - .context("Cannot execute tests") + + ret } /// Tries to find the version of the dist artifacts (either nightly, beta, or 1.XY.Z). diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index 67fb73696f7..65fb342f752 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -145,19 +145,19 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> { let mut result = vec![]; if fps.is_empty() { debug!("Unrestricted search for {:?} impls...", trait_); - self.for_trait_impls(trait_, self_ty_fp, |impls| { + let _ = self.for_trait_impls(trait_, self_ty_fp, |impls| { result.extend(impls.for_trait(trait_).map(id_to_chalk)); ControlFlow::Continue(()) - }) + }); } else { - self.for_trait_impls(trait_, self_ty_fp, |impls| { + let _ = self.for_trait_impls(trait_, self_ty_fp, |impls| { result.extend( fps.iter().flat_map(move |fp| { impls.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk) }), ); ControlFlow::Continue(()) - }) + }); }; debug!("impls_for_trait returned {} impls", result.len()); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs index 6a01579bccc..e042c35d0c6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs @@ -116,7 +116,7 @@ pub fn dyn_compatibility_of_trait_query( trait_: TraitId, ) -> Option<DynCompatibilityViolation> { let mut res = None; - dyn_compatibility_of_trait_with_callback(db, trait_, &mut |osv| { + let _ = dyn_compatibility_of_trait_with_callback(db, trait_, &mut |osv| { res = Some(osv); ControlFlow::Break(()) }); @@ -597,7 +597,7 @@ fn contains_illegal_impl_trait_in_trait( let ret = sig.skip_binders().ret(); let mut visitor = OpaqueTypeCollector(FxHashSet::default()); - ret.visit_with(visitor.as_dyn(), DebruijnIndex::INNERMOST); + let _ = ret.visit_with(visitor.as_dyn(), DebruijnIndex::INNERMOST); // Since we haven't implemented RPITIT in proper way like rustc yet, // just check whether `ret` contains RPIT for now diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs index 3060b610bb6..50851325bd5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs @@ -53,7 +53,7 @@ fn check_dyn_compatibility<'a>( continue; }; let mut osvs = FxHashSet::default(); - dyn_compatibility_with_callback(&db, trait_id, &mut |osv| { + let _ = dyn_compatibility_with_callback(&db, trait_id, &mut |osv| { osvs.insert(match osv { DynCompatibilityViolation::SizedSelf => SizedSelf, DynCompatibilityViolation::SelfReferential => SelfReferential, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 556091c4046..3e0ce7f1933 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs @@ -1143,7 +1143,7 @@ impl<'a> InferenceContext<'a> { non_assocs: FxHashMap::default(), }; for ty in tait_candidates { - ty.visit_with(collector.as_dyn(), DebruijnIndex::INNERMOST); + let _ = ty.visit_with(collector.as_dyn(), DebruijnIndex::INNERMOST); } // Non-assoc TAITs can be define-used everywhere as long as they are diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 624767cedf8..cc02b71f05c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -1033,7 +1033,7 @@ where T: ?Sized + TypeVisitable<Interner>, { let mut collector = PlaceholderCollector { db, placeholders: FxHashSet::default() }; - value.visit_with(&mut collector, DebruijnIndex::INNERMOST); + let _ = value.visit_with(&mut collector, DebruijnIndex::INNERMOST); collector.placeholders.into_iter().collect() } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs index db94351dcc9..c7228005271 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs @@ -596,7 +596,7 @@ pub(crate) fn iterate_method_candidates<T>( mut callback: impl FnMut(ReceiverAdjustments, AssocItemId, bool) -> Option<T>, ) -> Option<T> { let mut slot = None; - iterate_method_candidates_dyn( + let _ = iterate_method_candidates_dyn( ty, db, env, diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs index 4351a34e822..4e45b5a250e 100644 --- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs @@ -260,7 +260,7 @@ fn resolve_impl_trait_item( // attributes here. Use path resolution directly instead. // // FIXME: resolve type aliases (which are not yielded by iterate_path_candidates) - method_resolution::iterate_path_candidates( + let _ = method_resolution::iterate_path_candidates( &canonical, db, environment, diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index a8075509474..29f45846650 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -2911,7 +2911,7 @@ impl Trait { db: &dyn HirDatabase, ) -> Option<Vec<DynCompatibilityViolation>> { let mut violations = vec![]; - hir_ty::dyn_compatibility::dyn_compatibility_with_callback(db, self.id, &mut |violation| { + let _ = hir_ty::dyn_compatibility::dyn_compatibility_with_callback(db, self.id, &mut |violation| { violations.push(violation); ControlFlow::Continue(()) }); @@ -5497,7 +5497,7 @@ impl Type { .generic_def() .map_or_else(|| TraitEnvironment::empty(krate.id), |d| db.trait_environment(d)); - method_resolution::iterate_method_candidates_dyn( + let _ = method_resolution::iterate_method_candidates_dyn( &canonical, db, environment, @@ -5584,7 +5584,7 @@ impl Type { .generic_def() .map_or_else(|| TraitEnvironment::empty(krate.id), |d| db.trait_environment(d)); - method_resolution::iterate_path_candidates( + let _ = method_resolution::iterate_path_candidates( &canonical, db, environment, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs index 330587e0dbf..6f4b886a28d 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs @@ -750,7 +750,7 @@ impl FunctionBody { ast::Stmt::Item(_) => (), ast::Stmt::LetStmt(stmt) => { if let Some(pat) = stmt.pat() { - walk_pat(&pat, &mut |pat| { + let _ = walk_pat(&pat, &mut |pat| { cb(pat); std::ops::ControlFlow::<(), ()>::Continue(()) }); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs index 0b2e8aa6836..56a66070ef7 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs @@ -121,7 +121,7 @@ pub fn walk_patterns_in_expr(start: &ast::Expr, cb: &mut dyn FnMut(ast::Pat)) { match ast::Stmt::cast(node.clone()) { Some(ast::Stmt::LetStmt(l)) => { if let Some(pat) = l.pat() { - walk_pat(&pat, &mut |pat| { + let _ = walk_pat(&pat, &mut |pat| { cb(pat); ControlFlow::<(), ()>::Continue(()) }); @@ -159,7 +159,7 @@ pub fn walk_patterns_in_expr(start: &ast::Expr, cb: &mut dyn FnMut(ast::Pat)) { } } else if let Some(pat) = ast::Pat::cast(node) { preorder.skip_subtree(); - walk_pat(&pat, &mut |pat| { + let _ = walk_pat(&pat, &mut |pat| { cb(pat); ControlFlow::<(), ()>::Continue(()) }); diff --git a/src/tools/rustdoc-gui-test/src/main.rs b/src/tools/rustdoc-gui-test/src/main.rs index 5adb525d7e6..f1c6e13d3ae 100644 --- a/src/tools/rustdoc-gui-test/src/main.rs +++ b/src/tools/rustdoc-gui-test/src/main.rs @@ -20,7 +20,7 @@ fn get_browser_ui_test_version_inner(npm: &Path, global: bool) -> Option<String> Err(e) => { eprintln!( "path to npm can be wrong, provided path: {npm:?}. Try to set npm path \ - in config.toml in [build.npm]", + in bootstrap.toml in [build.npm]", ); panic!("{:?}", e) } diff --git a/src/tools/rustfmt/src/chains.rs b/src/tools/rustfmt/src/chains.rs index fd2ef9cb1db..034ecde068a 100644 --- a/src/tools/rustfmt/src/chains.rs +++ b/src/tools/rustfmt/src/chains.rs @@ -192,6 +192,7 @@ enum ChainItemKind { StructField(symbol::Ident), TupleField(symbol::Ident, bool), Await, + Yield, Comment(String, CommentPosition), } @@ -203,6 +204,7 @@ impl ChainItemKind { | ChainItemKind::StructField(..) | ChainItemKind::TupleField(..) | ChainItemKind::Await + | ChainItemKind::Yield | ChainItemKind::Comment(..) => false, } } @@ -257,6 +259,10 @@ impl ChainItemKind { let span = mk_sp(nested.span.hi(), expr.span.hi()); (ChainItemKind::Await, span) } + ast::ExprKind::Yield(ast::YieldKind::Postfix(ref nested)) => { + let span = mk_sp(nested.span.hi(), expr.span.hi()); + (ChainItemKind::Yield, span) + } _ => { return ( ChainItemKind::Parent { @@ -306,6 +312,7 @@ impl Rewrite for ChainItem { rewrite_ident(context, ident) ), ChainItemKind::Await => ".await".to_owned(), + ChainItemKind::Yield => ".yield".to_owned(), ChainItemKind::Comment(ref comment, _) => { rewrite_comment(comment, false, shape, context.config)? } @@ -508,7 +515,8 @@ impl Chain { }), ast::ExprKind::Field(ref subexpr, _) | ast::ExprKind::Try(ref subexpr) - | ast::ExprKind::Await(ref subexpr, _) => Some(SubExpr { + | ast::ExprKind::Await(ref subexpr, _) + | ast::ExprKind::Yield(ast::YieldKind::Postfix(ref subexpr)) => Some(SubExpr { expr: Self::convert_try(subexpr, context), is_method_call_receiver: false, }), diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index eff2d2e3ff4..e866f13efc7 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -221,7 +221,7 @@ pub(crate) fn format_expr( Ok(format!("break{id_str}")) } } - ast::ExprKind::Yield(ref opt_expr) => { + ast::ExprKind::Yield(ast::YieldKind::Prefix(ref opt_expr)) => { if let Some(ref expr) = *opt_expr { rewrite_unary_prefix(context, "yield ", &**expr, shape) } else { @@ -243,7 +243,8 @@ pub(crate) fn format_expr( ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) - | ast::ExprKind::Await(_, _) => rewrite_chain(expr, context, shape), + | ast::ExprKind::Await(_, _) + | ast::ExprKind::Yield(ast::YieldKind::Postfix(_)) => rewrite_chain(expr, context, shape), ast::ExprKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|_| { wrap_str( diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index fe716c18638..fcd475b1784 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -4,7 +4,7 @@ use rustc_ast::ast::{ self, Attribute, MetaItem, MetaItemInner, MetaItemKind, NodeId, Path, Visibility, VisibilityKind, }; -use rustc_ast::ptr; +use rustc_ast::{YieldKind, ptr}; use rustc_ast_pretty::pprust; use rustc_span::{BytePos, LocalExpnId, Span, Symbol, SyntaxContext, sym, symbol}; use unicode_width::UnicodeWidthStr; @@ -485,7 +485,9 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::Index(_, ref expr, _) | ast::ExprKind::Unary(_, ref expr) | ast::ExprKind::Try(ref expr) - | ast::ExprKind::Yield(Some(ref expr)) => is_block_expr(context, expr, repr), + | ast::ExprKind::Yield(YieldKind::Prefix(Some(ref expr))) => { + is_block_expr(context, expr, repr) + } ast::ExprKind::Closure(ref closure) => is_block_expr(context, &closure.body, repr), // This can only be a string lit ast::ExprKind::Lit(_) => { @@ -515,7 +517,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::Tup(..) | ast::ExprKind::Use(..) | ast::ExprKind::Type(..) - | ast::ExprKind::Yield(None) + | ast::ExprKind::Yield(..) | ast::ExprKind::Underscore => false, } } diff --git a/src/tools/rustfmt/tests/target/postfix-yield.rs b/src/tools/rustfmt/tests/target/postfix-yield.rs new file mode 100644 index 00000000000..8ee34ec4312 --- /dev/null +++ b/src/tools/rustfmt/tests/target/postfix-yield.rs @@ -0,0 +1,17 @@ +// This demonstrates a proposed alternate or additional option of having yield in postfix position. +//@ edition: 2024 + +#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr)] + +use std::ops::{Coroutine, CoroutineState}; +use std::pin::pin; + +fn main() { + let mut coro = pin!( + #[coroutine] + |_: i32| { + let x = 1.yield; + (x + 2).await; + } + ); +} diff --git a/src/tools/suggest-tests/src/main.rs b/src/tools/suggest-tests/src/main.rs index ee8cc40404d..ee212af3626 100644 --- a/src/tools/suggest-tests/src/main.rs +++ b/src/tools/suggest-tests/src/main.rs @@ -14,11 +14,7 @@ fn main() -> ExitCode { &Vec::new(), ); let modified_files = match modified_files { - Ok(Some(files)) => files, - Ok(None) => { - eprintln!("git error"); - return ExitCode::FAILURE; - } + Ok(files) => files, Err(err) => { eprintln!("Could not get modified files from git: \"{err}\""); return ExitCode::FAILURE; diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 2b9ae195478..4a929a376d7 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -2000,7 +2000,6 @@ ui/issues/issue-28586.rs ui/issues/issue-28600.rs ui/issues/issue-28625.rs ui/issues/issue-28776.rs -ui/issues/issue-28777.rs ui/issues/issue-28828.rs ui/issues/issue-28839.rs ui/issues/issue-28936.rs @@ -2063,7 +2062,6 @@ ui/issues/issue-3091.rs ui/issues/issue-31011.rs ui/issues/issue-3109.rs ui/issues/issue-3121.rs -ui/issues/issue-31260.rs ui/issues/issue-31267-additional.rs ui/issues/issue-31267.rs ui/issues/issue-31299.rs @@ -2608,7 +2606,6 @@ ui/issues/issue-9243.rs ui/issues/issue-9249.rs ui/issues/issue-9259.rs ui/issues/issue-92741.rs -ui/issues/issue-9382.rs ui/issues/issue-9446.rs ui/issues/issue-9719.rs ui/issues/issue-9725.rs diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index fe51231c481..61728d0553f 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -17,7 +17,7 @@ use ignore::Walk; const ENTRY_LIMIT: u32 = 901; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: u32 = 1634; +const ISSUES_ENTRY_LIMIT: u32 = 1631; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/assembly/powerpc64-struct-abi.rs b/tests/assembly/powerpc64-struct-abi.rs index eb27afc4f23..ee4965deb4f 100644 --- a/tests/assembly/powerpc64-struct-abi.rs +++ b/tests/assembly/powerpc64-struct-abi.rs @@ -6,7 +6,7 @@ //@[elfv1-be] needs-llvm-components: powerpc //@[elfv2-be] compile-flags: --target powerpc64-unknown-linux-musl //@[elfv2-be] needs-llvm-components: powerpc -//@[elfv2-le] compile-flags: --target powerpc64le-unknown-linux-gnu +//@[elfv2-le] compile-flags: --target powerpc64le-unknown-linux-gnu -C target-cpu=pwr8 //@[elfv2-le] needs-llvm-components: powerpc //@[aix] compile-flags: --target powerpc64-ibm-aix //@[aix] needs-llvm-components: powerpc diff --git a/tests/assembly/s390x-vector-abi.rs b/tests/assembly/s390x-vector-abi.rs index 7d86559c002..e159a357685 100644 --- a/tests/assembly/s390x-vector-abi.rs +++ b/tests/assembly/s390x-vector-abi.rs @@ -2,9 +2,9 @@ // ignore-tidy-linelength //@ assembly-output: emit-asm //@ compile-flags: -Copt-level=3 -Z merge-functions=disabled -//@[z10] compile-flags: --target s390x-unknown-linux-gnu --cfg no_vector +//@[z10] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z10 --cfg no_vector //@[z10] needs-llvm-components: systemz -//@[z10_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=+vector +//@[z10_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z10 -C target-feature=+vector //@[z10_vector] needs-llvm-components: systemz //@[z13] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13 //@[z13] needs-llvm-components: systemz diff --git a/tests/codegen/alloc-optimisation.rs b/tests/codegen/alloc-optimisation.rs index 8abeecf8550..19f14647c1d 100644 --- a/tests/codegen/alloc-optimisation.rs +++ b/tests/codegen/alloc-optimisation.rs @@ -5,7 +5,7 @@ pub fn alloc_test(data: u32) { // CHECK-LABEL: @alloc_test // CHECK-NEXT: start: - // CHECK-NEXT: {{.*}} load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1 + // CHECK-NEXT: {{.*}} load volatile i8, ptr @{{.*}}__rust_no_alloc_shim_is_unstable, align 1 // CHECK-NEXT: ret void let x = Box::new(data); drop(x); diff --git a/tests/codegen/asm/goto.rs b/tests/codegen/asm/goto.rs index 7a87bb7983b..f68c399c920 100644 --- a/tests/codegen/asm/goto.rs +++ b/tests/codegen/asm/goto.rs @@ -2,7 +2,7 @@ //@ only-x86_64 #![crate_type = "rlib"] -#![feature(asm_goto, asm_goto_with_outputs)] +#![feature(asm_goto_with_outputs)] use std::arch::asm; diff --git a/tests/codegen/asm/s390x-clobbers.rs b/tests/codegen/asm/s390x-clobbers.rs index cbb6630553c..0ba22a32abf 100644 --- a/tests/codegen/asm/s390x-clobbers.rs +++ b/tests/codegen/asm/s390x-clobbers.rs @@ -1,6 +1,6 @@ //@ add-core-stubs //@ revisions: s390x -//@[s390x] compile-flags: --target s390x-unknown-linux-gnu +//@[s390x] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z10 //@[s390x] needs-llvm-components: systemz #![crate_type = "rlib"] diff --git a/tests/codegen/box-uninit-bytes.rs b/tests/codegen/box-uninit-bytes.rs index 3b83ef3e250..0cc01148595 100644 --- a/tests/codegen/box-uninit-bytes.rs +++ b/tests/codegen/box-uninit-bytes.rs @@ -41,6 +41,6 @@ pub fn box_lotsa_padding() -> Box<LotsaPadding> { // Hide the `allocalign` attribute in the declaration of __rust_alloc // from the CHECK-NOT above, and also verify the attributes got set reasonably. -// CHECK: declare {{(dso_local )?}}noalias noundef ptr @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]] +// CHECK: declare {{(dso_local )?}}noalias noundef ptr @{{.*}}__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]] // CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) {{(uwtable )?}}"alloc-family"="__rust_alloc" {{.*}} } diff --git a/tests/codegen/dealloc-no-unwind.rs b/tests/codegen/dealloc-no-unwind.rs index c560d7a9932..68597817d6f 100644 --- a/tests/codegen/dealloc-no-unwind.rs +++ b/tests/codegen/dealloc-no-unwind.rs @@ -18,7 +18,7 @@ impl Drop for A { #[no_mangle] pub fn a(a: Box<i32>) { // CHECK-LABEL: define{{.*}}void @a - // CHECK: call void @__rust_dealloc + // CHECK: call void @{{.*}}__rust_dealloc // CHECK-NEXT: call void @foo let _a = A; drop(a); diff --git a/tests/codegen/issues/issue-129795.rs b/tests/codegen/issues/issue-129795.rs new file mode 100644 index 00000000000..dc64ee35c97 --- /dev/null +++ b/tests/codegen/issues/issue-129795.rs @@ -0,0 +1,17 @@ +//@ compile-flags: -Copt-level=3 +//@ min-llvm-version: 20 +#![crate_type = "lib"] + +// Ensure that a modulo operation with an operand that is known to be +// a power-of-two is properly optimized. + +// CHECK-LABEL: @modulo_with_power_of_two_divisor +// CHECK: add i64 %divisor, -1 +// CHECK-NEXT: and i64 +// CHECK-NEXT: ret i64 +#[no_mangle] +pub fn modulo_with_power_of_two_divisor(dividend: u64, divisor: u64) -> u64 { + assert!(divisor.is_power_of_two()); + // should be optimized to (dividend & (divisor - 1)) + dividend % divisor +} diff --git a/tests/codegen/iter-repeat-n-trivial-drop.rs b/tests/codegen/iter-repeat-n-trivial-drop.rs index 4dab499a8a5..3bb942d11d5 100644 --- a/tests/codegen/iter-repeat-n-trivial-drop.rs +++ b/tests/codegen/iter-repeat-n-trivial-drop.rs @@ -47,7 +47,7 @@ pub fn iter_repeat_n_next(it: &mut std::iter::RepeatN<NotCopy>) -> Option<NotCop #[no_mangle] // CHECK-LABEL: @vec_extend_via_iter_repeat_n pub fn vec_extend_via_iter_repeat_n() -> Vec<u8> { - // CHECK: %[[ADDR:.+]] = tail call {{(noalias )?}}noundef dereferenceable_or_null(1234) ptr @__rust_alloc(i64 noundef {{(range\(i64 1, 0\) )?}}1234, i64 noundef {{(range\(i64 1, -9223372036854775807\) )?}}1) + // CHECK: %[[ADDR:.+]] = tail call {{(noalias )?}}noundef dereferenceable_or_null(1234) ptr @{{.*}}__rust_alloc(i64 noundef {{(range\(i64 1, 0\) )?}}1234, i64 noundef {{(range\(i64 1, -9223372036854775807\) )?}}1) // CHECK: tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(1234) %[[ADDR]], i8 42, i64 1234, let n = 1234_usize; diff --git a/tests/codegen/sanitizer/cfi/external_weak_symbols.rs b/tests/codegen/sanitizer/cfi/external_weak_symbols.rs new file mode 100644 index 00000000000..00e9b5029af --- /dev/null +++ b/tests/codegen/sanitizer/cfi/external_weak_symbols.rs @@ -0,0 +1,24 @@ +// Verifies that type metadata identifiers for for weakly-linked symbols are +// emitted correctly. +// +//@ needs-sanitizer-cfi +//@ compile-flags: -Clinker-plugin-lto -Copt-level=0 -Zsanitizer=cfi -Ctarget-feature=-crt-static +#![crate_type = "bin"] +#![feature(linkage)] + +unsafe extern "C" { + #[linkage = "extern_weak"] + static FOO: Option<unsafe extern "C" fn(f64) -> ()>; +} +// CHECK: @_rust_extern_with_linkage_FOO = internal global ptr @FOO + +fn main() { + unsafe { + if let Some(method) = FOO { + method(4.2); + // CHECK: call i1 @llvm.type.test(ptr {{%method|%0}}, metadata !"_ZTSFvdE") + } + } +} + +// CHECK: declare !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} extern_weak void @FOO(double) unnamed_addr #{{[0-9]+}} diff --git a/tests/codegen/slice-is-ascii.rs b/tests/codegen/slice-is-ascii.rs index b1e97154609..67537c871a0 100644 --- a/tests/codegen/slice-is-ascii.rs +++ b/tests/codegen/slice-is-ascii.rs @@ -1,5 +1,5 @@ //@ only-x86_64 -//@ compile-flags: -C opt-level=3 +//@ compile-flags: -C opt-level=3 -C target-cpu=x86-64 #![crate_type = "lib"] /// Check that the fast-path of `is_ascii` uses a `pmovmskb` instruction. diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs index 23a084c51f4..3a3453b22b4 100644 --- a/tests/codegen/try_question_mark_nop.rs +++ b/tests/codegen/try_question_mark_nop.rs @@ -63,6 +63,57 @@ pub fn result_nop_traits_32(x: Result<i32, u32>) -> Result<i32, u32> { try { x? } } +// CHECK-LABEL: @control_flow_nop_match_32 +#[no_mangle] +pub fn control_flow_nop_match_32(x: ControlFlow<i32, u32>) -> ControlFlow<i32, u32> { + // CHECK: start: + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: ret { i32, i32 } + match x { + Continue(x) => Continue(x), + Break(x) => Break(x), + } +} + +// CHECK-LABEL: @control_flow_nop_traits_32 +#[no_mangle] +pub fn control_flow_nop_traits_32(x: ControlFlow<i32, u32>) -> ControlFlow<i32, u32> { + // CHECK: start: + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: insertvalue { i32, i32 } + // CHECK-NEXT: ret { i32, i32 } + try { x? } +} + +// CHECK-LABEL: @option_nop_match_64 +#[no_mangle] +pub fn option_nop_match_64(x: Option<u64>) -> Option<u64> { + // CHECK: start: + // TWENTY-NEXT: %[[TRUNC:[0-9]+]] = trunc nuw i64 %0 to i1 + // TWENTY-NEXT: %[[SEL:\.[0-9]+]] = select i1 %[[TRUNC]], i64 %1, i64 undef + // CHECK-NEXT: [[REG1:%[0-9a-zA-Z_.]+]] = insertvalue { i64, i64 } poison, i64 %0, 0 + // NINETEEN-NEXT: [[REG2:%[0-9a-zA-Z_.]+]] = insertvalue { i64, i64 } [[REG1]], i64 %1, 1 + // TWENTY-NEXT: [[REG2:%[0-9a-zA-Z_.]+]] = insertvalue { i64, i64 } [[REG1]], i64 %[[SEL]], 1 + // CHECK-NEXT: ret { i64, i64 } [[REG2]] + match x { + Some(x) => Some(x), + None => None, + } +} + +// CHECK-LABEL: @option_nop_traits_64 +#[no_mangle] +pub fn option_nop_traits_64(x: Option<u64>) -> Option<u64> { + // CHECK: start: + // TWENTY-NEXT: %[[TRUNC:[0-9]+]] = trunc nuw i64 %0 to i1 + // TWENTY-NEXT: %[[SEL:\.[0-9]+]] = select i1 %[[TRUNC]], i64 %1, i64 undef + // CHECK-NEXT: insertvalue { i64, i64 } + // CHECK-NEXT: insertvalue { i64, i64 } + // CHECK-NEXT: ret { i64, i64 } + try { x? } +} + // CHECK-LABEL: @result_nop_match_64 #[no_mangle] pub fn result_nop_match_64(x: Result<i64, u64>) -> Result<i64, u64> { @@ -86,48 +137,98 @@ pub fn result_nop_traits_64(x: Result<i64, u64>) -> Result<i64, u64> { try { x? } } -// CHECK-LABEL: @result_nop_match_ptr +// CHECK-LABEL: @control_flow_nop_match_64 #[no_mangle] -pub fn result_nop_match_ptr(x: Result<usize, Box<()>>) -> Result<usize, Box<()>> { +pub fn control_flow_nop_match_64(x: ControlFlow<i64, u64>) -> ControlFlow<i64, u64> { // CHECK: start: - // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } - // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } - // CHECK-NEXT: ret + // CHECK-NEXT: insertvalue { i64, i64 } + // CHECK-NEXT: insertvalue { i64, i64 } + // CHECK-NEXT: ret { i64, i64 } + match x { + Continue(x) => Continue(x), + Break(x) => Break(x), + } +} + +// CHECK-LABEL: @control_flow_nop_traits_64 +#[no_mangle] +pub fn control_flow_nop_traits_64(x: ControlFlow<i64, u64>) -> ControlFlow<i64, u64> { + // CHECK: start: + // CHECK-NEXT: insertvalue { i64, i64 } + // CHECK-NEXT: insertvalue { i64, i64 } + // CHECK-NEXT: ret { i64, i64 } + try { x? } +} + +// CHECK-LABEL: @result_nop_match_128 +#[no_mangle] +pub fn result_nop_match_128(x: Result<i128, u128>) -> Result<i128, u128> { + // CHECK: start: + // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 + // CHECK-NEXT: store i128 + // CHECK-NEXT: store i128 + // CHECK-NEXT: ret void match x { Ok(x) => Ok(x), Err(x) => Err(x), } } -// CHECK-LABEL: @result_nop_traits_ptr +// CHECK-LABEL: @result_nop_traits_128 #[no_mangle] -pub fn result_nop_traits_ptr(x: Result<u64, NonNull<()>>) -> Result<u64, NonNull<()>> { +pub fn result_nop_traits_128(x: Result<i128, u128>) -> Result<i128, u128> { // CHECK: start: - // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } - // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } - // CHECK-NEXT: ret + // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 + // CHECK-NEXT: store i128 + // CHECK-NEXT: store i128 + // CHECK-NEXT: ret void try { x? } } -// CHECK-LABEL: @control_flow_nop_match_32 +// CHECK-LABEL: @control_flow_nop_match_128 #[no_mangle] -pub fn control_flow_nop_match_32(x: ControlFlow<i32, u32>) -> ControlFlow<i32, u32> { +pub fn control_flow_nop_match_128(x: ControlFlow<i128, u128>) -> ControlFlow<i128, u128> { // CHECK: start: - // CHECK-NEXT: insertvalue { i32, i32 } - // CHECK-NEXT: insertvalue { i32, i32 } - // CHECK-NEXT: ret { i32, i32 } + // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 + // CHECK-NEXT: store i128 + // CHECK-NEXT: store i128 + // CHECK-NEXT: ret void match x { Continue(x) => Continue(x), Break(x) => Break(x), } } -// CHECK-LABEL: @control_flow_nop_traits_32 +// CHECK-LABEL: @control_flow_nop_traits_128 #[no_mangle] -pub fn control_flow_nop_traits_32(x: ControlFlow<i32, u32>) -> ControlFlow<i32, u32> { +pub fn control_flow_nop_traits_128(x: ControlFlow<i128, u128>) -> ControlFlow<i128, u128> { // CHECK: start: - // CHECK-NEXT: insertvalue { i32, i32 } - // CHECK-NEXT: insertvalue { i32, i32 } - // CHECK-NEXT: ret { i32, i32 } + // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 + // CHECK-NEXT: store i128 + // CHECK-NEXT: store i128 + // CHECK-NEXT: ret void + try { x? } +} + +// CHECK-LABEL: @result_nop_match_ptr +#[no_mangle] +pub fn result_nop_match_ptr(x: Result<usize, Box<()>>) -> Result<usize, Box<()>> { + // CHECK: start: + // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } + // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } + // CHECK-NEXT: ret + match x { + Ok(x) => Ok(x), + Err(x) => Err(x), + } +} + +// CHECK-LABEL: @result_nop_traits_ptr +#[no_mangle] +pub fn result_nop_traits_ptr(x: Result<u64, NonNull<()>>) -> Result<u64, NonNull<()>> { + // CHECK: start: + // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } + // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } + // CHECK-NEXT: ret try { x? } } diff --git a/tests/codegen/vec-calloc.rs b/tests/codegen/vec-calloc.rs index 2e2769ce130..d1c320ead01 100644 --- a/tests/codegen/vec-calloc.rs +++ b/tests/codegen/vec-calloc.rs @@ -177,6 +177,6 @@ pub fn vec_option_i32(n: usize) -> Vec<Option<i32>> { } // Ensure that __rust_alloc_zeroed gets the right attributes for LLVM to optimize it away. -// CHECK: declare noalias noundef ptr @__rust_alloc_zeroed(i64 noundef, i64 allocalign noundef) unnamed_addr [[RUST_ALLOC_ZEROED_ATTRS:#[0-9]+]] +// CHECK: declare noalias noundef ptr @{{.*}}__rust_alloc_zeroed(i64 noundef, i64 allocalign noundef) unnamed_addr [[RUST_ALLOC_ZEROED_ATTRS:#[0-9]+]] // CHECK-DAG: attributes [[RUST_ALLOC_ZEROED_ATTRS]] = { {{.*}} allockind("alloc,zeroed,aligned") allocsize(0) uwtable "alloc-family"="__rust_alloc" {{.*}} } diff --git a/tests/codegen/vec-optimizes-away.rs b/tests/codegen/vec-optimizes-away.rs index 39d5c1614c8..f6ed2898bda 100644 --- a/tests/codegen/vec-optimizes-away.rs +++ b/tests/codegen/vec-optimizes-away.rs @@ -5,7 +5,7 @@ pub fn sum_me() -> i32 { // CHECK-LABEL: @sum_me // CHECK-NEXT: {{^.*:$}} - // CHECK-NEXT: {{.*}} load volatile i8, ptr @__rust_no_alloc_shim_is_unstable, align 1 + // CHECK-NEXT: {{.*}} load volatile i8, ptr @{{.*}}__rust_no_alloc_shim_is_unstable, align 1 // CHECK-NEXT: ret i32 6 vec![1, 2, 3].iter().sum::<i32>() } diff --git a/tests/crashes/122904.rs b/tests/crashes/122904.rs deleted file mode 100644 index 2068cd9d239..00000000000 --- a/tests/crashes/122904.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: #122904 -trait T {} - -type Alias<'a> = impl T; - -struct S; -impl<'a> T for &'a S {} - -#[define_opaque(Alias)] -fn with_positive(fun: impl Fn(Alias<'_>)) { - with_positive(|&n| ()); -} diff --git a/tests/crashes/132826.rs b/tests/crashes/132826.rs deleted file mode 100644 index 9889cecdac5..00000000000 --- a/tests/crashes/132826.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: #132826 -pub trait MyTrait { - type Item; -} - -impl<K> MyTrait for Vec<K> { - type Item = Vec<K>; -} - -impl<K> From<Vec<K>> for <Vec<K> as MyTrait>::Item {} diff --git a/tests/crashes/136286.rs b/tests/crashes/136286.rs deleted file mode 100644 index f0ea14bd167..00000000000 --- a/tests/crashes/136286.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: #136286 -//@ compile-flags: --edition=2024 - -#![feature(async_fn_in_dyn_trait)] -trait A { - async fn b(self: A); -} diff --git a/tests/crashes/137706.rs b/tests/crashes/137706.rs deleted file mode 100644 index 0b46f9c237a..00000000000 --- a/tests/crashes/137706.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: #137706 -//@ needs-rustc-debug-assertions -trait A { - fn b() -> impl IntoIterator<Item = ()>; -} - -impl A<()> for dyn A {} diff --git a/tests/crashes/137895.rs b/tests/crashes/137895.rs deleted file mode 100644 index bb624d2e9fa..00000000000 --- a/tests/crashes/137895.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ known-bug: #137895 -trait A { - fn b() -> impl ?Sized + 'a; -} - -impl A for dyn A {} diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir new file mode 100644 index 00000000000..0c8a17ff70b --- /dev/null +++ b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir @@ -0,0 +1,81 @@ +// MIR for `foo::{closure#0}::{closure#0}` after built + +fn foo::{closure#0}::{closure#0}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: ResumeTy) -> () +yields () + { + debug _task_context => _2; + debug f => (*(_1.0: &&Foo)); + let mut _0: (); + let mut _3: &Foo; + let mut _4: &&Foo; + let mut _5: &&&Foo; + let mut _6: isize; + let mut _7: bool; + + bb0: { + PlaceMention((*(_1.0: &&Foo))); + _6 = discriminant((*(*(_1.0: &&Foo)))); + switchInt(move _6) -> [0: bb2, otherwise: bb1]; + } + + bb1: { + _0 = const (); + goto -> bb10; + } + + bb2: { + falseEdge -> [real: bb5, imaginary: bb1]; + } + + bb3: { + goto -> bb1; + } + + bb4: { + FakeRead(ForMatchedPlace(None), (*(_1.0: &&Foo))); + unreachable; + } + + bb5: { + _3 = &fake shallow (*(*(_1.0: &&Foo))); + _4 = &fake shallow (*(_1.0: &&Foo)); + _5 = &fake shallow (_1.0: &&Foo); + StorageLive(_7); + _7 = const true; + switchInt(move _7) -> [0: bb8, otherwise: bb7]; + } + + bb6: { + falseEdge -> [real: bb3, imaginary: bb1]; + } + + bb7: { + StorageDead(_7); + FakeRead(ForMatchGuard, _3); + FakeRead(ForMatchGuard, _4); + FakeRead(ForMatchGuard, _5); + _0 = const (); + goto -> bb10; + } + + bb8: { + goto -> bb9; + } + + bb9: { + StorageDead(_7); + goto -> bb6; + } + + bb10: { + drop(_1) -> [return: bb11, unwind: bb12]; + } + + bb11: { + return; + } + + bb12 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir new file mode 100644 index 00000000000..bd0baddb1f8 --- /dev/null +++ b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir @@ -0,0 +1,64 @@ +// MIR for `foo::{closure#0}::{closure#1}` after built + +fn foo::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: ResumeTy) -> () +yields () + { + debug _task_context => _2; + debug f => (_1.0: &Foo); + let mut _0: (); + let mut _3: &Foo; + let mut _4: &&Foo; + let mut _5: &&&Foo; + let mut _6: isize; + let mut _7: bool; + + bb0: { + PlaceMention((_1.0: &Foo)); + _6 = discriminant((*(_1.0: &Foo))); + switchInt(move _6) -> [0: bb2, otherwise: bb1]; + } + + bb1: { + _0 = const (); + goto -> bb6; + } + + bb2: { + falseEdge -> [real: bb3, imaginary: bb1]; + } + + bb3: { + _3 = &fake shallow (*(_1.0: &Foo)); + _4 = &fake shallow (_1.0: &Foo); + nop; + StorageLive(_7); + _7 = const true; + switchInt(move _7) -> [0: bb5, otherwise: bb4]; + } + + bb4: { + StorageDead(_7); + FakeRead(ForMatchGuard, _3); + FakeRead(ForMatchGuard, _4); + FakeRead(ForMatchGuard, _5); + _0 = const (); + goto -> bb6; + } + + bb5: { + StorageDead(_7); + falseEdge -> [real: bb1, imaginary: bb1]; + } + + bb6: { + drop(_1) -> [return: bb7, unwind: bb8]; + } + + bb7: { + return; + } + + bb8 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.rs b/tests/mir-opt/async_closure_fake_read_for_by_move.rs new file mode 100644 index 00000000000..3c5aec94bbf --- /dev/null +++ b/tests/mir-opt/async_closure_fake_read_for_by_move.rs @@ -0,0 +1,18 @@ +//@ edition:2021 +// skip-filecheck + +enum Foo { + Bar, + Baz, +} + +// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir +// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir +fn foo(f: &Foo) { + let x = async move || match f { + Foo::Bar if true => {} + _ => {} + }; +} + +fn main() {} diff --git a/tests/mir-opt/building/user_type_annotations.let_else.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_else.built.after.mir new file mode 100644 index 00000000000..3a515787c10 --- /dev/null +++ b/tests/mir-opt/building/user_type_annotations.let_else.built.after.mir @@ -0,0 +1,80 @@ +// MIR for `let_else` after built + +| User Type Annotations +| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:35:20: 35:45, inferred_ty: (u32, u64, &char) +| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:35:20: 35:45, inferred_ty: (u32, u64, &char) +| +fn let_else() -> () { + let mut _0: (); + let mut _1: !; + let _2: u32 as UserTypeProjection { base: UserType(0), projs: [Field(0, ())] }; + let _3: u64 as UserTypeProjection { base: UserType(0), projs: [Field(1, ())] }; + let _4: &char as UserTypeProjection { base: UserType(0), projs: [Field(2, ())] }; + let mut _5: (u32, u64, &char); + let mut _6: &char; + let _7: &char; + let _8: char; + scope 1 { + debug x => _2; + debug y => _3; + debug z => _4; + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + StorageLive(_7); + StorageLive(_8); + _8 = const 'u'; + _7 = &_8; + _6 = &(*_7); + _5 = (const 7_u32, const 12_u64, move _6); + StorageDead(_6); + PlaceMention(_5); + falseEdge -> [real: bb4, imaginary: bb3]; + } + + bb1: { + _1 = core::panicking::panic(const "internal error: entered unreachable code") -> bb6; + } + + bb2: { + unreachable; + } + + bb3: { + goto -> bb5; + } + + bb4: { + AscribeUserType(_5, +, UserTypeProjection { base: UserType(1), projs: [] }); + _2 = copy (_5.0: u32); + _3 = copy (_5.1: u64); + _4 = copy (_5.2: &char); + StorageDead(_7); + StorageDead(_5); + _0 = const (); + StorageDead(_8); + StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + return; + } + + bb5: { + StorageDead(_7); + StorageDead(_5); + StorageDead(_8); + StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + goto -> bb1; + } + + bb6 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir new file mode 100644 index 00000000000..52a6d904d45 --- /dev/null +++ b/tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir @@ -0,0 +1,62 @@ +// MIR for `let_else_bindless` after built + +| User Type Annotations +| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:40:20: 40:45, inferred_ty: (u32, u64, &char) +| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:40:20: 40:45, inferred_ty: (u32, u64, &char) +| +fn let_else_bindless() -> () { + let mut _0: (); + let mut _1: !; + let mut _2: (u32, u64, &char); + let mut _3: &char; + let _4: &char; + let _5: char; + scope 1 { + } + + bb0: { + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + _5 = const 'u'; + _4 = &_5; + _3 = &(*_4); + _2 = (const 7_u32, const 12_u64, move _3); + StorageDead(_3); + PlaceMention(_2); + falseEdge -> [real: bb4, imaginary: bb3]; + } + + bb1: { + _1 = core::panicking::panic(const "internal error: entered unreachable code") -> bb6; + } + + bb2: { + unreachable; + } + + bb3: { + goto -> bb5; + } + + bb4: { + AscribeUserType(_2, +, UserTypeProjection { base: UserType(1), projs: [] }); + StorageDead(_4); + StorageDead(_2); + _0 = const (); + StorageDead(_5); + return; + } + + bb5: { + StorageDead(_4); + StorageDead(_2); + StorageDead(_5); + goto -> bb1; + } + + bb6 (cleanup): { + resume; + } +} diff --git a/tests/mir-opt/building/user_type_annotations.let_init.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_init.built.after.mir new file mode 100644 index 00000000000..d1b8f823e9b --- /dev/null +++ b/tests/mir-opt/building/user_type_annotations.let_init.built.after.mir @@ -0,0 +1,54 @@ +// MIR for `let_init` after built + +| User Type Annotations +| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:25:20: 25:45, inferred_ty: (u32, u64, &char) +| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:25:20: 25:45, inferred_ty: (u32, u64, &char) +| +fn let_init() -> () { + let mut _0: (); + let _1: u32 as UserTypeProjection { base: UserType(0), projs: [Field(0, ())] }; + let _2: u64 as UserTypeProjection { base: UserType(0), projs: [Field(1, ())] }; + let _3: &char as UserTypeProjection { base: UserType(0), projs: [Field(2, ())] }; + let mut _4: (u32, u64, &char); + let mut _5: &char; + let _6: &char; + let _7: char; + scope 1 { + debug x => _1; + debug y => _2; + debug z => _3; + } + + bb0: { + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + StorageLive(_7); + _7 = const 'u'; + _6 = &_7; + _5 = &(*_6); + _4 = (const 7_u32, const 12_u64, move _5); + StorageDead(_5); + PlaceMention(_4); + AscribeUserType(_4, +, UserTypeProjection { base: UserType(1), projs: [] }); + StorageLive(_1); + _1 = copy (_4.0: u32); + StorageLive(_2); + _2 = copy (_4.1: u64); + StorageLive(_3); + _3 = copy (_4.2: &char); + StorageDead(_6); + StorageDead(_4); + _0 = const (); + StorageDead(_3); + StorageDead(_2); + StorageDead(_1); + StorageDead(_7); + return; + } + + bb1: { + FakeRead(ForMatchedPlace(None), _4); + unreachable; + } +} diff --git a/tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir new file mode 100644 index 00000000000..6702f930060 --- /dev/null +++ b/tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir @@ -0,0 +1,39 @@ +// MIR for `let_init_bindless` after built + +| User Type Annotations +| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:30:20: 30:45, inferred_ty: (u32, u64, &char) +| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:30:20: 30:45, inferred_ty: (u32, u64, &char) +| +fn let_init_bindless() -> () { + let mut _0: (); + let mut _1: (u32, u64, &char); + let mut _2: &char; + let _3: &char; + let _4: char; + scope 1 { + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); + _4 = const 'u'; + _3 = &_4; + _2 = &(*_3); + _1 = (const 7_u32, const 12_u64, move _2); + StorageDead(_2); + PlaceMention(_1); + AscribeUserType(_1, +, UserTypeProjection { base: UserType(1), projs: [] }); + StorageDead(_3); + StorageDead(_1); + _0 = const (); + StorageDead(_4); + return; + } + + bb1: { + FakeRead(ForMatchedPlace(None), _1); + unreachable; + } +} diff --git a/tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir new file mode 100644 index 00000000000..76b5938b87d --- /dev/null +++ b/tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir @@ -0,0 +1,27 @@ +// MIR for `let_uninit` after built + +| User Type Annotations +| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:15:20: 15:45, inferred_ty: (u32, u64, &char) +| +fn let_uninit() -> () { + let mut _0: (); + let _1: u32 as UserTypeProjection { base: UserType(0), projs: [Field(0, ())] }; + let _2: u64 as UserTypeProjection { base: UserType(0), projs: [Field(1, ())] }; + let _3: &char as UserTypeProjection { base: UserType(0), projs: [Field(2, ())] }; + scope 1 { + debug x => _1; + debug y => _2; + debug z => _3; + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + StorageLive(_3); + _0 = const (); + StorageDead(_3); + StorageDead(_2); + StorageDead(_1); + return; + } +} diff --git a/tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir new file mode 100644 index 00000000000..0cd12558771 --- /dev/null +++ b/tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir @@ -0,0 +1,15 @@ +// MIR for `let_uninit_bindless` after built + +| User Type Annotations +| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:20:20: 20:45, inferred_ty: (u32, u64, &char) +| +fn let_uninit_bindless() -> () { + let mut _0: (); + scope 1 { + } + + bb0: { + _0 = const (); + return; + } +} diff --git a/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir b/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir new file mode 100644 index 00000000000..c0ce6f1d06b --- /dev/null +++ b/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir @@ -0,0 +1,46 @@ +// MIR for `match_assoc_const` after built + +| User Type Annotations +| 0: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:54:9: 54:44, inferred_ty: u32 +| 1: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:54:9: 54:44, inferred_ty: u32 +| +fn match_assoc_const() -> () { + let mut _0: (); + let mut _1: u32; + + bb0: { + StorageLive(_1); + _1 = const 8_u32; + PlaceMention(_1); + switchInt(copy _1) -> [99: bb2, otherwise: bb1]; + } + + bb1: { + _0 = const (); + goto -> bb6; + } + + bb2: { + falseEdge -> [real: bb5, imaginary: bb1]; + } + + bb3: { + goto -> bb1; + } + + bb4: { + FakeRead(ForMatchedPlace(None), _1); + unreachable; + } + + bb5: { + AscribeUserType(_1, -, UserTypeProjection { base: UserType(1), projs: [] }); + _0 = const (); + goto -> bb6; + } + + bb6: { + StorageDead(_1); + return; + } +} diff --git a/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir b/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir new file mode 100644 index 00000000000..3a6aa5b7c2c --- /dev/null +++ b/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir @@ -0,0 +1,74 @@ +// MIR for `match_assoc_const_range` after built + +| User Type Annotations +| 0: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:62:11: 62:46, inferred_ty: u32 +| 1: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:62:11: 62:46, inferred_ty: u32 +| 2: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:63:9: 63:44, inferred_ty: u32 +| 3: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:63:9: 63:44, inferred_ty: u32 +| +fn match_assoc_const_range() -> () { + let mut _0: (); + let mut _1: u32; + let mut _2: bool; + let mut _3: bool; + + bb0: { + StorageLive(_1); + _1 = const 8_u32; + PlaceMention(_1); + _3 = Lt(copy _1, const 99_u32); + switchInt(move _3) -> [0: bb4, otherwise: bb2]; + } + + bb1: { + _0 = const (); + goto -> bb11; + } + + bb2: { + falseEdge -> [real: bb10, imaginary: bb4]; + } + + bb3: { + goto -> bb1; + } + + bb4: { + _2 = Le(const 99_u32, copy _1); + switchInt(move _2) -> [0: bb5, otherwise: bb6]; + } + + bb5: { + goto -> bb1; + } + + bb6: { + falseEdge -> [real: bb9, imaginary: bb1]; + } + + bb7: { + goto -> bb5; + } + + bb8: { + FakeRead(ForMatchedPlace(None), _1); + unreachable; + } + + bb9: { + AscribeUserType(_1, -, UserTypeProjection { base: UserType(3), projs: [] }); + _0 = const (); + goto -> bb11; + } + + bb10: { + AscribeUserType(_1, -, UserTypeProjection { base: UserType(1), projs: [] }); + _0 = const (); + goto -> bb11; + } + + bb11: { + StorageDead(_1); + return; + } +} diff --git a/tests/mir-opt/building/user_type_annotations.rs b/tests/mir-opt/building/user_type_annotations.rs new file mode 100644 index 00000000000..d55c678d5ae --- /dev/null +++ b/tests/mir-opt/building/user_type_annotations.rs @@ -0,0 +1,66 @@ +//@ edition: 2024 +// skip-filecheck + +// This test demonstrates how many user type annotations are recorded in MIR +// for various binding constructs. In particular, this makes it possible to see +// the number of duplicate user-type-annotation entries, and whether that +// number has changed. +// +// Duplicates are mostly harmless, other than being inefficient. +// "Unused" entries that are _not_ duplicates may nevertheless be necessary so +// that they are seen by MIR lifetime checks. + +// EMIT_MIR user_type_annotations.let_uninit.built.after.mir +fn let_uninit() { + let (x, y, z): (u32, u64, &'static char); +} + +// EMIT_MIR user_type_annotations.let_uninit_bindless.built.after.mir +fn let_uninit_bindless() { + let (_, _, _): (u32, u64, &'static char); +} + +// EMIT_MIR user_type_annotations.let_init.built.after.mir +fn let_init() { + let (x, y, z): (u32, u64, &'static char) = (7, 12, &'u'); +} + +// EMIT_MIR user_type_annotations.let_init_bindless.built.after.mir +fn let_init_bindless() { + let (_, _, _): (u32, u64, &'static char) = (7, 12, &'u'); +} + +// EMIT_MIR user_type_annotations.let_else.built.after.mir +fn let_else() { + let (x, y, z): (u32, u64, &'static char) = (7, 12, &'u') else { unreachable!() }; +} + +// EMIT_MIR user_type_annotations.let_else_bindless.built.after.mir +fn let_else_bindless() { + let (_, _, _): (u32, u64, &'static char) = (7, 12, &'u') else { unreachable!() }; +} + +trait MyTrait<'a> { + const FOO: u32; +} +struct MyStruct {} +impl MyTrait<'static> for MyStruct { + const FOO: u32 = 99; +} + +// EMIT_MIR user_type_annotations.match_assoc_const.built.after.mir +fn match_assoc_const() { + match 8 { + <MyStruct as MyTrait<'static>>::FOO => {} + _ => {} + } +} + +// EMIT_MIR user_type_annotations.match_assoc_const_range.built.after.mir +fn match_assoc_const_range() { + match 8 { + ..<MyStruct as MyTrait<'static>>::FOO => {} + <MyStruct as MyTrait<'static>>::FOO.. => {} + _ => {} + } +} diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff index e9f48a85f9c..8e1cdb7182b 100644 --- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff @@ -26,7 +26,6 @@ debug a => _9; } -+ coverage body span: $DIR/branch_match_arms.rs:14:11: 21:2 (#0) + coverage Code { bcb: bcb0 } => $DIR/branch_match_arms.rs:14:1: 15:21 (#0); + coverage Code { bcb: bcb1 } => $DIR/branch_match_arms.rs:16:17: 16:33 (#0); + coverage Code { bcb: bcb3 } => $DIR/branch_match_arms.rs:17:17: 17:33 (#0); diff --git a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff index cbef6de917d..06e5f011c76 100644 --- a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff @@ -4,8 +4,7 @@ fn bar() -> bool { let mut _0: bool; -+ coverage body span: $DIR/instrument_coverage.rs:29:18: 31:2 (#0) -+ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:29:1: 31:2 (#0); ++ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:27:1: 29:2 (#0); + bb0: { + Coverage::VirtualCounter(bcb0); diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff index b166d79a412..1a71cb8dea7 100644 --- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff @@ -7,12 +7,11 @@ let mut _2: bool; let mut _3: !; -+ coverage body span: $DIR/instrument_coverage.rs:14:11: 20:2 (#0) -+ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:14:1: 14:11 (#0); -+ coverage Code { bcb: bcb1 } => $DIR/instrument_coverage.rs:16:12: 16:17 (#0); -+ coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:17:13: 17:18 (#0); -+ coverage Code { bcb: bcb3 } => $DIR/instrument_coverage.rs:18:10: 18:10 (#0); -+ coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:20:2: 20:2 (#0); ++ coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:13:1: 13:11 (#0); ++ coverage Code { bcb: bcb1 } => $DIR/instrument_coverage.rs:15:12: 15:17 (#0); ++ coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:16:13: 16:18 (#0); ++ coverage Code { bcb: bcb3 } => $DIR/instrument_coverage.rs:17:10: 17:10 (#0); ++ coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:19:2: 19:2 (#0); + bb0: { + Coverage::VirtualCounter(bcb0); diff --git a/tests/mir-opt/coverage/instrument_coverage.rs b/tests/mir-opt/coverage/instrument_coverage.rs index 48647402d0f..d4ed4b67375 100644 --- a/tests/mir-opt/coverage/instrument_coverage.rs +++ b/tests/mir-opt/coverage/instrument_coverage.rs @@ -7,7 +7,6 @@ // EMIT_MIR instrument_coverage.main.InstrumentCoverage.diff // CHECK-LABEL: fn main() -// CHECK: coverage body span: // CHECK: coverage Code { bcb: bcb{{[0-9]+}} } => // CHECK: bb0: // CHECK: Coverage::VirtualCounter @@ -21,7 +20,6 @@ fn main() { // EMIT_MIR instrument_coverage.bar.InstrumentCoverage.diff // CHECK-LABEL: fn bar() -// CHECK: coverage body span: // CHECK: coverage Code { bcb: bcb{{[0-9]+}} } => // CHECK: bb0: // CHECK: Coverage::VirtualCounter diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff index 855f806aae1..1a22adeba6f 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff @@ -7,7 +7,6 @@ coverage branch { true: BlockMarkerId(0), false: BlockMarkerId(1) } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0) - coverage body span: $DIR/instrument_coverage_cleanup.rs:13:11: 15:2 (#0) coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 14:36 (#0); coverage Code { bcb: bcb3 } => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0); coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0); diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff index df1f1e8bc50..b77969a3e16 100644 --- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff @@ -7,7 +7,6 @@ coverage branch { true: BlockMarkerId(0), false: BlockMarkerId(1) } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0) -+ coverage body span: $DIR/instrument_coverage_cleanup.rs:13:11: 15:2 (#0) + coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 14:36 (#0); + coverage Code { bcb: bcb3 } => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0); + coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0); diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff index 45fc7365d8d..6baa902b6f4 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff @@ -29,16 +29,10 @@ debug precision => _8; let _8: usize; scope 5 (inlined Formatter::<'_>::precision) { - let mut _22: std::option::Option<u16>; - scope 6 (inlined Option::<u16>::map::<usize, {closure@Formatter<'_>::precision::{closure#0}}>) { - let mut _23: isize; - let _24: u16; - let mut _25: usize; - scope 7 { - scope 8 (inlined Formatter::<'_>::precision::{closure#0}) { - } - } - } + let mut _22: u32; + let mut _23: u32; + let mut _24: usize; + let mut _25: u16; } } } @@ -53,7 +47,7 @@ StorageLive(_20); StorageLive(_21); _21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); - _20 = BitAnd(move _21, const 1_u32); + _20 = BitAnd(move _21, const core::fmt::flags::SIGN_PLUS_FLAG); StorageDead(_21); _4 = Ne(move _20, const 0_u32); StorageDead(_20); @@ -75,12 +69,12 @@ bb3: { StorageLive(_6); - StorageLive(_24); StorageLive(_22); - _22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<u16>); StorageLive(_23); - _23 = discriminant(_22); - switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10]; + _23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); + _22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG); + StorageDead(_23); + switchInt(move _22) -> [0: bb10, otherwise: bb11]; } bb4: { @@ -148,30 +142,31 @@ } bb9: { - StorageDead(_23); - StorageDead(_22); - StorageDead(_24); _7 = discriminant(_6); - switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10]; + switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb12]; } bb10: { - unreachable; - } - - bb11: { + StorageDead(_22); _6 = const Option::<usize>::None; goto -> bb9; } - bb12: { - _24 = move ((_22 as Some).0: u16); + bb11: { + StorageDead(_22); + StorageLive(_24); StorageLive(_25); - _25 = copy _24 as usize (IntToInt); - _6 = Option::<usize>::Some(move _25); + _25 = copy (((*_1).0: std::fmt::FormattingOptions).2: u16); + _24 = move _25 as usize (IntToInt); StorageDead(_25); + _6 = Option::<usize>::Some(move _24); + StorageDead(_24); goto -> bb9; } + + bb12: { + unreachable; + } } ALLOC0 (size: 8, align: 4) { diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff index 578d2c2194b..36540e03865 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff @@ -29,16 +29,10 @@ debug precision => _8; let _8: usize; scope 5 (inlined Formatter::<'_>::precision) { - let mut _22: std::option::Option<u16>; - scope 6 (inlined Option::<u16>::map::<usize, {closure@Formatter<'_>::precision::{closure#0}}>) { - let mut _23: isize; - let _24: u16; - let mut _25: usize; - scope 7 { - scope 8 (inlined Formatter::<'_>::precision::{closure#0}) { - } - } - } + let mut _22: u32; + let mut _23: u32; + let mut _24: usize; + let mut _25: u16; } } } @@ -53,7 +47,7 @@ StorageLive(_20); StorageLive(_21); _21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); - _20 = BitAnd(move _21, const 1_u32); + _20 = BitAnd(move _21, const core::fmt::flags::SIGN_PLUS_FLAG); StorageDead(_21); _4 = Ne(move _20, const 0_u32); StorageDead(_20); @@ -75,12 +69,12 @@ bb3: { StorageLive(_6); - StorageLive(_24); StorageLive(_22); - _22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<u16>); StorageLive(_23); - _23 = discriminant(_22); - switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10]; + _23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); + _22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG); + StorageDead(_23); + switchInt(move _22) -> [0: bb10, otherwise: bb11]; } bb4: { @@ -148,30 +142,31 @@ } bb9: { - StorageDead(_23); - StorageDead(_22); - StorageDead(_24); _7 = discriminant(_6); - switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10]; + switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb12]; } bb10: { - unreachable; - } - - bb11: { + StorageDead(_22); _6 = const Option::<usize>::None; goto -> bb9; } - bb12: { - _24 = move ((_22 as Some).0: u16); + bb11: { + StorageDead(_22); + StorageLive(_24); StorageLive(_25); - _25 = copy _24 as usize (IntToInt); - _6 = Option::<usize>::Some(move _25); + _25 = copy (((*_1).0: std::fmt::FormattingOptions).2: u16); + _24 = move _25 as usize (IntToInt); StorageDead(_25); + _6 = Option::<usize>::Some(move _24); + StorageDead(_24); goto -> bb9; } + + bb12: { + unreachable; + } } ALLOC0 (size: 8, align: 4) { diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff index 5f0f7d6cc74..41c350f3eae 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff @@ -29,16 +29,10 @@ debug precision => _8; let _8: usize; scope 5 (inlined Formatter::<'_>::precision) { - let mut _22: std::option::Option<u16>; - scope 6 (inlined Option::<u16>::map::<usize, {closure@Formatter<'_>::precision::{closure#0}}>) { - let mut _23: isize; - let _24: u16; - let mut _25: usize; - scope 7 { - scope 8 (inlined Formatter::<'_>::precision::{closure#0}) { - } - } - } + let mut _22: u32; + let mut _23: u32; + let mut _24: usize; + let mut _25: u16; } } } @@ -53,7 +47,7 @@ StorageLive(_20); StorageLive(_21); _21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); - _20 = BitAnd(move _21, const 1_u32); + _20 = BitAnd(move _21, const core::fmt::flags::SIGN_PLUS_FLAG); StorageDead(_21); _4 = Ne(move _20, const 0_u32); StorageDead(_20); @@ -75,12 +69,12 @@ bb3: { StorageLive(_6); - StorageLive(_24); StorageLive(_22); - _22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<u16>); StorageLive(_23); - _23 = discriminant(_22); - switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10]; + _23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); + _22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG); + StorageDead(_23); + switchInt(move _22) -> [0: bb10, otherwise: bb11]; } bb4: { @@ -148,30 +142,31 @@ } bb9: { - StorageDead(_23); - StorageDead(_22); - StorageDead(_24); _7 = discriminant(_6); - switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10]; + switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb12]; } bb10: { - unreachable; - } - - bb11: { + StorageDead(_22); _6 = const Option::<usize>::None; goto -> bb9; } - bb12: { - _24 = move ((_22 as Some).0: u16); + bb11: { + StorageDead(_22); + StorageLive(_24); StorageLive(_25); - _25 = copy _24 as usize (IntToInt); - _6 = Option::<usize>::Some(move _25); + _25 = copy (((*_1).0: std::fmt::FormattingOptions).2: u16); + _24 = move _25 as usize (IntToInt); StorageDead(_25); + _6 = Option::<usize>::Some(move _24); + StorageDead(_24); goto -> bb9; } + + bb12: { + unreachable; + } } ALLOC0 (size: 16, align: 8) { diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff index 10cc46a8b82..b839bf81eaf 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff @@ -29,16 +29,10 @@ debug precision => _8; let _8: usize; scope 5 (inlined Formatter::<'_>::precision) { - let mut _22: std::option::Option<u16>; - scope 6 (inlined Option::<u16>::map::<usize, {closure@Formatter<'_>::precision::{closure#0}}>) { - let mut _23: isize; - let _24: u16; - let mut _25: usize; - scope 7 { - scope 8 (inlined Formatter::<'_>::precision::{closure#0}) { - } - } - } + let mut _22: u32; + let mut _23: u32; + let mut _24: usize; + let mut _25: u16; } } } @@ -53,7 +47,7 @@ StorageLive(_20); StorageLive(_21); _21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); - _20 = BitAnd(move _21, const 1_u32); + _20 = BitAnd(move _21, const core::fmt::flags::SIGN_PLUS_FLAG); StorageDead(_21); _4 = Ne(move _20, const 0_u32); StorageDead(_20); @@ -75,12 +69,12 @@ bb3: { StorageLive(_6); - StorageLive(_24); StorageLive(_22); - _22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<u16>); StorageLive(_23); - _23 = discriminant(_22); - switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10]; + _23 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32); + _22 = BitAnd(move _23, const core::fmt::flags::PRECISION_FLAG); + StorageDead(_23); + switchInt(move _22) -> [0: bb10, otherwise: bb11]; } bb4: { @@ -148,30 +142,31 @@ } bb9: { - StorageDead(_23); - StorageDead(_22); - StorageDead(_24); _7 = discriminant(_6); - switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10]; + switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb12]; } bb10: { - unreachable; - } - - bb11: { + StorageDead(_22); _6 = const Option::<usize>::None; goto -> bb9; } - bb12: { - _24 = move ((_22 as Some).0: u16); + bb11: { + StorageDead(_22); + StorageLive(_24); StorageLive(_25); - _25 = copy _24 as usize (IntToInt); - _6 = Option::<usize>::Some(move _25); + _25 = copy (((*_1).0: std::fmt::FormattingOptions).2: u16); + _24 = move _25 as usize (IntToInt); StorageDead(_25); + _6 = Option::<usize>::Some(move _24); + StorageDead(_24); goto -> bb9; } + + bb12: { + unreachable; + } } ALLOC0 (size: 16, align: 8) { diff --git a/tests/mir-opt/gvn_on_unsafe_binder.propagate.GVN.diff b/tests/mir-opt/gvn_on_unsafe_binder.propagate.GVN.diff new file mode 100644 index 00000000000..e28d04f1d58 --- /dev/null +++ b/tests/mir-opt/gvn_on_unsafe_binder.propagate.GVN.diff @@ -0,0 +1,35 @@ +- // MIR for `propagate` before GVN ++ // MIR for `propagate` after GVN + + fn propagate() -> unsafe<> i32 { + let mut _0: unsafe<> i32; + let _1: i32; + let mut _3: i32; + scope 1 { + debug x => _1; + let _2: unsafe<> i32; + scope 2 { + debug binder => _2; + } + } + + bb0: { +- StorageLive(_1); ++ nop; + _1 = const 1_i32; + StorageLive(_2); + StorageLive(_3); +- _3 = copy _1; +- _2 = wrap_binder!(move _3; unsafe<> i32); ++ _3 = const 1_i32; ++ _2 = const {transmute(0x00000001): unsafe<> i32}; + StorageDead(_3); +- _0 = move _2; ++ _0 = const {transmute(0x00000001): unsafe<> i32}; + StorageDead(_2); +- StorageDead(_1); ++ nop; + return; + } + } + diff --git a/tests/mir-opt/gvn_on_unsafe_binder.rs b/tests/mir-opt/gvn_on_unsafe_binder.rs new file mode 100644 index 00000000000..b3c0576f990 --- /dev/null +++ b/tests/mir-opt/gvn_on_unsafe_binder.rs @@ -0,0 +1,29 @@ +// skip-filecheck +//@ test-mir-pass: GVN + +// EMIT_MIR gvn_on_unsafe_binder.test.GVN.diff +// EMIT_MIR gvn_on_unsafe_binder.propagate.GVN.diff + +#![feature(unsafe_binders)] + +use std::unsafe_binder::wrap_binder; + +// Test for ICE <https://github.com/rust-lang/rust/issues/137846>. +fn test() { + unsafe { + let x = 1; + let binder: unsafe<'a> &'a i32 = wrap_binder!(&x); + } +} + +// Test that GVN propagates const values through unsafe binders. +// +// The lifetime `'a` is redundant (and doesn't print when we print out the type). +// However, we need it so that rustfmt doesn't rip out the `unsafe<>` part for now. +fn propagate() -> unsafe<'a> i32 { + unsafe { + let x = 1; + let binder: unsafe<'a> i32 = wrap_binder!(x); + binder + } +} diff --git a/tests/mir-opt/gvn_on_unsafe_binder.test.GVN.diff b/tests/mir-opt/gvn_on_unsafe_binder.test.GVN.diff new file mode 100644 index 00000000000..33814fb34f3 --- /dev/null +++ b/tests/mir-opt/gvn_on_unsafe_binder.test.GVN.diff @@ -0,0 +1,30 @@ +- // MIR for `test` before GVN ++ // MIR for `test` after GVN + + fn test() -> () { + let mut _0: (); + let _1: i32; + let mut _3: &i32; + scope 1 { + debug x => _1; + let _2: unsafe<'a> &'a i32; + scope 2 { + debug binder => _2; + } + } + + bb0: { + StorageLive(_1); + _1 = const 1_i32; + StorageLive(_2); + StorageLive(_3); + _3 = &_1; + _2 = wrap_binder!(move _3; unsafe<'a> &'a i32); + StorageDead(_3); + _0 = const (); + StorageDead(_2); + StorageDead(_1); + return; + } + } + diff --git a/tests/pretty/autodiff_forward.pp b/tests/pretty/autodiff_forward.pp index 23c3b5b34a8..dc7a2712f42 100644 --- a/tests/pretty/autodiff_forward.pp +++ b/tests/pretty/autodiff_forward.pp @@ -53,7 +53,7 @@ pub fn df2(x: &[f64], bx: &[f64], y: f64) -> f64 { pub fn f3(x: &[f64], y: f64) -> f64 { ::core::panicking::panic("not implemented") } -#[rustc_autodiff(ForwardFirst, Dual, Const, Const,)] +#[rustc_autodiff(Forward, Dual, Const, Const,)] #[inline(never)] pub fn df3(x: &[f64], bx: &[f64], y: f64) -> f64 { unsafe { asm!("NOP", options(pure, nomem)); }; @@ -73,10 +73,6 @@ pub fn df4() { } #[rustc_autodiff] #[inline(never)] -#[rustc_autodiff] -#[inline(never)] -#[rustc_autodiff] -#[inline(never)] pub fn f5(x: &[f64], y: f64) -> f64 { ::core::panicking::panic("not implemented") } diff --git a/tests/pretty/autodiff_forward.rs b/tests/pretty/autodiff_forward.rs index 35108d0d6f1..bc558211632 100644 --- a/tests/pretty/autodiff_forward.rs +++ b/tests/pretty/autodiff_forward.rs @@ -19,7 +19,7 @@ pub fn f2(x: &[f64], y: f64) -> f64 { unimplemented!() } -#[autodiff(df3, ForwardFirst, Dual, Const, Const)] +#[autodiff(df3, Forward, Dual, Const, Const)] pub fn f3(x: &[f64], y: f64) -> f64 { unimplemented!() } diff --git a/tests/pretty/autodiff_reverse.pp b/tests/pretty/autodiff_reverse.pp index a98d3782c70..b2cf0244af4 100644 --- a/tests/pretty/autodiff_reverse.pp +++ b/tests/pretty/autodiff_reverse.pp @@ -51,7 +51,7 @@ pub fn df2() { pub fn f3(x: &[f64], y: f64) -> f64 { ::core::panicking::panic("not implemented") } -#[rustc_autodiff(ReverseFirst, Duplicated, Const, Active,)] +#[rustc_autodiff(Reverse, Duplicated, Const, Active,)] #[inline(never)] pub fn df3(x: &[f64], dx: &mut [f64], y: f64, dret: f64) -> f64 { unsafe { asm!("NOP", options(pure, nomem)); }; diff --git a/tests/pretty/autodiff_reverse.rs b/tests/pretty/autodiff_reverse.rs index 657201caa94..3c024272f40 100644 --- a/tests/pretty/autodiff_reverse.rs +++ b/tests/pretty/autodiff_reverse.rs @@ -18,7 +18,7 @@ pub fn f1(x: &[f64], y: f64) -> f64 { #[autodiff(df2, Reverse)] pub fn f2() {} -#[autodiff(df3, ReverseFirst, Duplicated, Const, Active)] +#[autodiff(df3, Reverse, Duplicated, Const, Active)] pub fn f3(x: &[f64], y: f64) -> f64 { unimplemented!() } diff --git a/tests/pretty/hir-fn-params.pp b/tests/pretty/hir-fn-params.pp new file mode 100644 index 00000000000..3799c8a3c3b --- /dev/null +++ b/tests/pretty/hir-fn-params.pp @@ -0,0 +1,38 @@ +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:hir-fn-params.pp + +// This tests the pretty-printing of various kinds of function parameters. + +//--------------------------------------------------------------------------- +// Normal functions and methods. + +fn normal_fn(_: u32, a: u32) { } + +struct S; +impl S { + fn method(_: u32, a: u32) { } +} + +//--------------------------------------------------------------------------- +// More exotic forms, which get a different pretty-printing path. In the past, +// anonymous params and `_` params printed incorrectly, e.g. `fn(u32, _: u32)` +// was printed as `fn(: u32, : u32)`. +// +// Ideally we would also test invalid patterns, e.g. `fn(1: u32, &a: u32)`, +// because they had similar problems. But the pretty-printing tests currently +// can't contain compile errors. + +fn bare_fn(x: fn(u32, _: u32, a: u32)) { } + +extern "C" { + unsafe fn foreign_fn(_: u32, a: u32); +} + +trait T { + fn trait_fn(u32, _: u32, a: u32); +} diff --git a/tests/pretty/hir-fn-params.rs b/tests/pretty/hir-fn-params.rs new file mode 100644 index 00000000000..5ace5289d08 --- /dev/null +++ b/tests/pretty/hir-fn-params.rs @@ -0,0 +1,34 @@ +//@ pretty-compare-only +//@ pretty-mode:hir +//@ pp-exact:hir-fn-params.pp + +// This tests the pretty-printing of various kinds of function parameters. + +//--------------------------------------------------------------------------- +// Normal functions and methods. + +fn normal_fn(_: u32, a: u32) {} + +struct S; +impl S { + fn method(_: u32, a: u32) {} +} + +//--------------------------------------------------------------------------- +// More exotic forms, which get a different pretty-printing path. In the past, +// anonymous params and `_` params printed incorrectly, e.g. `fn(u32, _: u32)` +// was printed as `fn(: u32, : u32)`. +// +// Ideally we would also test invalid patterns, e.g. `fn(1: u32, &a: u32)`, +// because they had similar problems. But the pretty-printing tests currently +// can't contain compile errors. + +fn bare_fn(x: fn(u32, _: u32, a: u32)) {} + +extern "C" { + fn foreign_fn(_: u32, a: u32); +} + +trait T { + fn trait_fn(u32, _: u32, a: u32); +} diff --git a/tests/pretty/postfix-yield.rs b/tests/pretty/postfix-yield.rs new file mode 100644 index 00000000000..f76e8142ae8 --- /dev/null +++ b/tests/pretty/postfix-yield.rs @@ -0,0 +1,15 @@ +// This demonstrates a proposed alternate or additional option of having yield in postfix position. +//@ edition: 2024 +//@ pp-exact + +#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr)] + +use std::ops::{Coroutine, CoroutineState}; +use std::pin::pin; + +fn main() { + let mut gn = gen { yield 1; 2.yield; (1 + 2).yield; }; + + let mut coro = + pin!(#[coroutine] |_: i32| { let x = 1.yield; (x + 2).yield; }); +} diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs index 73ad248b6f3..bc21739fefc 100644 --- a/tests/run-make/linker-warning/rmake.rs +++ b/tests/run-make/linker-warning/rmake.rs @@ -4,7 +4,7 @@ fn run_rustc() -> Rustc { let mut rustc = rustc(); rustc .arg("main.rs") - // NOTE: `link-self-contained` can vary depending on config.toml. + // NOTE: `link-self-contained` can vary depending on bootstrap.toml. // Make sure we use a consistent value. .arg("-Clink-self-contained=-linker") .arg("-Zunstable-options") diff --git a/tests/run-make/non-unicode-env/non_unicode_env.stderr b/tests/run-make/non-unicode-env/non_unicode_env.stderr index 1f260ac9c07..32868b13f74 100644 --- a/tests/run-make/non-unicode-env/non_unicode_env.stderr +++ b/tests/run-make/non-unicode-env/non_unicode_env.stderr @@ -3,16 +3,12 @@ error: environment variable `NON_UNICODE_VAR` is not a valid Unicode string | 2 | let _ = env!("NON_UNICODE_VAR"); | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: environment variable `NON_UNICODE_VAR` is not a valid Unicode string --> non_unicode_env.rs:3:13 | 3 | let _ = option_env!("NON_UNICODE_VAR"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `option_env` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/run-make/symbols-all-mangled/a_lib.rs b/tests/run-make/symbols-all-mangled/a_lib.rs new file mode 100644 index 00000000000..716dd3263c5 --- /dev/null +++ b/tests/run-make/symbols-all-mangled/a_lib.rs @@ -0,0 +1 @@ +pub fn public_rust_function() {} diff --git a/tests/run-make/symbols-all-mangled/an_executable.rs b/tests/run-make/symbols-all-mangled/an_executable.rs new file mode 100644 index 00000000000..db8df13b9a7 --- /dev/null +++ b/tests/run-make/symbols-all-mangled/an_executable.rs @@ -0,0 +1,3 @@ +pub fn public_rust_function_from_exe() {} + +fn main() {} diff --git a/tests/run-make/symbols-all-mangled/rmake.rs b/tests/run-make/symbols-all-mangled/rmake.rs new file mode 100644 index 00000000000..1fb03c62399 --- /dev/null +++ b/tests/run-make/symbols-all-mangled/rmake.rs @@ -0,0 +1,96 @@ +// Check that all symbols in cdylibs, staticlibs and bins are mangled +//@ only-elf some object file formats create multiple symbols for each function with different names + +use run_make_support::object::read::{Object, ObjectSymbol}; +use run_make_support::{bin_name, dynamic_lib_name, object, rfs, rustc, static_lib_name}; + +fn main() { + let staticlib_name = static_lib_name("a_lib"); + let cdylib_name = dynamic_lib_name("a_lib"); + let exe_name = bin_name("an_executable"); + rustc().crate_type("cdylib").input("a_lib.rs").run(); + rustc().crate_type("staticlib").input("a_lib.rs").run(); + rustc().crate_type("bin").input("an_executable.rs").run(); + + symbols_check_archive(&staticlib_name); + symbols_check(&cdylib_name); + symbols_check(&exe_name); +} + +fn symbols_check_archive(path: &str) { + let binary_data = rfs::read(path); + let file = object::read::archive::ArchiveFile::parse(&*binary_data).unwrap(); + for symbol in file.symbols().unwrap().unwrap() { + let symbol = symbol.unwrap(); + let name = strip_underscore_if_apple(std::str::from_utf8(symbol.name()).unwrap()); + if name.starts_with("_ZN") || name.starts_with("_R") { + continue; // Correctly mangled + } + + let member_name = + std::str::from_utf8(file.member(symbol.offset()).unwrap().name()).unwrap(); + if !member_name.ends_with(".rcgu.o") || member_name.contains("compiler_builtins") { + continue; // All compiler-builtins symbols must remain unmangled + } + + if name == "__rust_no_alloc_shim_is_unstable" { + continue; // FIXME remove exception once we mangle this symbol + } + + if name.contains("rust_eh_personality") { + continue; // Unfortunately LLVM doesn't allow us to mangle this symbol + } + + if name.contains(".llvm.") { + // Starting in LLVM 21 we get various implementation-detail functions which + // contain .llvm. that are not a problem. + continue; + } + + panic!("Unmangled symbol found in {path}: {name}"); + } +} + +fn symbols_check(path: &str) { + let binary_data = rfs::read(path); + let file = object::File::parse(&*binary_data).unwrap(); + for symbol in file.symbols() { + if !symbol.is_definition() || !symbol.is_global() { + continue; + } + if symbol.is_weak() { + continue; // Likely an intrinsic from compiler-builtins + } + let name = strip_underscore_if_apple(symbol.name().unwrap()); + if name.starts_with("_ZN") || name.starts_with("_R") { + continue; // Correctly mangled + } + + if !name.contains("rust") { + // Assume that this symbol doesn't originate from rustc. This may + // be wrong, but even if so symbol_check_archive will likely + // catch it. + continue; + } + + if name == "__rust_no_alloc_shim_is_unstable" { + continue; // FIXME remove exception once we mangle this symbol + } + + if name.contains("rust_eh_personality") { + continue; // Unfortunately LLVM doesn't allow us to mangle this symbol + } + + if name.contains(".llvm.") { + // Starting in LLVM 21 we get various implementation-detail functions which + // contain .llvm. that are not a problem. + continue; + } + + panic!("Unmangled symbol found in {path}: {name}"); + } +} + +fn strip_underscore_if_apple(symbol: &str) -> &str { + if cfg!(target_vendor = "apple") { symbol.strip_prefix("_").unwrap() } else { symbol } +} diff --git a/tests/rustdoc-json/assoc_items.rs b/tests/rustdoc-json/assoc_items.rs index f315f37966d..f47a522e81a 100644 --- a/tests/rustdoc-json/assoc_items.rs +++ b/tests/rustdoc-json/assoc_items.rs @@ -3,32 +3,32 @@ pub struct Simple; impl Simple { - //@ has "$.index[*][?(@.name=='CONSTANT')].inner.assoc_const" + //@ has "$.index[?(@.name=='CONSTANT')].inner.assoc_const" pub const CONSTANT: usize = 0; } pub trait EasyToImpl { - //@ has "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type" - //@ is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.type" null - //@ is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.bounds" [] + //@ has "$.index[?(@.docs=='ToDeclare trait')].inner.assoc_type" + //@ is "$.index[?(@.docs=='ToDeclare trait')].inner.assoc_type.type" null + //@ is "$.index[?(@.docs=='ToDeclare trait')].inner.assoc_type.bounds" [] /// ToDeclare trait type ToDeclare; - //@ has "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const" - //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.value" null - //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.type.primitive" '"usize"' + //@ has "$.index[?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const" + //@ is "$.index[?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.value" null + //@ is "$.index[?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.type.primitive" '"usize"' /// AN_ATTRIBUTE trait const AN_ATTRIBUTE: usize; } impl EasyToImpl for Simple { - //@ has "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type" - //@ is "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type.type.primitive" \"usize\" + //@ has "$.index[?(@.docs=='ToDeclare impl')].inner.assoc_type" + //@ is "$.index[?(@.docs=='ToDeclare impl')].inner.assoc_type.type.primitive" \"usize\" /// ToDeclare impl type ToDeclare = usize; - //@ has "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const" - //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.type.primitive" \"usize\" - //@ is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.value" \"12\" + //@ has "$.index[?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const" + //@ is "$.index[?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.type.primitive" \"usize\" + //@ is "$.index[?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.value" \"12\" /// AN_ATTRIBUTE impl const AN_ATTRIBUTE: usize = 12; } diff --git a/tests/rustdoc-json/assoc_type.rs b/tests/rustdoc-json/assoc_type.rs index 43b4d387d92..816075ca17a 100644 --- a/tests/rustdoc-json/assoc_type.rs +++ b/tests/rustdoc-json/assoc_type.rs @@ -1,9 +1,9 @@ // Regression test for <https://github.com/rust-lang/rust/issues/98547>. -//@ has "$.index[*][?(@.name=='Trait')]" -//@ has "$.index[*][?(@.name=='AssocType')]" -//@ has "$.index[*][?(@.name=='S')]" -//@ has "$.index[*][?(@.name=='S2')]" +//@ has "$.index[?(@.name=='Trait')]" +//@ has "$.index[?(@.name=='AssocType')]" +//@ has "$.index[?(@.name=='S')]" +//@ has "$.index[?(@.name=='S2')]" pub trait Trait { type AssocType; diff --git a/tests/rustdoc-json/attrs/deprecated.rs b/tests/rustdoc-json/attrs/deprecated.rs new file mode 100644 index 00000000000..0799471fc88 --- /dev/null +++ b/tests/rustdoc-json/attrs/deprecated.rs @@ -0,0 +1,38 @@ +//@ is "$.index[?(@.name=='not')].attrs" [] +//@ is "$.index[?(@.name=='not')].deprecation" null +pub fn not() {} + +//@ is "$.index[?(@.name=='raw')].attrs" [] +//@ is "$.index[?(@.name=='raw')].deprecation" '{"since": null, "note": null}' +#[deprecated] +pub fn raw() {} + +//@ is "$.index[?(@.name=='equals_string')].attrs" [] +//@ is "$.index[?(@.name=='equals_string')].deprecation" '{"since": null, "note": "here is a reason"}' +#[deprecated = "here is a reason"] +pub fn equals_string() {} + +//@ is "$.index[?(@.name=='since')].attrs" [] +//@ is "$.index[?(@.name=='since')].deprecation" '{"since": "yoinks ago", "note": null}' +#[deprecated(since = "yoinks ago")] +pub fn since() {} + +//@ is "$.index[?(@.name=='note')].attrs" [] +//@ is "$.index[?(@.name=='note')].deprecation" '{"since": null, "note": "7"}' +#[deprecated(note = "7")] +pub fn note() {} + +//@ is "$.index[?(@.name=='since_and_note')].attrs" [] +//@ is "$.index[?(@.name=='since_and_note')].deprecation" '{"since": "tomorrow", "note": "sorry"}' +#[deprecated(since = "tomorrow", note = "sorry")] +pub fn since_and_note() {} + +//@ is "$.index[?(@.name=='note_and_since')].attrs" [] +//@ is "$.index[?(@.name=='note_and_since')].deprecation" '{"since": "a year from tomorrow", "note": "your welcome"}' +#[deprecated(note = "your welcome", since = "a year from tomorrow")] +pub fn note_and_since() {} + +//@ is "$.index[?(@.name=='neither_but_parens')].attrs" [] +//@ is "$.index[?(@.name=='neither_but_parens')].deprecation" '{"since": null, "note": null}' +#[deprecated()] +pub fn neither_but_parens() {} diff --git a/tests/rustdoc-json/attrs/export_name_2021.rs b/tests/rustdoc-json/attrs/export_name_2021.rs index badf124bdde..254e9f6ef5b 100644 --- a/tests/rustdoc-json/attrs/export_name_2021.rs +++ b/tests/rustdoc-json/attrs/export_name_2021.rs @@ -1,6 +1,6 @@ //@ edition: 2021 #![no_std] -//@ is "$.index[*][?(@.name=='example')].attrs" '["#[export_name = \"altered\"]"]' +//@ is "$.index[?(@.name=='example')].attrs" '["#[export_name = \"altered\"]"]' #[export_name = "altered"] pub extern "C" fn example() {} diff --git a/tests/rustdoc-json/attrs/export_name_2024.rs b/tests/rustdoc-json/attrs/export_name_2024.rs index c5bb9dcc8f6..8129c109306 100644 --- a/tests/rustdoc-json/attrs/export_name_2024.rs +++ b/tests/rustdoc-json/attrs/export_name_2024.rs @@ -4,6 +4,6 @@ // The representation of `#[unsafe(export_name = ..)]` in rustdoc in edition 2024 // is still `#[export_name = ..]` without the `unsafe` attribute wrapper. -//@ is "$.index[*][?(@.name=='example')].attrs" '["#[export_name = \"altered\"]"]' +//@ is "$.index[?(@.name=='example')].attrs" '["#[export_name = \"altered\"]"]' #[unsafe(export_name = "altered")] pub extern "C" fn example() {} diff --git a/tests/rustdoc-json/attrs/must_use.rs b/tests/rustdoc-json/attrs/must_use.rs index dca73abc76a..64df8e5f509 100644 --- a/tests/rustdoc-json/attrs/must_use.rs +++ b/tests/rustdoc-json/attrs/must_use.rs @@ -1,9 +1,9 @@ #![no_std] -//@ is "$.index[*][?(@.name=='example')].attrs" '["#[must_use]"]' +//@ is "$.index[?(@.name=='example')].attrs" '["#[must_use]"]' #[must_use] pub fn example() -> impl Iterator<Item = i64> {} -//@ is "$.index[*][?(@.name=='explicit_message')].attrs" '["#[must_use = \"does nothing if you do not use it\"]"]' +//@ is "$.index[?(@.name=='explicit_message')].attrs" '["#[must_use = \"does nothing if you do not use it\"]"]' #[must_use = "does nothing if you do not use it"] pub fn explicit_message() -> impl Iterator<Item = i64> {} diff --git a/tests/rustdoc-json/attrs/no_mangle_2021.rs b/tests/rustdoc-json/attrs/no_mangle_2021.rs index 258542086ec..588be7256db 100644 --- a/tests/rustdoc-json/attrs/no_mangle_2021.rs +++ b/tests/rustdoc-json/attrs/no_mangle_2021.rs @@ -1,6 +1,6 @@ //@ edition: 2021 #![no_std] -//@ is "$.index[*][?(@.name=='example')].attrs" '["#[no_mangle]"]' +//@ is "$.index[?(@.name=='example')].attrs" '["#[no_mangle]"]' #[no_mangle] pub extern "C" fn example() {} diff --git a/tests/rustdoc-json/attrs/no_mangle_2024.rs b/tests/rustdoc-json/attrs/no_mangle_2024.rs index 4c01082d045..0d500e20e6c 100644 --- a/tests/rustdoc-json/attrs/no_mangle_2024.rs +++ b/tests/rustdoc-json/attrs/no_mangle_2024.rs @@ -4,6 +4,6 @@ // The representation of `#[unsafe(no_mangle)]` in rustdoc in edition 2024 // is still `#[no_mangle]` without the `unsafe` attribute wrapper. -//@ is "$.index[*][?(@.name=='example')].attrs" '["#[no_mangle]"]' +//@ is "$.index[?(@.name=='example')].attrs" '["#[no_mangle]"]' #[unsafe(no_mangle)] pub extern "C" fn example() {} diff --git a/tests/rustdoc-json/attrs/non_exhaustive.rs b/tests/rustdoc-json/attrs/non_exhaustive.rs index 5d738fc0560..b95f1a8171f 100644 --- a/tests/rustdoc-json/attrs/non_exhaustive.rs +++ b/tests/rustdoc-json/attrs/non_exhaustive.rs @@ -1,18 +1,18 @@ #![no_std] -//@ is "$.index[*][?(@.name=='MyEnum')].attrs" '["#[non_exhaustive]"]' +//@ is "$.index[?(@.name=='MyEnum')].attrs" '["#[non_exhaustive]"]' #[non_exhaustive] pub enum MyEnum { First, } pub enum NonExhaustiveVariant { - //@ is "$.index[*][?(@.name=='Variant')].attrs" '["#[non_exhaustive]"]' + //@ is "$.index[?(@.name=='Variant')].attrs" '["#[non_exhaustive]"]' #[non_exhaustive] Variant(i64), } -//@ is "$.index[*][?(@.name=='MyStruct')].attrs" '["#[non_exhaustive]"]' +//@ is "$.index[?(@.name=='MyStruct')].attrs" '["#[non_exhaustive]"]' #[non_exhaustive] pub struct MyStruct { pub x: i64, diff --git a/tests/rustdoc-json/attrs/repr_align.rs b/tests/rustdoc-json/attrs/repr_align.rs new file mode 100644 index 00000000000..c6debda7f1c --- /dev/null +++ b/tests/rustdoc-json/attrs/repr_align.rs @@ -0,0 +1,8 @@ +#![no_std] + +//@ is "$.index[?(@.name=='Aligned')].attrs" '["#[repr(align(4))]"]' +#[repr(align(4))] +pub struct Aligned { + a: i8, + b: i64, +} diff --git a/tests/rustdoc-json/attrs/repr_c.rs b/tests/rustdoc-json/attrs/repr_c.rs new file mode 100644 index 00000000000..e6219413f30 --- /dev/null +++ b/tests/rustdoc-json/attrs/repr_c.rs @@ -0,0 +1,18 @@ +#![no_std] + +//@ is "$.index[?(@.name=='ReprCStruct')].attrs" '["#[repr(C)]"]' +#[repr(C)] +pub struct ReprCStruct(pub i64); + +//@ is "$.index[?(@.name=='ReprCEnum')].attrs" '["#[repr(C)]"]' +#[repr(C)] +pub enum ReprCEnum { + First, +} + +//@ is "$.index[?(@.name=='ReprCUnion')].attrs" '["#[repr(C)]"]' +#[repr(C)] +pub union ReprCUnion { + pub left: i64, + pub right: u64, +} diff --git a/tests/rustdoc-json/attrs/repr_combination.rs b/tests/rustdoc-json/attrs/repr_combination.rs new file mode 100644 index 00000000000..0e8e2ef0d83 --- /dev/null +++ b/tests/rustdoc-json/attrs/repr_combination.rs @@ -0,0 +1,79 @@ +#![no_std] + +// Combinations of `#[repr(..)]` attributes. +// Rustdoc JSON emits normalized output, regardless of the original source. + +//@ is "$.index[?(@.name=='ReprCI8')].attrs" '["#[repr(C, i8)]"]' +#[repr(C, i8)] +pub enum ReprCI8 { + First, +} + +//@ is "$.index[?(@.name=='SeparateReprCI16')].attrs" '["#[repr(C, i16)]"]' +#[repr(C)] +#[repr(i16)] +pub enum SeparateReprCI16 { + First, +} + +//@ is "$.index[?(@.name=='ReversedReprCUsize')].attrs" '["#[repr(C, usize)]"]' +#[repr(usize, C)] +pub enum ReversedReprCUsize { + First, +} + +//@ is "$.index[?(@.name=='ReprCPacked')].attrs" '["#[repr(C, packed(1))]"]' +#[repr(C, packed)] +pub struct ReprCPacked { + a: i8, + b: i64, +} + +//@ is "$.index[?(@.name=='SeparateReprCPacked')].attrs" '["#[repr(C, packed(2))]"]' +#[repr(C)] +#[repr(packed(2))] +pub struct SeparateReprCPacked { + a: i8, + b: i64, +} + +//@ is "$.index[?(@.name=='ReversedReprCPacked')].attrs" '["#[repr(C, packed(2))]"]' +#[repr(packed(2), C)] +pub struct ReversedReprCPacked { + a: i8, + b: i64, +} + +//@ is "$.index[?(@.name=='ReprCAlign')].attrs" '["#[repr(C, align(16))]"]' +#[repr(C, align(16))] +pub struct ReprCAlign { + a: i8, + b: i64, +} + +//@ is "$.index[?(@.name=='SeparateReprCAlign')].attrs" '["#[repr(C, align(2))]"]' +#[repr(C)] +#[repr(align(2))] +pub struct SeparateReprCAlign { + a: i8, + b: i64, +} + +//@ is "$.index[?(@.name=='ReversedReprCAlign')].attrs" '["#[repr(C, align(2))]"]' +#[repr(align(2), C)] +pub struct ReversedReprCAlign { + a: i8, + b: i64, +} + +//@ is "$.index[?(@.name=='AlignedExplicitRepr')].attrs" '["#[repr(C, align(16), isize)]"]' +#[repr(C, align(16), isize)] +pub enum AlignedExplicitRepr { + First, +} + +//@ is "$.index[?(@.name=='ReorderedAlignedExplicitRepr')].attrs" '["#[repr(C, align(16), isize)]"]' +#[repr(isize, C, align(16))] +pub enum ReorderedAlignedExplicitRepr { + First, +} diff --git a/tests/rustdoc-json/attrs/repr_int_enum.rs b/tests/rustdoc-json/attrs/repr_int_enum.rs new file mode 100644 index 00000000000..9b09f341d4f --- /dev/null +++ b/tests/rustdoc-json/attrs/repr_int_enum.rs @@ -0,0 +1,19 @@ +#![no_std] + +//@ is "$.index[?(@.name=='I8')].attrs" '["#[repr(i8)]"]' +#[repr(i8)] +pub enum I8 { + First, +} + +//@ is "$.index[?(@.name=='I32')].attrs" '["#[repr(i32)]"]' +#[repr(i32)] +pub enum I32 { + First, +} + +//@ is "$.index[?(@.name=='Usize')].attrs" '["#[repr(usize)]"]' +#[repr(usize)] +pub enum Usize { + First, +} diff --git a/tests/rustdoc-json/attrs/repr_packed.rs b/tests/rustdoc-json/attrs/repr_packed.rs new file mode 100644 index 00000000000..9f3fd86c4b0 --- /dev/null +++ b/tests/rustdoc-json/attrs/repr_packed.rs @@ -0,0 +1,18 @@ +#![no_std] + +// Note the normalization: +// `#[repr(packed)]` in source becomes `#[repr(packed(1))]` in rustdoc JSON. +// +//@ is "$.index[?(@.name=='Packed')].attrs" '["#[repr(packed(1))]"]' +#[repr(packed)] +pub struct Packed { + a: i8, + b: i64, +} + +//@ is "$.index[?(@.name=='PackedAligned')].attrs" '["#[repr(packed(4))]"]' +#[repr(packed(4))] +pub struct PackedAligned { + a: i8, + b: i64, +} diff --git a/tests/rustdoc-json/attrs/repr_transparent.rs b/tests/rustdoc-json/attrs/repr_transparent.rs new file mode 100644 index 00000000000..1e634ca901d --- /dev/null +++ b/tests/rustdoc-json/attrs/repr_transparent.rs @@ -0,0 +1,37 @@ +#![no_std] + +// Rustdoc JSON *only* includes `#[repr(transparent)]` +// if the transparency is public API: +// - if a non-1-ZST field exists, it has to be public +// - otherwise, all fields are 1-ZST and at least one of them is public +// +// More info: https://doc.rust-lang.org/nomicon/other-reprs.html#reprtransparent + +// Here, the non-1-ZST field is public. +// We expect `#[repr(transparent)]` in the attributes. +// +//@ is "$.index[?(@.name=='Transparent')].attrs" '["#[repr(transparent)]"]' +#[repr(transparent)] +pub struct Transparent(pub i64); + +// Here the non-1-ZST field isn't public, so the attribute isn't included. +// +//@ has "$.index[?(@.name=='TransparentNonPub')]" +//@ is "$.index[?(@.name=='TransparentNonPub')].attrs" '[]' +#[repr(transparent)] +pub struct TransparentNonPub(i64); + +// Only 1-ZST fields here, and one of them is public. +// We expect `#[repr(transparent)]` in the attributes. +// +//@ is "$.index[?(@.name=='AllZst')].attrs" '["#[repr(transparent)]"]' +#[repr(transparent)] +pub struct AllZst<'a>(pub core::marker::PhantomData<&'a ()>, ()); + +// Only 1-ZST fields here but none of them are public. +// The attribute isn't included. +// +//@ has "$.index[?(@.name=='AllZstNotPublic')]" +//@ is "$.index[?(@.name=='AllZstNotPublic')].attrs" '[]' +#[repr(transparent)] +pub struct AllZstNotPublic<'a>(core::marker::PhantomData<&'a ()>, ()); diff --git a/tests/rustdoc-json/blanket_impls.rs b/tests/rustdoc-json/blanket_impls.rs index bf0983e66a1..d500bf5af6b 100644 --- a/tests/rustdoc-json/blanket_impls.rs +++ b/tests/rustdoc-json/blanket_impls.rs @@ -2,7 +2,7 @@ #![no_std] -//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type" -//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path" -//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path.path" \"Infallible\" +//@ has "$.index[?(@.name=='Error')].inner.assoc_type" +//@ has "$.index[?(@.name=='Error')].inner.assoc_type.type.resolved_path" +//@ has "$.index[?(@.name=='Error')].inner.assoc_type.type.resolved_path.path" \"Infallible\" pub struct ForBlanketTryFromImpl; diff --git a/tests/rustdoc-json/doc_hidden_failure.rs b/tests/rustdoc-json/doc_hidden_failure.rs index 249e35b7243..e68df7e9c61 100644 --- a/tests/rustdoc-json/doc_hidden_failure.rs +++ b/tests/rustdoc-json/doc_hidden_failure.rs @@ -11,8 +11,8 @@ mod auto { } } -//@ count "$.index[*][?(@.name=='builders')]" 1 -//@ has "$.index[*][?(@.name == 'ActionRowBuilder')"] +//@ count "$.index[?(@.name=='builders')]" 1 +//@ has "$.index[?(@.name == 'ActionRowBuilder')"] pub use auto::*; pub mod builders { diff --git a/tests/rustdoc-json/enums/discriminant/basic.rs b/tests/rustdoc-json/enums/discriminant/basic.rs index 06a240404fb..c7f164f3408 100644 --- a/tests/rustdoc-json/enums/discriminant/basic.rs +++ b/tests/rustdoc-json/enums/discriminant/basic.rs @@ -1,12 +1,12 @@ #[repr(i8)] pub enum Ordering { - //@ is "$.index[*][?(@.name=='Less')].inner.variant.discriminant.expr" '"-1"' - //@ is "$.index[*][?(@.name=='Less')].inner.variant.discriminant.value" '"-1"' + //@ is "$.index[?(@.name=='Less')].inner.variant.discriminant.expr" '"-1"' + //@ is "$.index[?(@.name=='Less')].inner.variant.discriminant.value" '"-1"' Less = -1, - //@ is "$.index[*][?(@.name=='Equal')].inner.variant.discriminant.expr" '"0"' - //@ is "$.index[*][?(@.name=='Equal')].inner.variant.discriminant.value" '"0"' + //@ is "$.index[?(@.name=='Equal')].inner.variant.discriminant.expr" '"0"' + //@ is "$.index[?(@.name=='Equal')].inner.variant.discriminant.value" '"0"' Equal = 0, - //@ is "$.index[*][?(@.name=='Greater')].inner.variant.discriminant.expr" '"1"' - //@ is "$.index[*][?(@.name=='Greater')].inner.variant.discriminant.value" '"1"' + //@ is "$.index[?(@.name=='Greater')].inner.variant.discriminant.expr" '"1"' + //@ is "$.index[?(@.name=='Greater')].inner.variant.discriminant.value" '"1"' Greater = 1, } diff --git a/tests/rustdoc-json/enums/discriminant/expr.rs b/tests/rustdoc-json/enums/discriminant/expr.rs index bf2bce85108..3743b13fec8 100644 --- a/tests/rustdoc-json/enums/discriminant/expr.rs +++ b/tests/rustdoc-json/enums/discriminant/expr.rs @@ -1,30 +1,30 @@ pub enum Foo { - //@ is "$.index[*][?(@.name=='Addition')].inner.variant.discriminant.value" '"0"' - //@ is "$.index[*][?(@.name=='Addition')].inner.variant.discriminant.expr" '"{ _ }"' + //@ is "$.index[?(@.name=='Addition')].inner.variant.discriminant.value" '"0"' + //@ is "$.index[?(@.name=='Addition')].inner.variant.discriminant.expr" '"{ _ }"' Addition = 0 + 0, - //@ is "$.index[*][?(@.name=='Bin')].inner.variant.discriminant.value" '"1"' - //@ is "$.index[*][?(@.name=='Bin')].inner.variant.discriminant.expr" '"0b1"' + //@ is "$.index[?(@.name=='Bin')].inner.variant.discriminant.value" '"1"' + //@ is "$.index[?(@.name=='Bin')].inner.variant.discriminant.expr" '"0b1"' Bin = 0b1, - //@ is "$.index[*][?(@.name=='Oct')].inner.variant.discriminant.value" '"2"' - //@ is "$.index[*][?(@.name=='Oct')].inner.variant.discriminant.expr" '"0o2"' + //@ is "$.index[?(@.name=='Oct')].inner.variant.discriminant.value" '"2"' + //@ is "$.index[?(@.name=='Oct')].inner.variant.discriminant.expr" '"0o2"' Oct = 0o2, - //@ is "$.index[*][?(@.name=='PubConst')].inner.variant.discriminant.value" '"3"' - //@ is "$.index[*][?(@.name=='PubConst')].inner.variant.discriminant.expr" '"THREE"' + //@ is "$.index[?(@.name=='PubConst')].inner.variant.discriminant.value" '"3"' + //@ is "$.index[?(@.name=='PubConst')].inner.variant.discriminant.expr" '"THREE"' PubConst = THREE, - //@ is "$.index[*][?(@.name=='Hex')].inner.variant.discriminant.value" '"4"' - //@ is "$.index[*][?(@.name=='Hex')].inner.variant.discriminant.expr" '"0x4"' + //@ is "$.index[?(@.name=='Hex')].inner.variant.discriminant.value" '"4"' + //@ is "$.index[?(@.name=='Hex')].inner.variant.discriminant.expr" '"0x4"' Hex = 0x4, - //@ is "$.index[*][?(@.name=='Cast')].inner.variant.discriminant.value" '"5"' - //@ is "$.index[*][?(@.name=='Cast')].inner.variant.discriminant.expr" '"{ _ }"' + //@ is "$.index[?(@.name=='Cast')].inner.variant.discriminant.value" '"5"' + //@ is "$.index[?(@.name=='Cast')].inner.variant.discriminant.expr" '"{ _ }"' Cast = 5 as isize, - //@ is "$.index[*][?(@.name=='PubCall')].inner.variant.discriminant.value" '"6"' - //@ is "$.index[*][?(@.name=='PubCall')].inner.variant.discriminant.expr" '"{ _ }"' + //@ is "$.index[?(@.name=='PubCall')].inner.variant.discriminant.value" '"6"' + //@ is "$.index[?(@.name=='PubCall')].inner.variant.discriminant.expr" '"{ _ }"' PubCall = six(), - //@ is "$.index[*][?(@.name=='PrivCall')].inner.variant.discriminant.value" '"7"' - //@ is "$.index[*][?(@.name=='PrivCall')].inner.variant.discriminant.expr" '"{ _ }"' + //@ is "$.index[?(@.name=='PrivCall')].inner.variant.discriminant.value" '"7"' + //@ is "$.index[?(@.name=='PrivCall')].inner.variant.discriminant.expr" '"{ _ }"' PrivCall = seven(), - //@ is "$.index[*][?(@.name=='PrivConst')].inner.variant.discriminant.value" '"8"' - //@ is "$.index[*][?(@.name=='PrivConst')].inner.variant.discriminant.expr" '"EIGHT"' + //@ is "$.index[?(@.name=='PrivConst')].inner.variant.discriminant.value" '"8"' + //@ is "$.index[?(@.name=='PrivConst')].inner.variant.discriminant.expr" '"EIGHT"' PrivConst = EIGHT, } diff --git a/tests/rustdoc-json/enums/discriminant/limits.rs b/tests/rustdoc-json/enums/discriminant/limits.rs index 7508490d666..c84181334e3 100644 --- a/tests/rustdoc-json/enums/discriminant/limits.rs +++ b/tests/rustdoc-json/enums/discriminant/limits.rs @@ -3,40 +3,40 @@ #[repr(u64)] pub enum U64 { - //@ is "$.index[*][?(@.name=='U64Min')].inner.variant.discriminant.value" '"0"' - //@ is "$.index[*][?(@.name=='U64Min')].inner.variant.discriminant.expr" '"u64::MIN"' + //@ is "$.index[?(@.name=='U64Min')].inner.variant.discriminant.value" '"0"' + //@ is "$.index[?(@.name=='U64Min')].inner.variant.discriminant.expr" '"u64::MIN"' U64Min = u64::MIN, - //@ is "$.index[*][?(@.name=='U64Max')].inner.variant.discriminant.value" '"18446744073709551615"' - //@ is "$.index[*][?(@.name=='U64Max')].inner.variant.discriminant.expr" '"u64::MAX"' + //@ is "$.index[?(@.name=='U64Max')].inner.variant.discriminant.value" '"18446744073709551615"' + //@ is "$.index[?(@.name=='U64Max')].inner.variant.discriminant.expr" '"u64::MAX"' U64Max = u64::MAX, } #[repr(i64)] pub enum I64 { - //@ is "$.index[*][?(@.name=='I64Min')].inner.variant.discriminant.value" '"-9223372036854775808"' - //@ is "$.index[*][?(@.name=='I64Min')].inner.variant.discriminant.expr" '"i64::MIN"' + //@ is "$.index[?(@.name=='I64Min')].inner.variant.discriminant.value" '"-9223372036854775808"' + //@ is "$.index[?(@.name=='I64Min')].inner.variant.discriminant.expr" '"i64::MIN"' I64Min = i64::MIN, - //@ is "$.index[*][?(@.name=='I64Max')].inner.variant.discriminant.value" '"9223372036854775807"' - //@ is "$.index[*][?(@.name=='I64Max')].inner.variant.discriminant.expr" '"i64::MAX"' + //@ is "$.index[?(@.name=='I64Max')].inner.variant.discriminant.value" '"9223372036854775807"' + //@ is "$.index[?(@.name=='I64Max')].inner.variant.discriminant.expr" '"i64::MAX"' I64Max = i64::MAX, } #[repr(u128)] pub enum U128 { - //@ is "$.index[*][?(@.name=='U128Min')].inner.variant.discriminant.value" '"0"' - //@ is "$.index[*][?(@.name=='U128Min')].inner.variant.discriminant.expr" '"u128::MIN"' + //@ is "$.index[?(@.name=='U128Min')].inner.variant.discriminant.value" '"0"' + //@ is "$.index[?(@.name=='U128Min')].inner.variant.discriminant.expr" '"u128::MIN"' U128Min = u128::MIN, - //@ is "$.index[*][?(@.name=='U128Max')].inner.variant.discriminant.value" '"340282366920938463463374607431768211455"' - //@ is "$.index[*][?(@.name=='U128Max')].inner.variant.discriminant.expr" '"u128::MAX"' + //@ is "$.index[?(@.name=='U128Max')].inner.variant.discriminant.value" '"340282366920938463463374607431768211455"' + //@ is "$.index[?(@.name=='U128Max')].inner.variant.discriminant.expr" '"u128::MAX"' U128Max = u128::MAX, } #[repr(i128)] pub enum I128 { - //@ is "$.index[*][?(@.name=='I128Min')].inner.variant.discriminant.value" '"-170141183460469231731687303715884105728"' - //@ is "$.index[*][?(@.name=='I128Min')].inner.variant.discriminant.expr" '"i128::MIN"' + //@ is "$.index[?(@.name=='I128Min')].inner.variant.discriminant.value" '"-170141183460469231731687303715884105728"' + //@ is "$.index[?(@.name=='I128Min')].inner.variant.discriminant.expr" '"i128::MIN"' I128Min = i128::MIN, - //@ is "$.index[*][?(@.name=='I128Max')].inner.variant.discriminant.value" '"170141183460469231731687303715884105727"' - //@ is "$.index[*][?(@.name=='I128Max')].inner.variant.discriminant.expr" '"i128::MAX"' + //@ is "$.index[?(@.name=='I128Max')].inner.variant.discriminant.value" '"170141183460469231731687303715884105727"' + //@ is "$.index[?(@.name=='I128Max')].inner.variant.discriminant.expr" '"i128::MAX"' I128Max = i128::MAX, } diff --git a/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs b/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs index 6f66495bed2..acf58048d3a 100644 --- a/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs +++ b/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs @@ -1,15 +1,15 @@ #[repr(u32)] pub enum Foo { - //@ is "$.index[*][?(@.name=='Basic')].inner.variant.discriminant.value" '"0"' - //@ is "$.index[*][?(@.name=='Basic')].inner.variant.discriminant.expr" '"0"' + //@ is "$.index[?(@.name=='Basic')].inner.variant.discriminant.value" '"0"' + //@ is "$.index[?(@.name=='Basic')].inner.variant.discriminant.expr" '"0"' Basic = 0, - //@ is "$.index[*][?(@.name=='Suffix')].inner.variant.discriminant.value" '"10"' - //@ is "$.index[*][?(@.name=='Suffix')].inner.variant.discriminant.expr" '"10u32"' + //@ is "$.index[?(@.name=='Suffix')].inner.variant.discriminant.value" '"10"' + //@ is "$.index[?(@.name=='Suffix')].inner.variant.discriminant.expr" '"10u32"' Suffix = 10u32, - //@ is "$.index[*][?(@.name=='Underscore')].inner.variant.discriminant.value" '"100"' - //@ is "$.index[*][?(@.name=='Underscore')].inner.variant.discriminant.expr" '"1_0_0"' + //@ is "$.index[?(@.name=='Underscore')].inner.variant.discriminant.value" '"100"' + //@ is "$.index[?(@.name=='Underscore')].inner.variant.discriminant.expr" '"1_0_0"' Underscore = 1_0_0, - //@ is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant.discriminant.value" '"1000"' - //@ is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant.discriminant.expr" '"1_0_0_0u32"' + //@ is "$.index[?(@.name=='SuffixUnderscore')].inner.variant.discriminant.value" '"1000"' + //@ is "$.index[?(@.name=='SuffixUnderscore')].inner.variant.discriminant.expr" '"1_0_0_0u32"' SuffixUnderscore = 1_0_0_0u32, } diff --git a/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs b/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs index 8e7985f07f4..d8b92cfabb3 100644 --- a/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs +++ b/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs @@ -1,10 +1,10 @@ pub enum Foo { - //@ is "$.index[*][?(@.name=='Has')].inner.variant.discriminant" '{"expr":"0", "value":"0"}' + //@ is "$.index[?(@.name=='Has')].inner.variant.discriminant" '{"expr":"0", "value":"0"}' Has = 0, - //@ is "$.index[*][?(@.name=='Doesnt')].inner.variant.discriminant" null + //@ is "$.index[?(@.name=='Doesnt')].inner.variant.discriminant" null Doesnt, - //@ is "$.index[*][?(@.name=='AlsoDoesnt')].inner.variant.discriminant" null + //@ is "$.index[?(@.name=='AlsoDoesnt')].inner.variant.discriminant" null AlsoDoesnt, - //@ is "$.index[*][?(@.name=='AlsoHas')].inner.variant.discriminant" '{"expr":"44", "value":"44"}' + //@ is "$.index[?(@.name=='AlsoHas')].inner.variant.discriminant" '{"expr":"44", "value":"44"}' AlsoHas = 44, } diff --git a/tests/rustdoc-json/enums/discriminant/struct.rs b/tests/rustdoc-json/enums/discriminant/struct.rs index f2bed77902b..ea669e6a0b3 100644 --- a/tests/rustdoc-json/enums/discriminant/struct.rs +++ b/tests/rustdoc-json/enums/discriminant/struct.rs @@ -1,13 +1,13 @@ #[repr(i32)] -//@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[attr = Repr([ReprInt(SignedInt(I32))])]\n"]' +//@ is "$.index[?(@.name=='Foo')].attrs" '["#[repr(i32)]"]' pub enum Foo { - //@ is "$.index[*][?(@.name=='Struct')].inner.variant.discriminant" null - //@ count "$.index[*][?(@.name=='Struct')].inner.variant.kind.struct.fields[*]" 0 + //@ is "$.index[?(@.name=='Struct')].inner.variant.discriminant" null + //@ count "$.index[?(@.name=='Struct')].inner.variant.kind.struct.fields[*]" 0 Struct {}, - //@ is "$.index[*][?(@.name=='StructWithDiscr')].inner.variant.discriminant" '{"expr": "42", "value": "42"}' - //@ count "$.index[*][?(@.name=='StructWithDiscr')].inner.variant.kind.struct.fields[*]" 1 + //@ is "$.index[?(@.name=='StructWithDiscr')].inner.variant.discriminant" '{"expr": "42", "value": "42"}' + //@ count "$.index[?(@.name=='StructWithDiscr')].inner.variant.kind.struct.fields[*]" 1 StructWithDiscr { x: i32 } = 42, - //@ is "$.index[*][?(@.name=='StructWithHexDiscr')].inner.variant.discriminant" '{"expr": "0x42", "value": "66"}' - //@ count "$.index[*][?(@.name=='StructWithHexDiscr')].inner.variant.kind.struct.fields[*]" 2 + //@ is "$.index[?(@.name=='StructWithHexDiscr')].inner.variant.discriminant" '{"expr": "0x42", "value": "66"}' + //@ count "$.index[?(@.name=='StructWithHexDiscr')].inner.variant.kind.struct.fields[*]" 2 StructWithHexDiscr { x: i32, y: bool } = 0x42, } diff --git a/tests/rustdoc-json/enums/discriminant/tuple.rs b/tests/rustdoc-json/enums/discriminant/tuple.rs index 201c1cdc88e..1b8e791eb23 100644 --- a/tests/rustdoc-json/enums/discriminant/tuple.rs +++ b/tests/rustdoc-json/enums/discriminant/tuple.rs @@ -1,13 +1,13 @@ #[repr(u32)] -//@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[attr = Repr([ReprInt(UnsignedInt(U32))])]\n"]' +//@ is "$.index[?(@.name=='Foo')].attrs" '["#[repr(u32)]"]' pub enum Foo { - //@ is "$.index[*][?(@.name=='Tuple')].inner.variant.discriminant" null - //@ count "$.index[*][?(@.name=='Tuple')].inner.variant.kind.tuple[*]" 0 + //@ is "$.index[?(@.name=='Tuple')].inner.variant.discriminant" null + //@ count "$.index[?(@.name=='Tuple')].inner.variant.kind.tuple[*]" 0 Tuple(), - //@ is "$.index[*][?(@.name=='TupleWithDiscr')].inner.variant.discriminant" '{"expr": "1", "value": "1"}' - //@ count "$.index[*][?(@.name=='TupleWithDiscr')].inner.variant.kind.tuple[*]" 1 + //@ is "$.index[?(@.name=='TupleWithDiscr')].inner.variant.discriminant" '{"expr": "1", "value": "1"}' + //@ count "$.index[?(@.name=='TupleWithDiscr')].inner.variant.kind.tuple[*]" 1 TupleWithDiscr(i32) = 1, - //@ is "$.index[*][?(@.name=='TupleWithBinDiscr')].inner.variant.discriminant" '{"expr": "0b10", "value": "2"}' - //@ count "$.index[*][?(@.name=='TupleWithBinDiscr')].inner.variant.kind.tuple[*]" 2 + //@ is "$.index[?(@.name=='TupleWithBinDiscr')].inner.variant.discriminant" '{"expr": "0b10", "value": "2"}' + //@ count "$.index[?(@.name=='TupleWithBinDiscr')].inner.variant.kind.tuple[*]" 2 TupleWithBinDiscr(i32, i32) = 0b10, } diff --git a/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs b/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs index 6aec6960b5f..6ecd98fadf5 100644 --- a/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs +++ b/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs @@ -5,7 +5,7 @@ extern crate color; use color::Color::Red; -//@ set red = "$.index[*][?(@.inner.module.is_crate)].links.Red" +//@ set red = "$.index[?(@.inner.module.is_crate)].links.Red" -//@ !has "$.index[*][?(@.name == 'Red')]" -//@ !has "$.index[*][?(@.name == 'Color')]" +//@ !has "$.index[?(@.name == 'Red')]" +//@ !has "$.index[?(@.name == 'Color')]" diff --git a/tests/rustdoc-json/enums/field_hidden.rs b/tests/rustdoc-json/enums/field_hidden.rs index b353678ac92..07ee0e62ea9 100644 --- a/tests/rustdoc-json/enums/field_hidden.rs +++ b/tests/rustdoc-json/enums/field_hidden.rs @@ -1,9 +1,9 @@ // Regression test for <https://github.com/rust-lang/rust/issues/100529>. -//@ has "$.index[*][?(@.name=='ParseError')]" -//@ has "$.index[*][?(@.name=='UnexpectedEndTag')]" -//@ is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant.kind.tuple" [null] -//@ is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant.discriminant" null +//@ has "$.index[?(@.name=='ParseError')]" +//@ has "$.index[?(@.name=='UnexpectedEndTag')]" +//@ is "$.index[?(@.name=='UnexpectedEndTag')].inner.variant.kind.tuple" [null] +//@ is "$.index[?(@.name=='UnexpectedEndTag')].inner.variant.discriminant" null pub enum ParseError { UnexpectedEndTag(#[doc(hidden)] u32), diff --git a/tests/rustdoc-json/enums/field_order.rs b/tests/rustdoc-json/enums/field_order.rs index a78be200b41..e8560687954 100644 --- a/tests/rustdoc-json/enums/field_order.rs +++ b/tests/rustdoc-json/enums/field_order.rs @@ -17,24 +17,24 @@ pub enum Whatever { }, } -//@ set 0 = '$.index[*][?(@.name == "ews_0")].id' -//@ set 1 = '$.index[*][?(@.name == "dik_1")].id' -//@ set 2 = '$.index[*][?(@.name == "hsk_2")].id' -//@ set 3 = '$.index[*][?(@.name == "djt_3")].id' -//@ set 4 = '$.index[*][?(@.name == "jnr_4")].id' -//@ set 5 = '$.index[*][?(@.name == "dfs_5")].id' -//@ set 6 = '$.index[*][?(@.name == "bja_6")].id' -//@ set 7 = '$.index[*][?(@.name == "lyc_7")].id' -//@ set 8 = '$.index[*][?(@.name == "yqd_8")].id' -//@ set 9 = '$.index[*][?(@.name == "vll_9")].id' +//@ set 0 = '$.index[?(@.name == "ews_0")].id' +//@ set 1 = '$.index[?(@.name == "dik_1")].id' +//@ set 2 = '$.index[?(@.name == "hsk_2")].id' +//@ set 3 = '$.index[?(@.name == "djt_3")].id' +//@ set 4 = '$.index[?(@.name == "jnr_4")].id' +//@ set 5 = '$.index[?(@.name == "dfs_5")].id' +//@ set 6 = '$.index[?(@.name == "bja_6")].id' +//@ set 7 = '$.index[?(@.name == "lyc_7")].id' +//@ set 8 = '$.index[?(@.name == "yqd_8")].id' +//@ set 9 = '$.index[?(@.name == "vll_9")].id' -//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[0]' $0 -//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[1]' $1 -//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[2]' $2 -//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[3]' $3 -//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[4]' $4 -//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[5]' $5 -//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[6]' $6 -//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[7]' $7 -//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[8]' $8 -//@ is '$.index[*][?(@.name == "Foo")].inner.variant.kind.struct.fields[9]' $9 +//@ is '$.index[?(@.name == "Foo")].inner.variant.kind.struct.fields[0]' $0 +//@ is '$.index[?(@.name == "Foo")].inner.variant.kind.struct.fields[1]' $1 +//@ is '$.index[?(@.name == "Foo")].inner.variant.kind.struct.fields[2]' $2 +//@ is '$.index[?(@.name == "Foo")].inner.variant.kind.struct.fields[3]' $3 +//@ is '$.index[?(@.name == "Foo")].inner.variant.kind.struct.fields[4]' $4 +//@ is '$.index[?(@.name == "Foo")].inner.variant.kind.struct.fields[5]' $5 +//@ is '$.index[?(@.name == "Foo")].inner.variant.kind.struct.fields[6]' $6 +//@ is '$.index[?(@.name == "Foo")].inner.variant.kind.struct.fields[7]' $7 +//@ is '$.index[?(@.name == "Foo")].inner.variant.kind.struct.fields[8]' $8 +//@ is '$.index[?(@.name == "Foo")].inner.variant.kind.struct.fields[9]' $9 diff --git a/tests/rustdoc-json/enums/kind.rs b/tests/rustdoc-json/enums/kind.rs index 517a53828b7..3c011858630 100644 --- a/tests/rustdoc-json/enums/kind.rs +++ b/tests/rustdoc-json/enums/kind.rs @@ -1,27 +1,27 @@ pub enum Foo { - //@ set Unit = "$.index[*][?(@.name=='Unit')].id" - //@ is "$.index[*][?(@.name=='Unit')].inner.variant.kind" '"plain"' + //@ set Unit = "$.index[?(@.name=='Unit')].id" + //@ is "$.index[?(@.name=='Unit')].inner.variant.kind" '"plain"' Unit, - //@ set Named = "$.index[*][?(@.name=='Named')].id" - //@ is "$.index[*][?(@.name=='Named')].inner.variant.kind.struct" '{"fields": [], "has_stripped_fields": false}' + //@ set Named = "$.index[?(@.name=='Named')].id" + //@ is "$.index[?(@.name=='Named')].inner.variant.kind.struct" '{"fields": [], "has_stripped_fields": false}' Named {}, - //@ set Tuple = "$.index[*][?(@.name=='Tuple')].id" - //@ is "$.index[*][?(@.name=='Tuple')].inner.variant.kind.tuple" [] + //@ set Tuple = "$.index[?(@.name=='Tuple')].id" + //@ is "$.index[?(@.name=='Tuple')].inner.variant.kind.tuple" [] Tuple(), - //@ set NamedField = "$.index[*][?(@.name=='NamedField')].id" - //@ set x = "$.index[*][?(@.name=='x' && @.inner.struct_field)].id" - //@ is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.fields[*]" $x - //@ is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.has_stripped_fields" false + //@ set NamedField = "$.index[?(@.name=='NamedField')].id" + //@ set x = "$.index[?(@.name=='x' && @.inner.struct_field)].id" + //@ is "$.index[?(@.name=='NamedField')].inner.variant.kind.struct.fields[*]" $x + //@ is "$.index[?(@.name=='NamedField')].inner.variant.kind.struct.has_stripped_fields" false NamedField { x: i32 }, - //@ set TupleField = "$.index[*][?(@.name=='TupleField')].id" - //@ set tup_field = "$.index[*][?(@.name=='0' && @.inner.struct_field)].id" - //@ is "$.index[*][?(@.name=='TupleField')].inner.variant.kind.tuple[*]" $tup_field + //@ set TupleField = "$.index[?(@.name=='TupleField')].id" + //@ set tup_field = "$.index[?(@.name=='0' && @.inner.struct_field)].id" + //@ is "$.index[?(@.name=='TupleField')].inner.variant.kind.tuple[*]" $tup_field TupleField(i32), } -//@ is "$.index[*][?(@.name=='Foo')].inner.enum.variants[0]" $Unit -//@ is "$.index[*][?(@.name=='Foo')].inner.enum.variants[1]" $Named -//@ is "$.index[*][?(@.name=='Foo')].inner.enum.variants[2]" $Tuple -//@ is "$.index[*][?(@.name=='Foo')].inner.enum.variants[3]" $NamedField -//@ is "$.index[*][?(@.name=='Foo')].inner.enum.variants[4]" $TupleField -//@ count "$.index[*][?(@.name=='Foo')].inner.enum.variants[*]" 5 +//@ is "$.index[?(@.name=='Foo')].inner.enum.variants[0]" $Unit +//@ is "$.index[?(@.name=='Foo')].inner.enum.variants[1]" $Named +//@ is "$.index[?(@.name=='Foo')].inner.enum.variants[2]" $Tuple +//@ is "$.index[?(@.name=='Foo')].inner.enum.variants[3]" $NamedField +//@ is "$.index[?(@.name=='Foo')].inner.enum.variants[4]" $TupleField +//@ count "$.index[?(@.name=='Foo')].inner.enum.variants[*]" 5 diff --git a/tests/rustdoc-json/enums/struct_field_hidden.rs b/tests/rustdoc-json/enums/struct_field_hidden.rs index 2184f58b1da..cd9d2ce0b8a 100644 --- a/tests/rustdoc-json/enums/struct_field_hidden.rs +++ b/tests/rustdoc-json/enums/struct_field_hidden.rs @@ -2,15 +2,15 @@ pub enum Foo { Variant { #[doc(hidden)] a: i32, - //@ set b = "$.index[*][?(@.name=='b')].id" + //@ set b = "$.index[?(@.name=='b')].id" b: i32, #[doc(hidden)] x: i32, - //@ set y = "$.index[*][?(@.name=='y')].id" + //@ set y = "$.index[?(@.name=='y')].id" y: i32, }, - //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.has_stripped_fields" true - //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[0]" $b - //@ is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[1]" $y - //@ count "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[*]" 2 + //@ is "$.index[?(@.name=='Variant')].inner.variant.kind.struct.has_stripped_fields" true + //@ is "$.index[?(@.name=='Variant')].inner.variant.kind.struct.fields[0]" $b + //@ is "$.index[?(@.name=='Variant')].inner.variant.kind.struct.fields[1]" $y + //@ count "$.index[?(@.name=='Variant')].inner.variant.kind.struct.fields[*]" 2 } diff --git a/tests/rustdoc-json/enums/tuple_fields_hidden.rs b/tests/rustdoc-json/enums/tuple_fields_hidden.rs index 3ac7a3ce0fc..aa25625b94c 100644 --- a/tests/rustdoc-json/enums/tuple_fields_hidden.rs +++ b/tests/rustdoc-json/enums/tuple_fields_hidden.rs @@ -1,80 +1,80 @@ -//@ set 1.1.0 = "$.index[*][?(@.docs=='1.1.0')].id" -//@ set 2.1.0 = "$.index[*][?(@.docs=='2.1.0')].id" -//@ set 2.1.1 = "$.index[*][?(@.docs=='2.1.1')].id" -//@ set 2.2.1 = "$.index[*][?(@.docs=='2.2.1')].id" -//@ set 2.3.0 = "$.index[*][?(@.docs=='2.3.0')].id" -//@ set 3.1.1 = "$.index[*][?(@.docs=='3.1.1')].id" -//@ set 3.1.2 = "$.index[*][?(@.docs=='3.1.2')].id" -//@ set 3.2.0 = "$.index[*][?(@.docs=='3.2.0')].id" -//@ set 3.2.2 = "$.index[*][?(@.docs=='3.2.2')].id" -//@ set 3.3.0 = "$.index[*][?(@.docs=='3.3.0')].id" -//@ set 3.3.1 = "$.index[*][?(@.docs=='3.3.1')].id" +//@ set 1.1.0 = "$.index[?(@.docs=='1.1.0')].id" +//@ set 2.1.0 = "$.index[?(@.docs=='2.1.0')].id" +//@ set 2.1.1 = "$.index[?(@.docs=='2.1.1')].id" +//@ set 2.2.1 = "$.index[?(@.docs=='2.2.1')].id" +//@ set 2.3.0 = "$.index[?(@.docs=='2.3.0')].id" +//@ set 3.1.1 = "$.index[?(@.docs=='3.1.1')].id" +//@ set 3.1.2 = "$.index[?(@.docs=='3.1.2')].id" +//@ set 3.2.0 = "$.index[?(@.docs=='3.2.0')].id" +//@ set 3.2.2 = "$.index[?(@.docs=='3.2.2')].id" +//@ set 3.3.0 = "$.index[?(@.docs=='3.3.0')].id" +//@ set 3.3.1 = "$.index[?(@.docs=='3.3.1')].id" pub enum EnumWithStrippedTupleVariants { - //@ count "$.index[*][?(@.name=='None')].inner.variant.kind.tuple[*]" 0 + //@ count "$.index[?(@.name=='None')].inner.variant.kind.tuple[*]" 0 None(), - //@ count "$.index[*][?(@.name=='One')].inner.variant.kind.tuple[*]" 1 - //@ is "$.index[*][?(@.name=='One')].inner.variant.kind.tuple[0]" $1.1.0 + //@ count "$.index[?(@.name=='One')].inner.variant.kind.tuple[*]" 1 + //@ is "$.index[?(@.name=='One')].inner.variant.kind.tuple[0]" $1.1.0 One(/** 1.1.0*/ bool), - //@ count "$.index[*][?(@.name=='OneHidden')].inner.variant.kind.tuple[*]" 1 - //@ is "$.index[*][?(@.name=='OneHidden')].inner.variant.kind.tuple[0]" null + //@ count "$.index[?(@.name=='OneHidden')].inner.variant.kind.tuple[*]" 1 + //@ is "$.index[?(@.name=='OneHidden')].inner.variant.kind.tuple[0]" null OneHidden(#[doc(hidden)] bool), - //@ count "$.index[*][?(@.name=='Two')].inner.variant.kind.tuple[*]" 2 - //@ is "$.index[*][?(@.name=='Two')].inner.variant.kind.tuple[0]" $2.1.0 - //@ is "$.index[*][?(@.name=='Two')].inner.variant.kind.tuple[1]" $2.1.1 + //@ count "$.index[?(@.name=='Two')].inner.variant.kind.tuple[*]" 2 + //@ is "$.index[?(@.name=='Two')].inner.variant.kind.tuple[0]" $2.1.0 + //@ is "$.index[?(@.name=='Two')].inner.variant.kind.tuple[1]" $2.1.1 Two(/** 2.1.0*/ bool, /** 2.1.1*/ bool), - //@ count "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant.kind.tuple[*]" 2 - //@ is "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant.kind.tuple[0]" null - //@ is "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant.kind.tuple[1]" $2.2.1 + //@ count "$.index[?(@.name=='TwoLeftHidden')].inner.variant.kind.tuple[*]" 2 + //@ is "$.index[?(@.name=='TwoLeftHidden')].inner.variant.kind.tuple[0]" null + //@ is "$.index[?(@.name=='TwoLeftHidden')].inner.variant.kind.tuple[1]" $2.2.1 TwoLeftHidden(#[doc(hidden)] bool, /** 2.2.1*/ bool), - //@ count "$.index[*][?(@.name=='TwoRightHidden')].inner.variant.kind.tuple[*]" 2 - //@ is "$.index[*][?(@.name=='TwoRightHidden')].inner.variant.kind.tuple[0]" $2.3.0 - //@ is "$.index[*][?(@.name=='TwoRightHidden')].inner.variant.kind.tuple[1]" null + //@ count "$.index[?(@.name=='TwoRightHidden')].inner.variant.kind.tuple[*]" 2 + //@ is "$.index[?(@.name=='TwoRightHidden')].inner.variant.kind.tuple[0]" $2.3.0 + //@ is "$.index[?(@.name=='TwoRightHidden')].inner.variant.kind.tuple[1]" null TwoRightHidden(/** 2.3.0*/ bool, #[doc(hidden)] bool), - //@ count "$.index[*][?(@.name=='TwoBothHidden')].inner.variant.kind.tuple[*]" 2 - //@ is "$.index[*][?(@.name=='TwoBothHidden')].inner.variant.kind.tuple[0]" null - //@ is "$.index[*][?(@.name=='TwoBothHidden')].inner.variant.kind.tuple[1]" null + //@ count "$.index[?(@.name=='TwoBothHidden')].inner.variant.kind.tuple[*]" 2 + //@ is "$.index[?(@.name=='TwoBothHidden')].inner.variant.kind.tuple[0]" null + //@ is "$.index[?(@.name=='TwoBothHidden')].inner.variant.kind.tuple[1]" null TwoBothHidden(#[doc(hidden)] bool, #[doc(hidden)] bool), - //@ count "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[*]" 3 - //@ is "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[0]" null - //@ is "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[1]" $3.1.1 - //@ is "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[2]" $3.1.2 + //@ count "$.index[?(@.name=='Three1')].inner.variant.kind.tuple[*]" 3 + //@ is "$.index[?(@.name=='Three1')].inner.variant.kind.tuple[0]" null + //@ is "$.index[?(@.name=='Three1')].inner.variant.kind.tuple[1]" $3.1.1 + //@ is "$.index[?(@.name=='Three1')].inner.variant.kind.tuple[2]" $3.1.2 Three1(#[doc(hidden)] bool, /** 3.1.1*/ bool, /** 3.1.2*/ bool), - //@ count "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[*]" 3 - //@ is "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[0]" $3.2.0 - //@ is "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[1]" null - //@ is "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[2]" $3.2.2 + //@ count "$.index[?(@.name=='Three2')].inner.variant.kind.tuple[*]" 3 + //@ is "$.index[?(@.name=='Three2')].inner.variant.kind.tuple[0]" $3.2.0 + //@ is "$.index[?(@.name=='Three2')].inner.variant.kind.tuple[1]" null + //@ is "$.index[?(@.name=='Three2')].inner.variant.kind.tuple[2]" $3.2.2 Three2(/** 3.2.0*/ bool, #[doc(hidden)] bool, /** 3.2.2*/ bool), - //@ count "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[*]" 3 - //@ is "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[0]" $3.3.0 - //@ is "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[1]" $3.3.1 - //@ is "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[2]" null + //@ count "$.index[?(@.name=='Three3')].inner.variant.kind.tuple[*]" 3 + //@ is "$.index[?(@.name=='Three3')].inner.variant.kind.tuple[0]" $3.3.0 + //@ is "$.index[?(@.name=='Three3')].inner.variant.kind.tuple[1]" $3.3.1 + //@ is "$.index[?(@.name=='Three3')].inner.variant.kind.tuple[2]" null Three3(/** 3.3.0*/ bool, /** 3.3.1*/ bool, #[doc(hidden)] bool), } -//@ is "$.index[*][?(@.docs=='1.1.0')].name" '"0"' -//@ is "$.index[*][?(@.docs=='2.1.0')].name" '"0"' -//@ is "$.index[*][?(@.docs=='2.1.1')].name" '"1"' -//@ is "$.index[*][?(@.docs=='2.2.1')].name" '"1"' -//@ is "$.index[*][?(@.docs=='2.3.0')].name" '"0"' -//@ is "$.index[*][?(@.docs=='3.1.1')].name" '"1"' -//@ is "$.index[*][?(@.docs=='3.1.2')].name" '"2"' -//@ is "$.index[*][?(@.docs=='3.2.0')].name" '"0"' -//@ is "$.index[*][?(@.docs=='3.2.2')].name" '"2"' -//@ is "$.index[*][?(@.docs=='3.3.0')].name" '"0"' -//@ is "$.index[*][?(@.docs=='3.3.1')].name" '"1"' +//@ is "$.index[?(@.docs=='1.1.0')].name" '"0"' +//@ is "$.index[?(@.docs=='2.1.0')].name" '"0"' +//@ is "$.index[?(@.docs=='2.1.1')].name" '"1"' +//@ is "$.index[?(@.docs=='2.2.1')].name" '"1"' +//@ is "$.index[?(@.docs=='2.3.0')].name" '"0"' +//@ is "$.index[?(@.docs=='3.1.1')].name" '"1"' +//@ is "$.index[?(@.docs=='3.1.2')].name" '"2"' +//@ is "$.index[?(@.docs=='3.2.0')].name" '"0"' +//@ is "$.index[?(@.docs=='3.2.2')].name" '"2"' +//@ is "$.index[?(@.docs=='3.3.0')].name" '"0"' +//@ is "$.index[?(@.docs=='3.3.1')].name" '"1"' -//@ is "$.index[*][?(@.docs=='1.1.0')].inner.struct_field" '{"primitive": "bool"}' -//@ is "$.index[*][?(@.docs=='2.1.0')].inner.struct_field" '{"primitive": "bool"}' -//@ is "$.index[*][?(@.docs=='2.1.1')].inner.struct_field" '{"primitive": "bool"}' -//@ is "$.index[*][?(@.docs=='2.2.1')].inner.struct_field" '{"primitive": "bool"}' -//@ is "$.index[*][?(@.docs=='2.3.0')].inner.struct_field" '{"primitive": "bool"}' -//@ is "$.index[*][?(@.docs=='3.1.1')].inner.struct_field" '{"primitive": "bool"}' -//@ is "$.index[*][?(@.docs=='3.1.2')].inner.struct_field" '{"primitive": "bool"}' -//@ is "$.index[*][?(@.docs=='3.2.0')].inner.struct_field" '{"primitive": "bool"}' -//@ is "$.index[*][?(@.docs=='3.2.2')].inner.struct_field" '{"primitive": "bool"}' -//@ is "$.index[*][?(@.docs=='3.3.0')].inner.struct_field" '{"primitive": "bool"}' -//@ is "$.index[*][?(@.docs=='3.3.1')].inner.struct_field" '{"primitive": "bool"}' +//@ is "$.index[?(@.docs=='1.1.0')].inner.struct_field" '{"primitive": "bool"}' +//@ is "$.index[?(@.docs=='2.1.0')].inner.struct_field" '{"primitive": "bool"}' +//@ is "$.index[?(@.docs=='2.1.1')].inner.struct_field" '{"primitive": "bool"}' +//@ is "$.index[?(@.docs=='2.2.1')].inner.struct_field" '{"primitive": "bool"}' +//@ is "$.index[?(@.docs=='2.3.0')].inner.struct_field" '{"primitive": "bool"}' +//@ is "$.index[?(@.docs=='3.1.1')].inner.struct_field" '{"primitive": "bool"}' +//@ is "$.index[?(@.docs=='3.1.2')].inner.struct_field" '{"primitive": "bool"}' +//@ is "$.index[?(@.docs=='3.2.0')].inner.struct_field" '{"primitive": "bool"}' +//@ is "$.index[?(@.docs=='3.2.2')].inner.struct_field" '{"primitive": "bool"}' +//@ is "$.index[?(@.docs=='3.3.0')].inner.struct_field" '{"primitive": "bool"}' +//@ is "$.index[?(@.docs=='3.3.1')].inner.struct_field" '{"primitive": "bool"}' diff --git a/tests/rustdoc-json/enums/use_glob.rs b/tests/rustdoc-json/enums/use_glob.rs index 2631b43da8e..18f21ff0903 100644 --- a/tests/rustdoc-json/enums/use_glob.rs +++ b/tests/rustdoc-json/enums/use_glob.rs @@ -1,15 +1,15 @@ // Regression test for <https://github.com/rust-lang/rust/issues/104942> -//@ set Color = "$.index[*][?(@.name == 'Color')].id" +//@ set Color = "$.index[?(@.name == 'Color')].id" pub enum Color { Red, Green, Blue, } -//@ set use_Color = "$.index[*][?(@.inner.use)].id" -//@ is "$.index[*][?(@.inner.use)].inner.use.id" $Color -//@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" true +//@ set use_Color = "$.index[?(@.inner.use)].id" +//@ is "$.index[?(@.inner.use)].inner.use.id" $Color +//@ is "$.index[?(@.inner.use)].inner.use.is_glob" true pub use Color::*; -//@ ismany "$.index[*][?(@.name == 'use_glob')].inner.module.items[*]" $Color $use_Color +//@ ismany "$.index[?(@.name == 'use_glob')].inner.module.items[*]" $Color $use_Color diff --git a/tests/rustdoc-json/enums/use_variant.rs b/tests/rustdoc-json/enums/use_variant.rs index 6d3322e0ba9..26cca0743d9 100644 --- a/tests/rustdoc-json/enums/use_variant.rs +++ b/tests/rustdoc-json/enums/use_variant.rs @@ -1,12 +1,12 @@ -//@ set AlwaysNone = "$.index[*][?(@.name == 'AlwaysNone')].id" +//@ set AlwaysNone = "$.index[?(@.name == 'AlwaysNone')].id" pub enum AlwaysNone { - //@ set None = "$.index[*][?(@.name == 'None')].id" + //@ set None = "$.index[?(@.name == 'None')].id" None, } -//@ is "$.index[*][?(@.name == 'AlwaysNone')].inner.enum.variants[*]" $None +//@ is "$.index[?(@.name == 'AlwaysNone')].inner.enum.variants[*]" $None -//@ set use_None = "$.index[*][?(@.inner.use)].id" -//@ is "$.index[*][?(@.inner.use)].inner.use.id" $None +//@ set use_None = "$.index[?(@.inner.use)].id" +//@ is "$.index[?(@.inner.use)].inner.use.id" $None pub use AlwaysNone::None; -//@ ismany "$.index[*][?(@.name == 'use_variant')].inner.module.items[*]" $AlwaysNone $use_None +//@ ismany "$.index[?(@.name == 'use_variant')].inner.module.items[*]" $AlwaysNone $use_None diff --git a/tests/rustdoc-json/enums/use_variant_foreign.rs b/tests/rustdoc-json/enums/use_variant_foreign.rs index a9ad61b9fe3..14e07b4123e 100644 --- a/tests/rustdoc-json/enums/use_variant_foreign.rs +++ b/tests/rustdoc-json/enums/use_variant_foreign.rs @@ -2,8 +2,8 @@ extern crate color; -//@ has "$.index[*].inner.use[?(@.name == 'Red')]" +//@ has "$.index[?(@.inner.use.name == 'Red')]" pub use color::Color::Red; -//@ !has "$.index[*][?(@.name == 'Red')]" -//@ !has "$.index[*][?(@.name == 'Color')]" +//@ !has "$.index[?(@.name == 'Red')]" +//@ !has "$.index[?(@.name == 'Color')]" diff --git a/tests/rustdoc-json/enums/variant_order.rs b/tests/rustdoc-json/enums/variant_order.rs index 6ebe28c94ca..dd11c0963ee 100644 --- a/tests/rustdoc-json/enums/variant_order.rs +++ b/tests/rustdoc-json/enums/variant_order.rs @@ -15,24 +15,24 @@ pub enum Foo { Vll9, } -//@ set 0 = '$.index[*][?(@.name == "Ews0")].id' -//@ set 1 = '$.index[*][?(@.name == "Dik1")].id' -//@ set 2 = '$.index[*][?(@.name == "Hsk2")].id' -//@ set 3 = '$.index[*][?(@.name == "Djt3")].id' -//@ set 4 = '$.index[*][?(@.name == "Jnr4")].id' -//@ set 5 = '$.index[*][?(@.name == "Dfs5")].id' -//@ set 6 = '$.index[*][?(@.name == "Bja6")].id' -//@ set 7 = '$.index[*][?(@.name == "Lyc7")].id' -//@ set 8 = '$.index[*][?(@.name == "Yqd8")].id' -//@ set 9 = '$.index[*][?(@.name == "Vll9")].id' +//@ set 0 = '$.index[?(@.name == "Ews0")].id' +//@ set 1 = '$.index[?(@.name == "Dik1")].id' +//@ set 2 = '$.index[?(@.name == "Hsk2")].id' +//@ set 3 = '$.index[?(@.name == "Djt3")].id' +//@ set 4 = '$.index[?(@.name == "Jnr4")].id' +//@ set 5 = '$.index[?(@.name == "Dfs5")].id' +//@ set 6 = '$.index[?(@.name == "Bja6")].id' +//@ set 7 = '$.index[?(@.name == "Lyc7")].id' +//@ set 8 = '$.index[?(@.name == "Yqd8")].id' +//@ set 9 = '$.index[?(@.name == "Vll9")].id' -//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[0]' $0 -//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[1]' $1 -//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[2]' $2 -//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[3]' $3 -//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[4]' $4 -//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[5]' $5 -//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[6]' $6 -//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[7]' $7 -//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[8]' $8 -//@ is '$.index[*][?(@.name == "Foo")].inner.enum.variants[9]' $9 +//@ is '$.index[?(@.name == "Foo")].inner.enum.variants[0]' $0 +//@ is '$.index[?(@.name == "Foo")].inner.enum.variants[1]' $1 +//@ is '$.index[?(@.name == "Foo")].inner.enum.variants[2]' $2 +//@ is '$.index[?(@.name == "Foo")].inner.enum.variants[3]' $3 +//@ is '$.index[?(@.name == "Foo")].inner.enum.variants[4]' $4 +//@ is '$.index[?(@.name == "Foo")].inner.enum.variants[5]' $5 +//@ is '$.index[?(@.name == "Foo")].inner.enum.variants[6]' $6 +//@ is '$.index[?(@.name == "Foo")].inner.enum.variants[7]' $7 +//@ is '$.index[?(@.name == "Foo")].inner.enum.variants[8]' $8 +//@ is '$.index[?(@.name == "Foo")].inner.enum.variants[9]' $9 diff --git a/tests/rustdoc-json/enums/variant_struct.rs b/tests/rustdoc-json/enums/variant_struct.rs index 44a0c946711..730689c8afa 100644 --- a/tests/rustdoc-json/enums/variant_struct.rs +++ b/tests/rustdoc-json/enums/variant_struct.rs @@ -1,10 +1,10 @@ -//@ is "$.index[*][?(@.name=='EnumStruct')].visibility" \"public\" -//@ has "$.index[*][?(@.name=='EnumStruct')].inner.enum" +//@ is "$.index[?(@.name=='EnumStruct')].visibility" \"public\" +//@ has "$.index[?(@.name=='EnumStruct')].inner.enum" pub enum EnumStruct { - //@ has "$.index[*][?(@.name=='x')].inner.struct_field" - //@ set x = "$.index[*][?(@.name=='x')].id" - //@ has "$.index[*][?(@.name=='y')].inner.struct_field" - //@ set y = "$.index[*][?(@.name=='y')].id" - //@ ismany "$.index[*][?(@.name=='VariantS')].inner.variant.kind.struct.fields[*]" $x $y + //@ has "$.index[?(@.name=='x')].inner.struct_field" + //@ set x = "$.index[?(@.name=='x')].id" + //@ has "$.index[?(@.name=='y')].inner.struct_field" + //@ set y = "$.index[?(@.name=='y')].id" + //@ ismany "$.index[?(@.name=='VariantS')].inner.variant.kind.struct.fields[*]" $x $y VariantS { x: u32, y: String }, } diff --git a/tests/rustdoc-json/enums/variant_tuple_struct.rs b/tests/rustdoc-json/enums/variant_tuple_struct.rs index 04f0cbb40c4..0fc06920e4b 100644 --- a/tests/rustdoc-json/enums/variant_tuple_struct.rs +++ b/tests/rustdoc-json/enums/variant_tuple_struct.rs @@ -1,10 +1,10 @@ -//@ is "$.index[*][?(@.name=='EnumTupleStruct')].visibility" \"public\" -//@ has "$.index[*][?(@.name=='EnumTupleStruct')].inner.enum" +//@ is "$.index[?(@.name=='EnumTupleStruct')].visibility" \"public\" +//@ has "$.index[?(@.name=='EnumTupleStruct')].inner.enum" pub enum EnumTupleStruct { - //@ has "$.index[*][?(@.name=='0')].inner.struct_field" - //@ set f0 = "$.index[*][?(@.name=='0')].id" - //@ has "$.index[*][?(@.name=='1')].inner.struct_field" - //@ set f1 = "$.index[*][?(@.name=='1')].id" - //@ ismany "$.index[*][?(@.name=='VariantA')].inner.variant.kind.tuple[*]" $f0 $f1 + //@ has "$.index[?(@.name=='0')].inner.struct_field" + //@ set f0 = "$.index[?(@.name=='0')].id" + //@ has "$.index[?(@.name=='1')].inner.struct_field" + //@ set f1 = "$.index[?(@.name=='1')].id" + //@ ismany "$.index[?(@.name=='VariantA')].inner.variant.kind.tuple[*]" $f0 $f1 VariantA(u32, String), } diff --git a/tests/rustdoc-json/fn_pointer/abi.rs b/tests/rustdoc-json/fn_pointer/abi.rs index 13a967bd35e..34150c0fe89 100644 --- a/tests/rustdoc-json/fn_pointer/abi.rs +++ b/tests/rustdoc-json/fn_pointer/abi.rs @@ -1,22 +1,22 @@ #![feature(abi_vectorcall)] -//@ is "$.index[*][?(@.name=='AbiRust')].inner.type_alias.type.function_pointer.header.abi" \"Rust\" +//@ is "$.index[?(@.name=='AbiRust')].inner.type_alias.type.function_pointer.header.abi" \"Rust\" pub type AbiRust = fn(); -//@ is "$.index[*][?(@.name=='AbiC')].inner.type_alias.type.function_pointer.header.abi" '{"C": {"unwind": false}}' +//@ is "$.index[?(@.name=='AbiC')].inner.type_alias.type.function_pointer.header.abi" '{"C": {"unwind": false}}' pub type AbiC = extern "C" fn(); -//@ is "$.index[*][?(@.name=='AbiSystem')].inner.type_alias.type.function_pointer.header.abi" '{"System": {"unwind": false}}' +//@ is "$.index[?(@.name=='AbiSystem')].inner.type_alias.type.function_pointer.header.abi" '{"System": {"unwind": false}}' pub type AbiSystem = extern "system" fn(); -//@ is "$.index[*][?(@.name=='AbiCUnwind')].inner.type_alias.type.function_pointer.header.abi" '{"C": {"unwind": true}}' +//@ is "$.index[?(@.name=='AbiCUnwind')].inner.type_alias.type.function_pointer.header.abi" '{"C": {"unwind": true}}' pub type AbiCUnwind = extern "C-unwind" fn(); -//@ is "$.index[*][?(@.name=='AbiSystemUnwind')].inner.type_alias.type.function_pointer.header.abi" '{"System": {"unwind": true}}' +//@ is "$.index[?(@.name=='AbiSystemUnwind')].inner.type_alias.type.function_pointer.header.abi" '{"System": {"unwind": true}}' pub type AbiSystemUnwind = extern "system-unwind" fn(); -//@ is "$.index[*][?(@.name=='AbiVecorcall')].inner.type_alias.type.function_pointer.header.abi.Other" '"\"vectorcall\""' +//@ is "$.index[?(@.name=='AbiVecorcall')].inner.type_alias.type.function_pointer.header.abi.Other" '"\"vectorcall\""' pub type AbiVecorcall = extern "vectorcall" fn(); -//@ is "$.index[*][?(@.name=='AbiVecorcallUnwind')].inner.type_alias.type.function_pointer.header.abi.Other" '"\"vectorcall-unwind\""' +//@ is "$.index[?(@.name=='AbiVecorcallUnwind')].inner.type_alias.type.function_pointer.header.abi.Other" '"\"vectorcall-unwind\""' pub type AbiVecorcallUnwind = extern "vectorcall-unwind" fn(); diff --git a/tests/rustdoc-json/fn_pointer/generics.rs b/tests/rustdoc-json/fn_pointer/generics.rs index c974b472297..960b91e7d8e 100644 --- a/tests/rustdoc-json/fn_pointer/generics.rs +++ b/tests/rustdoc-json/fn_pointer/generics.rs @@ -1,8 +1,8 @@ -//@ count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[0][0]" '"val"' -//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[0][1].borrowed_ref.lifetime" \"\'c\" -//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.output.primitive" \"i32\" -//@ count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[*]" 1 -//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[0].name" \"\'c\" -//@ is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }' +//@ count "$.index[?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1 +//@ is "$.index[?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[0][0]" '"val"' +//@ is "$.index[?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.inputs[0][1].borrowed_ref.lifetime" \"\'c\" +//@ is "$.index[?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.sig.output.primitive" \"i32\" +//@ count "$.index[?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[*]" 1 +//@ is "$.index[?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[0].name" \"\'c\" +//@ is "$.index[?(@.name=='WithHigherRankTraitBounds')].inner.type_alias.type.function_pointer.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }' pub type WithHigherRankTraitBounds = for<'c> fn(val: &'c i32) -> i32; diff --git a/tests/rustdoc-json/fn_pointer/qualifiers.rs b/tests/rustdoc-json/fn_pointer/qualifiers.rs index 398e31f72db..769749d0dd4 100644 --- a/tests/rustdoc-json/fn_pointer/qualifiers.rs +++ b/tests/rustdoc-json/fn_pointer/qualifiers.rs @@ -1,9 +1,9 @@ -//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_unsafe" false -//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_const" false -//@ is "$.index[*][?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_async" false +//@ is "$.index[?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_unsafe" false +//@ is "$.index[?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_const" false +//@ is "$.index[?(@.name=='FnPointer')].inner.type_alias.type.function_pointer.header.is_async" false pub type FnPointer = fn(); -//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_unsafe" true -//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_const" false -//@ is "$.index[*][?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_async" false +//@ is "$.index[?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_unsafe" true +//@ is "$.index[?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_const" false +//@ is "$.index[?(@.name=='UnsafePointer')].inner.type_alias.type.function_pointer.header.is_async" false pub type UnsafePointer = unsafe fn(); diff --git a/tests/rustdoc-json/fns/abi.rs b/tests/rustdoc-json/fns/abi.rs index 68957f79952..7277bb1f59a 100644 --- a/tests/rustdoc-json/fns/abi.rs +++ b/tests/rustdoc-json/fns/abi.rs @@ -1,22 +1,22 @@ #![feature(abi_vectorcall)] -//@ is "$.index[*][?(@.name=='abi_rust')].inner.function.header.abi" \"Rust\" +//@ is "$.index[?(@.name=='abi_rust')].inner.function.header.abi" \"Rust\" pub fn abi_rust() {} -//@ is "$.index[*][?(@.name=='abi_c')].inner.function.header.abi" '{"C": {"unwind": false}}' +//@ is "$.index[?(@.name=='abi_c')].inner.function.header.abi" '{"C": {"unwind": false}}' pub extern "C" fn abi_c() {} -//@ is "$.index[*][?(@.name=='abi_system')].inner.function.header.abi" '{"System": {"unwind": false}}' +//@ is "$.index[?(@.name=='abi_system')].inner.function.header.abi" '{"System": {"unwind": false}}' pub extern "system" fn abi_system() {} -//@ is "$.index[*][?(@.name=='abi_c_unwind')].inner.function.header.abi" '{"C": {"unwind": true}}' +//@ is "$.index[?(@.name=='abi_c_unwind')].inner.function.header.abi" '{"C": {"unwind": true}}' pub extern "C-unwind" fn abi_c_unwind() {} -//@ is "$.index[*][?(@.name=='abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}' +//@ is "$.index[?(@.name=='abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}' pub extern "system-unwind" fn abi_system_unwind() {} -//@ is "$.index[*][?(@.name=='abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""' +//@ is "$.index[?(@.name=='abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""' pub extern "vectorcall" fn abi_vectorcall() {} -//@ is "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""' +//@ is "$.index[?(@.name=='abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""' pub extern "vectorcall-unwind" fn abi_vectorcall_unwind() {} diff --git a/tests/rustdoc-json/fns/async_return.rs b/tests/rustdoc-json/fns/async_return.rs index ddfd4ccf90d..e7c6a2981ac 100644 --- a/tests/rustdoc-json/fns/async_return.rs +++ b/tests/rustdoc-json/fns/async_return.rs @@ -4,30 +4,30 @@ use std::future::Future; -//@ is "$.index[*][?(@.name=='get_int')].inner.function.sig.output.primitive" \"i32\" -//@ is "$.index[*][?(@.name=='get_int')].inner.function.header.is_async" false +//@ is "$.index[?(@.name=='get_int')].inner.function.sig.output.primitive" \"i32\" +//@ is "$.index[?(@.name=='get_int')].inner.function.header.is_async" false pub fn get_int() -> i32 { 42 } -//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.sig.output.primitive" \"i32\" -//@ is "$.index[*][?(@.name=='get_int_async')].inner.function.header.is_async" true +//@ is "$.index[?(@.name=='get_int_async')].inner.function.sig.output.primitive" \"i32\" +//@ is "$.index[?(@.name=='get_int_async')].inner.function.header.is_async" true pub async fn get_int_async() -> i32 { 42 } -//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.path" '"Future"' -//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"' -//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive" \"i32\" -//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.header.is_async" false +//@ is "$.index[?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.path" '"Future"' +//@ is "$.index[?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"' +//@ is "$.index[?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive" \"i32\" +//@ is "$.index[?(@.name=='get_int_future')].inner.function.header.is_async" false pub fn get_int_future() -> impl Future<Output = i32> { async { 42 } } -//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.path" '"Future"' -//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"' -//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive" \"i32\" -//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.header.is_async" true +//@ is "$.index[?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.path" '"Future"' +//@ is "$.index[?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"' +//@ is "$.index[?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive" \"i32\" +//@ is "$.index[?(@.name=='get_int_future_async')].inner.function.header.is_async" true pub async fn get_int_future_async() -> impl Future<Output = i32> { async { 42 } } diff --git a/tests/rustdoc-json/fns/extern_c_variadic.rs b/tests/rustdoc-json/fns/extern_c_variadic.rs index 8e9085640e0..d90bb83d98f 100644 --- a/tests/rustdoc-json/fns/extern_c_variadic.rs +++ b/tests/rustdoc-json/fns/extern_c_variadic.rs @@ -1,6 +1,6 @@ extern "C" { - //@ is "$.index[*][?(@.name == 'not_variadic')].inner.function.sig.is_c_variadic" false + //@ is "$.index[?(@.name == 'not_variadic')].inner.function.sig.is_c_variadic" false pub fn not_variadic(_: i32); - //@ is "$.index[*][?(@.name == 'variadic')].inner.function.sig.is_c_variadic" true + //@ is "$.index[?(@.name == 'variadic')].inner.function.sig.is_c_variadic" true pub fn variadic(_: i32, ...); } diff --git a/tests/rustdoc-json/fns/extern_safe.rs b/tests/rustdoc-json/fns/extern_safe.rs index b00f9f50bd2..bc217ae914c 100644 --- a/tests/rustdoc-json/fns/extern_safe.rs +++ b/tests/rustdoc-json/fns/extern_safe.rs @@ -1,17 +1,17 @@ extern "C" { - //@ is "$.index[*][?(@.name=='f1')].inner.function.header.is_unsafe" true + //@ is "$.index[?(@.name=='f1')].inner.function.header.is_unsafe" true pub fn f1(); // items in `extern` blocks without an `unsafe` qualifier cannot have safety qualifiers } unsafe extern "C" { - //@ is "$.index[*][?(@.name=='f4')].inner.function.header.is_unsafe" true + //@ is "$.index[?(@.name=='f4')].inner.function.header.is_unsafe" true pub fn f4(); - //@ is "$.index[*][?(@.name=='f5')].inner.function.header.is_unsafe" true + //@ is "$.index[?(@.name=='f5')].inner.function.header.is_unsafe" true pub unsafe fn f5(); - //@ is "$.index[*][?(@.name=='f6')].inner.function.header.is_unsafe" false + //@ is "$.index[?(@.name=='f6')].inner.function.header.is_unsafe" false pub safe fn f6(); } diff --git a/tests/rustdoc-json/fns/generic_args.rs b/tests/rustdoc-json/fns/generic_args.rs index 6a7124976f8..2ea68173d68 100644 --- a/tests/rustdoc-json/fns/generic_args.rs +++ b/tests/rustdoc-json/fns/generic_args.rs @@ -1,58 +1,58 @@ -//@ set foo = "$.index[*][?(@.name=='Foo')].id" +//@ set foo = "$.index[?(@.name=='Foo')].id" pub trait Foo {} -//@ set generic_foo = "$.index[*][?(@.name=='GenericFoo')].id" +//@ set generic_foo = "$.index[?(@.name=='GenericFoo')].id" pub trait GenericFoo<'a> {} -//@ is "$.index[*][?(@.name=='generics')].inner.function.generics.where_predicates" "[]" -//@ count "$.index[*][?(@.name=='generics')].inner.function.generics.params[*]" 1 -//@ is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].name" '"F"' -//@ is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.default" 'null' -//@ count "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[*]" 1 -//@ is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" '$foo' -//@ count "$.index[*][?(@.name=='generics')].inner.function.sig.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='generics')].inner.function.sig.inputs[0][0]" '"f"' -//@ is "$.index[*][?(@.name=='generics')].inner.function.sig.inputs[0][1].generic" '"F"' +//@ is "$.index[?(@.name=='generics')].inner.function.generics.where_predicates" "[]" +//@ count "$.index[?(@.name=='generics')].inner.function.generics.params[*]" 1 +//@ is "$.index[?(@.name=='generics')].inner.function.generics.params[0].name" '"F"' +//@ is "$.index[?(@.name=='generics')].inner.function.generics.params[0].kind.type.default" 'null' +//@ count "$.index[?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[*]" 1 +//@ is "$.index[?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" '$foo' +//@ count "$.index[?(@.name=='generics')].inner.function.sig.inputs[*]" 1 +//@ is "$.index[?(@.name=='generics')].inner.function.sig.inputs[0][0]" '"f"' +//@ is "$.index[?(@.name=='generics')].inner.function.sig.inputs[0][1].generic" '"F"' pub fn generics<F: Foo>(f: F) {} -//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.where_predicates" "[]" -//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[*]" 1 -//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[0].name" '"impl Foo"' -//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $foo -//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[0][0]" '"f"' -//@ count "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[0][1].impl_trait[*]" 1 -//@ is "$.index[*][?(@.name=='impl_trait')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.id" $foo +//@ is "$.index[?(@.name=='impl_trait')].inner.function.generics.where_predicates" "[]" +//@ count "$.index[?(@.name=='impl_trait')].inner.function.generics.params[*]" 1 +//@ is "$.index[?(@.name=='impl_trait')].inner.function.generics.params[0].name" '"impl Foo"' +//@ is "$.index[?(@.name=='impl_trait')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $foo +//@ count "$.index[?(@.name=='impl_trait')].inner.function.sig.inputs[*]" 1 +//@ is "$.index[?(@.name=='impl_trait')].inner.function.sig.inputs[0][0]" '"f"' +//@ count "$.index[?(@.name=='impl_trait')].inner.function.sig.inputs[0][1].impl_trait[*]" 1 +//@ is "$.index[?(@.name=='impl_trait')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.id" $foo pub fn impl_trait(f: impl Foo) {} -//@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[*]" 3 -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].name" '"F"' -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "is_synthetic": false}}' -//@ count "$.index[*][?(@.name=='where_clase')].inner.function.sig.inputs[*]" 3 -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.sig.inputs[0][0]" '"f"' -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.sig.inputs[0][1].generic" '"F"' -//@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[*]" 3 +//@ count "$.index[?(@.name=='where_clase')].inner.function.generics.params[*]" 3 +//@ is "$.index[?(@.name=='where_clase')].inner.function.generics.params[0].name" '"F"' +//@ is "$.index[?(@.name=='where_clase')].inner.function.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "is_synthetic": false}}' +//@ count "$.index[?(@.name=='where_clase')].inner.function.sig.inputs[*]" 3 +//@ is "$.index[?(@.name=='where_clase')].inner.function.sig.inputs[0][0]" '"f"' +//@ is "$.index[?(@.name=='where_clase')].inner.function.sig.inputs[0][1].generic" '"F"' +//@ count "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[*]" 3 -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.type.generic" \"F\" -//@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.bounds[*]" 1 -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.bounds[0].trait_bound.trait.id" $foo +//@ is "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.type.generic" \"F\" +//@ count "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.bounds[*]" 1 +//@ is "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.bounds[0].trait_bound.trait.id" $foo -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.type.generic" \"G\" -//@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[*]" 1 -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.trait.id" $generic_foo -//@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[*]" 1 -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].name" \"\'a\" -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].kind.lifetime.outlives" "[]" -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.generic_params" "[]" +//@ is "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.type.generic" \"G\" +//@ count "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[*]" 1 +//@ is "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.trait.id" $generic_foo +//@ count "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[*]" 1 +//@ is "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].name" \"\'a\" +//@ is "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].kind.lifetime.outlives" "[]" +//@ is "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.generic_params" "[]" -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.type.borrowed_ref.lifetime" \"\'b\" -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.type.borrowed_ref.type.generic" \"H\" -//@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.bounds[*]" 1 -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.trait.id" $foo -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.generic_params" "[]" -//@ count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.generic_params[*]" 1 -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.generic_params[0].name" \"\'b\" -//@ is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.generic_params[0].kind.lifetime.outlives" "[]" +//@ is "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.type.borrowed_ref.lifetime" \"\'b\" +//@ is "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.type.borrowed_ref.type.generic" \"H\" +//@ count "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.bounds[*]" 1 +//@ is "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.trait.id" $foo +//@ is "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.generic_params" "[]" +//@ count "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.generic_params[*]" 1 +//@ is "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.generic_params[0].name" \"\'b\" +//@ is "$.index[?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.generic_params[0].kind.lifetime.outlives" "[]" pub fn where_clase<F, G, H>(f: F, g: G, h: H) where F: Foo, diff --git a/tests/rustdoc-json/fns/generic_returns.rs b/tests/rustdoc-json/fns/generic_returns.rs index 90e17525c44..a0d4c745599 100644 --- a/tests/rustdoc-json/fns/generic_returns.rs +++ b/tests/rustdoc-json/fns/generic_returns.rs @@ -1,11 +1,11 @@ -//@ count "$.index[*][?(@.name=='generic_returns')].inner.module.items[*]" 2 +//@ count "$.index[?(@.name=='generic_returns')].inner.module.items[*]" 2 -//@ set foo = "$.index[*][?(@.name=='Foo')].id" +//@ set foo = "$.index[?(@.name=='Foo')].id" pub trait Foo {} -//@ is "$.index[*][?(@.name=='get_foo')].inner.function.sig.inputs" [] -//@ count "$.index[*][?(@.name=='get_foo')].inner.function.sig.output.impl_trait[*]" 1 -//@ is "$.index[*][?(@.name=='get_foo')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $foo +//@ is "$.index[?(@.name=='get_foo')].inner.function.sig.inputs" [] +//@ count "$.index[?(@.name=='get_foo')].inner.function.sig.output.impl_trait[*]" 1 +//@ is "$.index[?(@.name=='get_foo')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $foo pub fn get_foo() -> impl Foo { Fooer {} } diff --git a/tests/rustdoc-json/fns/generics.rs b/tests/rustdoc-json/fns/generics.rs index b953094b5de..3efd917309a 100644 --- a/tests/rustdoc-json/fns/generics.rs +++ b/tests/rustdoc-json/fns/generics.rs @@ -1,20 +1,20 @@ -//@ set wham_id = "$.index[*][?(@.name=='Wham')].id" +//@ set wham_id = "$.index[?(@.name=='Wham')].id" pub trait Wham {} -//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.where_predicates" [] -//@ count "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[*]" 1 -//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].name" '"T"' -//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.is_synthetic" false -//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id -//@ is "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.sig.inputs" '[["w", {"generic": "T"}]]' +//@ is "$.index[?(@.name=='one_generic_param_fn')].inner.function.generics.where_predicates" [] +//@ count "$.index[?(@.name=='one_generic_param_fn')].inner.function.generics.params[*]" 1 +//@ is "$.index[?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].name" '"T"' +//@ is "$.index[?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.is_synthetic" false +//@ is "$.index[?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id +//@ is "$.index[?(@.name=='one_generic_param_fn')].inner.function.sig.inputs" '[["w", {"generic": "T"}]]' pub fn one_generic_param_fn<T: Wham>(w: T) {} -//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.where_predicates" [] -//@ count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[*]" 1 -//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].name" '"impl Wham"' -//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.is_synthetic" true -//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id -//@ count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[0][0]" '"w"' -//@ is "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.id" $wham_id +//@ is "$.index[?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.where_predicates" [] +//@ count "$.index[?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[*]" 1 +//@ is "$.index[?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].name" '"impl Wham"' +//@ is "$.index[?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.is_synthetic" true +//@ is "$.index[?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id +//@ count "$.index[?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[*]" 1 +//@ is "$.index[?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[0][0]" '"w"' +//@ is "$.index[?(@.name=='one_synthetic_generic_param_fn')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.id" $wham_id pub fn one_synthetic_generic_param_fn(w: impl Wham) {} diff --git a/tests/rustdoc-json/fns/pattern_arg.rs b/tests/rustdoc-json/fns/pattern_arg.rs index d2a00f47438..059318a4295 100644 --- a/tests/rustdoc-json/fns/pattern_arg.rs +++ b/tests/rustdoc-json/fns/pattern_arg.rs @@ -1,7 +1,7 @@ -//@ is "$.index[*][?(@.name=='fst')].inner.function.sig.inputs[0][0]" '"(x, _)"' +//@ is "$.index[?(@.name=='fst')].inner.function.sig.inputs[0][0]" '"(x, _)"' pub fn fst<X, Y>((x, _): (X, Y)) -> X { x } -//@ is "$.index[*][?(@.name=='drop_int')].inner.function.sig.inputs[0][0]" '"_"' +//@ is "$.index[?(@.name=='drop_int')].inner.function.sig.inputs[0][0]" '"_"' pub fn drop_int(_: i32) {} diff --git a/tests/rustdoc-json/fns/qualifiers.rs b/tests/rustdoc-json/fns/qualifiers.rs index 67e49f0780a..7d93a3bf243 100644 --- a/tests/rustdoc-json/fns/qualifiers.rs +++ b/tests/rustdoc-json/fns/qualifiers.rs @@ -1,33 +1,33 @@ //@ edition:2018 -//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.is_async" false -//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.is_const" false -//@ is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.is_unsafe" false +//@ is "$.index[?(@.name=='nothing_fn')].inner.function.header.is_async" false +//@ is "$.index[?(@.name=='nothing_fn')].inner.function.header.is_const" false +//@ is "$.index[?(@.name=='nothing_fn')].inner.function.header.is_unsafe" false pub fn nothing_fn() {} -//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.is_async" false -//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.is_const" false -//@ is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.is_unsafe" true +//@ is "$.index[?(@.name=='unsafe_fn')].inner.function.header.is_async" false +//@ is "$.index[?(@.name=='unsafe_fn')].inner.function.header.is_const" false +//@ is "$.index[?(@.name=='unsafe_fn')].inner.function.header.is_unsafe" true pub unsafe fn unsafe_fn() {} -//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.is_async" false -//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.is_const" true -//@ is "$.index[*][?(@.name=='const_fn')].inner.function.header.is_unsafe" false +//@ is "$.index[?(@.name=='const_fn')].inner.function.header.is_async" false +//@ is "$.index[?(@.name=='const_fn')].inner.function.header.is_const" true +//@ is "$.index[?(@.name=='const_fn')].inner.function.header.is_unsafe" false pub const fn const_fn() {} -//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.is_async" true -//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.is_const" false -//@ is "$.index[*][?(@.name=='async_fn')].inner.function.header.is_unsafe" false +//@ is "$.index[?(@.name=='async_fn')].inner.function.header.is_async" true +//@ is "$.index[?(@.name=='async_fn')].inner.function.header.is_const" false +//@ is "$.index[?(@.name=='async_fn')].inner.function.header.is_unsafe" false pub async fn async_fn() {} -//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.is_async" true -//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.is_const" false -//@ is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.is_unsafe" true +//@ is "$.index[?(@.name=='async_unsafe_fn')].inner.function.header.is_async" true +//@ is "$.index[?(@.name=='async_unsafe_fn')].inner.function.header.is_const" false +//@ is "$.index[?(@.name=='async_unsafe_fn')].inner.function.header.is_unsafe" true pub async unsafe fn async_unsafe_fn() {} -//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.is_async" false -//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.is_const" true -//@ is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.is_unsafe" true +//@ is "$.index[?(@.name=='const_unsafe_fn')].inner.function.header.is_async" false +//@ is "$.index[?(@.name=='const_unsafe_fn')].inner.function.header.is_const" true +//@ is "$.index[?(@.name=='const_unsafe_fn')].inner.function.header.is_unsafe" true pub const unsafe fn const_unsafe_fn() {} // It's impossible for a function to be both const and async, so no test for that diff --git a/tests/rustdoc-json/fns/return_type_alias.rs b/tests/rustdoc-json/fns/return_type_alias.rs index d60c4b68258..0aa1db47b7f 100644 --- a/tests/rustdoc-json/fns/return_type_alias.rs +++ b/tests/rustdoc-json/fns/return_type_alias.rs @@ -1,9 +1,9 @@ // Regression test for <https://github.com/rust-lang/rust/issues/104851> -///@ set foo = "$.index[*][?(@.name=='Foo')].id" +///@ set foo = "$.index[?(@.name=='Foo')].id" pub type Foo = i32; -//@ is "$.index[*][?(@.name=='demo')].inner.function.sig.output.resolved_path.id" $foo +//@ is "$.index[?(@.name=='demo')].inner.function.sig.output.resolved_path.id" $foo pub fn demo() -> Foo { 42 } diff --git a/tests/rustdoc-json/generic-associated-types/gats.rs b/tests/rustdoc-json/generic-associated-types/gats.rs index d1172b35fda..5218cc886e3 100644 --- a/tests/rustdoc-json/generic-associated-types/gats.rs +++ b/tests/rustdoc-json/generic-associated-types/gats.rs @@ -1,32 +1,32 @@ pub trait Display {} pub trait LendingIterator { - //@ count "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.params[*]" 1 - //@ is "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.params[*].name" \"\'a\" - //@ count "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.where_predicates[*]" 1 - //@ is "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.where_predicates[*].bound_predicate.type.generic" \"Self\" - //@ is "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.where_predicates[*].bound_predicate.bounds[*].outlives" \"\'a\" - //@ count "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.bounds[*]" 1 + //@ count "$.index[?(@.name=='LendingItem')].inner.assoc_type.generics.params[*]" 1 + //@ is "$.index[?(@.name=='LendingItem')].inner.assoc_type.generics.params[*].name" \"\'a\" + //@ count "$.index[?(@.name=='LendingItem')].inner.assoc_type.generics.where_predicates[*]" 1 + //@ is "$.index[?(@.name=='LendingItem')].inner.assoc_type.generics.where_predicates[*].bound_predicate.type.generic" \"Self\" + //@ is "$.index[?(@.name=='LendingItem')].inner.assoc_type.generics.where_predicates[*].bound_predicate.bounds[*].outlives" \"\'a\" + //@ count "$.index[?(@.name=='LendingItem')].inner.assoc_type.bounds[*]" 1 type LendingItem<'a>: Display where Self: 'a; - //@ count "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.args.angle_bracketed.args[*]" 1 - //@ count "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.args.angle_bracketed.bindings[*]" 0 - //@ is "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.self_type.generic" \"Self\" - //@ is "$.index[*][?(@.name=='lending_next')].inner.function.sig.output.qualified_path.name" \"LendingItem\" + //@ count "$.index[?(@.name=='lending_next')].inner.function.sig.output.qualified_path.args.angle_bracketed.args[*]" 1 + //@ count "$.index[?(@.name=='lending_next')].inner.function.sig.output.qualified_path.args.angle_bracketed.bindings[*]" 0 + //@ is "$.index[?(@.name=='lending_next')].inner.function.sig.output.qualified_path.self_type.generic" \"Self\" + //@ is "$.index[?(@.name=='lending_next')].inner.function.sig.output.qualified_path.name" \"LendingItem\" fn lending_next<'a>(&'a self) -> Self::LendingItem<'a>; } pub trait Iterator { - //@ count "$.index[*][?(@.name=='Item')].inner.assoc_type.generics.params[*]" 0 - //@ count "$.index[*][?(@.name=='Item')].inner.assoc_type.generics.where_predicates[*]" 0 - //@ count "$.index[*][?(@.name=='Item')].inner.assoc_type.bounds[*]" 1 + //@ count "$.index[?(@.name=='Item')].inner.assoc_type.generics.params[*]" 0 + //@ count "$.index[?(@.name=='Item')].inner.assoc_type.generics.where_predicates[*]" 0 + //@ count "$.index[?(@.name=='Item')].inner.assoc_type.bounds[*]" 1 type Item: Display; - //@ count "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.args.angle_bracketed.args[*]" 0 - //@ count "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.args.angle_bracketed.bindings[*]" 0 - //@ is "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.self_type.generic" \"Self\" - //@ is "$.index[*][?(@.name=='next')].inner.function.sig.output.qualified_path.name" \"Item\" + //@ count "$.index[?(@.name=='next')].inner.function.sig.output.qualified_path.args.angle_bracketed.args[*]" 0 + //@ count "$.index[?(@.name=='next')].inner.function.sig.output.qualified_path.args.angle_bracketed.bindings[*]" 0 + //@ is "$.index[?(@.name=='next')].inner.function.sig.output.qualified_path.self_type.generic" \"Self\" + //@ is "$.index[?(@.name=='next')].inner.function.sig.output.qualified_path.name" \"Item\" fn next<'a>(&'a self) -> Self::Item; } diff --git a/tests/rustdoc-json/generic_impl.rs b/tests/rustdoc-json/generic_impl.rs index e7a5d2a78c1..90bda1644ff 100644 --- a/tests/rustdoc-json/generic_impl.rs +++ b/tests/rustdoc-json/generic_impl.rs @@ -1,8 +1,8 @@ // Regression test for <https://github.com/rust-lang/rust/issues/97986>. -//@ has "$.index[*][?(@.name=='f')]" -//@ has "$.index[*][?(@.name=='AssocTy')]" -//@ has "$.index[*][?(@.name=='AssocConst')]" +//@ has "$.index[?(@.name=='f')]" +//@ has "$.index[?(@.name=='AssocTy')]" +//@ has "$.index[?(@.name=='AssocConst')]" pub mod m { pub struct S; diff --git a/tests/rustdoc-json/glob_import.rs b/tests/rustdoc-json/glob_import.rs index b63e5dadd9e..6887f9ff63d 100644 --- a/tests/rustdoc-json/glob_import.rs +++ b/tests/rustdoc-json/glob_import.rs @@ -2,8 +2,8 @@ #![no_std] -//@ has "$.index[*][?(@.name=='glob')]" -//@ has "$.index[*][?(@.inner.use)].inner.use.name" \"*\" +//@ has "$.index[?(@.name=='glob')]" +//@ has "$.index[?(@.inner.use)].inner.use.name" \"*\" mod m1 { pub fn f() {} diff --git a/tests/rustdoc-json/impl-trait-in-assoc-type.rs b/tests/rustdoc-json/impl-trait-in-assoc-type.rs index fc12fc87e8d..742a46e8967 100644 --- a/tests/rustdoc-json/impl-trait-in-assoc-type.rs +++ b/tests/rustdoc-json/impl-trait-in-assoc-type.rs @@ -4,25 +4,25 @@ pub struct AlwaysTrue; /// impl IntoIterator impl IntoIterator for AlwaysTrue { - //@ set Item = '$.index[*][?(@.docs=="type Item")].id' + //@ set Item = '$.index[?(@.docs=="type Item")].id' /// type Item type Item = bool; - //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[*]' 1 - //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.path' '"Iterator"' - //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[*]' 1 - //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name' '"Item"' - //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive' '"bool"' + //@ count '$.index[?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[*]' 1 + //@ is '$.index[?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.path' '"Iterator"' + //@ count '$.index[?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[*]' 1 + //@ is '$.index[?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name' '"Item"' + //@ is '$.index[?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive' '"bool"' - //@ set IntoIter = '$.index[*][?(@.docs=="type IntoIter")].id' + //@ set IntoIter = '$.index[?(@.docs=="type IntoIter")].id' /// type IntoIter type IntoIter = impl Iterator<Item = bool>; - //@ set into_iter = '$.index[*][?(@.docs=="fn into_iter")].id' + //@ set into_iter = '$.index[?(@.docs=="fn into_iter")].id' /// fn into_iter fn into_iter(self) -> Self::IntoIter { std::iter::repeat(true) } } -//@ ismany '$.index[*][?(@.docs=="impl IntoIterator")].inner.impl.items[*]' $Item $IntoIter $into_iter +//@ ismany '$.index[?(@.docs=="impl IntoIterator")].inner.impl.items[*]' $Item $IntoIter $into_iter diff --git a/tests/rustdoc-json/impl-trait-precise-capturing.rs b/tests/rustdoc-json/impl-trait-precise-capturing.rs index 06be95099b4..37adb514f55 100644 --- a/tests/rustdoc-json/impl-trait-precise-capturing.rs +++ b/tests/rustdoc-json/impl-trait-precise-capturing.rs @@ -1,4 +1,4 @@ -//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[0].lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[1].param" \"T\" -//@ is "$.index[*][?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[2].param" \"N\" +//@ is "$.index[?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[0].lifetime" \"\'a\" +//@ is "$.index[?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[1].param" \"T\" +//@ is "$.index[?(@.name=='hello')].inner.function.sig.output.impl_trait[1].use[2].param" \"N\" pub fn hello<'a, T, const N: usize>() -> impl Sized + use<'a, T, N> {} diff --git a/tests/rustdoc-json/impls/auto.rs b/tests/rustdoc-json/impls/auto.rs index f37dae4c1ed..f94f7338480 100644 --- a/tests/rustdoc-json/impls/auto.rs +++ b/tests/rustdoc-json/impls/auto.rs @@ -15,8 +15,8 @@ impl Foo { } // Testing spans, so all tests below code -//@ is "$.index[*][?(@.docs=='has span')].span.begin" "[13, 0]" -//@ is "$.index[*][?(@.docs=='has span')].span.end" "[15, 1]" +//@ is "$.index[?(@.docs=='has span')].span.begin" "[13, 0]" +//@ is "$.index[?(@.docs=='has span')].span.end" "[15, 1]" // FIXME: this doesn't work due to https://github.com/freestrings/jsonpath/issues/91 -// is "$.index[*][?(@.inner.impl.is_synthetic==true)].span" null +// is "$.index[?(@.inner.impl.is_synthetic==true)].span" null pub struct Foo; diff --git a/tests/rustdoc-json/impls/blanket_with_local.rs b/tests/rustdoc-json/impls/blanket_with_local.rs index de92dafae0b..24ee6cf6670 100644 --- a/tests/rustdoc-json/impls/blanket_with_local.rs +++ b/tests/rustdoc-json/impls/blanket_with_local.rs @@ -1,11 +1,11 @@ // Test for the ICE in rust/83718 // A blanket impl plus a local type together shouldn't result in mismatched ID issues -//@ has "$.index[*][?(@.name=='Load')]" +//@ has "$.index[?(@.name=='Load')]" pub trait Load { - //@ has "$.index[*][?(@.name=='load')]" + //@ has "$.index[?(@.name=='load')]" fn load() {} - //@ has "$.index[*][?(@.name=='write')]" + //@ has "$.index[?(@.name=='write')]" fn write(self) {} } @@ -14,5 +14,5 @@ impl<P> Load for P { fn write(self) {} } -//@ has "$.index[*][?(@.name=='Wrapper')]" +//@ has "$.index[?(@.name=='Wrapper')]" pub struct Wrapper {} diff --git a/tests/rustdoc-json/impls/foreign_for_local.rs b/tests/rustdoc-json/impls/foreign_for_local.rs index 1347f954cad..e46b158d802 100644 --- a/tests/rustdoc-json/impls/foreign_for_local.rs +++ b/tests/rustdoc-json/impls/foreign_for_local.rs @@ -3,16 +3,16 @@ extern crate foreign_trait; /// ForeignTrait id hack pub use foreign_trait::ForeignTrait as _; -//@ set ForeignTrait = "$.index[*][?(@.docs=='ForeignTrait id hack')].inner.use.id" +//@ set ForeignTrait = "$.index[?(@.docs=='ForeignTrait id hack')].inner.use.id" pub struct LocalStruct; -//@ set LocalStruct = "$.index[*][?(@.name=='LocalStruct')].id" +//@ set LocalStruct = "$.index[?(@.name=='LocalStruct')].id" /// foreign for local impl foreign_trait::ForeignTrait for LocalStruct {} -//@ set impl = "$.index[*][?(@.docs=='foreign for local')].id" -//@ is "$.index[*][?(@.docs=='foreign for local')].inner.impl.for.resolved_path.id" $LocalStruct -//@ is "$.index[*][?(@.docs=='foreign for local')].inner.impl.trait.id" $ForeignTrait +//@ set impl = "$.index[?(@.docs=='foreign for local')].id" +//@ is "$.index[?(@.docs=='foreign for local')].inner.impl.for.resolved_path.id" $LocalStruct +//@ is "$.index[?(@.docs=='foreign for local')].inner.impl.trait.id" $ForeignTrait -//@ has "$.index[*][?(@.name=='LocalStruct')].inner.struct.impls[*]" $impl +//@ has "$.index[?(@.name=='LocalStruct')].inner.struct.impls[*]" $impl diff --git a/tests/rustdoc-json/impls/impl_item_visibility.rs b/tests/rustdoc-json/impls/impl_item_visibility.rs index 293dd965804..680ea175d0b 100644 --- a/tests/rustdoc-json/impls/impl_item_visibility.rs +++ b/tests/rustdoc-json/impls/impl_item_visibility.rs @@ -4,13 +4,13 @@ pub struct Foo; impl Foo { fn baz() {} } -//@ !has '$.index[*][?(@.docs=="impl Foo priv")]' +//@ !has '$.index[?(@.docs=="impl Foo priv")]' /// impl Foo pub impl Foo { pub fn qux() {} } -//@ is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"' +//@ is '$.index[?(@.docs=="impl Foo pub")].visibility' '"default"' /// impl Foo hidden impl Foo { @@ -18,4 +18,4 @@ impl Foo { pub fn __quazl() {} } // FIXME(#111564): Is this the right behaviour? -//@ is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"' +//@ is '$.index[?(@.docs=="impl Foo hidden")].visibility' '"default"' diff --git a/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs b/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs index 77ee717b03a..82d59b97b01 100644 --- a/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs +++ b/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs @@ -7,13 +7,13 @@ impl Foo { fn baz() {} } // FIXME(#111564): Is this the right behaviour? -//@ is '$.index[*][?(@.docs=="impl Foo priv")].visibility' '"default"' +//@ is '$.index[?(@.docs=="impl Foo priv")].visibility' '"default"' /// impl Foo pub impl Foo { pub fn qux() {} } -//@ is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"' +//@ is '$.index[?(@.docs=="impl Foo pub")].visibility' '"default"' /// impl Foo hidden impl Foo { @@ -21,4 +21,4 @@ impl Foo { pub fn __quazl() {} } // FIXME(#111564): Is this the right behaviour? -//@ is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"' +//@ is '$.index[?(@.docs=="impl Foo hidden")].visibility' '"default"' diff --git a/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs b/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs index 80c47eee6cb..a3b145adb86 100644 --- a/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs +++ b/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs @@ -6,13 +6,13 @@ pub struct Foo; impl Foo { fn baz() {} } -//@ is '$.index[*][?(@.docs=="impl Foo priv")].visibility' '"default"' +//@ is '$.index[?(@.docs=="impl Foo priv")].visibility' '"default"' /// impl Foo pub impl Foo { pub fn qux() {} } -//@ is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"' +//@ is '$.index[?(@.docs=="impl Foo pub")].visibility' '"default"' /// impl Foo hidden impl Foo { @@ -20,4 +20,4 @@ impl Foo { pub fn __quazl() {} } // FIXME(#111564): Is this the right behaviour? -//@ is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"' +//@ is '$.index[?(@.docs=="impl Foo hidden")].visibility' '"default"' diff --git a/tests/rustdoc-json/impls/import_from_private.rs b/tests/rustdoc-json/impls/import_from_private.rs index 32b9abb0717..02262d9b65f 100644 --- a/tests/rustdoc-json/impls/import_from_private.rs +++ b/tests/rustdoc-json/impls/import_from_private.rs @@ -1,20 +1,20 @@ // https://github.com/rust-lang/rust/issues/100252 mod bar { - //@ set baz = "$.index[*][?(@.name == 'Baz')].id" + //@ set baz = "$.index[?(@.name == 'Baz')].id" pub struct Baz; - //@ set impl = "$.index[*][?(@.docs == 'impl')].id" + //@ set impl = "$.index[?(@.docs == 'impl')].id" /// impl impl Baz { - //@ set doit = "$.index[*][?(@.name == 'doit')].id" + //@ set doit = "$.index[?(@.name == 'doit')].id" pub fn doit() {} } } -//@ set import = "$.index[*][?(@.inner.use)].id" +//@ set import = "$.index[?(@.inner.use)].id" pub use bar::Baz; //@ is "$.index[*].inner.module.items[*]" $import //@ is "$.index[*].inner.use.id" $baz -//@ has "$.index[*][?(@.name == 'Baz')].inner.struct.impls[*]" $impl -//@ is "$.index[*][?(@.docs=='impl')].inner.impl.items[*]" $doit +//@ has "$.index[?(@.name == 'Baz')].inner.struct.impls[*]" $impl +//@ is "$.index[?(@.docs=='impl')].inner.impl.items[*]" $doit diff --git a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-2.rs b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-2.rs index 4a313044920..54ec08135be 100644 --- a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-2.rs +++ b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-2.rs @@ -1,8 +1,8 @@ -//@ has "$.index[*][?(@.docs=='Here')]" -//@ !has "$.index[*][?(@.docs=='Not Here')]" -//@ !has "$.index[*][?(@.name == 'HiddenPubStruct')]" -//@ has "$.index[*][?(@.name == 'NotHiddenPubStruct')]" -//@ has "$.index[*][?(@.name=='PubTrait')]" +//@ has "$.index[?(@.docs=='Here')]" +//@ !has "$.index[?(@.docs=='Not Here')]" +//@ !has "$.index[?(@.name == 'HiddenPubStruct')]" +//@ has "$.index[?(@.name == 'NotHiddenPubStruct')]" +//@ has "$.index[?(@.name=='PubTrait')]" pub trait PubTrait {} #[doc(hidden)] diff --git a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-3.rs b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-3.rs index d3f2180f22c..afb29fd6316 100644 --- a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-3.rs +++ b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id-3.rs @@ -1,8 +1,8 @@ //@ compile-flags: --document-hidden-items -//@ has "$.index[*][?(@.name == 'HiddenPubStruct')]" -//@ has "$.index[*][?(@.inner.impl)]" -//@ has "$.index[*][?(@.name=='PubTrait')]" +//@ has "$.index[?(@.name == 'HiddenPubStruct')]" +//@ has "$.index[?(@.inner.impl)]" +//@ has "$.index[?(@.name=='PubTrait')]" pub trait PubTrait {} #[doc(hidden)] diff --git a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id.rs b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id.rs index a3f05818842..7fc3f70fe5a 100644 --- a/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id.rs +++ b/tests/rustdoc-json/impls/issue-112852-dangling-trait-impl-id.rs @@ -1,21 +1,21 @@ -//@ has "$.index[*][?(@.name=='PubTrait')]" +//@ has "$.index[?(@.name=='PubTrait')]" pub trait PubTrait {} #[doc(hidden)] pub mod hidden { - //@ !has "$.index[*][?(@.name == 'HiddenPubStruct')]" + //@ !has "$.index[?(@.name == 'HiddenPubStruct')]" pub struct HiddenPubStruct; - //@ !has "$.index[*][?(@.docs == 'Not Here')]" + //@ !has "$.index[?(@.docs == 'Not Here')]" /// Not Here impl crate::PubTrait for HiddenPubStruct {} } pub mod not_hidden { - //@ has "$.index[*][?(@.name == 'NotHiddenPubStruct')]" + //@ has "$.index[?(@.name == 'NotHiddenPubStruct')]" pub struct NotHiddenPubStruct; - //@ has "$.index[*][?(@.docs == 'Here')]" + //@ has "$.index[?(@.docs == 'Here')]" /// Here impl crate::PubTrait for NotHiddenPubStruct {} } diff --git a/tests/rustdoc-json/impls/local_for_foreign.rs b/tests/rustdoc-json/impls/local_for_foreign.rs index cd89c475348..86c72a580b2 100644 --- a/tests/rustdoc-json/impls/local_for_foreign.rs +++ b/tests/rustdoc-json/impls/local_for_foreign.rs @@ -3,16 +3,16 @@ extern crate foreign_struct; /// ForeignStruct id hack pub use foreign_struct::ForeignStruct as _; -//@ set ForeignStruct = "$.index[*][?(@.docs=='ForeignStruct id hack')].inner.use.id" +//@ set ForeignStruct = "$.index[?(@.docs=='ForeignStruct id hack')].inner.use.id" pub trait LocalTrait {} -//@ set LocalTrait = "$.index[*][?(@.name=='LocalTrait')].id" +//@ set LocalTrait = "$.index[?(@.name=='LocalTrait')].id" /// local for foreign impl LocalTrait for foreign_struct::ForeignStruct {} -//@ set impl = "$.index[*][?(@.docs=='local for foreign')].id" -//@ is "$.index[*][?(@.docs=='local for foreign')].inner.impl.trait.id" $LocalTrait -//@ is "$.index[*][?(@.docs=='local for foreign')].inner.impl.for.resolved_path.id" $ForeignStruct +//@ set impl = "$.index[?(@.docs=='local for foreign')].id" +//@ is "$.index[?(@.docs=='local for foreign')].inner.impl.trait.id" $LocalTrait +//@ is "$.index[?(@.docs=='local for foreign')].inner.impl.for.resolved_path.id" $ForeignStruct -//@ is "$.index[*][?(@.name=='LocalTrait')].inner.trait.implementations[*]" $impl +//@ is "$.index[?(@.name=='LocalTrait')].inner.trait.implementations[*]" $impl diff --git a/tests/rustdoc-json/impls/local_for_local.rs b/tests/rustdoc-json/impls/local_for_local.rs index 1d141d6e4de..876a7912f09 100644 --- a/tests/rustdoc-json/impls/local_for_local.rs +++ b/tests/rustdoc-json/impls/local_for_local.rs @@ -1,12 +1,12 @@ -//@ set struct = "$.index[*][?(@.name=='Struct')].id" +//@ set struct = "$.index[?(@.name=='Struct')].id" pub struct Struct; -//@ set trait = "$.index[*][?(@.name=='Trait')].id" +//@ set trait = "$.index[?(@.name=='Trait')].id" pub trait Trait {} -//@ set impl = "$.index[*][?(@.docs=='impl')].id" +//@ set impl = "$.index[?(@.docs=='impl')].id" /// impl impl Trait for Struct {} -//@ has "$.index[*][?(@.name=='Struct')].inner.struct.impls[*]" $impl -//@ is "$.index[*][?(@.name=='Trait')].inner.trait.implementations[*]" $impl -//@ is "$.index[*][?(@.docs=='impl')].inner.impl.trait.id" $trait -//@ is "$.index[*][?(@.docs=='impl')].inner.impl.for.resolved_path.id" $struct +//@ has "$.index[?(@.name=='Struct')].inner.struct.impls[*]" $impl +//@ is "$.index[?(@.name=='Trait')].inner.trait.implementations[*]" $impl +//@ is "$.index[?(@.docs=='impl')].inner.impl.trait.id" $trait +//@ is "$.index[?(@.docs=='impl')].inner.impl.for.resolved_path.id" $struct diff --git a/tests/rustdoc-json/impls/local_for_local_primitive.rs b/tests/rustdoc-json/impls/local_for_local_primitive.rs index 8c1eb044eae..859c0cb8ec8 100644 --- a/tests/rustdoc-json/impls/local_for_local_primitive.rs +++ b/tests/rustdoc-json/impls/local_for_local_primitive.rs @@ -1,18 +1,18 @@ #![feature(rustc_attrs)] -//@ set Local = "$.index[*][?(@.name=='Local')].id" +//@ set Local = "$.index[?(@.name=='Local')].id" pub trait Local {} -//@ is "$.index[*][?(@.docs=='Local for bool')].inner.impl.trait.id" $Local -//@ is "$.index[*][?(@.docs=='Local for bool')].inner.impl.for.primitive" '"bool"' +//@ is "$.index[?(@.docs=='Local for bool')].inner.impl.trait.id" $Local +//@ is "$.index[?(@.docs=='Local for bool')].inner.impl.for.primitive" '"bool"' /// Local for bool impl Local for bool {} -//@ set impl = "$.index[*][?(@.docs=='Local for bool')].id" -//@ is "$.index[*][?(@.name=='Local')].inner.trait.implementations[*]" $impl +//@ set impl = "$.index[?(@.docs=='Local for bool')].id" +//@ is "$.index[?(@.name=='Local')].inner.trait.implementations[*]" $impl // FIXME(#101695): Test bool's `impls` include "Local for bool" -//@ has "$.index[*][?(@.name=='bool')]" +//@ has "$.index[?(@.name=='bool')]" #[rustc_doc_primitive = "bool"] /// Boolean docs mod prim_bool {} diff --git a/tests/rustdoc-json/impls/local_for_primitive.rs b/tests/rustdoc-json/impls/local_for_primitive.rs index 56d930ca5c4..a5ab3ec8a1b 100644 --- a/tests/rustdoc-json/impls/local_for_primitive.rs +++ b/tests/rustdoc-json/impls/local_for_primitive.rs @@ -1,7 +1,7 @@ -//@ set local = "$.index[*][?(@.name=='Local')]" +//@ set local = "$.index[?(@.name=='Local')]" pub trait Local {} -//@ set impl = "$.index[*][?(@.docs=='local for bool')].id" -//@ is "$.index[*][?(@.name=='Local')].inner.trait.implementations[*]" $impl +//@ set impl = "$.index[?(@.docs=='local for bool')].id" +//@ is "$.index[?(@.name=='Local')].inner.trait.implementations[*]" $impl /// local for bool impl Local for bool {} diff --git a/tests/rustdoc-json/impls/pub_for_hidden_private.rs b/tests/rustdoc-json/impls/pub_for_hidden_private.rs index 261ffbfeb4a..eb89219022c 100644 --- a/tests/rustdoc-json/impls/pub_for_hidden_private.rs +++ b/tests/rustdoc-json/impls/pub_for_hidden_private.rs @@ -5,6 +5,6 @@ pub trait TheTrait {} #[doc(hidden)] struct Value {} -//@ has '$.index[*][?(@.docs=="THE IMPL")]' +//@ has '$.index[?(@.docs=="THE IMPL")]' /// THE IMPL impl TheTrait for Value {} diff --git a/tests/rustdoc-json/impls/trait-for-dyn-trait.rs b/tests/rustdoc-json/impls/trait-for-dyn-trait.rs index 0fbb4df0028..17cb07f3571 100644 --- a/tests/rustdoc-json/impls/trait-for-dyn-trait.rs +++ b/tests/rustdoc-json/impls/trait-for-dyn-trait.rs @@ -1,15 +1,15 @@ -//@ set t1 = '$.index[*][?(@.name=="T1")].id' +//@ set t1 = '$.index[?(@.name=="T1")].id' pub trait T1 {} -//@ set t2 = '$.index[*][?(@.name=="T2")].id' +//@ set t2 = '$.index[?(@.name=="T2")].id' pub trait T2 {} /// Fun impl impl T1 for dyn T2 {} -//@ set impl = '$.index[*][?(@.docs=="Fun impl")].id' -//@ is '$.index[*][?(@.name=="T1")].inner.trait.implementations[*]' $impl -//@ is '$.index[*][?(@.name=="T2")].inner.trait.implementations' [] +//@ set impl = '$.index[?(@.docs=="Fun impl")].id' +//@ is '$.index[?(@.name=="T1")].inner.trait.implementations[*]' $impl +//@ is '$.index[?(@.name=="T2")].inner.trait.implementations' [] -//@ is '$.index[*][?(@.docs=="Fun impl")].inner.impl.trait.id' $t1 -//@ is '$.index[*][?(@.docs=="Fun impl")].inner.impl.for.dyn_trait.traits[*].trait.id' $t2 +//@ is '$.index[?(@.docs=="Fun impl")].inner.impl.trait.id' $t1 +//@ is '$.index[?(@.docs=="Fun impl")].inner.impl.for.dyn_trait.traits[*].trait.id' $t2 diff --git a/tests/rustdoc-json/intra-doc-links/foreign_variant.rs b/tests/rustdoc-json/intra-doc-links/foreign_variant.rs index 251c4884fbb..b3e6f51d23c 100644 --- a/tests/rustdoc-json/intra-doc-links/foreign_variant.rs +++ b/tests/rustdoc-json/intra-doc-links/foreign_variant.rs @@ -8,6 +8,6 @@ pub struct Local; /// local impl impl enum_variant_in_trait_method::Trait for Local {} -//@ !has "$.index[*][?(@.name == 'Trait')]" -//@ !has "$.index[*][?(@.name == 'method')]" -//@ count "$.index[*][?(@.docs == 'local impl')].inner.items[*]" 0 +//@ !has "$.index[?(@.name == 'Trait')]" +//@ !has "$.index[?(@.name == 'method')]" +//@ count "$.index[?(@.docs == 'local impl')].inner.items[*]" 0 diff --git a/tests/rustdoc-json/intra-doc-links/non_page.rs b/tests/rustdoc-json/intra-doc-links/non_page.rs index 00987d93c1e..e2d00ee64e9 100644 --- a/tests/rustdoc-json/intra-doc-links/non_page.rs +++ b/tests/rustdoc-json/intra-doc-links/non_page.rs @@ -7,17 +7,17 @@ //! [`Trait::ASSOC_CONST`] //! [`Trait::method`] -//@ set struct_field = "$.index[*][?(@.name=='struct_field')].id" -//@ set Variant = "$.index[*][?(@.name=='Variant')].id" -//@ set AssocType = "$.index[*][?(@.name=='AssocType')].id" -//@ set ASSOC_CONST = "$.index[*][?(@.name=='ASSOC_CONST')].id" -//@ set method = "$.index[*][?(@.name=='method')].id" +//@ set struct_field = "$.index[?(@.name=='struct_field')].id" +//@ set Variant = "$.index[?(@.name=='Variant')].id" +//@ set AssocType = "$.index[?(@.name=='AssocType')].id" +//@ set ASSOC_CONST = "$.index[?(@.name=='ASSOC_CONST')].id" +//@ set method = "$.index[?(@.name=='method')].id" -//@ is "$.index[*][?(@.name=='non_page')].links['`Struct::struct_field`']" $struct_field -//@ is "$.index[*][?(@.name=='non_page')].links['`Enum::Variant`']" $Variant -//@ is "$.index[*][?(@.name=='non_page')].links['`Trait::AssocType`']" $AssocType -//@ is "$.index[*][?(@.name=='non_page')].links['`Trait::ASSOC_CONST`']" $ASSOC_CONST -//@ is "$.index[*][?(@.name=='non_page')].links['`Trait::method`']" $method +//@ is "$.index[?(@.name=='non_page')].links['`Struct::struct_field`']" $struct_field +//@ is "$.index[?(@.name=='non_page')].links['`Enum::Variant`']" $Variant +//@ is "$.index[?(@.name=='non_page')].links['`Trait::AssocType`']" $AssocType +//@ is "$.index[?(@.name=='non_page')].links['`Trait::ASSOC_CONST`']" $ASSOC_CONST +//@ is "$.index[?(@.name=='non_page')].links['`Trait::method`']" $method pub struct Struct { pub struct_field: i32, diff --git a/tests/rustdoc-json/intra-doc-links/user_written.rs b/tests/rustdoc-json/intra-doc-links/user_written.rs index c3f9df95a8f..97a643490e6 100644 --- a/tests/rustdoc-json/intra-doc-links/user_written.rs +++ b/tests/rustdoc-json/intra-doc-links/user_written.rs @@ -4,5 +4,5 @@ /// To test rustdoc json pub fn foo() {} -//@ set foo = "$.index[*][?(@.name=='foo')].id" -//@ is "$.index[*][?(@.name=='user_written')].links['foo#reasons']" $foo +//@ set foo = "$.index[?(@.name=='foo')].id" +//@ is "$.index[?(@.name=='user_written')].links['foo#reasons']" $foo diff --git a/tests/rustdoc-json/keyword.rs b/tests/rustdoc-json/keyword.rs index 8a2130f1978..566b2c68bd5 100644 --- a/tests/rustdoc-json/keyword.rs +++ b/tests/rustdoc-json/keyword.rs @@ -6,15 +6,15 @@ #![feature(rustdoc_internals)] #![no_std] -//@ !has "$.index[*][?(@.name=='match')]" -//@ has "$.index[*][?(@.name=='foo')]" +//@ !has "$.index[?(@.name=='match')]" +//@ has "$.index[?(@.name=='foo')]" #[doc(keyword = "match")] /// this is a test! pub mod foo {} -//@ !has "$.index[*][?(@.name=='break')]" -//@ !has "$.index[*][?(@.name=='bar')]" +//@ !has "$.index[?(@.name=='break')]" +//@ !has "$.index[?(@.name=='bar')]" #[doc(keyword = "break")] /// hello mod bar {} diff --git a/tests/rustdoc-json/keyword_private.rs b/tests/rustdoc-json/keyword_private.rs index 2a13bf10d5d..fea546c9fb6 100644 --- a/tests/rustdoc-json/keyword_private.rs +++ b/tests/rustdoc-json/keyword_private.rs @@ -3,18 +3,18 @@ //@ compile-flags: --document-private-items #![feature(rustdoc_internals)] -//@ !has "$.index[*][?(@.name=='match')]" -//@ has "$.index[*][?(@.name=='foo')]" -//@ is "$.index[*][?(@.name=='foo')].attrs" '["#[doc(keyword = \"match\")]"]' -//@ is "$.index[*][?(@.name=='foo')].docs" '"this is a test!"' +//@ !has "$.index[?(@.name=='match')]" +//@ has "$.index[?(@.name=='foo')]" +//@ is "$.index[?(@.name=='foo')].attrs" '["#[doc(keyword = \"match\")]"]' +//@ is "$.index[?(@.name=='foo')].docs" '"this is a test!"' #[doc(keyword = "match")] /// this is a test! pub mod foo {} -//@ !has "$.index[*][?(@.name=='break')]" -//@ has "$.index[*][?(@.name=='bar')]" -//@ is "$.index[*][?(@.name=='bar')].attrs" '["#[doc(keyword = \"break\")]"]' -//@ is "$.index[*][?(@.name=='bar')].docs" '"hello"' +//@ !has "$.index[?(@.name=='break')]" +//@ has "$.index[?(@.name=='bar')]" +//@ is "$.index[?(@.name=='bar')].attrs" '["#[doc(keyword = \"break\")]"]' +//@ is "$.index[?(@.name=='bar')].docs" '"hello"' #[doc(keyword = "break")] /// hello mod bar {} diff --git a/tests/rustdoc-json/lifetime/longest.rs b/tests/rustdoc-json/lifetime/longest.rs index 2d4e098d696..50cf084c398 100644 --- a/tests/rustdoc-json/lifetime/longest.rs +++ b/tests/rustdoc-json/lifetime/longest.rs @@ -1,24 +1,24 @@ -//@ is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].name" \"\'a\" -//@ is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].kind" '{"lifetime": {"outlives": []}}' -//@ is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].kind" '{"lifetime": {"outlives": []}}' -//@ count "$.index[*][?(@.name=='longest')].inner.function.generics.params[*]" 1 -//@ is "$.index[*][?(@.name=='longest')].inner.function.generics.where_predicates" [] +//@ is "$.index[?(@.name=='longest')].inner.function.generics.params[0].name" \"\'a\" +//@ is "$.index[?(@.name=='longest')].inner.function.generics.params[0].kind" '{"lifetime": {"outlives": []}}' +//@ is "$.index[?(@.name=='longest')].inner.function.generics.params[0].kind" '{"lifetime": {"outlives": []}}' +//@ count "$.index[?(@.name=='longest')].inner.function.generics.params[*]" 1 +//@ is "$.index[?(@.name=='longest')].inner.function.generics.where_predicates" [] -//@ count "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[*]" 2 -//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][0]" '"l"' -//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][0]" '"r"' +//@ count "$.index[?(@.name=='longest')].inner.function.sig.inputs[*]" 2 +//@ is "$.index[?(@.name=='longest')].inner.function.sig.inputs[0][0]" '"l"' +//@ is "$.index[?(@.name=='longest')].inner.function.sig.inputs[1][0]" '"r"' -//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable" false -//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.type.primitive" \"str\" +//@ is "$.index[?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.lifetime" \"\'a\" +//@ is "$.index[?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable" false +//@ is "$.index[?(@.name=='longest')].inner.function.sig.inputs[0][1].borrowed_ref.type.primitive" \"str\" -//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.is_mutable" false -//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.type.primitive" \"str\" +//@ is "$.index[?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.lifetime" \"\'a\" +//@ is "$.index[?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.is_mutable" false +//@ is "$.index[?(@.name=='longest')].inner.function.sig.inputs[1][1].borrowed_ref.type.primitive" \"str\" -//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.output.borrowed_ref.lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.output.borrowed_ref.is_mutable" false -//@ is "$.index[*][?(@.name=='longest')].inner.function.sig.output.borrowed_ref.type.primitive" \"str\" +//@ is "$.index[?(@.name=='longest')].inner.function.sig.output.borrowed_ref.lifetime" \"\'a\" +//@ is "$.index[?(@.name=='longest')].inner.function.sig.output.borrowed_ref.is_mutable" false +//@ is "$.index[?(@.name=='longest')].inner.function.sig.output.borrowed_ref.type.primitive" \"str\" pub fn longest<'a>(l: &'a str, r: &'a str) -> &'a str { if l.len() > r.len() { l } else { r } diff --git a/tests/rustdoc-json/lifetime/outlives.rs b/tests/rustdoc-json/lifetime/outlives.rs index 257e43985ac..f191b386c6c 100644 --- a/tests/rustdoc-json/lifetime/outlives.rs +++ b/tests/rustdoc-json/lifetime/outlives.rs @@ -1,16 +1,16 @@ -//@ count "$.index[*][?(@.name=='foo')].inner.function.generics.params[*]" 3 -//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates" [] -//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[0].name" \"\'a\" -//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[1].name" \"\'b\" -//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].name" '"T"' -//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[0].kind.lifetime.outlives" [] -//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[1].kind.lifetime.outlives" [\"\'a\"] -//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.default" null -//@ count "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[*]" 1 -//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[0].outlives" \"\'b\" -//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable" false -//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.lifetime" \"\'b\" -//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.is_mutable" false -//@ is "$.index[*][?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.type.generic" \"T\" +//@ count "$.index[?(@.name=='foo')].inner.function.generics.params[*]" 3 +//@ is "$.index[?(@.name=='foo')].inner.function.generics.where_predicates" [] +//@ is "$.index[?(@.name=='foo')].inner.function.generics.params[0].name" \"\'a\" +//@ is "$.index[?(@.name=='foo')].inner.function.generics.params[1].name" \"\'b\" +//@ is "$.index[?(@.name=='foo')].inner.function.generics.params[2].name" '"T"' +//@ is "$.index[?(@.name=='foo')].inner.function.generics.params[0].kind.lifetime.outlives" [] +//@ is "$.index[?(@.name=='foo')].inner.function.generics.params[1].kind.lifetime.outlives" [\"\'a\"] +//@ is "$.index[?(@.name=='foo')].inner.function.generics.params[2].kind.type.default" null +//@ count "$.index[?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[*]" 1 +//@ is "$.index[?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[0].outlives" \"\'b\" +//@ is "$.index[?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.lifetime" \"\'a\" +//@ is "$.index[?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable" false +//@ is "$.index[?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.lifetime" \"\'b\" +//@ is "$.index[?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.is_mutable" false +//@ is "$.index[?(@.name=='foo')].inner.function.sig.inputs[0][1].borrowed_ref.type.borrowed_ref.type.generic" \"T\" pub fn foo<'a, 'b: 'a, T: 'b>(_: &'a &'b T) {} diff --git a/tests/rustdoc-json/lifetime/outlives_in_param.rs b/tests/rustdoc-json/lifetime/outlives_in_param.rs index 55ff5250541..dc9f57ff8a1 100644 --- a/tests/rustdoc-json/lifetime/outlives_in_param.rs +++ b/tests/rustdoc-json/lifetime/outlives_in_param.rs @@ -1,6 +1,6 @@ -//@ count '$.index[*][?(@.name=="outlives")].inner.function.generics.params[*]' 2 -//@ is '$.index[*][?(@.name=="outlives")].inner.function.generics.params[0].name' \"\'a\" -//@ is '$.index[*][?(@.name=="outlives")].inner.function.generics.params[0].kind.lifetime.outlives' [] -//@ is '$.index[*][?(@.name=="outlives")].inner.function.generics.params[1].name' '"T"' -//@ is '$.index[*][?(@.name=="outlives")].inner.function.generics.params[1].kind.type.bounds' '[{"outlives": "'\''a"}]' +//@ count '$.index[?(@.name=="outlives")].inner.function.generics.params[*]' 2 +//@ is '$.index[?(@.name=="outlives")].inner.function.generics.params[0].name' \"\'a\" +//@ is '$.index[?(@.name=="outlives")].inner.function.generics.params[0].kind.lifetime.outlives' [] +//@ is '$.index[?(@.name=="outlives")].inner.function.generics.params[1].name' '"T"' +//@ is '$.index[?(@.name=="outlives")].inner.function.generics.params[1].kind.type.bounds' '[{"outlives": "'\''a"}]' pub fn outlives<'a, T: 'a>() {} diff --git a/tests/rustdoc-json/lifetime/outlives_in_where.rs b/tests/rustdoc-json/lifetime/outlives_in_where.rs index 5158ff118a0..48faf8ff830 100644 --- a/tests/rustdoc-json/lifetime/outlives_in_where.rs +++ b/tests/rustdoc-json/lifetime/outlives_in_where.rs @@ -1,20 +1,20 @@ -//@ is '$.index[*][?(@.name=="on_lifetimes")].inner.function.generics.where_predicates' '[{"lifetime_predicate": {"lifetime": "'\''all", "outlives": ["'\''a", "'\''b", "'\''c"]}}]' +//@ is '$.index[?(@.name=="on_lifetimes")].inner.function.generics.where_predicates' '[{"lifetime_predicate": {"lifetime": "'\''all", "outlives": ["'\''a", "'\''b", "'\''c"]}}]' pub fn on_lifetimes<'a, 'b, 'c, 'all>() where 'all: 'a + 'b + 'c, { } -//@ count '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[*]' 2 -//@ is '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[0].name' \"\'a\" -//@ is '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[0].kind.lifetime.outlives' [] -//@ is '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[1].name' '"T"' -//@ is '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[1].kind.type.bounds' [] -//@ is '$.index[*][?(@.name=="on_trait")].inner.function.generics.params[1].kind.type.bounds' [] -//@ count '$.index[*][?(@.name=="on_trait")].inner.function.generics.where_predicates[*]' 1 -//@ is '$.index[*][?(@.name=="on_trait")].inner.function.generics.where_predicates[0].bound_predicate.type.generic' '"T"' -//@ count '$.index[*][?(@.name=="on_trait")].inner.function.generics.where_predicates[0].bound_predicate.bounds[*]' 1 -//@ is '$.index[*][?(@.name=="on_trait")].inner.function.generics.where_predicates[0].bound_predicate.bounds[0].outlives' \"\'a\" +//@ count '$.index[?(@.name=="on_trait")].inner.function.generics.params[*]' 2 +//@ is '$.index[?(@.name=="on_trait")].inner.function.generics.params[0].name' \"\'a\" +//@ is '$.index[?(@.name=="on_trait")].inner.function.generics.params[0].kind.lifetime.outlives' [] +//@ is '$.index[?(@.name=="on_trait")].inner.function.generics.params[1].name' '"T"' +//@ is '$.index[?(@.name=="on_trait")].inner.function.generics.params[1].kind.type.bounds' [] +//@ is '$.index[?(@.name=="on_trait")].inner.function.generics.params[1].kind.type.bounds' [] +//@ count '$.index[?(@.name=="on_trait")].inner.function.generics.where_predicates[*]' 1 +//@ is '$.index[?(@.name=="on_trait")].inner.function.generics.where_predicates[0].bound_predicate.type.generic' '"T"' +//@ count '$.index[?(@.name=="on_trait")].inner.function.generics.where_predicates[0].bound_predicate.bounds[*]' 1 +//@ is '$.index[?(@.name=="on_trait")].inner.function.generics.where_predicates[0].bound_predicate.bounds[0].outlives' \"\'a\" pub fn on_trait<'a, T>() where T: 'a, diff --git a/tests/rustdoc-json/methods/abi.rs b/tests/rustdoc-json/methods/abi.rs index dac02a6ce3c..fa2387ddf67 100644 --- a/tests/rustdoc-json/methods/abi.rs +++ b/tests/rustdoc-json/methods/abi.rs @@ -1,50 +1,50 @@ #![feature(abi_vectorcall)] -//@ has "$.index[*][?(@.name=='Foo')]" +//@ has "$.index[?(@.name=='Foo')]" pub struct Foo; impl Foo { - //@ is "$.index[*][?(@.name=='abi_rust')].inner.function.header.abi" \"Rust\" + //@ is "$.index[?(@.name=='abi_rust')].inner.function.header.abi" \"Rust\" pub fn abi_rust() {} - //@ is "$.index[*][?(@.name=='abi_c')].inner.function.header.abi" '{"C": {"unwind": false}}' + //@ is "$.index[?(@.name=='abi_c')].inner.function.header.abi" '{"C": {"unwind": false}}' pub extern "C" fn abi_c() {} - //@ is "$.index[*][?(@.name=='abi_system')].inner.function.header.abi" '{"System": {"unwind": false}}' + //@ is "$.index[?(@.name=='abi_system')].inner.function.header.abi" '{"System": {"unwind": false}}' pub extern "system" fn abi_system() {} - //@ is "$.index[*][?(@.name=='abi_c_unwind')].inner.function.header.abi" '{"C": {"unwind": true}}' + //@ is "$.index[?(@.name=='abi_c_unwind')].inner.function.header.abi" '{"C": {"unwind": true}}' pub extern "C-unwind" fn abi_c_unwind() {} - //@ is "$.index[*][?(@.name=='abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}' + //@ is "$.index[?(@.name=='abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}' pub extern "system-unwind" fn abi_system_unwind() {} - //@ is "$.index[*][?(@.name=='abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""' + //@ is "$.index[?(@.name=='abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""' pub extern "vectorcall" fn abi_vectorcall() {} - //@ is "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""' + //@ is "$.index[?(@.name=='abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""' pub extern "vectorcall-unwind" fn abi_vectorcall_unwind() {} } pub trait Bar { - //@ is "$.index[*][?(@.name=='trait_abi_rust')].inner.function.header.abi" \"Rust\" + //@ is "$.index[?(@.name=='trait_abi_rust')].inner.function.header.abi" \"Rust\" fn trait_abi_rust() {} - //@ is "$.index[*][?(@.name=='trait_abi_c')].inner.function.header.abi" '{"C": {"unwind": false}}' + //@ is "$.index[?(@.name=='trait_abi_c')].inner.function.header.abi" '{"C": {"unwind": false}}' extern "C" fn trait_abi_c() {} - //@ is "$.index[*][?(@.name=='trait_abi_system')].inner.function.header.abi" '{"System": {"unwind": false}}' + //@ is "$.index[?(@.name=='trait_abi_system')].inner.function.header.abi" '{"System": {"unwind": false}}' extern "system" fn trait_abi_system() {} - //@ is "$.index[*][?(@.name=='trait_abi_c_unwind')].inner.function.header.abi" '{"C": {"unwind": true}}' + //@ is "$.index[?(@.name=='trait_abi_c_unwind')].inner.function.header.abi" '{"C": {"unwind": true}}' extern "C-unwind" fn trait_abi_c_unwind() {} - //@ is "$.index[*][?(@.name=='trait_abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}' + //@ is "$.index[?(@.name=='trait_abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}' extern "system-unwind" fn trait_abi_system_unwind() {} - //@ is "$.index[*][?(@.name=='trait_abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""' + //@ is "$.index[?(@.name=='trait_abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""' extern "vectorcall" fn trait_abi_vectorcall() {} - //@ is "$.index[*][?(@.name=='trait_abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""' + //@ is "$.index[?(@.name=='trait_abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""' extern "vectorcall-unwind" fn trait_abi_vectorcall_unwind() {} } diff --git a/tests/rustdoc-json/methods/qualifiers.rs b/tests/rustdoc-json/methods/qualifiers.rs index ba7c2e60936..b1d9f0c1af3 100644 --- a/tests/rustdoc-json/methods/qualifiers.rs +++ b/tests/rustdoc-json/methods/qualifiers.rs @@ -3,34 +3,34 @@ pub struct Foo; impl Foo { - //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.is_async" false - //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.is_const" true - //@ is "$.index[*][?(@.name=='const_meth')].inner.function.header.is_unsafe" false + //@ is "$.index[?(@.name=='const_meth')].inner.function.header.is_async" false + //@ is "$.index[?(@.name=='const_meth')].inner.function.header.is_const" true + //@ is "$.index[?(@.name=='const_meth')].inner.function.header.is_unsafe" false pub const fn const_meth() {} - //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.is_async" false - //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.is_const" false - //@ is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.is_unsafe" false + //@ is "$.index[?(@.name=='nothing_meth')].inner.function.header.is_async" false + //@ is "$.index[?(@.name=='nothing_meth')].inner.function.header.is_const" false + //@ is "$.index[?(@.name=='nothing_meth')].inner.function.header.is_unsafe" false pub fn nothing_meth() {} - //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.is_async" false - //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.is_const" false - //@ is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.is_unsafe" true + //@ is "$.index[?(@.name=='unsafe_meth')].inner.function.header.is_async" false + //@ is "$.index[?(@.name=='unsafe_meth')].inner.function.header.is_const" false + //@ is "$.index[?(@.name=='unsafe_meth')].inner.function.header.is_unsafe" true pub unsafe fn unsafe_meth() {} - //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.is_async" true - //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.is_const" false - //@ is "$.index[*][?(@.name=='async_meth')].inner.function.header.is_unsafe" false + //@ is "$.index[?(@.name=='async_meth')].inner.function.header.is_async" true + //@ is "$.index[?(@.name=='async_meth')].inner.function.header.is_const" false + //@ is "$.index[?(@.name=='async_meth')].inner.function.header.is_unsafe" false pub async fn async_meth() {} - //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.is_async" true - //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.is_const" false - //@ is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.is_unsafe" true + //@ is "$.index[?(@.name=='async_unsafe_meth')].inner.function.header.is_async" true + //@ is "$.index[?(@.name=='async_unsafe_meth')].inner.function.header.is_const" false + //@ is "$.index[?(@.name=='async_unsafe_meth')].inner.function.header.is_unsafe" true pub async unsafe fn async_unsafe_meth() {} - //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.is_async" false - //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.is_const" true - //@ is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.is_unsafe" true + //@ is "$.index[?(@.name=='const_unsafe_meth')].inner.function.header.is_async" false + //@ is "$.index[?(@.name=='const_unsafe_meth')].inner.function.header.is_const" true + //@ is "$.index[?(@.name=='const_unsafe_meth')].inner.function.header.is_unsafe" true pub const unsafe fn const_unsafe_meth() {} // It's impossible for a method to be both const and async, so no test for that diff --git a/tests/rustdoc-json/nested.rs b/tests/rustdoc-json/nested.rs index 10ec2831c21..8cc564706d6 100644 --- a/tests/rustdoc-json/nested.rs +++ b/tests/rustdoc-json/nested.rs @@ -2,31 +2,31 @@ //@ compile-flags: --crate-version 1.0.0 //@ is "$.crate_version" \"1.0.0\" -//@ has "$.index[*][?(@.name=='nested')].inner.module" -//@ is "$.index[*][?(@.name=='nested')].inner.module.is_crate" true +//@ has "$.index[?(@.name=='nested')].inner.module" +//@ is "$.index[?(@.name=='nested')].inner.module.is_crate" true -//@ set l1_id = "$.index[*][?(@.name=='l1')].id" -//@ ismany "$.index[*][?(@.name=='nested')].inner.module.items[*]" $l1_id +//@ set l1_id = "$.index[?(@.name=='l1')].id" +//@ ismany "$.index[?(@.name=='nested')].inner.module.items[*]" $l1_id -//@ has "$.index[*][?(@.name=='l1')].inner.module" -//@ is "$.index[*][?(@.name=='l1')].inner.module.is_crate" false +//@ has "$.index[?(@.name=='l1')].inner.module" +//@ is "$.index[?(@.name=='l1')].inner.module.is_crate" false pub mod l1 { - //@ has "$.index[*][?(@.name=='l3')].inner.module" - //@ is "$.index[*][?(@.name=='l3')].inner.module.is_crate" false - //@ set l3_id = "$.index[*][?(@.name=='l3')].id" + //@ has "$.index[?(@.name=='l3')].inner.module" + //@ is "$.index[?(@.name=='l3')].inner.module.is_crate" false + //@ set l3_id = "$.index[?(@.name=='l3')].id" pub mod l3 { - //@ has "$.index[*][?(@.name=='L4')].inner.struct" - //@ is "$.index[*][?(@.name=='L4')].inner.struct.kind" '"unit"' - //@ set l4_id = "$.index[*][?(@.name=='L4')].id" - //@ ismany "$.index[*][?(@.name=='l3')].inner.module.items[*]" $l4_id + //@ has "$.index[?(@.name=='L4')].inner.struct" + //@ is "$.index[?(@.name=='L4')].inner.struct.kind" '"unit"' + //@ set l4_id = "$.index[?(@.name=='L4')].id" + //@ ismany "$.index[?(@.name=='l3')].inner.module.items[*]" $l4_id pub struct L4; } - //@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" false - //@ is "$.index[*][?(@.inner.use)].inner.use.source" '"l3::L4"' - //@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" false - //@ is "$.index[*][?(@.inner.use)].inner.use.id" $l4_id - //@ set l4_use_id = "$.index[*][?(@.inner.use)].id" + //@ is "$.index[?(@.inner.use)].inner.use.is_glob" false + //@ is "$.index[?(@.inner.use)].inner.use.source" '"l3::L4"' + //@ is "$.index[?(@.inner.use)].inner.use.is_glob" false + //@ is "$.index[?(@.inner.use)].inner.use.id" $l4_id + //@ set l4_use_id = "$.index[?(@.inner.use)].id" pub use l3::L4; } -//@ ismany "$.index[*][?(@.name=='l1')].inner.module.items[*]" $l3_id $l4_use_id +//@ ismany "$.index[?(@.name=='l1')].inner.module.items[*]" $l3_id $l4_use_id diff --git a/tests/rustdoc-json/non_lifetime_binders.rs b/tests/rustdoc-json/non_lifetime_binders.rs index 7c518a8f5a7..84318821c50 100644 --- a/tests/rustdoc-json/non_lifetime_binders.rs +++ b/tests/rustdoc-json/non_lifetime_binders.rs @@ -5,11 +5,11 @@ pub trait Trait {} pub struct Wrapper<T_>(std::marker::PhantomData<T_>); -//@ count "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[*]" 2 -//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].name" \"\'a\" -//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }' -//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].name" \"T\" -//@ is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].kind" '{ "type": { "bounds": [], "default": null, "is_synthetic": false } }' +//@ count "$.index[?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[*]" 2 +//@ is "$.index[?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].name" \"\'a\" +//@ is "$.index[?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }' +//@ is "$.index[?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].name" \"T\" +//@ is "$.index[?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].kind" '{ "type": { "bounds": [], "default": null, "is_synthetic": false } }' pub fn foo() where for<'a, T> &'a Wrapper<T>: Trait, diff --git a/tests/rustdoc-json/output_generics.rs b/tests/rustdoc-json/output_generics.rs index 3454f421636..4d4339ceb23 100644 --- a/tests/rustdoc-json/output_generics.rs +++ b/tests/rustdoc-json/output_generics.rs @@ -2,11 +2,11 @@ // This is a regression test for #98009. -//@ has "$.index[*][?(@.name=='this_compiles')]" -//@ has "$.index[*][?(@.name=='this_does_not')]" -//@ has "$.index[*][?(@.name=='Events')]" -//@ has "$.index[*][?(@.name=='Other')]" -//@ has "$.index[*][?(@.name=='Trait')]" +//@ has "$.index[?(@.name=='this_compiles')]" +//@ has "$.index[?(@.name=='this_does_not')]" +//@ has "$.index[?(@.name=='Events')]" +//@ has "$.index[?(@.name=='Other')]" +//@ has "$.index[?(@.name=='Trait')]" struct Events<R>(R); diff --git a/tests/rustdoc-json/path_name.rs b/tests/rustdoc-json/path_name.rs index a1b3ae294fa..dcfaa0607c4 100644 --- a/tests/rustdoc-json/path_name.rs +++ b/tests/rustdoc-json/path_name.rs @@ -19,49 +19,49 @@ pub use priv_mod::{InPrivMod, InPrivMod as InPrivMod2}; use pub_mod::InPubMod as InPubMod3; pub use pub_mod::{InPubMod, InPubMod as InPubMod2}; -//@ is "$.index[*][?(@.name=='T0')].inner.type_alias.type.resolved_path.path" '"priv_mod::InPrivMod"' +//@ is "$.index[?(@.name=='T0')].inner.type_alias.type.resolved_path.path" '"priv_mod::InPrivMod"' pub type T0 = priv_mod::InPrivMod; -//@ is "$.index[*][?(@.name=='T1')].inner.type_alias.type.resolved_path.path" '"InPrivMod"' +//@ is "$.index[?(@.name=='T1')].inner.type_alias.type.resolved_path.path" '"InPrivMod"' pub type T1 = InPrivMod; -//@ is "$.index[*][?(@.name=='T2')].inner.type_alias.type.resolved_path.path" '"InPrivMod2"' +//@ is "$.index[?(@.name=='T2')].inner.type_alias.type.resolved_path.path" '"InPrivMod2"' pub type T2 = InPrivMod2; -//@ is "$.index[*][?(@.name=='T3')].inner.type_alias.type.resolved_path.path" '"priv_mod::InPrivMod"' +//@ is "$.index[?(@.name=='T3')].inner.type_alias.type.resolved_path.path" '"priv_mod::InPrivMod"' pub type T3 = InPrivMod3; -//@ is "$.index[*][?(@.name=='U0')].inner.type_alias.type.resolved_path.path" '"pub_mod::InPubMod"' +//@ is "$.index[?(@.name=='U0')].inner.type_alias.type.resolved_path.path" '"pub_mod::InPubMod"' pub type U0 = pub_mod::InPubMod; -//@ is "$.index[*][?(@.name=='U1')].inner.type_alias.type.resolved_path.path" '"InPubMod"' +//@ is "$.index[?(@.name=='U1')].inner.type_alias.type.resolved_path.path" '"InPubMod"' pub type U1 = InPubMod; -//@ is "$.index[*][?(@.name=='U2')].inner.type_alias.type.resolved_path.path" '"InPubMod2"' +//@ is "$.index[?(@.name=='U2')].inner.type_alias.type.resolved_path.path" '"InPubMod2"' pub type U2 = InPubMod2; -//@ is "$.index[*][?(@.name=='U3')].inner.type_alias.type.resolved_path.path" '"pub_mod::InPubMod"' +//@ is "$.index[?(@.name=='U3')].inner.type_alias.type.resolved_path.path" '"pub_mod::InPubMod"' pub type U3 = InPubMod3; // Check we only have paths for structs at their original path -//@ ismany "$.paths[*][?(@.crate_id==0 && @.kind=='struct')].path" '["path_name", "priv_mod", "InPrivMod"]' '["path_name", "pub_mod", "InPubMod"]' +//@ ismany "$.paths[?(@.crate_id==0 && @.kind=='struct')].path" '["path_name", "priv_mod", "InPrivMod"]' '["path_name", "pub_mod", "InPubMod"]' pub use defines_and_reexports::{InPrivMod as XPrivMod, InPubMod as XPubMod}; use defines_and_reexports::{InPrivMod as XPrivMod2, InPubMod as XPubMod2}; -//@ is "$.index[*][?(@.name=='X0')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::m1::InPubMod"' +//@ is "$.index[?(@.name=='X0')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::m1::InPubMod"' pub type X0 = defines_and_reexports::m1::InPubMod; -//@ is "$.index[*][?(@.name=='X1')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod"' +//@ is "$.index[?(@.name=='X1')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod"' pub type X1 = defines_and_reexports::InPubMod; -//@ is "$.index[*][?(@.name=='X2')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod2"' +//@ is "$.index[?(@.name=='X2')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod2"' pub type X2 = defines_and_reexports::InPubMod2; -//@ is "$.index[*][?(@.name=='X3')].inner.type_alias.type.resolved_path.path" '"XPubMod"' +//@ is "$.index[?(@.name=='X3')].inner.type_alias.type.resolved_path.path" '"XPubMod"' pub type X3 = XPubMod; // N.B. This isn't the path as used *or* the original path! -//@ is "$.index[*][?(@.name=='X4')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod"' +//@ is "$.index[?(@.name=='X4')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod"' pub type X4 = XPubMod2; -//@ is "$.index[*][?(@.name=='Y1')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod"' +//@ is "$.index[?(@.name=='Y1')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod"' pub type Y1 = defines_and_reexports::InPrivMod; -//@ is "$.index[*][?(@.name=='Y2')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod2"' +//@ is "$.index[?(@.name=='Y2')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod2"' pub type Y2 = defines_and_reexports::InPrivMod2; -//@ is "$.index[*][?(@.name=='Y3')].inner.type_alias.type.resolved_path.path" '"XPrivMod"' +//@ is "$.index[?(@.name=='Y3')].inner.type_alias.type.resolved_path.path" '"XPrivMod"' pub type Y3 = XPrivMod; -//@ is "$.index[*][?(@.name=='Y4')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod"' +//@ is "$.index[?(@.name=='Y4')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod"' pub type Y4 = XPrivMod2; // For foreign items, $.paths contains the *origional* path, even if it's not publicly @@ -74,9 +74,9 @@ pub type Y4 = XPrivMod2; // Tests for the example in the docs of Path::name. // If these change, chage the docs. -//@ is "$.index[*][?(@.name=='Vec1')].inner.type_alias.type.resolved_path.path" '"std::vec::Vec"' +//@ is "$.index[?(@.name=='Vec1')].inner.type_alias.type.resolved_path.path" '"std::vec::Vec"' pub type Vec1 = std::vec::Vec<i32>; -//@ is "$.index[*][?(@.name=='Vec2')].inner.type_alias.type.resolved_path.path" '"Vec"' +//@ is "$.index[?(@.name=='Vec2')].inner.type_alias.type.resolved_path.path" '"Vec"' pub type Vec2 = Vec<i32>; -//@ is "$.index[*][?(@.name=='Vec3')].inner.type_alias.type.resolved_path.path" '"std::prelude::v1::Vec"' +//@ is "$.index[?(@.name=='Vec3')].inner.type_alias.type.resolved_path.path" '"std::prelude::v1::Vec"' pub type Vec3 = std::prelude::v1::Vec<i32>; diff --git a/tests/rustdoc-json/primitives/local_primitive.rs b/tests/rustdoc-json/primitives/local_primitive.rs index b10ae45f3ec..b58120bae05 100644 --- a/tests/rustdoc-json/primitives/local_primitive.rs +++ b/tests/rustdoc-json/primitives/local_primitive.rs @@ -11,11 +11,11 @@ #[rustc_doc_primitive = "i32"] mod prim_i32 {} -//@ set local_i32 = "$.index[*][?(@.name=='i32')].id" +//@ set local_i32 = "$.index[?(@.name=='i32')].id" -//@ has "$.index[*][?(@.name=='local_primitive')]" -//@ ismany "$.index[*][?(@.name=='local_primitive')].inner.module.items[*]" $local_i32 -//@ is "$.index[*][?(@.name=='local_primitive')].links['prim@i32']" $local_i32 +//@ has "$.index[?(@.name=='local_primitive')]" +//@ ismany "$.index[?(@.name=='local_primitive')].inner.module.items[*]" $local_i32 +//@ is "$.index[?(@.name=='local_primitive')].links['prim@i32']" $local_i32 // Let's ensure the `prim_i32` module isn't present in the output JSON: -//@ !has "$.index[*][?(@.name=='prim_i32')]" +//@ !has "$.index[?(@.name=='prim_i32')]" diff --git a/tests/rustdoc-json/primitives/primitive_impls.rs b/tests/rustdoc-json/primitives/primitive_impls.rs index 58c222ce4f0..a1f0ebd11b6 100644 --- a/tests/rustdoc-json/primitives/primitive_impls.rs +++ b/tests/rustdoc-json/primitives/primitive_impls.rs @@ -4,26 +4,26 @@ #![no_core] #![rustc_coherence_is_core] -//@ set impl_i32 = "$.index[*][?(@.docs=='Only core can do this')].id" +//@ set impl_i32 = "$.index[?(@.docs=='Only core can do this')].id" #[lang = "sized"] trait Sized {} /// Only core can do this impl i32 { - //@ set identity = "$.index[*][?(@.docs=='Do Nothing')].id" + //@ set identity = "$.index[?(@.docs=='Do Nothing')].id" /// Do Nothing pub fn identity(self) -> Self { self } - //@ is "$.index[*][?(@.docs=='Only core can do this')].inner.impl.items[*]" $identity + //@ is "$.index[?(@.docs=='Only core can do this')].inner.impl.items[*]" $identity } -//@ set Trait = "$.index[*][?(@.name=='Trait')].id" +//@ set Trait = "$.index[?(@.name=='Trait')].id" pub trait Trait {} -//@ set impl_trait_for_i32 = "$.index[*][?(@.docs=='impl Trait for i32')].id" +//@ set impl_trait_for_i32 = "$.index[?(@.docs=='impl Trait for i32')].id" /// impl Trait for i32 impl Trait for i32 {} @@ -31,7 +31,7 @@ impl Trait for i32 {} #[rustc_doc_primitive = "i32"] mod prim_i32 {} -//@ set i32 = "$.index[*][?(@.docs=='i32')].id" -//@ is "$.index[*][?(@.docs=='i32')].name" '"i32"' -//@ is "$.index[*][?(@.docs=='i32')].inner.primitive.name" '"i32"' -//@ ismany "$.index[*][?(@.docs=='i32')].inner.primitive.impls[*]" $impl_i32 $impl_trait_for_i32 +//@ set i32 = "$.index[?(@.docs=='i32')].id" +//@ is "$.index[?(@.docs=='i32')].name" '"i32"' +//@ is "$.index[?(@.docs=='i32')].inner.primitive.name" '"i32"' +//@ ismany "$.index[?(@.docs=='i32')].inner.primitive.impls[*]" $impl_i32 $impl_trait_for_i32 diff --git a/tests/rustdoc-json/primitives/primitive_overloading.rs b/tests/rustdoc-json/primitives/primitive_overloading.rs index 5e5f3974ab3..ae0306843c5 100644 --- a/tests/rustdoc-json/primitives/primitive_overloading.rs +++ b/tests/rustdoc-json/primitives/primitive_overloading.rs @@ -4,8 +4,8 @@ #![feature(rustc_attrs)] -//@ has "$.index[*][?(@.name=='usize')]" -//@ has "$.index[*][?(@.name=='prim')]" +//@ has "$.index[?(@.name=='usize')]" +//@ has "$.index[?(@.name=='prim')]" #[rustc_doc_primitive = "usize"] /// This is the built-in type `usize`. diff --git a/tests/rustdoc-json/primitives/primitive_type.rs b/tests/rustdoc-json/primitives/primitive_type.rs index 21ef5ab7196..a0d34218b80 100644 --- a/tests/rustdoc-json/primitives/primitive_type.rs +++ b/tests/rustdoc-json/primitives/primitive_type.rs @@ -1,17 +1,17 @@ #![feature(never_type)] -//@ is "$.index[*][?(@.name=='PrimNever')].visibility" \"public\" -//@ is "$.index[*][?(@.name=='PrimNever')].inner.type_alias.type.primitive" \"never\" +//@ is "$.index[?(@.name=='PrimNever')].visibility" \"public\" +//@ is "$.index[?(@.name=='PrimNever')].inner.type_alias.type.primitive" \"never\" pub type PrimNever = !; -//@ is "$.index[*][?(@.name=='PrimStr')].inner.type_alias.type.primitive" \"str\" +//@ is "$.index[?(@.name=='PrimStr')].inner.type_alias.type.primitive" \"str\" pub type PrimStr = str; -//@ is "$.index[*][?(@.name=='PrimBool')].inner.type_alias.type.primitive" \"bool\" +//@ is "$.index[?(@.name=='PrimBool')].inner.type_alias.type.primitive" \"bool\" pub type PrimBool = bool; -//@ is "$.index[*][?(@.name=='PrimChar')].inner.type_alias.type.primitive" \"char\" +//@ is "$.index[?(@.name=='PrimChar')].inner.type_alias.type.primitive" \"char\" pub type PrimChar = char; -//@ is "$.index[*][?(@.name=='PrimU8')].inner.type_alias.type.primitive" \"u8\" +//@ is "$.index[?(@.name=='PrimU8')].inner.type_alias.type.primitive" \"u8\" pub type PrimU8 = u8; diff --git a/tests/rustdoc-json/primitives/use_primitive.rs b/tests/rustdoc-json/primitives/use_primitive.rs index d4cdef84de8..2991cc1e47c 100644 --- a/tests/rustdoc-json/primitives/use_primitive.rs +++ b/tests/rustdoc-json/primitives/use_primitive.rs @@ -5,15 +5,15 @@ #[rustc_doc_primitive = "usize"] mod usize {} -//@ set local_crate_id = "$.index[*][?(@.name=='use_primitive')].crate_id" +//@ set local_crate_id = "$.index[?(@.name=='use_primitive')].crate_id" -//@ has "$.index[*][?(@.name=='ilog10')]" -//@ !is "$.index[*][?(@.name=='ilog10')].crate_id" $local_crate_id -//@ has "$.index[*][?(@.name=='checked_add')]" -//@ !is "$.index[*][?(@.name=='checked_add')]" $local_crate_id -//@ !has "$.index[*][?(@.name=='is_ascii_uppercase')]" +//@ has "$.index[?(@.name=='ilog10')]" +//@ !is "$.index[?(@.name=='ilog10')].crate_id" $local_crate_id +//@ has "$.index[?(@.name=='checked_add')]" +//@ !is "$.index[?(@.name=='checked_add')]" $local_crate_id +//@ !has "$.index[?(@.name=='is_ascii_uppercase')]" -//@ is "$.index[*].inner.use[?(@.name=='my_i32')].id" null +//@ is "$.index[?(@.inner.use.name=='my_i32')].inner.use.id" null pub use i32 as my_i32; -//@ is "$.index[*].inner.use[?(@.name=='u32')].id" null +//@ is "$.index[?(@.inner.use.name=='u32')].inner.use.id" null pub use u32; diff --git a/tests/rustdoc-json/pub_mod_in_private_mod.rs b/tests/rustdoc-json/pub_mod_in_private_mod.rs index 112ab9c68f0..8b31ad0bcfe 100644 --- a/tests/rustdoc-json/pub_mod_in_private_mod.rs +++ b/tests/rustdoc-json/pub_mod_in_private_mod.rs @@ -1,6 +1,6 @@ // See https://github.com/rust-lang/rust/issues/101105 -//@ !has "$.index[*][?(@.name=='nucleus')]" +//@ !has "$.index[?(@.name=='nucleus')]" mod corpus { pub mod nucleus {} } diff --git a/tests/rustdoc-json/reexport/doc_inline_external_crate.rs b/tests/rustdoc-json/reexport/doc_inline_external_crate.rs index 4debd395496..f7067857ddf 100644 --- a/tests/rustdoc-json/reexport/doc_inline_external_crate.rs +++ b/tests/rustdoc-json/reexport/doc_inline_external_crate.rs @@ -4,7 +4,7 @@ #[doc(inline)] pub extern crate enum_with_discriminant; -//@ !has '$.index[*][?(@.docs == "Should not be inlined")]' -//@ has '$.index[*][?(@.name == "enum_with_discriminant")].inner.extern_crate' -//@ set enum_with_discriminant = '$.index[*][?(@.name == "enum_with_discriminant")].id' -//@ is '$.index[*][?(@.name == "doc_inline_external_crate")].inner.module.items[*]' $enum_with_discriminant +//@ !has '$.index[?(@.docs == "Should not be inlined")]' +//@ has '$.index[?(@.name == "enum_with_discriminant")].inner.extern_crate' +//@ set enum_with_discriminant = '$.index[?(@.name == "enum_with_discriminant")].id' +//@ is '$.index[?(@.name == "doc_inline_external_crate")].inner.module.items[*]' $enum_with_discriminant diff --git a/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs b/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs index 4efacd283ef..746749e0204 100644 --- a/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs +++ b/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs @@ -2,5 +2,5 @@ #![crate_name = "export_extern_crate_as_self"] -//@ is "$.index[*][?(@.inner.module)].name" \"export_extern_crate_as_self\" +//@ is "$.index[?(@.inner.module)].name" \"export_extern_crate_as_self\" pub extern crate self as export_extern_crate_as_self; // Must be the same name as the crate already has diff --git a/tests/rustdoc-json/reexport/extern_crate_glob.rs b/tests/rustdoc-json/reexport/extern_crate_glob.rs index dfe6e7a03b1..8a4388feaca 100644 --- a/tests/rustdoc-json/reexport/extern_crate_glob.rs +++ b/tests/rustdoc-json/reexport/extern_crate_glob.rs @@ -5,7 +5,7 @@ extern crate enum_with_discriminant; #[doc(inline)] pub use enum_with_discriminant::*; -//@ !has '$.index[*][?(@.docs == "Should not be inlined")]' -//@ is '$.index[*][?(@.inner.use)].inner.use.name' \"enum_with_discriminant\" -//@ set use = '$.index[*][?(@.inner.use)].id' -//@ is '$.index[*][?(@.name == "extern_crate_glob")].inner.module.items[*]' $use +//@ !has '$.index[?(@.docs == "Should not be inlined")]' +//@ is '$.index[?(@.inner.use)].inner.use.name' \"enum_with_discriminant\" +//@ set use = '$.index[?(@.inner.use)].id' +//@ is '$.index[?(@.name == "extern_crate_glob")].inner.module.items[*]' $use diff --git a/tests/rustdoc-json/reexport/glob_collision.rs b/tests/rustdoc-json/reexport/glob_collision.rs index 8142c35f4c7..48de1b5e772 100644 --- a/tests/rustdoc-json/reexport/glob_collision.rs +++ b/tests/rustdoc-json/reexport/glob_collision.rs @@ -1,27 +1,27 @@ // Regression test for https://github.com/rust-lang/rust/issues/100973 -//@ set m1 = "$.index[*][?(@.name == 'm1' && @.inner.module)].id" -//@ is "$.index[*][?(@.name == 'm1')].inner.module.items" [] -//@ is "$.index[*][?(@.name == 'm1')].inner.module.is_stripped" true +//@ set m1 = "$.index[?(@.name == 'm1' && @.inner.module)].id" +//@ is "$.index[?(@.name == 'm1')].inner.module.items" [] +//@ is "$.index[?(@.name == 'm1')].inner.module.is_stripped" true mod m1 { pub fn f() {} } -//@ set m2 = "$.index[*][?(@.name == 'm2' && @.inner.module)].id" -//@ is "$.index[*][?(@.name == 'm2')].inner.module.items" [] -//@ is "$.index[*][?(@.name == 'm2')].inner.module.is_stripped" true +//@ set m2 = "$.index[?(@.name == 'm2' && @.inner.module)].id" +//@ is "$.index[?(@.name == 'm2')].inner.module.items" [] +//@ is "$.index[?(@.name == 'm2')].inner.module.is_stripped" true mod m2 { pub fn f(_: u8) {} } -//@ set m1_use = "$.index[*][?(@.docs=='m1 re-export')].id" -//@ is "$.index[*].inner.use[?(@.name=='m1')].id" $m1 -//@ is "$.index[*].inner.use[?(@.name=='m1')].is_glob" true +//@ set m1_use = "$.index[?(@.docs=='m1 re-export')].id" +//@ is "$.index[?(@.inner.use.name=='m1')].inner.use.id" $m1 +//@ is "$.index[?(@.inner.use.name=='m1')].inner.use.is_glob" true /// m1 re-export pub use m1::*; -//@ set m2_use = "$.index[*][?(@.docs=='m2 re-export')].id" -//@ is "$.index[*].inner.use[?(@.name=='m2')].id" $m2 -//@ is "$.index[*].inner.use[?(@.name=='m2')].is_glob" true +//@ set m2_use = "$.index[?(@.docs=='m2 re-export')].id" +//@ is "$.index[?(@.inner.use.name=='m2')].inner.use.id" $m2 +//@ is "$.index[?(@.inner.use.name=='m2')].inner.use.is_glob" true /// m2 re-export pub use m2::*; -//@ ismany "$.index[*].inner.module[?(@.is_crate==true)].items[*]" $m1_use $m2_use +//@ ismany "$.index[?(@.name=='glob_collision')].inner.module.items[*]" $m1_use $m2_use diff --git a/tests/rustdoc-json/reexport/glob_empty_mod.rs b/tests/rustdoc-json/reexport/glob_empty_mod.rs index ee1779407f4..69c0c0e6d5f 100644 --- a/tests/rustdoc-json/reexport/glob_empty_mod.rs +++ b/tests/rustdoc-json/reexport/glob_empty_mod.rs @@ -1,8 +1,8 @@ // Regression test for https://github.com/rust-lang/rust/issues/100973 -//@ is "$.index[*][?(@.name=='m1' && @.inner.module)].inner.module.is_stripped" true -//@ set m1 = "$.index[*][?(@.name=='m1')].id" +//@ is "$.index[?(@.name=='m1' && @.inner.module)].inner.module.is_stripped" true +//@ set m1 = "$.index[?(@.name=='m1')].id" mod m1 {} -//@ is "$.index[*][?(@.inner.use)].inner.use.id" $m1 +//@ is "$.index[?(@.inner.use)].inner.use.id" $m1 pub use m1::*; diff --git a/tests/rustdoc-json/reexport/glob_extern.rs b/tests/rustdoc-json/reexport/glob_extern.rs index 98be4773941..ccc6faffc8e 100644 --- a/tests/rustdoc-json/reexport/glob_extern.rs +++ b/tests/rustdoc-json/reexport/glob_extern.rs @@ -1,19 +1,19 @@ //@ edition:2018 -//@ is "$.index[*][?(@.name=='mod1')].inner.module.is_stripped" "true" +//@ is "$.index[?(@.name=='mod1')].inner.module.is_stripped" "true" mod mod1 { extern "C" { - //@ set public_fn_id = "$.index[*][?(@.name=='public_fn')].id" + //@ set public_fn_id = "$.index[?(@.name=='public_fn')].id" pub fn public_fn(); - //@ !has "$.index[*][?(@.name=='private_fn')]" + //@ !has "$.index[?(@.name=='private_fn')]" fn private_fn(); } - //@ ismany "$.index[*][?(@.name=='mod1')].inner.module.items[*]" $public_fn_id - //@ set mod1_id = "$.index[*][?(@.name=='mod1')].id" + //@ ismany "$.index[?(@.name=='mod1')].inner.module.items[*]" $public_fn_id + //@ set mod1_id = "$.index[?(@.name=='mod1')].id" } -//@ is "$.index[*][?(@.inner.use)].inner.use.is_glob" true -//@ is "$.index[*][?(@.inner.use)].inner.use.id" $mod1_id -//@ set use_id = "$.index[*][?(@.inner.use)].id" -//@ ismany "$.index[*][?(@.name=='glob_extern')].inner.module.items[*]" $use_id +//@ is "$.index[?(@.inner.use)].inner.use.is_glob" true +//@ is "$.index[?(@.inner.use)].inner.use.id" $mod1_id +//@ set use_id = "$.index[?(@.inner.use)].id" +//@ ismany "$.index[?(@.name=='glob_extern')].inner.module.items[*]" $use_id pub use mod1::*; diff --git a/tests/rustdoc-json/reexport/glob_private.rs b/tests/rustdoc-json/reexport/glob_private.rs index 2084ffc356e..f232914787b 100644 --- a/tests/rustdoc-json/reexport/glob_private.rs +++ b/tests/rustdoc-json/reexport/glob_private.rs @@ -1,32 +1,32 @@ //@ edition:2018 -//@ is "$.index[*][?(@.name=='mod1')].inner.module.is_stripped" "true" +//@ is "$.index[?(@.name=='mod1')].inner.module.is_stripped" "true" mod mod1 { - //@ is "$.index[*][?(@.name=='mod2')].inner.module.is_stripped" "true" + //@ is "$.index[?(@.name=='mod2')].inner.module.is_stripped" "true" mod mod2 { - //@ set m2pub_id = "$.index[*][?(@.name=='Mod2Public')].id" + //@ set m2pub_id = "$.index[?(@.name=='Mod2Public')].id" pub struct Mod2Public; - //@ !has "$.index[*][?(@.name=='Mod2Private')]" + //@ !has "$.index[?(@.name=='Mod2Private')]" struct Mod2Private; } - //@ set mod2_use_id = "$.index[*][?(@.docs=='Mod2 re-export')].id" - //@ is "$.index[*][?(@.docs=='Mod2 re-export')].inner.use.name" \"mod2\" + //@ set mod2_use_id = "$.index[?(@.docs=='Mod2 re-export')].id" + //@ is "$.index[?(@.docs=='Mod2 re-export')].inner.use.name" \"mod2\" /// Mod2 re-export pub use self::mod2::*; - //@ set m1pub_id = "$.index[*][?(@.name=='Mod1Public')].id" + //@ set m1pub_id = "$.index[?(@.name=='Mod1Public')].id" pub struct Mod1Public; - //@ !has "$.index[*][?(@.name=='Mod1Private')]" + //@ !has "$.index[?(@.name=='Mod1Private')]" struct Mod1Private; } -//@ set mod1_use_id = "$.index[*][?(@.docs=='Mod1 re-export')].id" -//@ is "$.index[*][?(@.docs=='Mod1 re-export')].inner.use.name" \"mod1\" +//@ set mod1_use_id = "$.index[?(@.docs=='Mod1 re-export')].id" +//@ is "$.index[?(@.docs=='Mod1 re-export')].inner.use.name" \"mod1\" /// Mod1 re-export pub use mod1::*; -//@ ismany "$.index[*][?(@.name=='mod2')].inner.module.items[*]" $m2pub_id -//@ ismany "$.index[*][?(@.name=='mod1')].inner.module.items[*]" $m1pub_id $mod2_use_id -//@ ismany "$.index[*][?(@.name=='glob_private')].inner.module.items[*]" $mod1_use_id +//@ ismany "$.index[?(@.name=='mod2')].inner.module.items[*]" $m2pub_id +//@ ismany "$.index[?(@.name=='mod1')].inner.module.items[*]" $m1pub_id $mod2_use_id +//@ ismany "$.index[?(@.name=='glob_private')].inner.module.items[*]" $mod1_use_id diff --git a/tests/rustdoc-json/reexport/in_root_and_mod.rs b/tests/rustdoc-json/reexport/in_root_and_mod.rs index a1d2080c068..005004e3b86 100644 --- a/tests/rustdoc-json/reexport/in_root_and_mod.rs +++ b/tests/rustdoc-json/reexport/in_root_and_mod.rs @@ -1,13 +1,13 @@ -//@ !has "$.index[*][?(@.name=='foo')]" +//@ !has "$.index[*].name" '"foo"' mod foo { - //@ has "$.index[*][?(@.name=='Foo')]" + //@ has "$.index[*].name" '"Foo"' pub struct Foo; } -//@ has "$.index[*].inner[?(@.use.source=='foo::Foo')]" +//@ has "$.index[*].inner.use.source" '"foo::Foo"' pub use foo::Foo; pub mod bar { - //@ has "$.index[*].inner[?(@.use.source=='crate::foo::Foo')]" + //@ has "$.index[*].inner.use.source" '"crate::foo::Foo"' pub use crate::foo::Foo; } diff --git a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs index 7d26d2a970d..54dda2a3cd0 100644 --- a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs +++ b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs @@ -1,19 +1,19 @@ pub mod foo { - //@ set bar_id = "$.index[*][?(@.name=='Bar')].id" - //@ ismany "$.index[*][?(@.name=='foo')].inner.module.items[*]" $bar_id + //@ set bar_id = "$.index[?(@.name=='Bar')].id" + //@ ismany "$.index[?(@.name=='foo')].inner.module.items[*]" $bar_id pub struct Bar; } -//@ set root_import_id = "$.index[*][?(@.docs=='Outer re-export')].id" -//@ is "$.index[*].inner[?(@.use.source=='foo::Bar')].use.id" $bar_id -//@ has "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.module.items[*]" $root_import_id +//@ set root_import_id = "$.index[?(@.docs=='Outer re-export')].id" +//@ is "$.index[?(@.inner.use.source=='foo::Bar')].inner.use.id" $bar_id +//@ has "$.index[?(@.name=='in_root_and_mod_pub')].inner.module.items[*]" $root_import_id /// Outer re-export pub use foo::Bar; pub mod baz { - //@ set baz_import_id = "$.index[*][?(@.docs=='Inner re-export')].id" - //@ is "$.index[*].inner[?(@.use.source=='crate::foo::Bar')].use.id" $bar_id - //@ ismany "$.index[*][?(@.name=='baz')].inner.module.items[*]" $baz_import_id + //@ set baz_import_id = "$.index[?(@.docs=='Inner re-export')].id" + //@ is "$.index[?(@.inner.use.source=='crate::foo::Bar')].inner.use.id" $bar_id + //@ ismany "$.index[?(@.name=='baz')].inner.module.items[*]" $baz_import_id /// Inner re-export pub use crate::foo::Bar; } diff --git a/tests/rustdoc-json/reexport/macro.rs b/tests/rustdoc-json/reexport/macro.rs index f182208c341..0bd37768255 100644 --- a/tests/rustdoc-json/reexport/macro.rs +++ b/tests/rustdoc-json/reexport/macro.rs @@ -1,13 +1,13 @@ //@ edition:2018 -//@ set repro_id = "$.index[*][?(@.name=='repro')].id" +//@ set repro_id = "$.index[?(@.name=='repro')].id" #[macro_export] macro_rules! repro { () => {}; } -//@ set repro2_id = "$.index[*][?(@.docs=='Re-export')].id" +//@ set repro2_id = "$.index[?(@.docs=='Re-export')].id" /// Re-export pub use crate::repro as repro2; -//@ ismany "$.index[*][?(@.name=='macro')].inner.module.items[*]" $repro_id $repro2_id +//@ ismany "$.index[?(@.name=='macro')].inner.module.items[*]" $repro_id $repro2_id diff --git a/tests/rustdoc-json/reexport/mod_not_included.rs b/tests/rustdoc-json/reexport/mod_not_included.rs index d0ce95749f1..59e5fff59c9 100644 --- a/tests/rustdoc-json/reexport/mod_not_included.rs +++ b/tests/rustdoc-json/reexport/mod_not_included.rs @@ -6,6 +6,6 @@ mod m1 { pub use m1::x; -//@ has "$.index[*][?(@.name=='x' && @.inner.function)]" -//@ has "$.index[*].inner[?(@.use.name=='x')].use.source" '"m1::x"' -//@ !has "$.index[*][?(@.name=='m1')]" +//@ has "$.index[?(@.name=='x' && @.inner.function)]" +//@ has "$.index[?(@.inner.use.name=='x')].inner.use.source" '"m1::x"' +//@ !has "$.index[?(@.name=='m1')]" diff --git a/tests/rustdoc-json/reexport/private_twice_one_inline.rs b/tests/rustdoc-json/reexport/private_twice_one_inline.rs index fdf8cda103b..6b5d03e207e 100644 --- a/tests/rustdoc-json/reexport/private_twice_one_inline.rs +++ b/tests/rustdoc-json/reexport/private_twice_one_inline.rs @@ -5,19 +5,19 @@ extern crate pub_struct as foo; #[doc(inline)] -//@ set crate_use_id = "$.index[*][?(@.docs=='Hack A')].id" -//@ set foo_id = "$.index[*][?(@.docs=='Hack A')].inner.use.id" +//@ set crate_use_id = "$.index[?(@.docs=='Hack A')].id" +//@ set foo_id = "$.index[?(@.docs=='Hack A')].inner.use.id" /// Hack A pub use foo::Foo; -//@ set bar_id = "$.index[*][?(@.name=='bar')].id" +//@ set bar_id = "$.index[?(@.name=='bar')].id" pub mod bar { - //@ is "$.index[*][?(@.docs=='Hack B')].inner.use.id" $foo_id - //@ set bar_use_id = "$.index[*][?(@.docs=='Hack B')].id" - //@ ismany "$.index[*][?(@.name=='bar')].inner.module.items[*]" $bar_use_id + //@ is "$.index[?(@.docs=='Hack B')].inner.use.id" $foo_id + //@ set bar_use_id = "$.index[?(@.docs=='Hack B')].id" + //@ ismany "$.index[?(@.name=='bar')].inner.module.items[*]" $bar_use_id /// Hack B pub use foo::Foo; } -//@ ismany "$.index[*][?(@.inner.use)].id" $crate_use_id $bar_use_id -//@ ismany "$.index[*][?(@.name=='private_twice_one_inline')].inner.module.items[*]" $bar_id $crate_use_id +//@ ismany "$.index[?(@.inner.use)].id" $crate_use_id $bar_use_id +//@ ismany "$.index[?(@.name=='private_twice_one_inline')].inner.module.items[*]" $bar_id $crate_use_id diff --git a/tests/rustdoc-json/reexport/private_two_names.rs b/tests/rustdoc-json/reexport/private_two_names.rs index 049100d7f49..79af40b83a4 100644 --- a/tests/rustdoc-json/reexport/private_two_names.rs +++ b/tests/rustdoc-json/reexport/private_two_names.rs @@ -1,21 +1,21 @@ // Test for the ICE in https://github.com/rust-lang/rust/issues/83720 // A pub-in-private type re-exported under two different names shouldn't cause an error -//@ !has "$.index[*][?(@.name=='style')]" +//@ !has "$.index[?(@.name=='style')]" mod style { - //@ set color_struct_id = "$.index[*][?(@.inner.struct && @.name=='Color')].id" + //@ set color_struct_id = "$.index[?(@.inner.struct && @.name=='Color')].id" pub struct Color; } -//@ is "$.index[*][?(@.docs=='First re-export')].inner.use.id" $color_struct_id -//@ is "$.index[*][?(@.docs=='First re-export')].inner.use.name" \"Color\" -//@ set color_export_id = "$.index[*][?(@.docs=='First re-export')].id" +//@ is "$.index[?(@.docs=='First re-export')].inner.use.id" $color_struct_id +//@ is "$.index[?(@.docs=='First re-export')].inner.use.name" \"Color\" +//@ set color_export_id = "$.index[?(@.docs=='First re-export')].id" /// First re-export pub use style::Color; -//@ is "$.index[*][?(@.docs=='Second re-export')].inner.use.id" $color_struct_id -//@ is "$.index[*][?(@.docs=='Second re-export')].inner.use.name" \"Colour\" -//@ set colour_export_id = "$.index[*][?(@.docs=='Second re-export')].id" +//@ is "$.index[?(@.docs=='Second re-export')].inner.use.id" $color_struct_id +//@ is "$.index[?(@.docs=='Second re-export')].inner.use.name" \"Colour\" +//@ set colour_export_id = "$.index[?(@.docs=='Second re-export')].id" /// Second re-export pub use style::Color as Colour; -//@ ismany "$.index[*][?(@.name=='private_two_names')].inner.module.items[*]" $color_export_id $colour_export_id +//@ ismany "$.index[?(@.name=='private_two_names')].inner.module.items[*]" $color_export_id $colour_export_id diff --git a/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs b/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs index e021b51ab4b..129ccb7e2eb 100644 --- a/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs +++ b/tests/rustdoc-json/reexport/pub_use_doc_hidden.rs @@ -9,5 +9,5 @@ mod repeat_n { /// not here pub use repeat_n::RepeatN; -//@ count "$.index[*][?(@.name=='pub_use_doc_hidden')].inner.items[*]" 0 -//@ !has "$.index[*][?(@.docs == 'not here')]" +//@ count "$.index[?(@.name=='pub_use_doc_hidden')].inner.items[*]" 0 +//@ !has "$.index[?(@.docs == 'not here')]" diff --git a/tests/rustdoc-json/reexport/reexport_method_from_private_module.rs b/tests/rustdoc-json/reexport/reexport_method_from_private_module.rs index 25edd5dbb28..56922340a6f 100644 --- a/tests/rustdoc-json/reexport/reexport_method_from_private_module.rs +++ b/tests/rustdoc-json/reexport/reexport_method_from_private_module.rs @@ -1,11 +1,11 @@ // Regression test for <https://github.com/rust-lang/rust/issues/102583>. -//@ set impl_S = "$.index[*][?(@.docs=='impl S')].id" -//@ has "$.index[*][?(@.name=='S')].inner.struct.impls[*]" $impl_S -//@ set is_present = "$.index[*][?(@.name=='is_present')].id" -//@ is "$.index[*][?(@.docs=='impl S')].inner.impl.items[*]" $is_present -//@ !has "$.index[*][?(@.name=='hidden_impl')]" -//@ !has "$.index[*][?(@.name=='hidden_fn')]" +//@ set impl_S = "$.index[?(@.docs=='impl S')].id" +//@ has "$.index[?(@.name=='S')].inner.struct.impls[*]" $impl_S +//@ set is_present = "$.index[?(@.name=='is_present')].id" +//@ is "$.index[?(@.docs=='impl S')].inner.impl.items[*]" $is_present +//@ !has "$.index[?(@.name=='hidden_impl')]" +//@ !has "$.index[?(@.name=='hidden_fn')]" #![no_std] diff --git a/tests/rustdoc-json/reexport/reexport_of_hidden.rs b/tests/rustdoc-json/reexport/reexport_of_hidden.rs index 80f171da888..119e699d815 100644 --- a/tests/rustdoc-json/reexport/reexport_of_hidden.rs +++ b/tests/rustdoc-json/reexport/reexport_of_hidden.rs @@ -1,7 +1,7 @@ //@ compile-flags: --document-hidden-items -//@ has "$.index[*].inner[?(@.use.name=='UsedHidden')]" -//@ has "$.index[*][?(@.name=='Hidden')]" +//@ has "$.index[*].inner.use.name" '"UsedHidden"' +//@ has "$.index[*].name" '"Hidden"' pub mod submodule { #[doc(hidden)] pub struct Hidden {} diff --git a/tests/rustdoc-json/reexport/rename_private.rs b/tests/rustdoc-json/reexport/rename_private.rs index 3f13f305d64..0494dff5bca 100644 --- a/tests/rustdoc-json/reexport/rename_private.rs +++ b/tests/rustdoc-json/reexport/rename_private.rs @@ -1,10 +1,10 @@ //@ edition:2018 -//@ !has "$.index[*][?(@.name=='inner')]" +//@ !has "$.index[?(@.name=='inner')]" mod inner { - //@ has "$.index[*][?(@.name=='Public')]" + //@ has "$.index[?(@.name=='Public')]" pub struct Public; } -//@ is "$.index[*][?(@.inner.use)].inner.use.name" \"NewName\" +//@ is "$.index[?(@.inner.use)].inner.use.name" \"NewName\" pub use inner::Public as NewName; diff --git a/tests/rustdoc-json/reexport/rename_public.rs b/tests/rustdoc-json/reexport/rename_public.rs index 81c003a51c4..a3d712358f2 100644 --- a/tests/rustdoc-json/reexport/rename_public.rs +++ b/tests/rustdoc-json/reexport/rename_public.rs @@ -1,15 +1,15 @@ //@ edition:2018 -//@ set inner_id = "$.index[*][?(@.name=='inner')].id" +//@ set inner_id = "$.index[?(@.name=='inner')].id" pub mod inner { - //@ set public_id = "$.index[*][?(@.name=='Public')].id" - //@ ismany "$.index[*][?(@.name=='inner')].inner.module.items[*]" $public_id + //@ set public_id = "$.index[?(@.name=='Public')].id" + //@ ismany "$.index[?(@.name=='inner')].inner.module.items[*]" $public_id pub struct Public; } -//@ set import_id = "$.index[*][?(@.docs=='Re-export')].id" -//@ !has "$.index[*].inner[?(@.use.name=='Public')]" -//@ is "$.index[*].inner[?(@.use.name=='NewName')].use.source" \"inner::Public\" +//@ set import_id = "$.index[?(@.docs=='Re-export')].id" +//@ !has "$.index[?(@.inner.use.name=='Public')]" +//@ is "$.index[?(@.inner.use.name=='NewName')].inner.use.source" \"inner::Public\" /// Re-export pub use inner::Public as NewName; -//@ ismany "$.index[*][?(@.name=='rename_public')].inner.module.items[*]" $inner_id $import_id +//@ ismany "$.index[?(@.name=='rename_public')].inner.module.items[*]" $inner_id $import_id diff --git a/tests/rustdoc-json/reexport/same_name_different_types.rs b/tests/rustdoc-json/reexport/same_name_different_types.rs index 760e2c6f775..6e7ad3393e5 100644 --- a/tests/rustdoc-json/reexport/same_name_different_types.rs +++ b/tests/rustdoc-json/reexport/same_name_different_types.rs @@ -1,22 +1,22 @@ // Regression test for <https://github.com/rust-lang/rust/issues/107677>. pub mod nested { - //@ set foo_struct = "$.index[*][?(@.docs == 'Foo the struct')].id" + //@ set foo_struct = "$.index[?(@.docs == 'Foo the struct')].id" /// Foo the struct pub struct Foo {} - //@ set foo_fn = "$.index[*][?(@.docs == 'Foo the function')].id" + //@ set foo_fn = "$.index[?(@.docs == 'Foo the function')].id" #[allow(non_snake_case)] /// Foo the function pub fn Foo() {} } -//@ ismany "$.index[*].inner[?(@.use.name == 'Foo')].use.id" $foo_fn $foo_struct -//@ ismany "$.index[*].inner[?(@.use.name == 'Bar')].use.id" $foo_fn $foo_struct +//@ ismany "$.index[?(@.inner.use.name == 'Foo')].inner.use.id" $foo_fn $foo_struct +//@ ismany "$.index[?(@.inner.use.name == 'Bar')].inner.use.id" $foo_fn $foo_struct -//@ count "$.index[*].inner[?(@.use.name == 'Foo')]" 2 -//@ count "$.index[*].inner[?(@.use.name == 'Bar')]" 2 +//@ count "$.index[?(@.inner.use.name == 'Foo')]" 2 +//@ count "$.index[?(@.inner.use.name == 'Bar')]" 2 pub use Foo as Bar; pub use nested::Foo; diff --git a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs index f313171afa5..05b55c7b12a 100644 --- a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs +++ b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs @@ -3,17 +3,17 @@ #![no_std] mod inner { - //@ set trait_id = "$.index[*][?(@.name=='Trait')].id" + //@ set trait_id = "$.index[?(@.name=='Trait')].id" pub trait Trait {} } -//@ set export_id = "$.index[*][?(@.docs=='First re-export')].id" -//@ is "$.index[*].inner[?(@.use.name=='Trait')].use.id" $trait_id +//@ set export_id = "$.index[?(@.docs=='First re-export')].id" +//@ is "$.index[?(@.inner.use.name=='Trait')].inner.use.id" $trait_id /// First re-export pub use inner::Trait; -//@ set reexport_id = "$.index[*][?(@.docs=='Second re-export')].id" -//@ is "$.index[*].inner[?(@.use.name=='Reexport')].use.id" $trait_id +//@ set reexport_id = "$.index[?(@.docs=='Second re-export')].id" +//@ is "$.index[?(@.inner.use.name=='Reexport')].inner.use.id" $trait_id /// Second re-export pub use inner::Trait as Reexport; -//@ ismany "$.index[*][?(@.name=='same_type_reexported_more_than_once')].inner.module.items[*]" $reexport_id $export_id +//@ ismany "$.index[?(@.name=='same_type_reexported_more_than_once')].inner.module.items[*]" $reexport_id $export_id diff --git a/tests/rustdoc-json/reexport/simple_private.rs b/tests/rustdoc-json/reexport/simple_private.rs index 405d57d342e..40be1708dc6 100644 --- a/tests/rustdoc-json/reexport/simple_private.rs +++ b/tests/rustdoc-json/reexport/simple_private.rs @@ -1,20 +1,20 @@ //@ edition:2018 -//@ !has "$.index[*][?(@.name=='inner')]" +//@ !has "$.index[?(@.name=='inner')]" mod inner { - //@ set pub_id = "$.index[*][?(@.name=='Public')].id" + //@ set pub_id = "$.index[?(@.name=='Public')].id" pub struct Public; } -//@ is "$.index[*][?(@.inner.use)].inner.use.name" \"Public\" -//@ is "$.index[*][?(@.inner.use)].inner.use.id" $pub_id -//@ set use_id = "$.index[*][?(@.inner.use)].id" +//@ is "$.index[?(@.inner.use)].inner.use.name" \"Public\" +//@ is "$.index[?(@.inner.use)].inner.use.id" $pub_id +//@ set use_id = "$.index[?(@.inner.use)].id" pub use inner::Public; -//@ ismany "$.index[*][?(@.name=='simple_private')].inner.module.items[*]" $use_id +//@ ismany "$.index[?(@.name=='simple_private')].inner.module.items[*]" $use_id // Test for https://github.com/rust-lang/rust/issues/135309 -//@ has "$.paths[*][?(@.kind=='module')].path" '["simple_private"]' +//@ has "$.paths[?(@.kind=='module')].path" '["simple_private"]' //@ !has "$.paths[*].path" '["simple_private", "inner"]' -//@ has "$.paths[*][?(@.kind=='struct')].path" '["simple_private", "inner", "Public"]' +//@ has "$.paths[?(@.kind=='struct')].path" '["simple_private", "inner", "Public"]' //@ !has "$.paths[*].path" '["simple_private", "Public"]' diff --git a/tests/rustdoc-json/reexport/simple_public.rs b/tests/rustdoc-json/reexport/simple_public.rs index f1335828314..cdb6c0dc88a 100644 --- a/tests/rustdoc-json/reexport/simple_public.rs +++ b/tests/rustdoc-json/reexport/simple_public.rs @@ -1,21 +1,21 @@ //@ edition:2018 -//@ set inner_id = "$.index[*][?(@.name=='inner')].id" +//@ set inner_id = "$.index[?(@.name=='inner')].id" pub mod inner { - //@ set public_id = "$.index[*][?(@.name=='Public')].id" - //@ ismany "$.index[*][?(@.name=='inner')].inner.module.items[*]" $public_id + //@ set public_id = "$.index[?(@.name=='Public')].id" + //@ ismany "$.index[?(@.name=='inner')].inner.module.items[*]" $public_id pub struct Public; } -//@ set import_id = "$.index[*][?(@.docs=='Outer')].id" -//@ is "$.index[*][?(@.docs=='Outer')].inner.use.source" \"inner::Public\" +//@ set import_id = "$.index[?(@.docs=='Outer')].id" +//@ is "$.index[?(@.docs=='Outer')].inner.use.source" \"inner::Public\" /// Outer pub use inner::Public; -//@ ismany "$.index[*][?(@.name=='simple_public')].inner.module.items[*]" $import_id $inner_id +//@ ismany "$.index[?(@.name=='simple_public')].inner.module.items[*]" $import_id $inner_id -//@ has "$.paths[*][?(@.kind=='module')].path" '["simple_public"]' -//@ has "$.paths[*][?(@.kind=='module')].path" '["simple_public", "inner"]' -//@ has "$.paths[*][?(@.kind=='struct')].path" '["simple_public", "inner", "Public"]' +//@ has "$.paths[?(@.kind=='module')].path" '["simple_public"]' +//@ has "$.paths[?(@.kind=='module')].path" '["simple_public", "inner"]' +//@ has "$.paths[?(@.kind=='struct')].path" '["simple_public", "inner", "Public"]' //@ !has "$.paths[*].path" '["simple_public", "Public"]' diff --git a/tests/rustdoc-json/reexport/synthesize_trait_with_docs.rs b/tests/rustdoc-json/reexport/synthesize_trait_with_docs.rs index 59699e4861b..89591690bca 100644 --- a/tests/rustdoc-json/reexport/synthesize_trait_with_docs.rs +++ b/tests/rustdoc-json/reexport/synthesize_trait_with_docs.rs @@ -7,4 +7,4 @@ pub struct Local; impl trait_with_docs::HasDocs for Local {} -//@ !has "$.index[*][?(@.name == 'HasDocs')]" +//@ !has "$.index[?(@.name == 'HasDocs')]" diff --git a/tests/rustdoc-json/return-type-notation.rs b/tests/rustdoc-json/return-type-notation.rs new file mode 100644 index 00000000000..7943991616b --- /dev/null +++ b/tests/rustdoc-json/return-type-notation.rs @@ -0,0 +1,18 @@ +//@ edition: 2021 +// ignore-tidy-linelength + +#![crate_type = "lib"] +#![feature(return_type_notation)] + +pub trait Foo { + async fn bar(); +} + +//@ is "$.index[?(@.name=='foo')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.args.angle_bracketed.constraints[0].args" '"return_type_notation"' +//@ ismany "$.index[?(@.name=='foo')].inner.function.generics.where_predicates[*].bound_predicate.type.qualified_path.args" '"return_type_notation"' '"return_type_notation"' +pub fn foo<T: Foo<bar(..): Send>>() +where + <T as Foo>::bar(..): 'static, + T::bar(..): Sync, +{ +} diff --git a/tests/rustdoc-json/return_private.rs b/tests/rustdoc-json/return_private.rs index 214fda14aca..8fbdb6be5c9 100644 --- a/tests/rustdoc-json/return_private.rs +++ b/tests/rustdoc-json/return_private.rs @@ -1,13 +1,13 @@ // Regression test for <https://github.com/rust-lang/rust/issues/96161>. mod secret { - //@ set struct_secret = "$.index[*][?(@.name == 'Secret' && @.inner.struct)].id" + //@ set struct_secret = "$.index[?(@.name == 'Secret' && @.inner.struct)].id" pub struct Secret; } -//@ has "$.index[*][?(@.name=='get_secret')].inner.function" -//@ is "$.index[*][?(@.name=='get_secret')].inner.function.sig.output.resolved_path.path" '"secret::Secret"' -//@ is "$.index[*][?(@.name=='get_secret')].inner.function.sig.output.resolved_path.id" $struct_secret +//@ has "$.index[?(@.name=='get_secret')].inner.function" +//@ is "$.index[?(@.name=='get_secret')].inner.function.sig.output.resolved_path.path" '"secret::Secret"' +//@ is "$.index[?(@.name=='get_secret')].inner.function.sig.output.resolved_path.id" $struct_secret pub fn get_secret() -> secret::Secret { secret::Secret } diff --git a/tests/rustdoc-json/statics/extern.rs b/tests/rustdoc-json/statics/extern.rs index 9e0265da8e2..5be13c8b8fc 100644 --- a/tests/rustdoc-json/statics/extern.rs +++ b/tests/rustdoc-json/statics/extern.rs @@ -1,38 +1,38 @@ //@ edition: 2021 extern "C" { - //@ is '$.index[*][?(@.name=="A")].inner.static.is_unsafe' true - //@ is '$.index[*][?(@.name=="A")].inner.static.is_mutable' false + //@ is '$.index[?(@.name=="A")].inner.static.is_unsafe' true + //@ is '$.index[?(@.name=="A")].inner.static.is_mutable' false pub static A: i32; - //@ is '$.index[*][?(@.name=="B")].inner.static.is_unsafe' true - //@ is '$.index[*][?(@.name=="B")].inner.static.is_mutable' true + //@ is '$.index[?(@.name=="B")].inner.static.is_unsafe' true + //@ is '$.index[?(@.name=="B")].inner.static.is_mutable' true pub static mut B: i32; // items in unadorned `extern` blocks cannot have safety qualifiers } unsafe extern "C" { - //@ is '$.index[*][?(@.name=="C")].inner.static.is_unsafe' true - //@ is '$.index[*][?(@.name=="C")].inner.static.is_mutable' false + //@ is '$.index[?(@.name=="C")].inner.static.is_unsafe' true + //@ is '$.index[?(@.name=="C")].inner.static.is_mutable' false pub static C: i32; - //@ is '$.index[*][?(@.name=="D")].inner.static.is_unsafe' true - //@ is '$.index[*][?(@.name=="D")].inner.static.is_mutable' true + //@ is '$.index[?(@.name=="D")].inner.static.is_unsafe' true + //@ is '$.index[?(@.name=="D")].inner.static.is_mutable' true pub static mut D: i32; - //@ is '$.index[*][?(@.name=="E")].inner.static.is_unsafe' false - //@ is '$.index[*][?(@.name=="E")].inner.static.is_mutable' false + //@ is '$.index[?(@.name=="E")].inner.static.is_unsafe' false + //@ is '$.index[?(@.name=="E")].inner.static.is_mutable' false pub safe static E: i32; - //@ is '$.index[*][?(@.name=="F")].inner.static.is_unsafe' false - //@ is '$.index[*][?(@.name=="F")].inner.static.is_mutable' true + //@ is '$.index[?(@.name=="F")].inner.static.is_unsafe' false + //@ is '$.index[?(@.name=="F")].inner.static.is_mutable' true pub safe static mut F: i32; - //@ is '$.index[*][?(@.name=="G")].inner.static.is_unsafe' true - //@ is '$.index[*][?(@.name=="G")].inner.static.is_mutable' false + //@ is '$.index[?(@.name=="G")].inner.static.is_unsafe' true + //@ is '$.index[?(@.name=="G")].inner.static.is_mutable' false pub unsafe static G: i32; - //@ is '$.index[*][?(@.name=="H")].inner.static.is_unsafe' true - //@ is '$.index[*][?(@.name=="H")].inner.static.is_mutable' true + //@ is '$.index[?(@.name=="H")].inner.static.is_unsafe' true + //@ is '$.index[?(@.name=="H")].inner.static.is_mutable' true pub unsafe static mut H: i32; } -//@ ismany '$.index[*][?(@.inner.static)].inner.static.expr' '""' '""' '""' '""' '""' '""' '""' '""' -//@ ismany '$.index[*][?(@.inner.static)].inner.static.type.primitive' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' +//@ ismany '$.index[?(@.inner.static)].inner.static.expr' '""' '""' '""' '""' '""' '""' '""' '""' +//@ ismany '$.index[?(@.inner.static)].inner.static.type.primitive' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' '"i32"' diff --git a/tests/rustdoc-json/statics/statics.rs b/tests/rustdoc-json/statics/statics.rs index a8af23cc87d..497a134c503 100644 --- a/tests/rustdoc-json/statics/statics.rs +++ b/tests/rustdoc-json/statics/statics.rs @@ -1,12 +1,12 @@ -//@ is '$.index[*][?(@.name=="A")].inner.static.type.primitive' '"i32"' -//@ is '$.index[*][?(@.name=="A")].inner.static.is_mutable' false -//@ is '$.index[*][?(@.name=="A")].inner.static.expr' '"5"' -//@ is '$.index[*][?(@.name=="A")].inner.static.is_unsafe' false +//@ is '$.index[?(@.name=="A")].inner.static.type.primitive' '"i32"' +//@ is '$.index[?(@.name=="A")].inner.static.is_mutable' false +//@ is '$.index[?(@.name=="A")].inner.static.expr' '"5"' +//@ is '$.index[?(@.name=="A")].inner.static.is_unsafe' false pub static A: i32 = 5; -//@ is '$.index[*][?(@.name=="B")].inner.static.type.primitive' '"u32"' -//@ is '$.index[*][?(@.name=="B")].inner.static.is_mutable' true +//@ is '$.index[?(@.name=="B")].inner.static.type.primitive' '"u32"' +//@ is '$.index[?(@.name=="B")].inner.static.is_mutable' true // Expr value isn't gaurenteed, it'd be fine to change it. -//@ is '$.index[*][?(@.name=="B")].inner.static.expr' '"_"' -//@ is '$.index[*][?(@.name=="B")].inner.static.is_unsafe' false +//@ is '$.index[?(@.name=="B")].inner.static.expr' '"_"' +//@ is '$.index[?(@.name=="B")].inner.static.is_unsafe' false pub static mut B: u32 = 2 + 3; diff --git a/tests/rustdoc-json/stripped_modules.rs b/tests/rustdoc-json/stripped_modules.rs index d0db9c6588b..ba6644190a2 100644 --- a/tests/rustdoc-json/stripped_modules.rs +++ b/tests/rustdoc-json/stripped_modules.rs @@ -1,17 +1,17 @@ -//@ !has "$.index[*][?(@.name=='no_pub_inner')]" +//@ !has "$.index[?(@.name=='no_pub_inner')]" mod no_pub_inner { fn priv_inner() {} } -//@ !has "$.index[*][?(@.name=='pub_inner_unreachable')]" +//@ !has "$.index[?(@.name=='pub_inner_unreachable')]" mod pub_inner_unreachable { - //@ !has "$.index[*][?(@.name=='pub_inner_1')]" + //@ !has "$.index[?(@.name=='pub_inner_1')]" pub fn pub_inner_1() {} } -//@ !has "$.index[*][?(@.name=='pub_inner_reachable')]" +//@ !has "$.index[?(@.name=='pub_inner_reachable')]" mod pub_inner_reachable { - //@ has "$.index[*][?(@.name=='pub_inner_2')]" + //@ has "$.index[?(@.name=='pub_inner_2')]" pub fn pub_inner_2() {} } diff --git a/tests/rustdoc-json/structs/field_order.rs b/tests/rustdoc-json/structs/field_order.rs index 7e556df777f..eb1740676a6 100644 --- a/tests/rustdoc-json/structs/field_order.rs +++ b/tests/rustdoc-json/structs/field_order.rs @@ -15,24 +15,24 @@ pub struct Foo { pub vll_9: i32, } -//@ set 0 = '$.index[*][?(@.name == "ews_0")].id' -//@ set 1 = '$.index[*][?(@.name == "dik_1")].id' -//@ set 2 = '$.index[*][?(@.name == "hsk_2")].id' -//@ set 3 = '$.index[*][?(@.name == "djt_3")].id' -//@ set 4 = '$.index[*][?(@.name == "jnr_4")].id' -//@ set 5 = '$.index[*][?(@.name == "dfs_5")].id' -//@ set 6 = '$.index[*][?(@.name == "bja_6")].id' -//@ set 7 = '$.index[*][?(@.name == "lyc_7")].id' -//@ set 8 = '$.index[*][?(@.name == "yqd_8")].id' -//@ set 9 = '$.index[*][?(@.name == "vll_9")].id' +//@ set 0 = '$.index[?(@.name == "ews_0")].id' +//@ set 1 = '$.index[?(@.name == "dik_1")].id' +//@ set 2 = '$.index[?(@.name == "hsk_2")].id' +//@ set 3 = '$.index[?(@.name == "djt_3")].id' +//@ set 4 = '$.index[?(@.name == "jnr_4")].id' +//@ set 5 = '$.index[?(@.name == "dfs_5")].id' +//@ set 6 = '$.index[?(@.name == "bja_6")].id' +//@ set 7 = '$.index[?(@.name == "lyc_7")].id' +//@ set 8 = '$.index[?(@.name == "yqd_8")].id' +//@ set 9 = '$.index[?(@.name == "vll_9")].id' -//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[0]' $0 -//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[1]' $1 -//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[2]' $2 -//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[3]' $3 -//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[4]' $4 -//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[5]' $5 -//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[6]' $6 -//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[7]' $7 -//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[8]' $8 -//@ is '$.index[*][?(@.name == "Foo")].inner.struct.kind.plain.fields[9]' $9 +//@ is '$.index[?(@.name == "Foo")].inner.struct.kind.plain.fields[0]' $0 +//@ is '$.index[?(@.name == "Foo")].inner.struct.kind.plain.fields[1]' $1 +//@ is '$.index[?(@.name == "Foo")].inner.struct.kind.plain.fields[2]' $2 +//@ is '$.index[?(@.name == "Foo")].inner.struct.kind.plain.fields[3]' $3 +//@ is '$.index[?(@.name == "Foo")].inner.struct.kind.plain.fields[4]' $4 +//@ is '$.index[?(@.name == "Foo")].inner.struct.kind.plain.fields[5]' $5 +//@ is '$.index[?(@.name == "Foo")].inner.struct.kind.plain.fields[6]' $6 +//@ is '$.index[?(@.name == "Foo")].inner.struct.kind.plain.fields[7]' $7 +//@ is '$.index[?(@.name == "Foo")].inner.struct.kind.plain.fields[8]' $8 +//@ is '$.index[?(@.name == "Foo")].inner.struct.kind.plain.fields[9]' $9 diff --git a/tests/rustdoc-json/structs/plain_all_pub.rs b/tests/rustdoc-json/structs/plain_all_pub.rs index 67d2a4a7a8c..501044f62cc 100644 --- a/tests/rustdoc-json/structs/plain_all_pub.rs +++ b/tests/rustdoc-json/structs/plain_all_pub.rs @@ -3,9 +3,9 @@ pub struct Demo { pub y: i32, } -//@ set x = "$.index[*][?(@.name=='x')].id" -//@ set y = "$.index[*][?(@.name=='y')].id" -//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x -//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[1]" $y -//@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 2 -//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.has_stripped_fields" false +//@ set x = "$.index[?(@.name=='x')].id" +//@ set y = "$.index[?(@.name=='y')].id" +//@ is "$.index[?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x +//@ is "$.index[?(@.name=='Demo')].inner.struct.kind.plain.fields[1]" $y +//@ count "$.index[?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 2 +//@ is "$.index[?(@.name=='Demo')].inner.struct.kind.plain.has_stripped_fields" false diff --git a/tests/rustdoc-json/structs/plain_doc_hidden.rs b/tests/rustdoc-json/structs/plain_doc_hidden.rs index 4573adc73fa..e62fb27ae86 100644 --- a/tests/rustdoc-json/structs/plain_doc_hidden.rs +++ b/tests/rustdoc-json/structs/plain_doc_hidden.rs @@ -4,8 +4,8 @@ pub struct Demo { pub y: i32, } -//@ set x = "$.index[*][?(@.name=='x')].id" -//@ !has "$.index[*][?(@.name=='y')].id" -//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x -//@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1 -//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.has_stripped_fields" true +//@ set x = "$.index[?(@.name=='x')].id" +//@ !has "$.index[?(@.name=='y')].id" +//@ is "$.index[?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x +//@ count "$.index[?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1 +//@ is "$.index[?(@.name=='Demo')].inner.struct.kind.plain.has_stripped_fields" true diff --git a/tests/rustdoc-json/structs/plain_empty.rs b/tests/rustdoc-json/structs/plain_empty.rs index 30013021abe..127f9ed1972 100644 --- a/tests/rustdoc-json/structs/plain_empty.rs +++ b/tests/rustdoc-json/structs/plain_empty.rs @@ -1,5 +1,5 @@ -//@ is "$.index[*][?(@.name=='PlainEmpty')].visibility" \"public\" -//@ has "$.index[*][?(@.name=='PlainEmpty')].inner.struct" -//@ is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.has_stripped_fields" false -//@ is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.fields" [] +//@ is "$.index[?(@.name=='PlainEmpty')].visibility" \"public\" +//@ has "$.index[?(@.name=='PlainEmpty')].inner.struct" +//@ is "$.index[?(@.name=='PlainEmpty')].inner.struct.kind.plain.has_stripped_fields" false +//@ is "$.index[?(@.name=='PlainEmpty')].inner.struct.kind.plain.fields" [] pub struct PlainEmpty {} diff --git a/tests/rustdoc-json/structs/plain_pub_priv.rs b/tests/rustdoc-json/structs/plain_pub_priv.rs index 91079a30d42..181d5ea0de2 100644 --- a/tests/rustdoc-json/structs/plain_pub_priv.rs +++ b/tests/rustdoc-json/structs/plain_pub_priv.rs @@ -3,7 +3,7 @@ pub struct Demo { y: i32, } -//@ set x = "$.index[*][?(@.name=='x')].id" -//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x -//@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1 -//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.has_stripped_fields" true +//@ set x = "$.index[?(@.name=='x')].id" +//@ is "$.index[?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x +//@ count "$.index[?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1 +//@ is "$.index[?(@.name=='Demo')].inner.struct.kind.plain.has_stripped_fields" true diff --git a/tests/rustdoc-json/structs/tuple.rs b/tests/rustdoc-json/structs/tuple.rs index 6c8dc79dfe2..115ce29bd70 100644 --- a/tests/rustdoc-json/structs/tuple.rs +++ b/tests/rustdoc-json/structs/tuple.rs @@ -1,4 +1,4 @@ -//@ is "$.index[*][?(@.name=='Tuple')].visibility" \"public\" -//@ has "$.index[*][?(@.name=='Tuple')].inner.struct" -//@ is "$.index[*][?(@.name=='Tuple')].inner.struct.kind.tuple" '[null, null]' +//@ is "$.index[?(@.name=='Tuple')].visibility" \"public\" +//@ has "$.index[?(@.name=='Tuple')].inner.struct" +//@ is "$.index[?(@.name=='Tuple')].inner.struct.kind.tuple" '[null, null]' pub struct Tuple(u32, String); diff --git a/tests/rustdoc-json/structs/tuple_empty.rs b/tests/rustdoc-json/structs/tuple_empty.rs index 137915e6c05..af5b57fb133 100644 --- a/tests/rustdoc-json/structs/tuple_empty.rs +++ b/tests/rustdoc-json/structs/tuple_empty.rs @@ -1,2 +1,2 @@ -//@ is "$.index[*][?(@.name=='TupleUnit')].inner.struct.kind.tuple" [] +//@ is "$.index[?(@.name=='TupleUnit')].inner.struct.kind.tuple" [] pub struct TupleUnit(); diff --git a/tests/rustdoc-json/structs/tuple_pub_priv.rs b/tests/rustdoc-json/structs/tuple_pub_priv.rs index 11af26e6ea3..b97a17cc46a 100644 --- a/tests/rustdoc-json/structs/tuple_pub_priv.rs +++ b/tests/rustdoc-json/structs/tuple_pub_priv.rs @@ -5,9 +5,9 @@ pub struct Demo( #[doc(hidden)] i32, ); -//@ set field = "$.index[*][?(@.docs=='field')].id" +//@ set field = "$.index[?(@.docs=='field')].id" -//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[0]" null -//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[1]" $field -//@ is "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[2]" null -//@ count "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[*]" 3 +//@ is "$.index[?(@.name=='Demo')].inner.struct.kind.tuple[0]" null +//@ is "$.index[?(@.name=='Demo')].inner.struct.kind.tuple[1]" $field +//@ is "$.index[?(@.name=='Demo')].inner.struct.kind.tuple[2]" null +//@ count "$.index[?(@.name=='Demo')].inner.struct.kind.tuple[*]" 3 diff --git a/tests/rustdoc-json/structs/unit.rs b/tests/rustdoc-json/structs/unit.rs index ad6af65c0e0..6a961725206 100644 --- a/tests/rustdoc-json/structs/unit.rs +++ b/tests/rustdoc-json/structs/unit.rs @@ -1,4 +1,4 @@ -//@ is "$.index[*][?(@.name=='Unit')].visibility" \"public\" -//@ has "$.index[*][?(@.name=='Unit')].inner.struct" -//@ is "$.index[*][?(@.name=='Unit')].inner.struct.kind" \"unit\" +//@ is "$.index[?(@.name=='Unit')].visibility" \"public\" +//@ has "$.index[?(@.name=='Unit')].inner.struct" +//@ is "$.index[?(@.name=='Unit')].inner.struct.kind" \"unit\" pub struct Unit; diff --git a/tests/rustdoc-json/structs/with_generics.rs b/tests/rustdoc-json/structs/with_generics.rs index 3e7f175a5a1..979b002d0ee 100644 --- a/tests/rustdoc-json/structs/with_generics.rs +++ b/tests/rustdoc-json/structs/with_generics.rs @@ -1,13 +1,13 @@ use std::collections::HashMap; -//@ is "$.index[*][?(@.name=='WithGenerics')].visibility" \"public\" -//@ has "$.index[*][?(@.name=='WithGenerics')].inner.struct" -//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[0].name" \"T\" -//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[0].kind.type.bounds" [] -//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[1].name" \"U\" -//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[1].kind.type.bounds" [] -//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.has_stripped_fields" true -//@ is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.fields" [] +//@ is "$.index[?(@.name=='WithGenerics')].visibility" \"public\" +//@ has "$.index[?(@.name=='WithGenerics')].inner.struct" +//@ is "$.index[?(@.name=='WithGenerics')].inner.struct.generics.params[0].name" \"T\" +//@ is "$.index[?(@.name=='WithGenerics')].inner.struct.generics.params[0].kind.type.bounds" [] +//@ is "$.index[?(@.name=='WithGenerics')].inner.struct.generics.params[1].name" \"U\" +//@ is "$.index[?(@.name=='WithGenerics')].inner.struct.generics.params[1].kind.type.bounds" [] +//@ is "$.index[?(@.name=='WithGenerics')].inner.struct.kind.plain.has_stripped_fields" true +//@ is "$.index[?(@.name=='WithGenerics')].inner.struct.kind.plain.fields" [] pub struct WithGenerics<T, U> { stuff: Vec<T>, things: HashMap<U, U>, diff --git a/tests/rustdoc-json/structs/with_primitives.rs b/tests/rustdoc-json/structs/with_primitives.rs index fe99292456d..4e856bda296 100644 --- a/tests/rustdoc-json/structs/with_primitives.rs +++ b/tests/rustdoc-json/structs/with_primitives.rs @@ -1,9 +1,9 @@ -//@ is "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\" -//@ has "$.index[*][?(@.name=='WithPrimitives')].inner.struct" -//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].name" \"\'a\" -//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].kind.lifetime.outlives" [] -//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.has_stripped_fields" true -//@ is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.fields" [] +//@ is "$.index[?(@.name=='WithPrimitives')].visibility" \"public\" +//@ has "$.index[?(@.name=='WithPrimitives')].inner.struct" +//@ is "$.index[?(@.name=='WithPrimitives')].inner.struct.generics.params[0].name" \"\'a\" +//@ is "$.index[?(@.name=='WithPrimitives')].inner.struct.generics.params[0].kind.lifetime.outlives" [] +//@ is "$.index[?(@.name=='WithPrimitives')].inner.struct.kind.plain.has_stripped_fields" true +//@ is "$.index[?(@.name=='WithPrimitives')].inner.struct.kind.plain.fields" [] pub struct WithPrimitives<'a> { num: u32, s: &'a str, diff --git a/tests/rustdoc-json/trait_alias.rs b/tests/rustdoc-json/trait_alias.rs index d9ef256b106..e7a586ee95a 100644 --- a/tests/rustdoc-json/trait_alias.rs +++ b/tests/rustdoc-json/trait_alias.rs @@ -1,17 +1,17 @@ #![feature(trait_alias)] -//@ set StrLike = "$.index[*][?(@.name=='StrLike')].id" -//@ is "$.index[*][?(@.name=='StrLike')].visibility" \"public\" -//@ has "$.index[*][?(@.name=='StrLike')].inner.trait_alias" -//@ is "$.index[*][?(@.name=='StrLike')].span.filename" $FILE +//@ set StrLike = "$.index[?(@.name=='StrLike')].id" +//@ is "$.index[?(@.name=='StrLike')].visibility" \"public\" +//@ has "$.index[?(@.name=='StrLike')].inner.trait_alias" +//@ is "$.index[?(@.name=='StrLike')].span.filename" $FILE pub trait StrLike = AsRef<str>; -//@ is "$.index[*][?(@.name=='f')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $StrLike +//@ is "$.index[?(@.name=='f')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $StrLike pub fn f() -> impl StrLike { "heya" } -//@ !is "$.index[*][?(@.name=='g')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $StrLike +//@ !is "$.index[?(@.name=='g')].inner.function.sig.output.impl_trait[0].trait_bound.trait.id" $StrLike pub fn g() -> impl AsRef<str> { "heya" } diff --git a/tests/rustdoc-json/traits/has_body.rs b/tests/rustdoc-json/traits/has_body.rs index 95e0f97b52c..d17988474f9 100644 --- a/tests/rustdoc-json/traits/has_body.rs +++ b/tests/rustdoc-json/traits/has_body.rs @@ -1,21 +1,21 @@ -//@ has "$.index[*][?(@.name=='Foo')]" +//@ has "$.index[?(@.name=='Foo')]" pub trait Foo { - //@ is "$.index[*][?(@.name=='no_self')].inner.function.has_body" false + //@ is "$.index[?(@.name=='no_self')].inner.function.has_body" false fn no_self(); - //@ is "$.index[*][?(@.name=='move_self')].inner.function.has_body" false + //@ is "$.index[?(@.name=='move_self')].inner.function.has_body" false fn move_self(self); - //@ is "$.index[*][?(@.name=='ref_self')].inner.function.has_body" false + //@ is "$.index[?(@.name=='ref_self')].inner.function.has_body" false fn ref_self(&self); - //@ is "$.index[*][?(@.name=='no_self_def')].inner.function.has_body" true + //@ is "$.index[?(@.name=='no_self_def')].inner.function.has_body" true fn no_self_def() {} - //@ is "$.index[*][?(@.name=='move_self_def')].inner.function.has_body" true + //@ is "$.index[?(@.name=='move_self_def')].inner.function.has_body" true fn move_self_def(self) {} - //@ is "$.index[*][?(@.name=='ref_self_def')].inner.function.has_body" true + //@ is "$.index[?(@.name=='ref_self_def')].inner.function.has_body" true fn ref_self_def(&self) {} } pub trait Bar: Clone { - //@ is "$.index[*][?(@.name=='method')].inner.function.has_body" false + //@ is "$.index[?(@.name=='method')].inner.function.has_body" false fn method(&self, param: usize); } diff --git a/tests/rustdoc-json/traits/implementors.rs b/tests/rustdoc-json/traits/implementors.rs index 9fdb763b61e..499acefedb7 100644 --- a/tests/rustdoc-json/traits/implementors.rs +++ b/tests/rustdoc-json/traits/implementors.rs @@ -5,14 +5,14 @@ pub struct GeorgeMichael {} impl Wham for GeorgeMichael {} // Find IDs. -//@ set wham = "$.index[*][?(@.name=='Wham')].id" -//@ set gmWham = "$.index[*][?(@.docs=='Wham for George Michael')].id" -//@ set gm = "$.index[*][?(@.name=='GeorgeMichael')].id" +//@ set wham = "$.index[?(@.name=='Wham')].id" +//@ set gmWham = "$.index[?(@.docs=='Wham for George Michael')].id" +//@ set gm = "$.index[?(@.name=='GeorgeMichael')].id" // Both struct and trait point to impl. -//@ has "$.index[*][?(@.name=='GeorgeMichael')].inner.struct.impls[*]" $gmWham -//@ is "$.index[*][?(@.name=='Wham')].inner.trait.implementations[*]" $gmWham +//@ has "$.index[?(@.name=='GeorgeMichael')].inner.struct.impls[*]" $gmWham +//@ is "$.index[?(@.name=='Wham')].inner.trait.implementations[*]" $gmWham // Impl points to both struct and trait. -//@ is "$.index[*][?(@.docs == 'Wham for George Michael')].inner.impl.trait.id" $wham -//@ is "$.index[*][?(@.docs == 'Wham for George Michael')].inner.impl.for.resolved_path.id" $gm +//@ is "$.index[?(@.docs == 'Wham for George Michael')].inner.impl.trait.id" $wham +//@ is "$.index[?(@.docs == 'Wham for George Michael')].inner.impl.for.resolved_path.id" $gm diff --git a/tests/rustdoc-json/traits/is_dyn_compatible.rs b/tests/rustdoc-json/traits/is_dyn_compatible.rs index bccf94d17d6..b172b53807b 100644 --- a/tests/rustdoc-json/traits/is_dyn_compatible.rs +++ b/tests/rustdoc-json/traits/is_dyn_compatible.rs @@ -1,19 +1,19 @@ #![no_std] -//@ has "$.index[*][?(@.name=='FooDynIncompatible')]" -//@ is "$.index[*][?(@.name=='FooDynIncompatible')].inner.trait.is_dyn_compatible" false +//@ has "$.index[?(@.name=='FooDynIncompatible')]" +//@ is "$.index[?(@.name=='FooDynIncompatible')].inner.trait.is_dyn_compatible" false pub trait FooDynIncompatible { fn foo() -> Self; } -//@ has "$.index[*][?(@.name=='BarDynIncompatible')]" -//@ is "$.index[*][?(@.name=='BarDynIncompatible')].inner.trait.is_dyn_compatible" false +//@ has "$.index[?(@.name=='BarDynIncompatible')]" +//@ is "$.index[?(@.name=='BarDynIncompatible')].inner.trait.is_dyn_compatible" false pub trait BarDynIncompatible<T> { fn foo(i: T); } -//@ has "$.index[*][?(@.name=='FooDynCompatible')]" -//@ is "$.index[*][?(@.name=='FooDynCompatible')].inner.trait.is_dyn_compatible" true +//@ has "$.index[?(@.name=='FooDynCompatible')]" +//@ is "$.index[?(@.name=='FooDynCompatible')].inner.trait.is_dyn_compatible" true pub trait FooDynCompatible { fn foo(&self); } diff --git a/tests/rustdoc-json/traits/private_supertrait.rs b/tests/rustdoc-json/traits/private_supertrait.rs index ce0642278e0..1e11abaecdf 100644 --- a/tests/rustdoc-json/traits/private_supertrait.rs +++ b/tests/rustdoc-json/traits/private_supertrait.rs @@ -1,9 +1,9 @@ -//@ !has "$.index[*][?(@.name == 'sealed')]" +//@ !has "$.index[?(@.name == 'sealed')]" mod sealed { - //@ set sealed_id = "$.index[*][?(@.name=='Sealed')].id" + //@ set sealed_id = "$.index[?(@.name=='Sealed')].id" pub trait Sealed {} } -//@ count "$.index[*][?(@.name=='Trait')].inner.trait.bounds[*]" 1 -//@ is "$.index[*][?(@.name=='Trait')].inner.trait.bounds[0].trait_bound.trait.id" $sealed_id +//@ count "$.index[?(@.name=='Trait')].inner.trait.bounds[*]" 1 +//@ is "$.index[?(@.name=='Trait')].inner.trait.bounds[0].trait_bound.trait.id" $sealed_id pub trait Trait: sealed::Sealed {} diff --git a/tests/rustdoc-json/traits/self.rs b/tests/rustdoc-json/traits/self.rs index efd9efd556f..018bda9cc3c 100644 --- a/tests/rustdoc-json/traits/self.rs +++ b/tests/rustdoc-json/traits/self.rs @@ -7,29 +7,29 @@ pub struct Foo; // Each assertion matches 3 times, and should be the same each time. impl Foo { - //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"' - //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' - //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' null null null - //@ ismany '$.index[*][?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' false false false + //@ ismany '$.index[?(@.name=="by_ref")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"' + //@ ismany '$.index[?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' + //@ ismany '$.index[?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' null null null + //@ ismany '$.index[?(@.name=="by_ref")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' false false false pub fn by_ref(&self) {} - //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"' - //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' - //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' null null null - //@ ismany '$.index[*][?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' true true true + //@ ismany '$.index[?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"' + //@ ismany '$.index[?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' + //@ ismany '$.index[?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' null null null + //@ ismany '$.index[?(@.name=="by_exclusive_ref")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' true true true pub fn by_exclusive_ref(&mut self) {} - //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"' - //@ ismany '$.index[*][?(@.name=="by_value")].inner.function.sig.inputs[0][1].generic' '"Self"' '"Self"' '"Self"' + //@ ismany '$.index[?(@.name=="by_value")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"' + //@ ismany '$.index[?(@.name=="by_value")].inner.function.sig.inputs[0][1].generic' '"Self"' '"Self"' '"Self"' pub fn by_value(self) {} - //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"' - //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' - //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' \"\'a\" \"\'a\" \"\'a\" - //@ ismany '$.index[*][?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' false false false + //@ ismany '$.index[?(@.name=="with_lifetime")].inner.function.sig.inputs[0][0]' '"self"' '"self"' '"self"' + //@ ismany '$.index[?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.type.generic' '"Self"' '"Self"' '"Self"' + //@ ismany '$.index[?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.lifetime' \"\'a\" \"\'a\" \"\'a\" + //@ ismany '$.index[?(@.name=="with_lifetime")].inner.function.sig.inputs[0][1].borrowed_ref.is_mutable' false false false pub fn with_lifetime<'a>(&'a self) {} - //@ ismany '$.index[*][?(@.name=="build")].inner.function.sig.output.generic' '"Self"' '"Self"' '"Self"' + //@ ismany '$.index[?(@.name=="build")].inner.function.sig.output.generic' '"Self"' '"Self"' '"Self"' pub fn build() -> Self { Self } diff --git a/tests/rustdoc-json/traits/supertrait.rs b/tests/rustdoc-json/traits/supertrait.rs index 4b6199d4b26..3accb0ff858 100644 --- a/tests/rustdoc-json/traits/supertrait.rs +++ b/tests/rustdoc-json/traits/supertrait.rs @@ -1,20 +1,20 @@ -//@ set loud_id = "$.index[*][?(@.name=='Loud')].id" +//@ set loud_id = "$.index[?(@.name=='Loud')].id" pub trait Loud {} -//@ set very_loud_id = "$.index[*][?(@.name=='VeryLoud')].id" -//@ count "$.index[*][?(@.name=='VeryLoud')].inner.trait.bounds[*]" 1 -//@ is "$.index[*][?(@.name=='VeryLoud')].inner.trait.bounds[0].trait_bound.trait.id" $loud_id +//@ set very_loud_id = "$.index[?(@.name=='VeryLoud')].id" +//@ count "$.index[?(@.name=='VeryLoud')].inner.trait.bounds[*]" 1 +//@ is "$.index[?(@.name=='VeryLoud')].inner.trait.bounds[0].trait_bound.trait.id" $loud_id pub trait VeryLoud: Loud {} -//@ set sounds_good_id = "$.index[*][?(@.name=='SoundsGood')].id" +//@ set sounds_good_id = "$.index[?(@.name=='SoundsGood')].id" pub trait SoundsGood {} -//@ count "$.index[*][?(@.name=='MetalBand')].inner.trait.bounds[*]" 2 -//@ is "$.index[*][?(@.name=='MetalBand')].inner.trait.bounds[0].trait_bound.trait.id" $very_loud_id -//@ is "$.index[*][?(@.name=='MetalBand')].inner.trait.bounds[1].trait_bound.trait.id" $sounds_good_id +//@ count "$.index[?(@.name=='MetalBand')].inner.trait.bounds[*]" 2 +//@ is "$.index[?(@.name=='MetalBand')].inner.trait.bounds[0].trait_bound.trait.id" $very_loud_id +//@ is "$.index[?(@.name=='MetalBand')].inner.trait.bounds[1].trait_bound.trait.id" $sounds_good_id pub trait MetalBand: VeryLoud + SoundsGood {} -//@ count "$.index[*][?(@.name=='DnabLatem')].inner.trait.bounds[*]" 2 -//@ is "$.index[*][?(@.name=='DnabLatem')].inner.trait.bounds[1].trait_bound.trait.id" $very_loud_id -//@ is "$.index[*][?(@.name=='DnabLatem')].inner.trait.bounds[0].trait_bound.trait.id" $sounds_good_id +//@ count "$.index[?(@.name=='DnabLatem')].inner.trait.bounds[*]" 2 +//@ is "$.index[?(@.name=='DnabLatem')].inner.trait.bounds[1].trait_bound.trait.id" $very_loud_id +//@ is "$.index[?(@.name=='DnabLatem')].inner.trait.bounds[0].trait_bound.trait.id" $sounds_good_id pub trait DnabLatem: SoundsGood + VeryLoud {} diff --git a/tests/rustdoc-json/traits/trait_alias.rs b/tests/rustdoc-json/traits/trait_alias.rs index 137b8947e23..497930a67c8 100644 --- a/tests/rustdoc-json/traits/trait_alias.rs +++ b/tests/rustdoc-json/traits/trait_alias.rs @@ -2,25 +2,25 @@ #![feature(trait_alias)] -//@ set Orig = "$.index[*][?(@.name == 'Orig')].id" -//@ has "$.index[*][?(@.name == 'Orig')].inner.trait" +//@ set Orig = "$.index[?(@.name == 'Orig')].id" +//@ has "$.index[?(@.name == 'Orig')].inner.trait" pub trait Orig<T> {} -//@ set Alias = "$.index[*][?(@.name == 'Alias')].id" -//@ has "$.index[*][?(@.name == 'Alias')].inner.trait_alias" -//@ is "$.index[*][?(@.name == 'Alias')].inner.trait_alias.generics" '{"params": [], "where_predicates": []}' -//@ count "$.index[*][?(@.name == 'Alias')].inner.trait_alias.params[*]" 1 -//@ is "$.index[*][?(@.name == 'Alias')].inner.trait_alias.params[0].trait_bound.trait.id" $Orig -//@ is "$.index[*][?(@.name == 'Alias')].inner.trait_alias.params[0].trait_bound.trait.args.angle_bracketed.args[0].type.primitive" '"i32"' +//@ set Alias = "$.index[?(@.name == 'Alias')].id" +//@ has "$.index[?(@.name == 'Alias')].inner.trait_alias" +//@ is "$.index[?(@.name == 'Alias')].inner.trait_alias.generics" '{"params": [], "where_predicates": []}' +//@ count "$.index[?(@.name == 'Alias')].inner.trait_alias.params[*]" 1 +//@ is "$.index[?(@.name == 'Alias')].inner.trait_alias.params[0].trait_bound.trait.id" $Orig +//@ is "$.index[?(@.name == 'Alias')].inner.trait_alias.params[0].trait_bound.trait.args.angle_bracketed.args[0].type.primitive" '"i32"' pub trait Alias = Orig<i32>; pub struct Struct; impl Orig<i32> for Struct {} -//@ has "$.index[*][?(@.name=='takes_alias')].inner.function.sig.inputs[0][1].impl_trait" -//@ is "$.index[*][?(@.name=='takes_alias')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.id" $Alias -//@ is "$.index[*][?(@.name=='takes_alias')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $Alias +//@ has "$.index[?(@.name=='takes_alias')].inner.function.sig.inputs[0][1].impl_trait" +//@ is "$.index[?(@.name=='takes_alias')].inner.function.sig.inputs[0][1].impl_trait[0].trait_bound.trait.id" $Alias +//@ is "$.index[?(@.name=='takes_alias')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $Alias pub fn takes_alias(_: impl Alias) {} // FIXME: Should the trait be mentioned in both the decl and generics? diff --git a/tests/rustdoc-json/traits/uses_extern_trait.rs b/tests/rustdoc-json/traits/uses_extern_trait.rs index 3a93bcaefd4..52983527f08 100644 --- a/tests/rustdoc-json/traits/uses_extern_trait.rs +++ b/tests/rustdoc-json/traits/uses_extern_trait.rs @@ -1,5 +1,5 @@ #![no_std] pub fn drop_default<T: core::default::Default>(_x: T) {} -//@ !has "$.index[*][?(@.name=='Debug')]" -//@ !has "$.index[*][?(@.name=='Default')]" +//@ !has "$.index[?(@.name=='Debug')]" +//@ !has "$.index[?(@.name=='Default')]" diff --git a/tests/rustdoc-json/type/dyn.rs b/tests/rustdoc-json/type/dyn.rs index d8686d4e2fb..4e533a67f8b 100644 --- a/tests/rustdoc-json/type/dyn.rs +++ b/tests/rustdoc-json/type/dyn.rs @@ -1,45 +1,45 @@ use std::fmt::Debug; -//@ count "$.index[*][?(@.name=='dyn')].inner.module.items[*]" 3 -//@ set sync_int_gen = "$.index[*][?(@.name=='SyncIntGen')].id" -//@ set ref_fn = "$.index[*][?(@.name=='RefFn')].id" -//@ set weird_order = "$.index[*][?(@.name=='WeirdOrder')].id" -//@ ismany "$.index[*][?(@.name=='dyn')].inner.module.items[*]" $sync_int_gen $ref_fn $weird_order +//@ count "$.index[?(@.name=='dyn')].inner.module.items[*]" 3 +//@ set sync_int_gen = "$.index[?(@.name=='SyncIntGen')].id" +//@ set ref_fn = "$.index[?(@.name=='RefFn')].id" +//@ set weird_order = "$.index[?(@.name=='WeirdOrder')].id" +//@ ismany "$.index[?(@.name=='dyn')].inner.module.items[*]" $sync_int_gen $ref_fn $weird_order -//@ has "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias" -//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.generics" '{"params": [], "where_predicates": []}' -//@ has "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path" -//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.path" \"Box\" -//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" [] -//@ count "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args" 1 -//@ has "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait" -//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.lifetime" \"\'static\" -//@ count "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[*]" 3 -//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].generic_params" [] -//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].generic_params" [] -//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].generic_params" [] -//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.path" '"Fn"' -//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.path" '"Send"' -//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].trait.path" '"Sync"' -//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.args" '{"parenthesized": {"inputs": [],"output": {"primitive": "i32"}}}' +//@ has "$.index[?(@.name=='SyncIntGen')].inner.type_alias" +//@ is "$.index[?(@.name=='SyncIntGen')].inner.type_alias.generics" '{"params": [], "where_predicates": []}' +//@ has "$.index[?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path" +//@ is "$.index[?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.path" \"Box\" +//@ is "$.index[?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" [] +//@ count "$.index[?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args" 1 +//@ has "$.index[?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait" +//@ is "$.index[?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.lifetime" \"\'static\" +//@ count "$.index[?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[*]" 3 +//@ is "$.index[?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].generic_params" [] +//@ is "$.index[?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].generic_params" [] +//@ is "$.index[?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].generic_params" [] +//@ is "$.index[?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.path" '"Fn"' +//@ is "$.index[?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.path" '"Send"' +//@ is "$.index[?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].trait.path" '"Sync"' +//@ is "$.index[?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.args" '{"parenthesized": {"inputs": [],"output": {"primitive": "i32"}}}' pub type SyncIntGen = Box<dyn Fn() -> i32 + Send + Sync + 'static>; -//@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias" -//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.generics" '{"params": [{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"}],"where_predicates": []}' -//@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref" -//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.is_mutable" 'false' -//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.lifetime" "\"'a\"" -//@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait" -//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.lifetime" null -//@ count "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[*]" 1 -//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' -//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.path" '"Fn"' -//@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref" -//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref.lifetime" "\"'b\"" -//@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref" -//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref.lifetime" "\"'b\"" +//@ has "$.index[?(@.name=='RefFn')].inner.type_alias" +//@ is "$.index[?(@.name=='RefFn')].inner.type_alias.generics" '{"params": [{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"}],"where_predicates": []}' +//@ has "$.index[?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref" +//@ is "$.index[?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.is_mutable" 'false' +//@ is "$.index[?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.lifetime" "\"'a\"" +//@ has "$.index[?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait" +//@ is "$.index[?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.lifetime" null +//@ count "$.index[?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[*]" 1 +//@ is "$.index[?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' +//@ is "$.index[?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.path" '"Fn"' +//@ has "$.index[?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref" +//@ is "$.index[?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref.lifetime" "\"'b\"" +//@ has "$.index[?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref" +//@ is "$.index[?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref.lifetime" "\"'b\"" pub type RefFn<'a> = &'a dyn for<'b> Fn(&'b i32) -> &'b i32; -//@ is "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.path" '"Send"' -//@ is "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.path" '"Debug"' +//@ is "$.index[?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.path" '"Send"' +//@ is "$.index[?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.path" '"Debug"' pub type WeirdOrder = Box<dyn Send + Debug>; diff --git a/tests/rustdoc-json/type/extern.rs b/tests/rustdoc-json/type/extern.rs index 97e1c3760ee..7963690e448 100644 --- a/tests/rustdoc-json/type/extern.rs +++ b/tests/rustdoc-json/type/extern.rs @@ -5,5 +5,5 @@ extern "C" { pub type Foo; } -//@ is "$.index[*][?(@.docs=='No inner information')].name" '"Foo"' -//@ is "$.index[*][?(@.docs=='No inner information')].inner" \"extern_type\" +//@ is "$.index[?(@.docs=='No inner information')].name" '"Foo"' +//@ is "$.index[?(@.docs=='No inner information')].inner" \"extern_type\" diff --git a/tests/rustdoc-json/type/fn_lifetime.rs b/tests/rustdoc-json/type/fn_lifetime.rs index aaa716bf11f..10e95cc5e56 100644 --- a/tests/rustdoc-json/type/fn_lifetime.rs +++ b/tests/rustdoc-json/type/fn_lifetime.rs @@ -1,24 +1,24 @@ -//@ has "$.index[*][?(@.name=='GenericFn')].inner.type_alias" +//@ has "$.index[?(@.name=='GenericFn')].inner.type_alias" -//@ ismany "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.params[*].name" \"\'a\" -//@ has "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.params[*].kind.lifetime" -//@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.params[*].kind.lifetime.outlives[*]" 0 -//@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.generics.where_predicates[*]" 0 -//@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.generic_params[*]" 0 -//@ count "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.inputs[*][1].borrowed_ref.lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.output.borrowed_ref.lifetime" \"\'a\" +//@ ismany "$.index[?(@.name=='GenericFn')].inner.type_alias.generics.params[*].name" \"\'a\" +//@ has "$.index[?(@.name=='GenericFn')].inner.type_alias.generics.params[*].kind.lifetime" +//@ count "$.index[?(@.name=='GenericFn')].inner.type_alias.generics.params[*].kind.lifetime.outlives[*]" 0 +//@ count "$.index[?(@.name=='GenericFn')].inner.type_alias.generics.where_predicates[*]" 0 +//@ count "$.index[?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.generic_params[*]" 0 +//@ count "$.index[?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1 +//@ is "$.index[?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.inputs[*][1].borrowed_ref.lifetime" \"\'a\" +//@ is "$.index[?(@.name=='GenericFn')].inner.type_alias.type.function_pointer.sig.output.borrowed_ref.lifetime" \"\'a\" pub type GenericFn<'a> = fn(&'a i32) -> &'a i32; -//@ has "$.index[*][?(@.name=='ForAll')].inner.type_alias" -//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.generics.params[*]" 0 -//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.generics.where_predicates[*]" 0 -//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*]" 1 -//@ is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].name" \"\'a\" -//@ has "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].kind.lifetime" -//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].kind.lifetime.outlives[*]" 0 -//@ count "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.inputs[*][1].borrowed_ref.lifetime" \"\'a\" -//@ is "$.index[*][?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.output.borrowed_ref.lifetime" \"\'a\" +//@ has "$.index[?(@.name=='ForAll')].inner.type_alias" +//@ count "$.index[?(@.name=='ForAll')].inner.type_alias.generics.params[*]" 0 +//@ count "$.index[?(@.name=='ForAll')].inner.type_alias.generics.where_predicates[*]" 0 +//@ count "$.index[?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*]" 1 +//@ is "$.index[?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].name" \"\'a\" +//@ has "$.index[?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].kind.lifetime" +//@ count "$.index[?(@.name=='ForAll')].inner.type_alias.type.function_pointer.generic_params[*].kind.lifetime.outlives[*]" 0 +//@ count "$.index[?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.inputs[*]" 1 +//@ is "$.index[?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.inputs[*][1].borrowed_ref.lifetime" \"\'a\" +//@ is "$.index[?(@.name=='ForAll')].inner.type_alias.type.function_pointer.sig.output.borrowed_ref.lifetime" \"\'a\" pub type ForAll = for<'a> fn(&'a i32) -> &'a i32; diff --git a/tests/rustdoc-json/type/generic_default.rs b/tests/rustdoc-json/type/generic_default.rs index 2d2ce9cd103..26a232a1562 100644 --- a/tests/rustdoc-json/type/generic_default.rs +++ b/tests/rustdoc-json/type/generic_default.rs @@ -1,31 +1,31 @@ -//@ set result = "$.index[*][?(@.name=='Result')].id" +//@ set result = "$.index[?(@.name=='Result')].id" pub enum Result<T, E> { Ok(T), Err(E), } -//@ set my_error = "$.index[*][?(@.name=='MyError')].id" +//@ set my_error = "$.index[?(@.name=='MyError')].id" pub struct MyError {} -//@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias" -//@ count "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.where_predicates[*]" 0 -//@ count "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[*]" 2 -//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].name" \"T\" -//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].name" \"E\" -//@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].kind.type" -//@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type" -//@ count "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].kind.type.bounds[*]" 0 -//@ count "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.bounds[*]" 0 -//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].kind.type.default" null -//@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path" -//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.id" $my_error -//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.path" \"MyError\" -//@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path" -//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.id" $result -//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.path" \"Result\" -//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" [] -//@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic" -//@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[1].type.generic" -//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic" \"T\" -//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[1].type.generic" \"E\" +//@ has "$.index[?(@.name=='MyResult')].inner.type_alias" +//@ count "$.index[?(@.name=='MyResult')].inner.type_alias.generics.where_predicates[*]" 0 +//@ count "$.index[?(@.name=='MyResult')].inner.type_alias.generics.params[*]" 2 +//@ is "$.index[?(@.name=='MyResult')].inner.type_alias.generics.params[0].name" \"T\" +//@ is "$.index[?(@.name=='MyResult')].inner.type_alias.generics.params[1].name" \"E\" +//@ has "$.index[?(@.name=='MyResult')].inner.type_alias.generics.params[0].kind.type" +//@ has "$.index[?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type" +//@ count "$.index[?(@.name=='MyResult')].inner.type_alias.generics.params[0].kind.type.bounds[*]" 0 +//@ count "$.index[?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.bounds[*]" 0 +//@ is "$.index[?(@.name=='MyResult')].inner.type_alias.generics.params[0].kind.type.default" null +//@ has "$.index[?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path" +//@ is "$.index[?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.id" $my_error +//@ is "$.index[?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.path" \"MyError\" +//@ has "$.index[?(@.name=='MyResult')].inner.type_alias.type.resolved_path" +//@ is "$.index[?(@.name=='MyResult')].inner.type_alias.type.resolved_path.id" $result +//@ is "$.index[?(@.name=='MyResult')].inner.type_alias.type.resolved_path.path" \"Result\" +//@ is "$.index[?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" [] +//@ has "$.index[?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic" +//@ has "$.index[?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[1].type.generic" +//@ is "$.index[?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic" \"T\" +//@ is "$.index[?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[1].type.generic" \"E\" pub type MyResult<T, E = MyError> = Result<T, E>; diff --git a/tests/rustdoc-json/type/hrtb.rs b/tests/rustdoc-json/type/hrtb.rs index 08b35b90a2b..68b7a556a69 100644 --- a/tests/rustdoc-json/type/hrtb.rs +++ b/tests/rustdoc-json/type/hrtb.rs @@ -1,5 +1,5 @@ -//@ is "$.index[*][?(@.name=='genfn')].inner.function.generics.where_predicates[0].bound_predicate.type" '{"generic": "F"}' -//@ is "$.index[*][?(@.name=='genfn')].inner.function.generics.where_predicates[0].bound_predicate.generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' +//@ is "$.index[?(@.name=='genfn')].inner.function.generics.where_predicates[0].bound_predicate.type" '{"generic": "F"}' +//@ is "$.index[?(@.name=='genfn')].inner.function.generics.where_predicates[0].bound_predicate.generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' pub fn genfn<F>(f: F) where for<'a, 'b> F: Fn(&'a i32, &'b i32), @@ -8,12 +8,12 @@ where f(&zero, &zero); } -//@ is "$.index[*][?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}' -//@ is "$.index[*][?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}' -//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null -//@ count "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1 -//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' -//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.path" '"Fn"' +//@ is "$.index[?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}' +//@ is "$.index[?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}' +//@ is "$.index[?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null +//@ count "$.index[?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1 +//@ is "$.index[?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' +//@ is "$.index[?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.path" '"Fn"' pub fn dynfn(f: &dyn for<'a, 'b> Fn(&'a i32, &'b i32)) { let zero = 0; f(&zero, &zero); diff --git a/tests/rustdoc-json/type/inherent_associated_type.rs b/tests/rustdoc-json/type/inherent_associated_type.rs index e26f8f7c651..e96a92f7cfb 100644 --- a/tests/rustdoc-json/type/inherent_associated_type.rs +++ b/tests/rustdoc-json/type/inherent_associated_type.rs @@ -1,23 +1,23 @@ #![feature(inherent_associated_types)] #![allow(incomplete_features)] -//@ set OwnerMetadata = '$.index[*][?(@.name=="OwnerMetadata")].id' +//@ set OwnerMetadata = '$.index[?(@.name=="OwnerMetadata")].id' pub struct OwnerMetadata; -//@ set Owner = '$.index[*][?(@.name=="Owner")].id' +//@ set Owner = '$.index[?(@.name=="Owner")].id' pub struct Owner; pub fn create() -> Owner::Metadata { OwnerMetadata } -//@ is '$.index[*][?(@.name=="create")].inner.function.sig.output.qualified_path.name' '"Metadata"' -//@ is '$.index[*][?(@.name=="create")].inner.function.sig.output.qualified_path.trait' null -//@ is '$.index[*][?(@.name=="create")].inner.function.sig.output.qualified_path.self_type.resolved_path.id' $Owner +//@ is '$.index[?(@.name=="create")].inner.function.sig.output.qualified_path.name' '"Metadata"' +//@ is '$.index[?(@.name=="create")].inner.function.sig.output.qualified_path.trait' null +//@ is '$.index[?(@.name=="create")].inner.function.sig.output.qualified_path.self_type.resolved_path.id' $Owner /// impl impl Owner { /// iat pub type Metadata = OwnerMetadata; } -//@ set iat = '$.index[*][?(@.docs=="iat")].id' -//@ is '$.index[*][?(@.docs=="impl")].inner.impl.items[*]' $iat -//@ is '$.index[*][?(@.docs=="iat")].inner.assoc_type.type.resolved_path.id' $OwnerMetadata +//@ set iat = '$.index[?(@.docs=="iat")].id' +//@ is '$.index[?(@.docs=="impl")].inner.impl.items[*]' $iat +//@ is '$.index[?(@.docs=="iat")].inner.assoc_type.type.resolved_path.id' $OwnerMetadata diff --git a/tests/rustdoc-json/type/inherent_associated_type_bound.rs b/tests/rustdoc-json/type/inherent_associated_type_bound.rs index 22c9c9c1149..20354909f8e 100644 --- a/tests/rustdoc-json/type/inherent_associated_type_bound.rs +++ b/tests/rustdoc-json/type/inherent_associated_type_bound.rs @@ -1,17 +1,17 @@ #![feature(inherent_associated_types)] #![allow(incomplete_features)] -//@ set Carrier = '$.index[*][?(@.name=="Carrier")].id' +//@ set Carrier = '$.index[?(@.name=="Carrier")].id' pub struct Carrier<'a>(&'a ()); -//@ count "$.index[*][?(@.name=='user')].inner.function.sig.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='user')].inner.function.sig.inputs[0][0]" '"_"' -//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.generic_params[*].name' \""'b"\" -//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier -//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\" -//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.name' '"Focus"' -//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.trait' null -//@ is '$.index[*][?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"' +//@ count "$.index[?(@.name=='user')].inner.function.sig.inputs[*]" 1 +//@ is "$.index[?(@.name=='user')].inner.function.sig.inputs[0][0]" '"_"' +//@ is '$.index[?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.generic_params[*].name' \""'b"\" +//@ is '$.index[?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier +//@ is '$.index[?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\" +//@ is '$.index[?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.name' '"Focus"' +//@ is '$.index[?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.trait' null +//@ is '$.index[?(@.name=="user")].inner.function.sig.inputs[0][1].function_pointer.sig.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"' pub fn user(_: for<'b> fn(Carrier<'b>::Focus<i32>)) {} impl<'a> Carrier<'a> { diff --git a/tests/rustdoc-json/type/inherent_associated_type_projections.rs b/tests/rustdoc-json/type/inherent_associated_type_projections.rs index 501694dce8b..934daba11bb 100644 --- a/tests/rustdoc-json/type/inherent_associated_type_projections.rs +++ b/tests/rustdoc-json/type/inherent_associated_type_projections.rs @@ -1,15 +1,15 @@ #![feature(inherent_associated_types)] #![allow(incomplete_features)] -//@ set Parametrized = '$.index[*][?(@.name=="Parametrized")].id' +//@ set Parametrized = '$.index[?(@.name=="Parametrized")].id' pub struct Parametrized<T>(T); -//@ count "$.index[*][?(@.name=='test')].inner.function.sig.inputs[*]" 1 -//@ is "$.index[*][?(@.name=='test')].inner.function.sig.inputs[0][0]" '"_"' -//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.id' $Parametrized -//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\" -//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.name' '"Proj"' -//@ is '$.index[*][?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.trait' null +//@ count "$.index[?(@.name=='test')].inner.function.sig.inputs[*]" 1 +//@ is "$.index[?(@.name=='test')].inner.function.sig.inputs[0][0]" '"_"' +//@ is '$.index[?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.id' $Parametrized +//@ is '$.index[?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\" +//@ is '$.index[?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.name' '"Proj"' +//@ is '$.index[?(@.name=="test")].inner.function.sig.inputs[0][1].qualified_path.trait' null pub fn test(_: Parametrized<i32>::Proj) {} /// param_bool @@ -24,10 +24,10 @@ impl Parametrized<i32> { pub type Proj = String; } -//@ set param_bool = '$.index[*][?(@.docs=="param_bool")].id' -//@ set param_i32 = '$.index[*][?(@.docs=="param_i32")].id' -//@ set param_bool_proj = '$.index[*][?(@.docs=="param_bool_proj")].id' -//@ set param_i32_proj = '$.index[*][?(@.docs=="param_i32_proj")].id' +//@ set param_bool = '$.index[?(@.docs=="param_bool")].id' +//@ set param_i32 = '$.index[?(@.docs=="param_i32")].id' +//@ set param_bool_proj = '$.index[?(@.docs=="param_bool_proj")].id' +//@ set param_i32_proj = '$.index[?(@.docs=="param_i32_proj")].id' -//@ is '$.index[*][?(@.docs=="param_bool")].inner.impl.items[*]' $param_bool_proj -//@ is '$.index[*][?(@.docs=="param_i32")].inner.impl.items[*]' $param_i32_proj +//@ is '$.index[?(@.docs=="param_bool")].inner.impl.items[*]' $param_bool_proj +//@ is '$.index[?(@.docs=="param_i32")].inner.impl.items[*]' $param_i32_proj diff --git a/tests/rustdoc-json/type_alias.rs b/tests/rustdoc-json/type_alias.rs index 2f2b4c42d44..7fd23a48040 100644 --- a/tests/rustdoc-json/type_alias.rs +++ b/tests/rustdoc-json/type_alias.rs @@ -1,15 +1,15 @@ -//@ set IntVec = "$.index[*][?(@.name=='IntVec')].id" -//@ is "$.index[*][?(@.name=='IntVec')].visibility" \"public\" -//@ has "$.index[*][?(@.name=='IntVec')].inner.type_alias" -//@ is "$.index[*][?(@.name=='IntVec')].span.filename" $FILE +//@ set IntVec = "$.index[?(@.name=='IntVec')].id" +//@ is "$.index[?(@.name=='IntVec')].visibility" \"public\" +//@ has "$.index[?(@.name=='IntVec')].inner.type_alias" +//@ is "$.index[?(@.name=='IntVec')].span.filename" $FILE pub type IntVec = Vec<u32>; -//@ is "$.index[*][?(@.name=='f')].inner.function.sig.output.resolved_path.id" $IntVec +//@ is "$.index[?(@.name=='f')].inner.function.sig.output.resolved_path.id" $IntVec pub fn f() -> IntVec { vec![0; 32] } -//@ !is "$.index[*][?(@.name=='g')].inner.function.sig.output.resolved_path.id" $IntVec +//@ !is "$.index[?(@.name=='g')].inner.function.sig.output.resolved_path.id" $IntVec pub fn g() -> Vec<u32> { vec![0; 32] } diff --git a/tests/rustdoc-json/unions/field_order.rs b/tests/rustdoc-json/unions/field_order.rs index a1616f62751..b3a07a13bc8 100644 --- a/tests/rustdoc-json/unions/field_order.rs +++ b/tests/rustdoc-json/unions/field_order.rs @@ -15,24 +15,24 @@ pub union Foo { pub vll_9: i32, } -//@ set 0 = '$.index[*][?(@.name == "ews_0")].id' -//@ set 1 = '$.index[*][?(@.name == "dik_1")].id' -//@ set 2 = '$.index[*][?(@.name == "hsk_2")].id' -//@ set 3 = '$.index[*][?(@.name == "djt_3")].id' -//@ set 4 = '$.index[*][?(@.name == "jnr_4")].id' -//@ set 5 = '$.index[*][?(@.name == "dfs_5")].id' -//@ set 6 = '$.index[*][?(@.name == "bja_6")].id' -//@ set 7 = '$.index[*][?(@.name == "lyc_7")].id' -//@ set 8 = '$.index[*][?(@.name == "yqd_8")].id' -//@ set 9 = '$.index[*][?(@.name == "vll_9")].id' +//@ set 0 = '$.index[?(@.name == "ews_0")].id' +//@ set 1 = '$.index[?(@.name == "dik_1")].id' +//@ set 2 = '$.index[?(@.name == "hsk_2")].id' +//@ set 3 = '$.index[?(@.name == "djt_3")].id' +//@ set 4 = '$.index[?(@.name == "jnr_4")].id' +//@ set 5 = '$.index[?(@.name == "dfs_5")].id' +//@ set 6 = '$.index[?(@.name == "bja_6")].id' +//@ set 7 = '$.index[?(@.name == "lyc_7")].id' +//@ set 8 = '$.index[?(@.name == "yqd_8")].id' +//@ set 9 = '$.index[?(@.name == "vll_9")].id' -//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[0]' $0 -//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[1]' $1 -//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[2]' $2 -//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[3]' $3 -//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[4]' $4 -//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[5]' $5 -//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[6]' $6 -//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[7]' $7 -//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[8]' $8 -//@ is '$.index[*][?(@.name == "Foo")].inner.union.fields[9]' $9 +//@ is '$.index[?(@.name == "Foo")].inner.union.fields[0]' $0 +//@ is '$.index[?(@.name == "Foo")].inner.union.fields[1]' $1 +//@ is '$.index[?(@.name == "Foo")].inner.union.fields[2]' $2 +//@ is '$.index[?(@.name == "Foo")].inner.union.fields[3]' $3 +//@ is '$.index[?(@.name == "Foo")].inner.union.fields[4]' $4 +//@ is '$.index[?(@.name == "Foo")].inner.union.fields[5]' $5 +//@ is '$.index[?(@.name == "Foo")].inner.union.fields[6]' $6 +//@ is '$.index[?(@.name == "Foo")].inner.union.fields[7]' $7 +//@ is '$.index[?(@.name == "Foo")].inner.union.fields[8]' $8 +//@ is '$.index[?(@.name == "Foo")].inner.union.fields[9]' $9 diff --git a/tests/rustdoc-json/unions/impl.rs b/tests/rustdoc-json/unions/impl.rs index 989a025f669..6f398cc23f6 100644 --- a/tests/rustdoc-json/unions/impl.rs +++ b/tests/rustdoc-json/unions/impl.rs @@ -1,15 +1,15 @@ #![no_std] -//@ is "$.index[*][?(@.name=='Ux')].visibility" \"public\" -//@ has "$.index[*][?(@.name=='Ux')].inner.union" +//@ is "$.index[?(@.name=='Ux')].visibility" \"public\" +//@ has "$.index[?(@.name=='Ux')].inner.union" pub union Ux { a: u32, b: u64, } -//@ is "$.index[*][?(@.name=='Num')].visibility" \"public\" -//@ has "$.index[*][?(@.name=='Num')].inner.trait" +//@ is "$.index[?(@.name=='Num')].visibility" \"public\" +//@ has "$.index[?(@.name=='Num')].inner.trait" pub trait Num {} -//@ count "$.index[*][?(@.name=='Ux')].inner.union.impls" 1 +//@ count "$.index[?(@.name=='Ux')].inner.union.impls" 1 impl Num for Ux {} diff --git a/tests/rustdoc-json/unions/union.rs b/tests/rustdoc-json/unions/union.rs index 7f135a72dec..24ee47f1957 100644 --- a/tests/rustdoc-json/unions/union.rs +++ b/tests/rustdoc-json/unions/union.rs @@ -1,14 +1,14 @@ -//@ has "$.index[*][?(@.name=='Union')].visibility" \"public\" -//@ has "$.index[*][?(@.name=='Union')].inner.union" -//@ !has "$.index[*][?(@.name=='Union')].inner.union.struct_type" -//@ set Union = "$.index[*][?(@.name=='Union')].id" +//@ has "$.index[?(@.name=='Union')].visibility" \"public\" +//@ has "$.index[?(@.name=='Union')].inner.union" +//@ !has "$.index[?(@.name=='Union')].inner.union.struct_type" +//@ set Union = "$.index[?(@.name=='Union')].id" pub union Union { int: i32, float: f32, } -//@ has "$.index[*][?(@.name=='make_int_union')].inner.function.sig.output.resolved_path" -//@ is "$.index[*][?(@.name=='make_int_union')].inner.function.sig.output.resolved_path.id" $Union +//@ has "$.index[?(@.name=='make_int_union')].inner.function.sig.output.resolved_path" +//@ is "$.index[?(@.name=='make_int_union')].inner.function.sig.output.resolved_path.id" $Union pub fn make_int_union(int: i32) -> Union { Union { int } } diff --git a/tests/rustdoc-ui/doc-cfg-check-cfg.rs b/tests/rustdoc-ui/doc-cfg-check-cfg.rs new file mode 100644 index 00000000000..e3420dc0789 --- /dev/null +++ b/tests/rustdoc-ui/doc-cfg-check-cfg.rs @@ -0,0 +1,16 @@ +// Ensure that `doc(cfg())` respects `check-cfg` +// Currently not properly working +#![feature(doc_cfg)] +#![deny(unexpected_cfgs)] + +//@revisions: no_check cfg_empty cfg_foo +//@[cfg_empty] compile-flags: --check-cfg cfg() +//@[cfg_foo] compile-flags: --check-cfg cfg(foo) + +//@[no_check] check-pass +//@[cfg_empty] check-pass +//@[cfg_empty] known-bug: #138358 +//@[cfg_foo] check-pass + +#[doc(cfg(foo))] +pub fn foo() {} diff --git a/tests/rustdoc-ui/doc-cfg-unstable.rs b/tests/rustdoc-ui/doc-cfg-unstable.rs new file mode 100644 index 00000000000..14c2e83ec85 --- /dev/null +++ b/tests/rustdoc-ui/doc-cfg-unstable.rs @@ -0,0 +1,10 @@ +// #138113: rustdoc didn't gate unstable predicates inside `doc(cfg(..))` +#![feature(doc_cfg)] + +// `cfg_boolean_literals` +#[doc(cfg(false))] //~ ERROR `cfg(false)` is experimental and subject to change +pub fn cfg_boolean_literals() {} + +// `cfg_version` +#[doc(cfg(sanitize = "thread"))] //~ ERROR `cfg(sanitize)` is experimental and subject to change +pub fn cfg_sanitize() {} diff --git a/tests/rustdoc-ui/doc-cfg-unstable.stderr b/tests/rustdoc-ui/doc-cfg-unstable.stderr new file mode 100644 index 00000000000..54de3b178ed --- /dev/null +++ b/tests/rustdoc-ui/doc-cfg-unstable.stderr @@ -0,0 +1,23 @@ +error[E0658]: `cfg(false)` is experimental and subject to change + --> $DIR/doc-cfg-unstable.rs:5:11 + | +LL | #[doc(cfg(false))] + | ^^^^^ + | + = note: see issue #131204 <https://github.com/rust-lang/rust/issues/131204> for more information + = help: add `#![feature(cfg_boolean_literals)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `cfg(sanitize)` is experimental and subject to change + --> $DIR/doc-cfg-unstable.rs:9:11 + | +LL | #[doc(cfg(sanitize = "thread"))] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #39699 <https://github.com/rust-lang/rust/issues/39699> for more information + = help: add `#![feature(cfg_sanitize)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.edition2015.stdout b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.edition2015.stdout index 13e142df837..ff26e7e3231 100644 --- a/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.edition2015.stdout +++ b/tests/rustdoc-ui/doctest/relative-path-include-bytes-132203.edition2015.stdout @@ -10,8 +10,6 @@ error: couldn't read `$DIR/relative-dir-empty-file`: $FILE_NOT_FOUND_MSG (os err | LL | let x = include_bytes!("relative-dir-empty-file"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/remap-path-prefix-macro.rs b/tests/rustdoc-ui/remap-path-prefix-macro.rs new file mode 100644 index 00000000000..1be22694b8c --- /dev/null +++ b/tests/rustdoc-ui/remap-path-prefix-macro.rs @@ -0,0 +1,9 @@ +// Regression test for "attempted to remap an already remapped filename" ICE in rustdoc +// when using --remap-path-prefix with macro rendering. +// <https://github.com/rust-lang/rust/issues/138520> + +//@ compile-flags:-Z unstable-options --remap-path-prefix={{src-base}}=remapped_path +//@ rustc-env:RUST_BACKTRACE=0 +//@ build-pass + +macro_rules! f(() => {}); diff --git a/tests/rustdoc/return-type-notation.rs b/tests/rustdoc/return-type-notation.rs new file mode 100644 index 00000000000..405e98eb28d --- /dev/null +++ b/tests/rustdoc/return-type-notation.rs @@ -0,0 +1,18 @@ +//@ edition: 2021 + +#![crate_type = "lib"] +#![feature(return_type_notation)] + +pub trait Foo { + async fn bar(); +} + +//@ has "return_type_notation/fn.foo.html" +//@ has - '//pre[@class="rust item-decl"]' "pub fn foo<T: Foo<bar(..): Send>>()" +//@ has - '//pre[@class="rust item-decl"]' "where <T as Foo>::bar(..): 'static, T::bar(..): Sync" +pub fn foo<T: Foo<bar(..): Send>>() +where + <T as Foo>::bar(..): 'static, + T::bar(..): Sync, +{ +} diff --git a/tests/ui-fulldeps/stable-mir/smir_visitor.rs b/tests/ui-fulldeps/stable-mir/smir_visitor.rs index cffb41742b4..0a579a07cef 100644 --- a/tests/ui-fulldeps/stable-mir/smir_visitor.rs +++ b/tests/ui-fulldeps/stable-mir/smir_visitor.rs @@ -18,6 +18,7 @@ extern crate stable_mir; use rustc_smir::rustc_internal; use stable_mir::mir::MirVisitor; +use stable_mir::mir::MutMirVisitor; use stable_mir::*; use std::collections::HashSet; use std::io::Write; @@ -99,6 +100,83 @@ impl<'a> mir::MirVisitor for TestVisitor<'a> { } } +fn test_mut_visitor() -> ControlFlow<()> { + let main_fn = stable_mir::entry_fn(); + let mut main_body = main_fn.unwrap().expect_body(); + let locals = main_body.locals().to_vec(); + let mut main_visitor = TestMutVisitor::collect(locals); + main_visitor.visit_body(&mut main_body); + assert!(main_visitor.ret_val.is_some()); + assert!(main_visitor.args.is_empty()); + assert!(main_visitor.tys.contains(&main_visitor.ret_val.unwrap().ty)); + assert!(!main_visitor.calls.is_empty()); + + let exit_fn = main_visitor.calls.last().unwrap(); + assert!(exit_fn.mangled_name().contains("exit_fn"), "Unexpected last function: {exit_fn:?}"); + + let mut exit_body = exit_fn.body().unwrap(); + let locals = exit_body.locals().to_vec(); + let mut exit_visitor = TestMutVisitor::collect(locals); + exit_visitor.visit_body(&mut exit_body); + assert!(exit_visitor.ret_val.is_some()); + assert_eq!(exit_visitor.args.len(), 1); + assert!(exit_visitor.tys.contains(&exit_visitor.ret_val.unwrap().ty)); + assert!(exit_visitor.tys.contains(&exit_visitor.args[0].ty)); + ControlFlow::Continue(()) +} + +struct TestMutVisitor { + locals: Vec<mir::LocalDecl>, + pub tys: HashSet<ty::Ty>, + pub ret_val: Option<mir::LocalDecl>, + pub args: Vec<mir::LocalDecl>, + pub calls: Vec<mir::mono::Instance>, +} + +impl TestMutVisitor { + fn collect(locals: Vec<mir::LocalDecl>) -> TestMutVisitor { + let visitor = TestMutVisitor { + locals: locals, + tys: Default::default(), + ret_val: None, + args: vec![], + calls: vec![], + }; + visitor + } +} + +impl mir::MutMirVisitor for TestMutVisitor { + fn visit_ty(&mut self, ty: &mut ty::Ty, _location: mir::visit::Location) { + self.tys.insert(*ty); + self.super_ty(ty) + } + + fn visit_ret_decl(&mut self, local: mir::Local, decl: &mut mir::LocalDecl) { + assert!(local == mir::RETURN_LOCAL); + assert!(self.ret_val.is_none()); + self.ret_val = Some(decl.clone()); + self.super_ret_decl(local, decl); + } + + fn visit_arg_decl(&mut self, local: mir::Local, decl: &mut mir::LocalDecl) { + self.args.push(decl.clone()); + assert_eq!(local, self.args.len()); + self.super_arg_decl(local, decl); + } + + fn visit_terminator(&mut self, term: &mut mir::Terminator, location: mir::visit::Location) { + if let mir::TerminatorKind::Call { func, .. } = &mut term.kind { + let ty::TyKind::RigidTy(ty) = func.ty(&self.locals).unwrap().kind() else { + unreachable!() + }; + let ty::RigidTy::FnDef(def, args) = ty else { unreachable!() }; + self.calls.push(mir::mono::Instance::resolve(def, &args).unwrap()); + } + self.super_terminator(term, location); + } +} + /// This test will generate and analyze a dummy crate using the stable mir. /// For that, it will first write the dummy crate into a file. /// Then it will create a `StableMir` using custom arguments and then @@ -113,7 +191,8 @@ fn main() { CRATE_NAME.to_string(), path.to_string(), ]; - run!(args, test_visitor).unwrap(); + run!(args.clone(), test_visitor).unwrap(); + run!(args, test_mut_visitor).unwrap(); } fn generate_input(path: &str) -> std::io::Result<()> { diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index 01d90717107..64e65ece85d 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -40,6 +40,7 @@ //@ revisions: loongarch64 //@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu //@[loongarch64] needs-llvm-components: loongarch +//@[loongarch64] min-llvm-version: 20 //FIXME: wasm is disabled due to <https://github.com/rust-lang/rust/issues/115666>. //FIXME @ revisions: wasm //FIXME @[wasm] compile-flags: --target wasm32-unknown-unknown diff --git a/tests/ui/abi/simd-abi-checks-avx.rs b/tests/ui/abi/simd-abi-checks-avx.rs index acab74300b8..fa4b3ba3054 100644 --- a/tests/ui/abi/simd-abi-checks-avx.rs +++ b/tests/ui/abi/simd-abi-checks-avx.rs @@ -1,6 +1,7 @@ //@ only-x86_64 //@ build-pass //@ ignore-pass (test emits codegen-time warnings) +//@ compile-flags: -C target-feature=-avx #![feature(avx512_target_feature)] #![feature(portable_simd)] diff --git a/tests/ui/abi/simd-abi-checks-avx.stderr b/tests/ui/abi/simd-abi-checks-avx.stderr index 0dddc7dfa1c..5419970f809 100644 --- a/tests/ui/abi/simd-abi-checks-avx.stderr +++ b/tests/ui/abi/simd-abi-checks-avx.stderr @@ -1,5 +1,5 @@ warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:64:11 + --> $DIR/simd-abi-checks-avx.rs:65:11 | LL | f(g()); | ^^^ function called here @@ -10,7 +10,7 @@ LL | f(g()); = note: `#[warn(abi_unsupported_vector_types)]` on by default warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:64:9 + --> $DIR/simd-abi-checks-avx.rs:65:9 | LL | f(g()); | ^^^^^^ function called here @@ -20,7 +20,7 @@ LL | f(g()); = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:72:14 + --> $DIR/simd-abi-checks-avx.rs:73:14 | LL | gavx(favx()); | ^^^^^^ function called here @@ -30,7 +30,7 @@ LL | gavx(favx()); = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:72:9 + --> $DIR/simd-abi-checks-avx.rs:73:9 | LL | gavx(favx()); | ^^^^^^^^^^^^ function called here @@ -40,7 +40,7 @@ LL | gavx(favx()); = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:84:19 + --> $DIR/simd-abi-checks-avx.rs:85:19 | LL | w(Wrapper(g())); | ^^^ function called here @@ -50,7 +50,7 @@ LL | w(Wrapper(g())); = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) warning: this function call uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:84:9 + --> $DIR/simd-abi-checks-avx.rs:85:9 | LL | w(Wrapper(g())); | ^^^^^^^^^^^^^^^ function called here @@ -60,7 +60,7 @@ LL | w(Wrapper(g())); = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:100:9 + --> $DIR/simd-abi-checks-avx.rs:101:9 | LL | some_extern(); | ^^^^^^^^^^^^^ function called here @@ -70,7 +70,7 @@ LL | some_extern(); = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) warning: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled - --> $DIR/simd-abi-checks-avx.rs:27:1 + --> $DIR/simd-abi-checks-avx.rs:28:1 | LL | unsafe extern "C" fn g() -> __m256 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -80,7 +80,7 @@ LL | unsafe extern "C" fn g() -> __m256 { = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) warning: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled - --> $DIR/simd-abi-checks-avx.rs:21:1 + --> $DIR/simd-abi-checks-avx.rs:22:1 | LL | unsafe extern "C" fn f(_: __m256) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -90,7 +90,7 @@ LL | unsafe extern "C" fn f(_: __m256) { = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) warning: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled - --> $DIR/simd-abi-checks-avx.rs:15:1 + --> $DIR/simd-abi-checks-avx.rs:16:1 | LL | unsafe extern "C" fn w(_: Wrapper) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -100,7 +100,7 @@ LL | unsafe extern "C" fn w(_: Wrapper) { = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:57:8 + --> $DIR/simd-abi-checks-avx.rs:58:8 | LL | || g() | ^^^ function called here @@ -113,7 +113,7 @@ warning: 11 warnings emitted Future incompatibility report: Future breakage diagnostic: warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:64:11 + --> $DIR/simd-abi-checks-avx.rs:65:11 | LL | f(g()); | ^^^ function called here @@ -125,7 +125,7 @@ LL | f(g()); Future breakage diagnostic: warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:64:9 + --> $DIR/simd-abi-checks-avx.rs:65:9 | LL | f(g()); | ^^^^^^ function called here @@ -137,7 +137,7 @@ LL | f(g()); Future breakage diagnostic: warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:72:14 + --> $DIR/simd-abi-checks-avx.rs:73:14 | LL | gavx(favx()); | ^^^^^^ function called here @@ -149,7 +149,7 @@ LL | gavx(favx()); Future breakage diagnostic: warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:72:9 + --> $DIR/simd-abi-checks-avx.rs:73:9 | LL | gavx(favx()); | ^^^^^^^^^^^^ function called here @@ -161,7 +161,7 @@ LL | gavx(favx()); Future breakage diagnostic: warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:84:19 + --> $DIR/simd-abi-checks-avx.rs:85:19 | LL | w(Wrapper(g())); | ^^^ function called here @@ -173,7 +173,7 @@ LL | w(Wrapper(g())); Future breakage diagnostic: warning: this function call uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:84:9 + --> $DIR/simd-abi-checks-avx.rs:85:9 | LL | w(Wrapper(g())); | ^^^^^^^^^^^^^^^ function called here @@ -185,7 +185,7 @@ LL | w(Wrapper(g())); Future breakage diagnostic: warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:100:9 + --> $DIR/simd-abi-checks-avx.rs:101:9 | LL | some_extern(); | ^^^^^^^^^^^^^ function called here @@ -197,7 +197,7 @@ LL | some_extern(); Future breakage diagnostic: warning: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled - --> $DIR/simd-abi-checks-avx.rs:27:1 + --> $DIR/simd-abi-checks-avx.rs:28:1 | LL | unsafe extern "C" fn g() -> __m256 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -209,7 +209,7 @@ LL | unsafe extern "C" fn g() -> __m256 { Future breakage diagnostic: warning: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled - --> $DIR/simd-abi-checks-avx.rs:21:1 + --> $DIR/simd-abi-checks-avx.rs:22:1 | LL | unsafe extern "C" fn f(_: __m256) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -221,7 +221,7 @@ LL | unsafe extern "C" fn f(_: __m256) { Future breakage diagnostic: warning: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled - --> $DIR/simd-abi-checks-avx.rs:15:1 + --> $DIR/simd-abi-checks-avx.rs:16:1 | LL | unsafe extern "C" fn w(_: Wrapper) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -233,7 +233,7 @@ LL | unsafe extern "C" fn w(_: Wrapper) { Future breakage diagnostic: warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:57:8 + --> $DIR/simd-abi-checks-avx.rs:58:8 | LL | || g() | ^^^ function called here diff --git a/tests/ui/abi/simd-abi-checks-s390x.rs b/tests/ui/abi/simd-abi-checks-s390x.rs index 424ac00edcf..3743c75bf1e 100644 --- a/tests/ui/abi/simd-abi-checks-s390x.rs +++ b/tests/ui/abi/simd-abi-checks-s390x.rs @@ -1,7 +1,7 @@ //@ add-core-stubs //@ revisions: z10 z13_no_vector z13_soft_float //@ build-fail -//@[z10] compile-flags: --target s390x-unknown-linux-gnu +//@[z10] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z10 //@[z10] needs-llvm-components: systemz //@[z13_no_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13 -C target-feature=-vector //@[z13_no_vector] needs-llvm-components: systemz diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr index 80ff10e13d8..15314fac37b 100644 --- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr +++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr @@ -18,7 +18,6 @@ LL | fn oom( | ^^^ LL | info: &Layout, | ------------- - = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types --> $DIR/alloc-error-handler-bad-signature-1.rs:10:1 @@ -35,7 +34,6 @@ LL | | } | = note: expected type `!` found unit type `()` - = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr index 7a495380f2b..2ab42638411 100644 --- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr +++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr @@ -26,7 +26,6 @@ LL | fn oom( | ^^^ LL | info: Layout, | ------------ - = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types --> $DIR/alloc-error-handler-bad-signature-2.rs:10:1 @@ -43,7 +42,6 @@ LL | | } | = note: expected type `!` found unit type `()` - = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr index 3be219bdb06..3a410174f54 100644 --- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr +++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr @@ -14,7 +14,6 @@ note: function defined here | LL | fn oom() -> ! { | ^^^ - = note: this error originates in the attribute macro `alloc_error_handler` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/allocator/not-an-allocator.stderr b/tests/ui/allocator/not-an-allocator.stderr index e1967b70013..079bf9334eb 100644 --- a/tests/ui/allocator/not-an-allocator.stderr +++ b/tests/ui/allocator/not-an-allocator.stderr @@ -7,7 +7,6 @@ LL | static A: usize = 0; | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` | = help: the trait `GlobalAlloc` is implemented for `System` - = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied --> $DIR/not-an-allocator.rs:2:11 @@ -19,7 +18,6 @@ LL | static A: usize = 0; | = help: the trait `GlobalAlloc` is implemented for `System` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied --> $DIR/not-an-allocator.rs:2:11 @@ -31,7 +29,6 @@ LL | static A: usize = 0; | = help: the trait `GlobalAlloc` is implemented for `System` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied --> $DIR/not-an-allocator.rs:2:11 @@ -43,7 +40,6 @@ LL | static A: usize = 0; | = help: the trait `GlobalAlloc` is implemented for `System` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/tests/ui/allocator/two-allocators.stderr b/tests/ui/allocator/two-allocators.stderr index 1eecbc0a97b..5308232a20b 100644 --- a/tests/ui/allocator/two-allocators.stderr +++ b/tests/ui/allocator/two-allocators.stderr @@ -7,8 +7,6 @@ LL | #[global_allocator] | ------------------- in this procedural macro expansion LL | static B: System = System; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot define a new global allocator - | - = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/asm/ice-bad-err-span-in-template-129503.stderr b/tests/ui/asm/ice-bad-err-span-in-template-129503.stderr index ffa9362ed95..066959a052d 100644 --- a/tests/ui/asm/ice-bad-err-span-in-template-129503.stderr +++ b/tests/ui/asm/ice-bad-err-span-in-template-129503.stderr @@ -5,7 +5,6 @@ LL | asm!(concat!(r#"lJÆ�.�"#, "r} {}")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unmatched `}` in asm template string | = note: if you intended to print `}`, you can escape it using `}}` - = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid asm template string: unmatched `}` found --> $DIR/ice-bad-err-span-in-template-129503.rs:18:10 @@ -14,7 +13,6 @@ LL | asm!(concat!("abc", "r} {}")); | ^^^^^^^^^^^^^^^^^^^^^^^ unmatched `}` in asm template string | = note: if you intended to print `}`, you can escape it using `}}` - = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid asm template string: unmatched `}` found --> $DIR/ice-bad-err-span-in-template-129503.rs:24:19 diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr index 0e544119650..c88f3af7642 100644 --- a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr +++ b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr @@ -1,35 +1,35 @@ error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:22:18 + --> $DIR/bad-reg.rs:23:18 | LL | asm!("", out("$r0") _); | ^^^^^^^^^^^^ error: invalid register `$tp`: reserved for TLS - --> $DIR/bad-reg.rs:24:18 + --> $DIR/bad-reg.rs:25:18 | LL | asm!("", out("$tp") _); | ^^^^^^^^^^^^ error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:26:18 + --> $DIR/bad-reg.rs:27:18 | LL | asm!("", out("$sp") _); | ^^^^^^^^^^^^ error: invalid register `$r21`: reserved by the ABI - --> $DIR/bad-reg.rs:28:18 + --> $DIR/bad-reg.rs:29:18 | LL | asm!("", out("$r21") _); | ^^^^^^^^^^^^^ error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:31:18 | LL | asm!("", out("$fp") _); | ^^^^^^^^^^^^ error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:33:18 | LL | asm!("", out("$r31") _); | ^^^^^^^^^^^^^ diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr index 6d0410dc6a1..cb8e55a9722 100644 --- a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr +++ b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr @@ -1,59 +1,59 @@ error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:22:18 + --> $DIR/bad-reg.rs:23:18 | LL | asm!("", out("$r0") _); | ^^^^^^^^^^^^ error: invalid register `$tp`: reserved for TLS - --> $DIR/bad-reg.rs:24:18 + --> $DIR/bad-reg.rs:25:18 | LL | asm!("", out("$tp") _); | ^^^^^^^^^^^^ error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:26:18 + --> $DIR/bad-reg.rs:27:18 | LL | asm!("", out("$sp") _); | ^^^^^^^^^^^^ error: invalid register `$r21`: reserved by the ABI - --> $DIR/bad-reg.rs:28:18 + --> $DIR/bad-reg.rs:29:18 | LL | asm!("", out("$r21") _); | ^^^^^^^^^^^^^ error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:31:18 | LL | asm!("", out("$fp") _); | ^^^^^^^^^^^^ error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:33:18 | LL | asm!("", out("$r31") _); | ^^^^^^^^^^^^^ error: register class `freg` requires at least one of the following target features: d, f - --> $DIR/bad-reg.rs:36:26 + --> $DIR/bad-reg.rs:37:26 | LL | asm!("/* {} */", in(freg) f); | ^^^^^^^^^^ error: register class `freg` requires at least one of the following target features: d, f - --> $DIR/bad-reg.rs:38:26 + --> $DIR/bad-reg.rs:39:26 | LL | asm!("/* {} */", out(freg) _); | ^^^^^^^^^^^ error: register class `freg` requires at least one of the following target features: d, f - --> $DIR/bad-reg.rs:40:26 + --> $DIR/bad-reg.rs:41:26 | LL | asm!("/* {} */", in(freg) d); | ^^^^^^^^^^ error: register class `freg` requires at least one of the following target features: d, f - --> $DIR/bad-reg.rs:42:26 + --> $DIR/bad-reg.rs:43:26 | LL | asm!("/* {} */", out(freg) d); | ^^^^^^^^^^^ diff --git a/tests/ui/asm/loongarch/bad-reg.rs b/tests/ui/asm/loongarch/bad-reg.rs index 685b460bc92..db1c778e5a2 100644 --- a/tests/ui/asm/loongarch/bad-reg.rs +++ b/tests/ui/asm/loongarch/bad-reg.rs @@ -1,6 +1,7 @@ //@ add-core-stubs //@ needs-asm-support //@ revisions: loongarch64_lp64d loongarch64_lp64s +//@ min-llvm-version: 20 //@[loongarch64_lp64d] compile-flags: --target loongarch64-unknown-linux-gnu //@[loongarch64_lp64d] needs-llvm-components: loongarch //@[loongarch64_lp64s] compile-flags: --target loongarch64-unknown-none-softfloat diff --git a/tests/ui/asm/naked-functions-target-feature.rs b/tests/ui/asm/naked-functions-target-feature.rs new file mode 100644 index 00000000000..afe1a389147 --- /dev/null +++ b/tests/ui/asm/naked-functions-target-feature.rs @@ -0,0 +1,21 @@ +//@ build-pass +//@ needs-asm-support + +#![feature(naked_functions, naked_functions_target_feature)] +#![crate_type = "lib"] + +use std::arch::{asm, naked_asm}; + +#[cfg(target_arch = "x86_64")] +#[target_feature(enable = "sse2")] +#[naked] +pub unsafe extern "C" fn compatible_target_feature() { + naked_asm!(""); +} + +#[cfg(target_arch = "aarch64")] +#[target_feature(enable = "neon")] +#[naked] +pub unsafe extern "C" fn compatible_target_feature() { + naked_asm!(""); +} diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index e7e5d84f2a5..3d4d414539c 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -230,13 +230,6 @@ pub unsafe extern "C" fn compatible_codegen_attributes() { naked_asm!("", options(raw)); } -#[cfg(target_arch = "x86_64")] -#[target_feature(enable = "sse2")] -#[naked] -pub unsafe extern "C" fn compatible_target_feature() { - naked_asm!(""); -} - #[doc = "foo bar baz"] /// a doc comment // a normal comment diff --git a/tests/ui/asm/x86_64/bad-options.rs b/tests/ui/asm/x86_64/bad-options.rs index 6424a1b1d42..123febc06fc 100644 --- a/tests/ui/asm/x86_64/bad-options.rs +++ b/tests/ui/asm/x86_64/bad-options.rs @@ -1,6 +1,6 @@ //@ only-x86_64 -#![feature(asm_unwind, asm_goto)] +#![feature(asm_unwind)] use std::arch::{asm, global_asm}; diff --git a/tests/ui/asm/x86_64/goto-block-safe.rs b/tests/ui/asm/x86_64/goto-block-safe.rs index ee833a48a4b..b739e9f9ced 100644 --- a/tests/ui/asm/x86_64/goto-block-safe.rs +++ b/tests/ui/asm/x86_64/goto-block-safe.rs @@ -2,7 +2,6 @@ //@ needs-asm-support #![deny(unreachable_code)] -#![feature(asm_goto)] use std::arch::asm; diff --git a/tests/ui/asm/x86_64/goto-block-safe.stderr b/tests/ui/asm/x86_64/goto-block-safe.stderr index 49818db7484..ee7313bc8be 100644 --- a/tests/ui/asm/x86_64/goto-block-safe.stderr +++ b/tests/ui/asm/x86_64/goto-block-safe.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `unreachable_unchecked` is unsafe and requires unsafe function or block - --> $DIR/goto-block-safe.rs:14:17 + --> $DIR/goto-block-safe.rs:13:17 | LL | unsafe { | ------ items do not inherit unsafety from separate enclosing items diff --git a/tests/ui/asm/x86_64/goto.rs b/tests/ui/asm/x86_64/goto.rs index 50e7441509a..00a8e588f96 100644 --- a/tests/ui/asm/x86_64/goto.rs +++ b/tests/ui/asm/x86_64/goto.rs @@ -3,7 +3,7 @@ //@ needs-asm-support #![deny(unreachable_code)] -#![feature(asm_goto, asm_goto_with_outputs)] +#![feature(asm_goto_with_outputs)] use std::arch::asm; diff --git a/tests/ui/asm/x86_64/goto.stderr b/tests/ui/asm/x86_64/goto.stderr index 8f89e2b1290..78b726b3f3d 100644 --- a/tests/ui/asm/x86_64/goto.stderr +++ b/tests/ui/asm/x86_64/goto.stderr @@ -17,7 +17,6 @@ note: the lint level is defined here | LL | #[warn(unreachable_code)] | ^^^^^^^^^^^^^^^^ - = note: this warning originates in the macro `unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) warning: 1 warning emitted diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index dc919299710..8a19142b730 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -53,7 +53,6 @@ LL | impl<T: NotNull> IntoNullable for T { | ------- ^^^^^^^^^^^^ ^ | | | unsatisfied trait bound introduced here - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting the associated type | LL | Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>, <Col as Expression>::SqlType: NotNull, @@ -73,7 +72,6 @@ LL | impl<T: NotNull> IntoNullable for T { | | | unsatisfied trait bound introduced here = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting the associated type | LL | Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>, <Col as Expression>::SqlType: NotNull, @@ -92,7 +90,6 @@ LL | impl<T: NotNull> IntoNullable for T { | ------- ^^^^^^^^^^^^ ^ | | | unsatisfied trait bound introduced here - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied --> $DIR/issue-38821.rs:23:10 @@ -108,7 +105,6 @@ LL | impl<T: NotNull> IntoNullable for T { | | | unsatisfied trait bound introduced here = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied --> $DIR/issue-38821.rs:23:17 @@ -123,7 +119,6 @@ LL | impl<T: NotNull> IntoNullable for T { | ------- ^^^^^^^^^^^^ ^ | | | unsatisfied trait bound introduced here - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting the associated type | LL | Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>, <Col as Expression>::SqlType: NotNull, @@ -143,7 +138,6 @@ LL | impl<T: NotNull> IntoNullable for T { | | | unsatisfied trait bound introduced here = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting the associated type | LL | Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>, <Col as Expression>::SqlType: NotNull, @@ -162,7 +156,6 @@ LL | impl<T: NotNull> IntoNullable for T { | ------- ^^^^^^^^^^^^ ^ | | | unsatisfied trait bound introduced here - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting the associated type | LL | Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>, <Col as Expression>::SqlType: NotNull, @@ -182,7 +175,6 @@ LL | impl<T: NotNull> IntoNullable for T { | | | unsatisfied trait bound introduced here = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting the associated type | LL | Expr: Expression<SqlType=<Col::SqlType as IntoNullable>::Nullable>, <Col as Expression>::SqlType: NotNull, @@ -201,7 +193,6 @@ LL | impl<T: NotNull> IntoNullable for T { | ------- ^^^^^^^^^^^^ ^ | | | unsatisfied trait bound introduced here - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied --> $DIR/issue-38821.rs:23:23 @@ -217,7 +208,6 @@ LL | impl<T: NotNull> IntoNullable for T { | | | unsatisfied trait bound introduced here = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied --> $DIR/issue-38821.rs:23:10 @@ -233,7 +223,6 @@ LL | impl<T: NotNull> IntoNullable for T { | | | unsatisfied trait bound introduced here = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied --> $DIR/issue-38821.rs:23:10 @@ -249,7 +238,6 @@ LL | impl<T: NotNull> IntoNullable for T { | | | unsatisfied trait bound introduced here = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied --> $DIR/issue-38821.rs:23:23 @@ -265,7 +253,6 @@ LL | impl<T: NotNull> IntoNullable for T { | | | unsatisfied trait bound introduced here = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied --> $DIR/issue-38821.rs:23:23 @@ -281,7 +268,6 @@ LL | impl<T: NotNull> IntoNullable for T { | | | unsatisfied trait bound introduced here = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied --> $DIR/issue-38821.rs:23:10 @@ -297,7 +283,6 @@ LL | impl<T: NotNull> IntoNullable for T { | | | unsatisfied trait bound introduced here = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not satisfied --> $DIR/issue-38821.rs:23:23 @@ -313,7 +298,6 @@ LL | impl<T: NotNull> IntoNullable for T { | | | unsatisfied trait bound introduced here = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 18 previous errors diff --git a/tests/ui/async-await/async-closures/imm-deref-lending.rs b/tests/ui/async-await/async-closures/imm-deref-lending.rs new file mode 100644 index 00000000000..59f8d434d9c --- /dev/null +++ b/tests/ui/async-await/async-closures/imm-deref-lending.rs @@ -0,0 +1,46 @@ +//@ edition: 2021 +//@ check-pass + +#![feature(impl_trait_in_bindings)] + +struct FooS { + precise: i32, +} + +fn ref_inside_mut(f: &mut &FooS) { + let x: impl AsyncFn() = async move || { + let y = &f.precise; + }; +} + +fn mut_inside_ref(f: &&mut FooS) { + let x: impl AsyncFn() = async move || { + let y = &f.precise; + }; +} + +fn mut_ref_inside_mut(f: &mut &mut FooS) { + let x: impl AsyncFn() = async move || { + let y = &f.precise; + }; +} + +fn ref_inside_box(f: Box<&FooS>) { + let x: impl AsyncFn() = async move || { + let y = &f.precise; + }; +} + +fn box_inside_ref(f: &Box<FooS>) { + let x: impl AsyncFn() = async move || { + let y = &f.precise; + }; +} + +fn box_inside_box(f: Box<Box<FooS>>) { + let x: impl AsyncFn() = async move || { + let y = &f.precise; + }; +} + +fn main() {} diff --git a/tests/ui/async-await/async-closures/imm-deref-not-lending.rs b/tests/ui/async-await/async-closures/imm-deref-not-lending.rs new file mode 100644 index 00000000000..bd1197cc636 --- /dev/null +++ b/tests/ui/async-await/async-closures/imm-deref-not-lending.rs @@ -0,0 +1,49 @@ +//@ edition: 2021 + +#![feature(impl_trait_in_bindings)] + +struct FooS { + precise: i32, +} + +fn ref_inside_mut(f: &mut &FooS) { + let x: impl Fn() -> _ = async move || { + let y = &f.precise; + }; +} + +fn mut_inside_ref(f: &&mut FooS) { + let x: impl Fn() -> _ = async move || { + let y = &f.precise; + }; +} + +// Expected to fail, no immutable reference here. +fn mut_ref_inside_mut(f: &mut &mut FooS) { + let x: impl Fn() -> _ = async move || { + //~^ ERROR async closure does not implement `Fn` + let y = &f.precise; + }; +} + +fn ref_inside_box(f: Box<&FooS>) { + let x: impl Fn() -> _ = async move || { + let y = &f.precise; + }; +} + +fn box_inside_ref(f: &Box<FooS>) { + let x: impl Fn() -> _ = async move || { + let y = &f.precise; + }; +} + +// Expected to fail, no immutable reference here. +fn box_inside_box(f: Box<Box<FooS>>) { + let x: impl Fn() -> _ = async move || { + //~^ ERROR async closure does not implement `Fn` + let y = &f.precise; + }; +} + +fn main() {} diff --git a/tests/ui/async-await/async-closures/imm-deref-not-lending.stderr b/tests/ui/async-await/async-closures/imm-deref-not-lending.stderr new file mode 100644 index 00000000000..cd3ff55e458 --- /dev/null +++ b/tests/ui/async-await/async-closures/imm-deref-not-lending.stderr @@ -0,0 +1,14 @@ +error: async closure does not implement `Fn` because it captures state from its environment + --> $DIR/imm-deref-not-lending.rs:23:29 + | +LL | let x: impl Fn() -> _ = async move || { + | ^^^^^^^^^^^^^ + +error: async closure does not implement `Fn` because it captures state from its environment + --> $DIR/imm-deref-not-lending.rs:43:29 + | +LL | let x: impl Fn() -> _ = async move || { + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/dyn/mut-is-pointer-like.rs b/tests/ui/async-await/dyn/mut-is-pointer-like.rs index 93e8281164c..a82567e372e 100644 --- a/tests/ui/async-await/dyn/mut-is-pointer-like.rs +++ b/tests/ui/async-await/dyn/mut-is-pointer-like.rs @@ -1,11 +1,9 @@ //@ aux-build:block-on.rs //@ edition: 2021 -//@ run-pass -//@ check-run-results +//@ known-bug: #133119 #![allow(refining_impl_trait)] #![feature(async_fn_in_dyn_trait)] -//~^ WARN the feature `async_fn_in_dyn_trait` is incomplete extern crate block_on; diff --git a/tests/ui/async-await/dyn/mut-is-pointer-like.stderr b/tests/ui/async-await/dyn/mut-is-pointer-like.stderr index 7c72ce43cf0..bf20473924b 100644 --- a/tests/ui/async-await/dyn/mut-is-pointer-like.stderr +++ b/tests/ui/async-await/dyn/mut-is-pointer-like.stderr @@ -1,5 +1,5 @@ warning: the feature `async_fn_in_dyn_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/mut-is-pointer-like.rs:7:12 + --> $DIR/mut-is-pointer-like.rs:6:12 | LL | #![feature(async_fn_in_dyn_trait)] | ^^^^^^^^^^^^^^^^^^^^^ @@ -7,5 +7,65 @@ LL | #![feature(async_fn_in_dyn_trait)] = note: see issue #133119 <https://github.com/rust-lang/rust/issues/133119> for more information = note: `#[warn(incomplete_features)]` on by default -warning: 1 warning emitted +error[E0038]: the trait `AsyncTrait` is not dyn compatible + --> $DIR/mut-is-pointer-like.rs:35:16 + | +LL | let x: Pin<&mut dyn AsyncTrait<Output = ()>> = f; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility> + --> $DIR/mut-is-pointer-like.rs:16:14 + | +LL | trait AsyncTrait { + | ---------- this trait is not dyn compatible... +... +LL | async fn async_dispatch(self: Pin<&mut Self>) -> Self::Output; + | ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async` + = help: consider moving `async_dispatch` to another trait + +error[E0038]: the trait `AsyncTrait` is not dyn compatible + --> $DIR/mut-is-pointer-like.rs:35:56 + | +LL | let x: Pin<&mut dyn AsyncTrait<Output = ()>> = f; + | ^ `AsyncTrait` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility> + --> $DIR/mut-is-pointer-like.rs:16:14 + | +LL | trait AsyncTrait { + | ---------- this trait is not dyn compatible... +... +LL | async fn async_dispatch(self: Pin<&mut Self>) -> Self::Output; + | ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async` + = help: consider moving `async_dispatch` to another trait + = note: required for the cast from `Pin<&mut {async block@$DIR/mut-is-pointer-like.rs:32:32: 32:37}>` to `Pin<&mut dyn AsyncTrait<Output = ()>>` + +error[E0277]: the trait bound `dyn AsyncTrait<Output = ()>: AsyncTrait` is not satisfied + --> $DIR/mut-is-pointer-like.rs:36:11 + | +LL | x.async_dispatch().await; + | ^^^^^^^^^^^^^^ the trait `AsyncTrait` is not implemented for `dyn AsyncTrait<Output = ()>` + +error[E0038]: the trait `AsyncTrait` is not dyn compatible + --> $DIR/mut-is-pointer-like.rs:36:9 + | +LL | x.async_dispatch().await; + | ^^^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility> + --> $DIR/mut-is-pointer-like.rs:16:14 + | +LL | trait AsyncTrait { + | ---------- this trait is not dyn compatible... +... +LL | async fn async_dispatch(self: Pin<&mut Self>) -> Self::Output; + | ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async` + = help: consider moving `async_dispatch` to another trait + +error: aborting due to 4 previous errors; 1 warning emitted +Some errors have detailed explanations: E0038, E0277. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/async-await/dyn/works.rs b/tests/ui/async-await/dyn/works.rs index 0732a3ee2f2..f406a7b593f 100644 --- a/tests/ui/async-await/dyn/works.rs +++ b/tests/ui/async-await/dyn/works.rs @@ -1,11 +1,9 @@ //@ aux-build:block-on.rs //@ edition: 2021 -//@ run-pass -//@ check-run-results +//@ known-bug: #133119 #![allow(refining_impl_trait)] #![feature(async_fn_in_dyn_trait)] -//~^ WARN the feature `async_fn_in_dyn_trait` is incomplete extern crate block_on; diff --git a/tests/ui/async-await/dyn/works.stderr b/tests/ui/async-await/dyn/works.stderr index 2c7db7c32f5..47abeab5aac 100644 --- a/tests/ui/async-await/dyn/works.stderr +++ b/tests/ui/async-await/dyn/works.stderr @@ -1,5 +1,5 @@ warning: the feature `async_fn_in_dyn_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/works.rs:7:12 + --> $DIR/works.rs:6:12 | LL | #![feature(async_fn_in_dyn_trait)] | ^^^^^^^^^^^^^^^^^^^^^ @@ -7,5 +7,75 @@ LL | #![feature(async_fn_in_dyn_trait)] = note: see issue #133119 <https://github.com/rust-lang/rust/issues/133119> for more information = note: `#[warn(incomplete_features)]` on by default -warning: 1 warning emitted +error[E0038]: the trait `AsyncTrait` is not dyn compatible + --> $DIR/works.rs:27:34 + | +LL | let x: &dyn AsyncTrait = &"hello, world!"; + | ^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility> + --> $DIR/works.rs:14:14 + | +LL | trait AsyncTrait { + | ---------- this trait is not dyn compatible... +LL | async fn async_dispatch(&self); + | ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async` + = help: consider moving `async_dispatch` to another trait + = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead. + = note: required for the cast from `&&'static str` to `&dyn AsyncTrait` + +error[E0038]: the trait `AsyncTrait` is not dyn compatible + --> $DIR/works.rs:27:16 + | +LL | let x: &dyn AsyncTrait = &"hello, world!"; + | ^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility> + --> $DIR/works.rs:14:14 + | +LL | trait AsyncTrait { + | ---------- this trait is not dyn compatible... +LL | async fn async_dispatch(&self); + | ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async` + = help: consider moving `async_dispatch` to another trait + = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead. + +error[E0038]: the trait `AsyncTrait` is not dyn compatible + --> $DIR/works.rs:28:11 + | +LL | x.async_dispatch().await; + | ^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility> + --> $DIR/works.rs:14:14 + | +LL | trait AsyncTrait { + | ---------- this trait is not dyn compatible... +LL | async fn async_dispatch(&self); + | ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async` + = help: consider moving `async_dispatch` to another trait + = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead. + +error[E0038]: the trait `AsyncTrait` is not dyn compatible + --> $DIR/works.rs:28:9 + | +LL | x.async_dispatch().await; + | ^^^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility> + --> $DIR/works.rs:14:14 + | +LL | trait AsyncTrait { + | ---------- this trait is not dyn compatible... +LL | async fn async_dispatch(&self); + | ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async` + = help: consider moving `async_dispatch` to another trait + = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead. + +error: aborting due to 4 previous errors; 1 warning emitted +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/async-await/dyn/wrong-size.rs b/tests/ui/async-await/dyn/wrong-size.rs index ac15dd26067..f5fce3648ac 100644 --- a/tests/ui/async-await/dyn/wrong-size.rs +++ b/tests/ui/async-await/dyn/wrong-size.rs @@ -1,7 +1,7 @@ //@ edition: 2021 +//@ known-bug: #133119 #![feature(async_fn_in_dyn_trait)] -//~^ WARN the feature `async_fn_in_dyn_trait` is incomplete use std::future::Future; @@ -19,5 +19,5 @@ impl AsyncTrait for &'static str { fn main() { let x: &dyn AsyncTrait = &"hello, world!"; - //~^ ERROR `impl Future<Output = ()>` needs to have the same ABI as a pointer + // FIXME ~^ ERROR `impl Future<Output = ()>` needs to have the same ABI as a pointer } diff --git a/tests/ui/async-await/dyn/wrong-size.stderr b/tests/ui/async-await/dyn/wrong-size.stderr index 0202b5f2409..b4684f4fc17 100644 --- a/tests/ui/async-await/dyn/wrong-size.stderr +++ b/tests/ui/async-await/dyn/wrong-size.stderr @@ -1,5 +1,5 @@ warning: the feature `async_fn_in_dyn_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/wrong-size.rs:3:12 + --> $DIR/wrong-size.rs:4:12 | LL | #![feature(async_fn_in_dyn_trait)] | ^^^^^^^^^^^^^^^^^^^^^ @@ -7,15 +7,41 @@ LL | #![feature(async_fn_in_dyn_trait)] = note: see issue #133119 <https://github.com/rust-lang/rust/issues/133119> for more information = note: `#[warn(incomplete_features)]` on by default -error[E0277]: `impl Future<Output = ()>` needs to have the same ABI as a pointer +error[E0038]: the trait `AsyncTrait` is not dyn compatible --> $DIR/wrong-size.rs:21:30 | LL | let x: &dyn AsyncTrait = &"hello, world!"; - | ^^^^^^^^^^^^^^^^ `impl Future<Output = ()>` needs to be a pointer-like type + | ^^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible | - = help: the trait `for<'a> PointerLike` is not implemented for `impl Future<Output = ()>` +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility> + --> $DIR/wrong-size.rs:9:14 + | +LL | trait AsyncTrait { + | ---------- this trait is not dyn compatible... +LL | async fn async_dispatch(&self); + | ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async` + = help: consider moving `async_dispatch` to another trait + = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead. = note: required for the cast from `&&'static str` to `&dyn AsyncTrait` -error: aborting due to 1 previous error; 1 warning emitted +error[E0038]: the trait `AsyncTrait` is not dyn compatible + --> $DIR/wrong-size.rs:21:12 + | +LL | let x: &dyn AsyncTrait = &"hello, world!"; + | ^^^^^^^^^^^^^^^ `AsyncTrait` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility> + --> $DIR/wrong-size.rs:9:14 + | +LL | trait AsyncTrait { + | ---------- this trait is not dyn compatible... +LL | async fn async_dispatch(&self); + | ^^^^^^^^^^^^^^ ...because method `async_dispatch` is `async` + = help: consider moving `async_dispatch` to another trait + = help: only type `&'static str` implements `AsyncTrait`; consider using it directly instead. + +error: aborting due to 2 previous errors; 1 warning emitted -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs b/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs index d94572ef5d6..8ea7a9cb4b5 100644 --- a/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs +++ b/tests/ui/attributes/auxiliary/used_pre_main_constructor.rs @@ -19,6 +19,7 @@ target_os = "netbsd", target_os = "nto", target_os = "openbsd", + target_os = "fuchsia", ), link_section = ".init_array" )] diff --git a/tests/ui/attributes/extented-attribute-macro-error.stderr b/tests/ui/attributes/extented-attribute-macro-error.stderr index 884f3c7b166..7b93b98f64c 100644 --- a/tests/ui/attributes/extented-attribute-macro-error.stderr +++ b/tests/ui/attributes/extented-attribute-macro-error.stderr @@ -3,8 +3,6 @@ error: couldn't read the file | LL | #![doc = include_str!("../not_existing_file.md")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/attributes/outer-mod-attr-applies-only-to-first.rs b/tests/ui/attributes/outer-mod-attr-applies-only-to-first.rs new file mode 100644 index 00000000000..ec521c1afb5 --- /dev/null +++ b/tests/ui/attributes/outer-mod-attr-applies-only-to-first.rs @@ -0,0 +1,16 @@ +//! Regression test to check that outer attributes applied to the first module item is applied to +//! its attached module item only, and not also to other subsequent module items +//! +//! Commit: <https://github.com/rust-lang/rust/commit/7aee9f7b56f8d96f9444ebb1d06e32e024b81974> + +//@ check-pass +//@ compile-flags: --cfg=first +//@ no-auto-check-cfg + +#[cfg(first)] +mod hello {} + +#[cfg(not_set)] +mod hello {} + +fn main() {} diff --git a/tests/ui/borrowck/issue-114374-invalid-help-fmt-args.stderr b/tests/ui/borrowck/issue-114374-invalid-help-fmt-args.stderr index 3ee89d9734a..30f292f71a2 100644 --- a/tests/ui/borrowck/issue-114374-invalid-help-fmt-args.stderr +++ b/tests/ui/borrowck/issue-114374-invalid-help-fmt-args.stderr @@ -11,7 +11,6 @@ LL | bar(x); | = note: the result of `format_args!` can only be assigned directly if no placeholders in its arguments are used = note: to learn more, visit <https://doc.rust-lang.org/std/macro.format_args.html> - = note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0716]: temporary value dropped while borrowed --> $DIR/issue-114374-invalid-help-fmt-args.rs:10:15 @@ -26,7 +25,6 @@ LL | bar(foo); | = note: the result of `format_args!` can only be assigned directly if no placeholders in its arguments are used = note: to learn more, visit <https://doc.rust-lang.org/std/macro.format_args.html> - = note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/borrowck/issue-81899.stderr b/tests/ui/borrowck/issue-81899.stderr index 2e6e7511ec9..b5cd5e4abf3 100644 --- a/tests/ui/borrowck/issue-81899.stderr +++ b/tests/ui/borrowck/issue-81899.stderr @@ -9,7 +9,6 @@ note: inside `f::<{closure@$DIR/issue-81899.rs:4:31: 4:34}>` | LL | panic!() | ^^^^^^^^ the failure occurred here - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/issue-81899.rs:4:23 diff --git a/tests/ui/borrowck/issue-88434-minimal-example.stderr b/tests/ui/borrowck/issue-88434-minimal-example.stderr index c8ac13a3473..d9f3b4dcb90 100644 --- a/tests/ui/borrowck/issue-88434-minimal-example.stderr +++ b/tests/ui/borrowck/issue-88434-minimal-example.stderr @@ -9,7 +9,6 @@ note: inside `f::<{closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:28}>` | LL | panic!() | ^^^^^^^^ the failure occurred here - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/issue-88434-minimal-example.rs:3:21 diff --git a/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr b/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr index 0041759609c..c82b5cf786d 100644 --- a/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr +++ b/tests/ui/borrowck/issue-88434-removal-index-should-be-less.stderr @@ -9,7 +9,6 @@ note: inside `f::<{closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31 | LL | panic!() | ^^^^^^^^ the failure occurred here - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/issue-88434-removal-index-should-be-less.rs:3:23 diff --git a/tests/ui/cast/cast_lit_suffix-issue-138392.fixed b/tests/ui/cast/cast_lit_suffix-issue-138392.fixed new file mode 100644 index 00000000000..c6fbd09f89c --- /dev/null +++ b/tests/ui/cast/cast_lit_suffix-issue-138392.fixed @@ -0,0 +1,6 @@ +//@ run-rustfix +#![allow(unused_parens)] +fn main() { + let _x: u8 = (4u8); //~ ERROR: mismatched types + let _y: u8 = (4u8); //~ ERROR: mismatched types +} diff --git a/tests/ui/cast/cast_lit_suffix-issue-138392.rs b/tests/ui/cast/cast_lit_suffix-issue-138392.rs new file mode 100644 index 00000000000..86dbbbbf126 --- /dev/null +++ b/tests/ui/cast/cast_lit_suffix-issue-138392.rs @@ -0,0 +1,6 @@ +//@ run-rustfix +#![allow(unused_parens)] +fn main() { + let _x: u8 = (4i32); //~ ERROR: mismatched types + let _y: u8 = (4.0f32); //~ ERROR: mismatched types +} diff --git a/tests/ui/cast/cast_lit_suffix-issue-138392.stderr b/tests/ui/cast/cast_lit_suffix-issue-138392.stderr new file mode 100644 index 00000000000..998fcfc36dc --- /dev/null +++ b/tests/ui/cast/cast_lit_suffix-issue-138392.stderr @@ -0,0 +1,31 @@ +error[E0308]: mismatched types + --> $DIR/cast_lit_suffix-issue-138392.rs:4:18 + | +LL | let _x: u8 = (4i32); + | -- ^^^^^^ expected `u8`, found `i32` + | | + | expected due to this + | +help: change the type of the numeric literal from `i32` to `u8` + | +LL - let _x: u8 = (4i32); +LL + let _x: u8 = (4u8); + | + +error[E0308]: mismatched types + --> $DIR/cast_lit_suffix-issue-138392.rs:5:18 + | +LL | let _y: u8 = (4.0f32); + | -- ^^^^^^^^ expected `u8`, found `f32` + | | + | expected due to this + | +help: change the type of the numeric literal from `f32` to `u8` + | +LL - let _y: u8 = (4.0f32); +LL + let _y: u8 = (4u8); + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index 5b82d3f539f..a9d67481ba1 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -60,6 +60,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `d32` `deflate-conversion` `dit` +`div32` `doloop` `dotprod` `dpb` @@ -133,8 +134,11 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `jsconv` `kl` `lahfsahf` +`lam-bh` +`lamcas` `lasx` `lbt` +`ld-seq-sa` `leoncasa` `lor` `lse` @@ -190,6 +194,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `reserve-x18` `rtm` `sb` +`scq` `sha` `sha2` `sha3` diff --git a/tests/ui/codemap_tests/issue-28308.stderr b/tests/ui/codemap_tests/issue-28308.stderr index efd8fa22fa5..7bc9e05dfc0 100644 --- a/tests/ui/codemap_tests/issue-28308.stderr +++ b/tests/ui/codemap_tests/issue-28308.stderr @@ -3,8 +3,6 @@ error[E0600]: cannot apply unary operator `!` to type `&'static str` | LL | assert!("foo"); | ^^^^^^^^^^^^^^ cannot apply unary operator `!` - | - = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/coercion/struct-coerce-vec-to-slice.rs b/tests/ui/coercion/struct-coerce-vec-to-slice.rs new file mode 100644 index 00000000000..9ef20ac4ea6 --- /dev/null +++ b/tests/ui/coercion/struct-coerce-vec-to-slice.rs @@ -0,0 +1,20 @@ +//! Regression test that ensures struct field literals can be coerced into slice and `Box` types + +//@ check-pass + +struct Thing1<'a> { + baz: &'a [Box<isize>], + bar: Box<u64>, +} + +struct Thing2<'a> { + baz: &'a [Box<isize>], + bar: u64, +} + +pub fn main() { + let _a = Thing1 { baz: &[], bar: Box::new(32) }; + let _b = Thing1 { baz: &Vec::new(), bar: Box::new(32) }; + let _c = Thing2 { baz: &[], bar: 32 }; + let _d = Thing2 { baz: &Vec::new(), bar: 32 }; +} diff --git a/tests/ui/coercion/struct-literal-field-type-coercion-to-expected-type.rs b/tests/ui/coercion/struct-literal-field-type-coercion-to-expected-type.rs new file mode 100644 index 00000000000..0b8ec7dc07a --- /dev/null +++ b/tests/ui/coercion/struct-literal-field-type-coercion-to-expected-type.rs @@ -0,0 +1,16 @@ +//! Regression test to check that literal expressions in a struct field can be coerced to the +//! expected field type, including block expressions. +//! +//! Issue: <https://github.com/rust-lang/rust/issues/31260> + +//@ check-pass + +pub struct Struct<K: 'static> { + pub field: K, +} + +static STRUCT: Struct<&'static [u8]> = Struct { field: { &[1] } }; + +static STRUCT2: Struct<&'static [u8]> = Struct { field: &[1] }; + +fn main() {} diff --git a/tests/ui/coherence/const-errs-dont-conflict-103369.stderr b/tests/ui/coherence/const-errs-dont-conflict-103369.stderr index 4acaaf22ae8..b2104299f65 100644 --- a/tests/ui/coherence/const-errs-dont-conflict-103369.stderr +++ b/tests/ui/coherence/const-errs-dont-conflict-103369.stderr @@ -9,7 +9,6 @@ note: inside `my_fn` | LL | panic!("Some error occurred"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the failure occurred here - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const-errs-dont-conflict-103369.rs:7:25 @@ -22,7 +21,6 @@ note: inside `my_fn` | LL | panic!("Some error occurred"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the failure occurred here - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/coherence/orphan-check-error-reporting-ty-var.rs b/tests/ui/coherence/orphan-check-error-reporting-ty-var.rs new file mode 100644 index 00000000000..99a83453354 --- /dev/null +++ b/tests/ui/coherence/orphan-check-error-reporting-ty-var.rs @@ -0,0 +1,17 @@ +// Regression test for #132826. + +// Make sure we don't try to resolve the variable `K1` in the generics of the impl +// (which only has `K2`). + +pub trait MyTrait { + type Item; +} + +impl<K1> MyTrait for Vec<K1> { + type Item = Vec<K1>; +} + +impl<K2> From<Vec<K2>> for <Vec<K2> as MyTrait>::Item {} +//~^ ERROR only traits defined in the current crate can be implemented for arbitrary types + +fn main() {} diff --git a/tests/ui/coherence/orphan-check-error-reporting-ty-var.stderr b/tests/ui/coherence/orphan-check-error-reporting-ty-var.stderr new file mode 100644 index 00000000000..f229f8b2e38 --- /dev/null +++ b/tests/ui/coherence/orphan-check-error-reporting-ty-var.stderr @@ -0,0 +1,16 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/orphan-check-error-reporting-ty-var.rs:14:1 + | +LL | impl<K2> From<Vec<K2>> for <Vec<K2> as MyTrait>::Item {} + | ^^^^^^^^^-------------^^^^^-------------------------- + | | | + | | `Vec` is not defined in the current crate + | `Vec` is not defined in the current crate + | + = note: impl doesn't have any local type before any uncovered type parameters + = note: for more information see https://doc.rust-lang.org/reference/items/implementations.html#orphan-rules + = note: define and implement a trait or new type instead + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr index af4dbfcad0e..a9a99fb28d8 100644 --- a/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr +++ b/tests/ui/coherence/warn-when-cycle-is-error-in-coherence.stderr @@ -9,8 +9,6 @@ LL | | where LL | | T: Borrow<Q>, LL | | Q: ?Sized + PartialOrd, | |___________________________- first implementation here - | - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/adt_const_params/check-type-in-mir.rs b/tests/ui/const-generics/adt_const_params/check-type-in-mir.rs new file mode 100644 index 00000000000..bec485b001c --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/check-type-in-mir.rs @@ -0,0 +1,16 @@ +// Ensure that we actually treat `N`'s type as `Invariant<'static>` in MIR typeck. + +#![feature(adt_const_params)] + +use std::marker::ConstParamTy; +use std::ops::Deref; + +#[derive(ConstParamTy, PartialEq, Eq)] +struct Invariant<'a>(<&'a () as Deref>::Target); + +fn test<'a, const N: Invariant<'static>>() { + let x: Invariant<'a> = N; + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/check-type-in-mir.stderr b/tests/ui/const-generics/adt_const_params/check-type-in-mir.stderr new file mode 100644 index 00000000000..7e265f33f35 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/check-type-in-mir.stderr @@ -0,0 +1,14 @@ +error: lifetime may not live long enough + --> $DIR/check-type-in-mir.rs:12:28 + | +LL | fn test<'a, const N: Invariant<'static>>() { + | -- lifetime `'a` defined here +LL | let x: Invariant<'a> = N; + | ^ assignment requires that `'a` must outlive `'static` + | + = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Invariant<'a>` is invariant over the parameter `'a` + = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr index 808a569fcad..a4e5736d834 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr @@ -15,8 +15,6 @@ LL | #[derive(std::marker::UnsizedConstParamTy, Eq, PartialEq)] LL | LL | struct CantParamDerive(NotParam); | -------- this field does not implement `ConstParamTy_` - | - = note: this error originates in the derive macro `std::marker::UnsizedConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr index 80d9942c591..b651cca3216 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr @@ -29,7 +29,6 @@ LL | #[derive(std::marker::UnsizedConstParamTy)] | note: required by a bound in `UnsizedConstParamTy` --> $SRC_DIR/core/src/marker.rs:LL:COL - = note: this error originates in the derive macro `std::marker::UnsizedConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `CantParamDerive` with `#[derive(Eq)]` | LL + #[derive(Eq)] @@ -44,7 +43,6 @@ LL | #[derive(std::marker::UnsizedConstParamTy)] | note: required by a bound in `UnsizedConstParamTy` --> $SRC_DIR/core/src/marker.rs:LL:COL - = note: this error originates in the derive macro `std::marker::UnsizedConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr index c2520f1d103..6b8d2394a86 100644 --- a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr +++ b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr @@ -12,7 +12,6 @@ note: the `ConstParamTy_` impl for `[*const u8; 1]` requires that `*const u8: Co | LL | struct Foo([*const u8; 1]); | ^^^^^^^^^^^^^^ - = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type --> $DIR/nested_bad_const_param_ty.rs:11:10 @@ -28,7 +27,6 @@ note: the `ConstParamTy_` impl for `[*mut u8; 1]` requires that `*mut u8: ConstP | LL | struct Foo2([*mut u8; 1]); | ^^^^^^^^^^^^ - = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type --> $DIR/nested_bad_const_param_ty.rs:16:10 @@ -44,7 +42,6 @@ note: the `ConstParamTy_` impl for `[fn(); 1]` requires that `fn(): ConstParamTy | LL | struct Foo3([fn(); 1]); | ^^^^^^^^^ - = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type --> $DIR/nested_bad_const_param_ty.rs:6:10 @@ -60,7 +57,6 @@ note: the `ConstParamTy_` impl for `[*const u8; 1]` requires that `*const u8: Un | LL | struct Foo([*const u8; 1]); | ^^^^^^^^^^^^^^ - = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type --> $DIR/nested_bad_const_param_ty.rs:11:10 @@ -76,7 +72,6 @@ note: the `ConstParamTy_` impl for `[*mut u8; 1]` requires that `*mut u8: Unsize | LL | struct Foo2([*mut u8; 1]); | ^^^^^^^^^^^^ - = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type --> $DIR/nested_bad_const_param_ty.rs:16:10 @@ -92,7 +87,6 @@ note: the `ConstParamTy_` impl for `[fn(); 1]` requires that `fn(): UnsizedConst | LL | struct Foo3([fn(); 1]); | ^^^^^^^^^ - = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 6 previous errors diff --git a/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr b/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr index 7a4f9b99c63..3089b30bd76 100644 --- a/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr +++ b/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr @@ -6,8 +6,6 @@ LL | #[derive(ConstParamTy, Eq, PartialEq)] LL | LL | struct A([u8]); | ---- this field does not implement `ConstParamTy_` - | - = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type --> $DIR/unsized_field-1.rs:12:10 @@ -17,8 +15,6 @@ LL | #[derive(ConstParamTy, Eq, PartialEq)] LL | LL | struct B(&'static [u8]); | ------------- this field does not implement `ConstParamTy_` - | - = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type --> $DIR/unsized_field-1.rs:16:10 @@ -28,8 +24,6 @@ LL | #[derive(ConstParamTy, Eq, PartialEq)] LL | LL | struct C(unsized_const_param::Foo); | ------------------------ this field does not implement `ConstParamTy_` - | - = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/adt_const_params/unsized_field-2.stderr b/tests/ui/const-generics/adt_const_params/unsized_field-2.stderr index 15acece538f..cef70ca0463 100644 --- a/tests/ui/const-generics/adt_const_params/unsized_field-2.stderr +++ b/tests/ui/const-generics/adt_const_params/unsized_field-2.stderr @@ -21,7 +21,6 @@ note: the `ConstParamTy_` impl for `GenericNotUnsizedParam<&'static [u8]>` requi | LL | struct A(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the derive macro `std::marker::ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr index 72f3fd9de90..992a27c1c0e 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr @@ -26,8 +26,6 @@ LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] ... LL | nested: &'static Bar<dyn std::fmt::Debug>, | ----------------------------------------- this field does not implement `ConstParamTy_` - | - = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type --> $DIR/unsizing-wfcheck-issue-126272.rs:8:32 @@ -53,7 +51,6 @@ note: the `ConstParamTy_` impl for `&'static Bar<(dyn Debug + 'static)>` require | LL | nested: &'static Bar<dyn std::fmt::Debug>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the derive macro `ConstParamTy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time --> $DIR/unsizing-wfcheck-issue-126272.rs:12:5 @@ -76,7 +73,6 @@ LL | struct Bar<T>(T); = note: 2 redundant requirements hidden = note: required for `&&'static Bar<(dyn Debug + 'static)>` to implement `Debug` = note: required for the cast from `&&&'static Bar<(dyn Debug + 'static)>` to `&dyn Debug` - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0369]: binary operation `==` cannot be applied to type `&Bar<dyn Debug>` --> $DIR/unsizing-wfcheck-issue-126272.rs:12:5 @@ -86,8 +82,6 @@ LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] ... LL | nested: &'static Bar<dyn std::fmt::Debug>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `dyn Debug: Eq` is not satisfied --> $DIR/unsizing-wfcheck-issue-126272.rs:12:5 @@ -108,7 +102,6 @@ LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] = note: required for `&'static Bar<dyn Debug>` to implement `Eq` note: required by a bound in `AssertParamIsEq` --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time --> $DIR/unsizing-wfcheck-issue-126272.rs:12:5 @@ -132,7 +125,6 @@ LL | struct Bar<T>(T); | ^ - ...if indirection were used here: `Box<T>` | | | this could be changed to `T: ?Sized`... - = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time --> $DIR/unsizing-wfcheck-issue-126272.rs:26:33 diff --git a/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.rs b/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.rs new file mode 100644 index 00000000000..d3bc544ed6c --- /dev/null +++ b/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.rs @@ -0,0 +1,12 @@ +// Ensure that we actually treat `N`'s type as `&'a u32` in MIR typeck. + +#![feature(unsized_const_params, adt_const_params, generic_const_parameter_types)] +//~^ WARN the feature `unsized_const_params` is incomplete +//~| WARN the feature `generic_const_parameter_types` is incomplete + +fn foo<'a, const N: &'a u32>() { + let b: &'static u32 = N; + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.stderr b/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.stderr new file mode 100644 index 00000000000..3dc7ce438fa --- /dev/null +++ b/tests/ui/const-generics/generic_const_parameter_types/check-type-in-mir.stderr @@ -0,0 +1,27 @@ +warning: the feature `unsized_const_params` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/check-type-in-mir.rs:3:12 + | +LL | #![feature(unsized_const_params, adt_const_params, generic_const_parameter_types)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: the feature `generic_const_parameter_types` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/check-type-in-mir.rs:3:52 + | +LL | #![feature(unsized_const_params, adt_const_params, generic_const_parameter_types)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #137626 <https://github.com/rust-lang/rust/issues/137626> for more information + +error: lifetime may not live long enough + --> $DIR/check-type-in-mir.rs:8:12 + | +LL | fn foo<'a, const N: &'a u32>() { + | -- lifetime `'a` defined here +LL | let b: &'static u32 = N; + | ^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + +error: aborting due to 1 previous error; 2 warnings emitted + diff --git a/tests/ui/const-ptr/forbidden_slices.stderr b/tests/ui/const-ptr/forbidden_slices.stderr index a4e9c972ceb..6f2da272ad3 100644 --- a/tests/ui/const-ptr/forbidden_slices.stderr +++ b/tests/ui/const-ptr/forbidden_slices.stderr @@ -109,7 +109,6 @@ note: inside `from_ptr_range::<'_, ()>` --> $SRC_DIR/core/src/slice/raw.rs:LL:COL note: inside `std::ptr::const_ptr::<impl *const ()>::offset_from_unsigned` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: could not evaluate static initializer --> $DIR/forbidden_slices.rs:54:25 diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 068720a53f6..58ddc047d03 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -13,7 +13,6 @@ note: required for `Foo<String>` to implement `Copy` LL | #[derive(Copy, Clone)] | ^^^^ unsatisfied trait bound introduced in this `derive` macro = note: the `Copy` trait is required because this value will be copied for each element of the array - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/const_panic-normalize-tabs-115498.stderr b/tests/ui/consts/const-eval/const_panic-normalize-tabs-115498.stderr index 64e227c4f45..fae971c09f2 100644 --- a/tests/ui/consts/const-eval/const_panic-normalize-tabs-115498.stderr +++ b/tests/ui/consts/const-eval/const_panic-normalize-tabs-115498.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of constant value failed | LL | struct Bug([u8; panic!{"\t"}]); | ^^^^^^^^^^^^ evaluation panicked: - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/const_panic.stderr b/tests/ui/consts/const-eval/const_panic.stderr index 0816b04faca..0874224e5f2 100644 --- a/tests/ui/consts/const-eval/const_panic.stderr +++ b/tests/ui/consts/const-eval/const_panic.stderr @@ -3,24 +3,18 @@ error[E0080]: evaluation of constant value failed | LL | const Z: () = std::panic!("cheese"); | ^^^^^^^^^^^^^^^^^^^^^ evaluation panicked: cheese - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:9:16 | LL | const Z2: () = std::panic!(); | ^^^^^^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:12:15 | LL | const Y: () = std::unreachable!(); | ^^^^^^^^^^^^^^^^^^^ evaluation panicked: internal error: entered unreachable code - | - = note: this error originates in the macro `$crate::panic::unreachable_2015` which comes from the expansion of the macro `std::unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:15:15 @@ -35,40 +29,30 @@ error[E0080]: evaluation of constant value failed | LL | const W: () = std::panic!(MSG); | ^^^^^^^^^^^^^^^^ evaluation panicked: hello - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:21:16 | LL | const W2: () = std::panic!("{}", MSG); | ^^^^^^^^^^^^^^^^^^^^^^ evaluation panicked: hello - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:24:20 | LL | const Z_CORE: () = core::panic!("cheese"); | ^^^^^^^^^^^^^^^^^^^^^^ evaluation panicked: cheese - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:27:21 | LL | const Z2_CORE: () = core::panic!(); | ^^^^^^^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:30:20 | LL | const Y_CORE: () = core::unreachable!(); | ^^^^^^^^^^^^^^^^^^^^ evaluation panicked: internal error: entered unreachable code - | - = note: this error originates in the macro `$crate::panic::unreachable_2015` which comes from the expansion of the macro `core::unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:33:20 @@ -83,16 +67,12 @@ error[E0080]: evaluation of constant value failed | LL | const W_CORE: () = core::panic!(MSG); | ^^^^^^^^^^^^^^^^^ evaluation panicked: hello - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const_panic.rs:39:21 | LL | const W2_CORE: () = core::panic!("{}", MSG); | ^^^^^^^^^^^^^^^^^^^^^^^ evaluation panicked: hello - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 12 previous errors diff --git a/tests/ui/consts/const-eval/const_panic_2021.stderr b/tests/ui/consts/const-eval/const_panic_2021.stderr index 4faa2a1e4cf..1496df4445a 100644 --- a/tests/ui/consts/const-eval/const_panic_2021.stderr +++ b/tests/ui/consts/const-eval/const_panic_2021.stderr @@ -3,24 +3,18 @@ error[E0080]: evaluation of constant value failed | LL | const A: () = std::panic!("blåhaj"); | ^^^^^^^^^^^^^^^^^^^^^ evaluation panicked: blåhaj - | - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const_panic_2021.rs:9:15 | LL | const B: () = std::panic!(); | ^^^^^^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const_panic_2021.rs:12:15 | LL | const C: () = std::unreachable!(); | ^^^^^^^^^^^^^^^^^^^ evaluation panicked: internal error: entered unreachable code - | - = note: this error originates in the macro `$crate::panic::unreachable_2021` which comes from the expansion of the macro `std::unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const_panic_2021.rs:15:15 @@ -35,32 +29,24 @@ error[E0080]: evaluation of constant value failed | LL | const E: () = std::panic!("{}", MSG); | ^^^^^^^^^^^^^^^^^^^^^^ evaluation panicked: hello - | - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `std::panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const_panic_2021.rs:21:20 | LL | const A_CORE: () = core::panic!("shark"); | ^^^^^^^^^^^^^^^^^^^^^ evaluation panicked: shark - | - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const_panic_2021.rs:24:20 | LL | const B_CORE: () = core::panic!(); | ^^^^^^^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const_panic_2021.rs:27:20 | LL | const C_CORE: () = core::unreachable!(); | ^^^^^^^^^^^^^^^^^^^^ evaluation panicked: internal error: entered unreachable code - | - = note: this error originates in the macro `$crate::panic::unreachable_2021` which comes from the expansion of the macro `core::unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const_panic_2021.rs:30:20 @@ -75,8 +61,6 @@ error[E0080]: evaluation of constant value failed | LL | const E_CORE: () = core::panic!("{}", MSG); | ^^^^^^^^^^^^^^^^^^^^^^^ evaluation panicked: hello - | - = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `core::panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 10 previous errors diff --git a/tests/ui/consts/const-eval/const_panic_libcore_bin.stderr b/tests/ui/consts/const-eval/const_panic_libcore_bin.stderr index 11e70c48499..2acab711290 100644 --- a/tests/ui/consts/const-eval/const_panic_libcore_bin.stderr +++ b/tests/ui/consts/const-eval/const_panic_libcore_bin.stderr @@ -3,16 +3,12 @@ error[E0080]: evaluation of constant value failed | LL | const Z: () = panic!("cheese"); | ^^^^^^^^^^^^^^^^ evaluation panicked: cheese - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const_panic_libcore_bin.rs:11:15 | LL | const Y: () = unreachable!(); | ^^^^^^^^^^^^^^ evaluation panicked: internal error: entered unreachable code - | - = note: this error originates in the macro `$crate::panic::unreachable_2015` which comes from the expansion of the macro `unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/const_panic_libcore_bin.rs:14:15 diff --git a/tests/ui/consts/const-eval/format.stderr b/tests/ui/consts/const-eval/format.stderr index af90acc2a26..e8d7bbcea09 100644 --- a/tests/ui/consts/const-eval/format.stderr +++ b/tests/ui/consts/const-eval/format.stderr @@ -5,7 +5,6 @@ LL | panic!("{:?}", 0); | ^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - = note: this error originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0015]: cannot call non-const formatting macro in constant functions --> $DIR/format.rs:7:15 diff --git a/tests/ui/consts/const-eval/issue-85907.stderr b/tests/ui/consts/const-eval/issue-85907.stderr index 519227bc693..fa1bbf2187f 100644 --- a/tests/ui/consts/const-eval/issue-85907.stderr +++ b/tests/ui/consts/const-eval/issue-85907.stderr @@ -3,8 +3,6 @@ error: argument to `panic!()` in a const context must have type `&str` | LL | panic!(123); | ^^^^^^^^^^^ - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/panic-assoc-never-type.stderr b/tests/ui/consts/const-eval/panic-assoc-never-type.stderr index efdbbe5698f..71b33d8d0d5 100644 --- a/tests/ui/consts/const-eval/panic-assoc-never-type.stderr +++ b/tests/ui/consts/const-eval/panic-assoc-never-type.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of constant value failed | LL | const VOID: ! = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/panic-assoc-never-type.rs:14:13 diff --git a/tests/ui/consts/const-eval/panic-never-type.stderr b/tests/ui/consts/const-eval/panic-never-type.stderr index 30a320f8db2..1d9bba9aea2 100644 --- a/tests/ui/consts/const-eval/panic-never-type.stderr +++ b/tests/ui/consts/const-eval/panic-never-type.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of constant value failed | LL | const VOID: ! = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/unwind-abort.stderr b/tests/ui/consts/const-eval/unwind-abort.stderr index 96c0dd7c5e9..7d096c5d587 100644 --- a/tests/ui/consts/const-eval/unwind-abort.stderr +++ b/tests/ui/consts/const-eval/unwind-abort.stderr @@ -9,7 +9,6 @@ note: inside `foo` | LL | panic!() | ^^^^^^^^ the failure occurred here - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-ptr-is-null.stderr b/tests/ui/consts/const-ptr-is-null.stderr index ff2db14a2f5..1a2be3b3cb1 100644 --- a/tests/ui/consts/const-ptr-is-null.stderr +++ b/tests/ui/consts/const-ptr-is-null.stderr @@ -8,7 +8,6 @@ note: inside `std::ptr::const_ptr::<impl *const i32>::is_null` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL note: inside `std::ptr::const_ptr::<impl *const T>::is_null::compiletime` --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL - = note: this error originates in the macro `$crate::intrinsics::const_eval_select` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/consts/const_cmp_type_id.stderr b/tests/ui/consts/const_cmp_type_id.stderr index 2e9a8024eae..62f8d42c0e6 100644 --- a/tests/ui/consts/const_cmp_type_id.stderr +++ b/tests/ui/consts/const_cmp_type_id.stderr @@ -27,7 +27,6 @@ LL | let _a = TypeId::of::<u8>() < TypeId::of::<u16>(); note: impl defined here, but it is not `const` --> $SRC_DIR/core/src/any.rs:LL:COL = note: calls in constants are limited to constant functions, tuple structs and tuple variants - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/consts/control-flow/assert.stderr b/tests/ui/consts/control-flow/assert.stderr index fc378f57fa4..3fa98b74bf6 100644 --- a/tests/ui/consts/control-flow/assert.stderr +++ b/tests/ui/consts/control-flow/assert.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of constant value failed | LL | const _: () = assert!(false); | ^^^^^^^^^^^^^^ evaluation panicked: assertion failed: false - | - = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/consts/issue-32829.stderr b/tests/ui/consts/issue-32829.stderr index 0cbc73cfaa3..542dce19151 100644 --- a/tests/ui/consts/issue-32829.stderr +++ b/tests/ui/consts/issue-32829.stderr @@ -3,8 +3,6 @@ error[E0080]: could not evaluate static initializer | LL | static S : u64 = { { panic!("foo"); 0 } }; | ^^^^^^^^^^^^^ evaluation panicked: foo - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/consts/issue-66693-panic-in-array-len.stderr b/tests/ui/consts/issue-66693-panic-in-array-len.stderr index 9cf5ad126f3..fdef515b6d4 100644 --- a/tests/ui/consts/issue-66693-panic-in-array-len.stderr +++ b/tests/ui/consts/issue-66693-panic-in-array-len.stderr @@ -3,16 +3,12 @@ error: argument to `panic!()` in a const context must have type `&str` | LL | let _ = [0i32; panic!(2f32)]; | ^^^^^^^^^^^^ - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/issue-66693-panic-in-array-len.rs:10:21 | LL | let _ = [false; panic!()]; | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/consts/issue-66693.stderr b/tests/ui/consts/issue-66693.stderr index 46f30a8cbab..ea657ec34bd 100644 --- a/tests/ui/consts/issue-66693.stderr +++ b/tests/ui/consts/issue-66693.stderr @@ -3,40 +3,30 @@ error: argument to `panic!()` in a const context must have type `&str` | LL | const _: () = panic!(1); | ^^^^^^^^^ - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: argument to `panic!()` in a const context must have type `&str` --> $DIR/issue-66693.rs:7:19 | LL | static _FOO: () = panic!(true); | ^^^^^^^^^^^^ - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/issue-66693.rs:16:15 | LL | const _: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: could not evaluate static initializer --> $DIR/issue-66693.rs:18:19 | LL | static _BAR: () = panic!("panic in static"); | ^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation panicked: panic in static - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: argument to `panic!()` in a const context must have type `&str` --> $DIR/issue-66693.rs:11:5 | LL | panic!(&1); | ^^^^^^^^^^ - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 5 previous errors diff --git a/tests/ui/consts/issue-76064.stderr b/tests/ui/consts/issue-76064.stderr index 55059220388..786d4213f1e 100644 --- a/tests/ui/consts/issue-76064.stderr +++ b/tests/ui/consts/issue-76064.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of constant value failed | LL | struct Bug([u8; panic!("panic")]); | ^^^^^^^^^^^^^^^ evaluation panicked: panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/consts/miri_unleashed/extern-static.stderr b/tests/ui/consts/miri_unleashed/extern-static.stderr index 0979a5e4fb1..4dbabbe44a2 100644 --- a/tests/ui/consts/miri_unleashed/extern-static.stderr +++ b/tests/ui/consts/miri_unleashed/extern-static.stderr @@ -2,13 +2,13 @@ error[E0080]: could not evaluate static initializer --> $DIR/extern-static.rs:11:25 | LL | unsafe { let _val = DATA; } - | ^^^^ cannot access extern static (DefId(0:4 ~ extern_static[c41e]::{extern#0}::DATA)) + | ^^^^ cannot access extern static `DATA` error[E0080]: could not evaluate static initializer --> $DIR/extern-static.rs:16:14 | LL | unsafe { DATA = 0; } - | ^^^^^^^^ cannot access extern static (DefId(0:4 ~ extern_static[c41e]::{extern#0}::DATA)) + | ^^^^^^^^ cannot access extern static `DATA` error: aborting due to 2 previous errors diff --git a/tests/ui/consts/miri_unleashed/tls.stderr b/tests/ui/consts/miri_unleashed/tls.stderr index a00b7eb1312..ef836544303 100644 --- a/tests/ui/consts/miri_unleashed/tls.stderr +++ b/tests/ui/consts/miri_unleashed/tls.stderr @@ -2,13 +2,13 @@ error[E0080]: could not evaluate static initializer --> $DIR/tls.rs:11:25 | LL | unsafe { let _val = A; } - | ^ cannot access thread local static (DefId(0:4 ~ tls[ca29]::A)) + | ^ cannot access thread local static `A` error[E0080]: could not evaluate static initializer --> $DIR/tls.rs:20:26 | LL | unsafe { let _val = &A; } - | ^ cannot access thread local static (DefId(0:4 ~ tls[ca29]::A)) + | ^ cannot access thread local static `A` warning: skipping const checks | diff --git a/tests/ui/consts/required-consts/collect-in-called-fn.noopt.stderr b/tests/ui/consts/required-consts/collect-in-called-fn.noopt.stderr index 08d0b338728..6812b3734ef 100644 --- a/tests/ui/consts/required-consts/collect-in-called-fn.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-called-fn.noopt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-called-fn.rs:19:17 diff --git a/tests/ui/consts/required-consts/collect-in-called-fn.opt.stderr b/tests/ui/consts/required-consts/collect-in-called-fn.opt.stderr index 08d0b338728..6812b3734ef 100644 --- a/tests/ui/consts/required-consts/collect-in-called-fn.opt.stderr +++ b/tests/ui/consts/required-consts/collect-in-called-fn.opt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-called-fn.rs:19:17 diff --git a/tests/ui/consts/required-consts/collect-in-dead-closure.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-closure.noopt.stderr index 41fe2cf84e4..661aea71604 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-closure.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-closure.noopt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-closure.rs:17:17 diff --git a/tests/ui/consts/required-consts/collect-in-dead-closure.opt.stderr b/tests/ui/consts/required-consts/collect-in-dead-closure.opt.stderr index 41fe2cf84e4..661aea71604 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-closure.opt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-closure.opt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-closure.rs:17:17 diff --git a/tests/ui/consts/required-consts/collect-in-dead-drop.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-drop.noopt.stderr index b62b25bd3aa..31e6b2f487f 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-drop.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-drop.noopt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-drop.rs:16:17 diff --git a/tests/ui/consts/required-consts/collect-in-dead-drop.opt.stderr b/tests/ui/consts/required-consts/collect-in-dead-drop.opt.stderr index b62b25bd3aa..31e6b2f487f 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-drop.opt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-drop.opt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-drop.rs:16:17 diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.noopt.stderr index c8a7cf983c4..32dc1cb304b 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.noopt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-fn-behind-assoc-type.rs:16:17 diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.opt.stderr b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.opt.stderr index c8a7cf983c4..32dc1cb304b 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.opt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-assoc-type.opt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-fn-behind-assoc-type.rs:16:17 diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.noopt.stderr index 1e68d66cf5e..d22cf579448 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.noopt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-fn-behind-generic.rs:15:17 diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.opt.stderr b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.opt.stderr index 1e68d66cf5e..d22cf579448 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.opt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-generic.opt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-fn-behind-generic.rs:15:17 diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.noopt.stderr index a9cc56fba45..91daa2f9bc3 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.noopt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `m::Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-fn-behind-opaque-type.rs:19:21 diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.opt.stderr b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.opt.stderr index a9cc56fba45..91daa2f9bc3 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.opt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.opt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `m::Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-fn-behind-opaque-type.rs:19:21 diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-fn.noopt.stderr index ec549561a17..d254fc60c0c 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-fn.noopt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-fn.rs:19:17 diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn.opt.stderr b/tests/ui/consts/required-consts/collect-in-dead-fn.opt.stderr index ec549561a17..d254fc60c0c 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fn.opt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-fn.opt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-fn.rs:19:17 diff --git a/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.noopt.stderr index dfaf69d52b2..c14837ce442 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.noopt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Late::<i32>::FAIL` failed | LL | const FAIL: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-fnptr-in-const.rs:10:28 diff --git a/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.opt.stderr b/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.opt.stderr index dfaf69d52b2..c14837ce442 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.opt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-fnptr-in-const.opt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Late::<i32>::FAIL` failed | LL | const FAIL: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-fnptr-in-const.rs:10:28 diff --git a/tests/ui/consts/required-consts/collect-in-dead-fnptr.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-fnptr.noopt.stderr index 7cbd423cdc0..284e1a70a20 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fnptr.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-fnptr.noopt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-fnptr.rs:18:17 diff --git a/tests/ui/consts/required-consts/collect-in-dead-fnptr.opt.stderr b/tests/ui/consts/required-consts/collect-in-dead-fnptr.opt.stderr index 7cbd423cdc0..284e1a70a20 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-fnptr.opt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-fnptr.opt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-fnptr.rs:18:17 diff --git a/tests/ui/consts/required-consts/collect-in-dead-move.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-move.noopt.stderr index 58e9d7a2c9a..8b43c67c085 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-move.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-move.noopt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-move.rs:16:17 diff --git a/tests/ui/consts/required-consts/collect-in-dead-move.opt.stderr b/tests/ui/consts/required-consts/collect-in-dead-move.opt.stderr index 58e9d7a2c9a..8b43c67c085 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-move.opt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-move.opt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-move.rs:16:17 diff --git a/tests/ui/consts/required-consts/collect-in-dead-vtable.noopt.stderr b/tests/ui/consts/required-consts/collect-in-dead-vtable.noopt.stderr index 6c78ca79fd6..4056f28541d 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-vtable.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-vtable.noopt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-vtable.rs:22:21 diff --git a/tests/ui/consts/required-consts/collect-in-dead-vtable.opt.stderr b/tests/ui/consts/required-consts/collect-in-dead-vtable.opt.stderr index 6c78ca79fd6..4056f28541d 100644 --- a/tests/ui/consts/required-consts/collect-in-dead-vtable.opt.stderr +++ b/tests/ui/consts/required-consts/collect-in-dead-vtable.opt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-dead-vtable.rs:22:21 diff --git a/tests/ui/consts/required-consts/collect-in-promoted-const.noopt.stderr b/tests/ui/consts/required-consts/collect-in-promoted-const.noopt.stderr index fd231e1101d..c5f3b0009f5 100644 --- a/tests/ui/consts/required-consts/collect-in-promoted-const.noopt.stderr +++ b/tests/ui/consts/required-consts/collect-in-promoted-const.noopt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-promoted-const.rs:20:21 diff --git a/tests/ui/consts/required-consts/collect-in-promoted-const.opt.stderr b/tests/ui/consts/required-consts/collect-in-promoted-const.opt.stderr index 0f3f77769ad..6f36aaf314d 100644 --- a/tests/ui/consts/required-consts/collect-in-promoted-const.opt.stderr +++ b/tests/ui/consts/required-consts/collect-in-promoted-const.opt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<T>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-promoted-const.rs:20:21 @@ -17,8 +15,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/collect-in-promoted-const.rs:20:21 diff --git a/tests/ui/consts/required-consts/interpret-in-const-called-fn.noopt.stderr b/tests/ui/consts/required-consts/interpret-in-const-called-fn.noopt.stderr index d2145089028..9184df472c4 100644 --- a/tests/ui/consts/required-consts/interpret-in-const-called-fn.noopt.stderr +++ b/tests/ui/consts/required-consts/interpret-in-const-called-fn.noopt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/interpret-in-const-called-fn.rs:17:9 diff --git a/tests/ui/consts/required-consts/interpret-in-const-called-fn.opt.stderr b/tests/ui/consts/required-consts/interpret-in-const-called-fn.opt.stderr index d2145089028..9184df472c4 100644 --- a/tests/ui/consts/required-consts/interpret-in-const-called-fn.opt.stderr +++ b/tests/ui/consts/required-consts/interpret-in-const-called-fn.opt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/interpret-in-const-called-fn.rs:17:9 diff --git a/tests/ui/consts/required-consts/interpret-in-static.noopt.stderr b/tests/ui/consts/required-consts/interpret-in-static.noopt.stderr index f999bf370b8..aa778deb542 100644 --- a/tests/ui/consts/required-consts/interpret-in-static.noopt.stderr +++ b/tests/ui/consts/required-consts/interpret-in-static.noopt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/interpret-in-static.rs:16:9 diff --git a/tests/ui/consts/required-consts/interpret-in-static.opt.stderr b/tests/ui/consts/required-consts/interpret-in-static.opt.stderr index f999bf370b8..aa778deb542 100644 --- a/tests/ui/consts/required-consts/interpret-in-static.opt.stderr +++ b/tests/ui/consts/required-consts/interpret-in-static.opt.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `Fail::<i32>::C` failed | LL | const C: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/interpret-in-static.rs:16:9 diff --git a/tests/ui/coroutine/postfix-yield.rs b/tests/ui/coroutine/postfix-yield.rs new file mode 100644 index 00000000000..ff843138c8c --- /dev/null +++ b/tests/ui/coroutine/postfix-yield.rs @@ -0,0 +1,34 @@ +// This demonstrates a proposed alternate or additional option of having yield in postfix position. + +//@ run-pass +//@ edition: 2024 + +#![feature(gen_blocks, coroutines, coroutine_trait, yield_expr)] + +use std::ops::{Coroutine, CoroutineState}; +use std::pin::pin; + +fn main() { + // generators (i.e. yield doesn't return anything useful) + let mut gn = gen { + yield 1; + 2.yield; + }; + + assert_eq!(gn.next(), Some(1)); + assert_eq!(gn.next(), Some(2)); + assert_eq!(gn.next(), None); + + //coroutines (i.e. yield returns something useful) + let mut coro = pin!( + #[coroutine] + |_: i32| { + let x = 1.yield; + (x + 2).yield; + } + ); + + assert_eq!(coro.as_mut().resume(0), CoroutineState::Yielded(1)); + assert_eq!(coro.as_mut().resume(2), CoroutineState::Yielded(4)); + assert_eq!(coro.as_mut().resume(3), CoroutineState::Complete(())); +} diff --git a/tests/ui/custom_test_frameworks/mismatch.stderr b/tests/ui/custom_test_frameworks/mismatch.stderr index dad93cfbba4..c7798635fbf 100644 --- a/tests/ui/custom_test_frameworks/mismatch.stderr +++ b/tests/ui/custom_test_frameworks/mismatch.stderr @@ -7,7 +7,6 @@ LL | fn wrong_kind(){} | ^^^^^^^^^^^^^^^^^ the trait `Testable` is not implemented for `TestDescAndFn` | = note: required for the cast from `&TestDescAndFn` to `&dyn Testable` - = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/derives/derives-span-Clone-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Clone-enum-struct-variant.stderr index 2c8d9431646..9aeb3a8c03d 100644 --- a/tests/ui/derives/derives-span-Clone-enum-struct-variant.stderr +++ b/tests/ui/derives/derives-span-Clone-enum-struct-variant.stderr @@ -7,7 +7,6 @@ LL | #[derive(Clone)] LL | x: Error | ^^^^^^^^ the trait `Clone` is not implemented for `Error` | - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/derives/derives-span-Clone-enum.stderr b/tests/ui/derives/derives-span-Clone-enum.stderr index b683a8b8944..6b4f2241663 100644 --- a/tests/ui/derives/derives-span-Clone-enum.stderr +++ b/tests/ui/derives/derives-span-Clone-enum.stderr @@ -7,7 +7,6 @@ LL | #[derive(Clone)] LL | Error | ^^^^^ the trait `Clone` is not implemented for `Error` | - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/derives/derives-span-Clone-struct.stderr b/tests/ui/derives/derives-span-Clone-struct.stderr index 305a9275271..17e3f0eccf9 100644 --- a/tests/ui/derives/derives-span-Clone-struct.stderr +++ b/tests/ui/derives/derives-span-Clone-struct.stderr @@ -7,7 +7,6 @@ LL | struct Struct { LL | x: Error | ^^^^^^^^ the trait `Clone` is not implemented for `Error` | - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/derives/derives-span-Clone-tuple-struct.stderr b/tests/ui/derives/derives-span-Clone-tuple-struct.stderr index b636404ad9e..f8380d197b0 100644 --- a/tests/ui/derives/derives-span-Clone-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-Clone-tuple-struct.stderr @@ -7,7 +7,6 @@ LL | struct Struct( LL | Error | ^^^^^ the trait `Clone` is not implemented for `Error` | - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr index 3f6c39bf939..a7f6d094681 100644 --- a/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr +++ b/tests/ui/derives/derives-span-Debug-enum-struct-variant.stderr @@ -9,7 +9,6 @@ LL | x: Error | = help: the trait `Debug` is not implemented for `Error` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Debug)]` | LL + #[derive(Debug)] diff --git a/tests/ui/derives/derives-span-Debug-enum.stderr b/tests/ui/derives/derives-span-Debug-enum.stderr index eaeffaeb849..b3a58478159 100644 --- a/tests/ui/derives/derives-span-Debug-enum.stderr +++ b/tests/ui/derives/derives-span-Debug-enum.stderr @@ -9,7 +9,6 @@ LL | Error | = help: the trait `Debug` is not implemented for `Error` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Debug)]` | LL + #[derive(Debug)] diff --git a/tests/ui/derives/derives-span-Debug-struct.stderr b/tests/ui/derives/derives-span-Debug-struct.stderr index 4a725e260de..c8ad652716c 100644 --- a/tests/ui/derives/derives-span-Debug-struct.stderr +++ b/tests/ui/derives/derives-span-Debug-struct.stderr @@ -9,7 +9,6 @@ LL | x: Error | = help: the trait `Debug` is not implemented for `Error` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Debug)]` | LL + #[derive(Debug)] diff --git a/tests/ui/derives/derives-span-Debug-tuple-struct.stderr b/tests/ui/derives/derives-span-Debug-tuple-struct.stderr index 2f816e1c85b..dbece4d2091 100644 --- a/tests/ui/derives/derives-span-Debug-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-Debug-tuple-struct.stderr @@ -9,7 +9,6 @@ LL | Error | = help: the trait `Debug` is not implemented for `Error` = note: add `#[derive(Debug)]` to `Error` or manually `impl Debug for Error` - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Debug)]` | LL + #[derive(Debug)] diff --git a/tests/ui/derives/derives-span-Default-struct.stderr b/tests/ui/derives/derives-span-Default-struct.stderr index 359b61528e1..442081f78ce 100644 --- a/tests/ui/derives/derives-span-Default-struct.stderr +++ b/tests/ui/derives/derives-span-Default-struct.stderr @@ -7,7 +7,6 @@ LL | struct Struct { LL | x: Error | ^^^^^^^^ the trait `Default` is not implemented for `Error` | - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Default)]` | LL + #[derive(Default)] diff --git a/tests/ui/derives/derives-span-Default-tuple-struct.stderr b/tests/ui/derives/derives-span-Default-tuple-struct.stderr index 1ddb4ec3f64..e786ec1e9da 100644 --- a/tests/ui/derives/derives-span-Default-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-Default-tuple-struct.stderr @@ -7,7 +7,6 @@ LL | struct Struct( LL | Error | ^^^^^ the trait `Default` is not implemented for `Error` | - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Default)]` | LL + #[derive(Default)] diff --git a/tests/ui/derives/derives-span-Eq-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Eq-enum-struct-variant.stderr index c9edc89e1bc..e0cb3c1b43d 100644 --- a/tests/ui/derives/derives-span-Eq-enum-struct-variant.stderr +++ b/tests/ui/derives/derives-span-Eq-enum-struct-variant.stderr @@ -9,7 +9,6 @@ LL | x: Error | note: required by a bound in `AssertParamIsEq` --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Eq)]` | LL + #[derive(Eq)] diff --git a/tests/ui/derives/derives-span-Eq-enum.stderr b/tests/ui/derives/derives-span-Eq-enum.stderr index 7db13e97111..2f09b9ea385 100644 --- a/tests/ui/derives/derives-span-Eq-enum.stderr +++ b/tests/ui/derives/derives-span-Eq-enum.stderr @@ -9,7 +9,6 @@ LL | Error | note: required by a bound in `AssertParamIsEq` --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Eq)]` | LL + #[derive(Eq)] diff --git a/tests/ui/derives/derives-span-Eq-struct.stderr b/tests/ui/derives/derives-span-Eq-struct.stderr index 36eeb89bde1..c16d9118e10 100644 --- a/tests/ui/derives/derives-span-Eq-struct.stderr +++ b/tests/ui/derives/derives-span-Eq-struct.stderr @@ -9,7 +9,6 @@ LL | x: Error | note: required by a bound in `AssertParamIsEq` --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Eq)]` | LL + #[derive(Eq)] diff --git a/tests/ui/derives/derives-span-Eq-tuple-struct.stderr b/tests/ui/derives/derives-span-Eq-tuple-struct.stderr index 126d1053540..dac295eed91 100644 --- a/tests/ui/derives/derives-span-Eq-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-Eq-tuple-struct.stderr @@ -9,7 +9,6 @@ LL | Error | note: required by a bound in `AssertParamIsEq` --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Eq)]` | LL + #[derive(Eq)] diff --git a/tests/ui/derives/derives-span-Hash-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Hash-enum-struct-variant.stderr index ae973228cac..9854b61d31b 100644 --- a/tests/ui/derives/derives-span-Hash-enum-struct-variant.stderr +++ b/tests/ui/derives/derives-span-Hash-enum-struct-variant.stderr @@ -7,7 +7,6 @@ LL | #[derive(Hash)] LL | x: Error | ^^^^^^^^ the trait `Hash` is not implemented for `Error` | - = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Hash)]` | LL + #[derive(Hash)] diff --git a/tests/ui/derives/derives-span-Hash-enum.stderr b/tests/ui/derives/derives-span-Hash-enum.stderr index 85e26c84fa7..60e7d0cf1ff 100644 --- a/tests/ui/derives/derives-span-Hash-enum.stderr +++ b/tests/ui/derives/derives-span-Hash-enum.stderr @@ -7,7 +7,6 @@ LL | #[derive(Hash)] LL | Error | ^^^^^ the trait `Hash` is not implemented for `Error` | - = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Hash)]` | LL + #[derive(Hash)] diff --git a/tests/ui/derives/derives-span-Hash-struct.stderr b/tests/ui/derives/derives-span-Hash-struct.stderr index f9a654b2df7..3851cf8ce8b 100644 --- a/tests/ui/derives/derives-span-Hash-struct.stderr +++ b/tests/ui/derives/derives-span-Hash-struct.stderr @@ -7,7 +7,6 @@ LL | struct Struct { LL | x: Error | ^^^^^^^^ the trait `Hash` is not implemented for `Error` | - = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Hash)]` | LL + #[derive(Hash)] diff --git a/tests/ui/derives/derives-span-Hash-tuple-struct.stderr b/tests/ui/derives/derives-span-Hash-tuple-struct.stderr index 0a5fbe28658..e5a3e7a5566 100644 --- a/tests/ui/derives/derives-span-Hash-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-Hash-tuple-struct.stderr @@ -7,7 +7,6 @@ LL | struct Struct( LL | Error | ^^^^^ the trait `Hash` is not implemented for `Error` | - = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Hash)]` | LL + #[derive(Hash)] diff --git a/tests/ui/derives/derives-span-Ord-enum-struct-variant.stderr b/tests/ui/derives/derives-span-Ord-enum-struct-variant.stderr index 96ef59ca963..e253a9173fc 100644 --- a/tests/ui/derives/derives-span-Ord-enum-struct-variant.stderr +++ b/tests/ui/derives/derives-span-Ord-enum-struct-variant.stderr @@ -7,7 +7,6 @@ LL | #[derive(Ord,Eq,PartialOrd,PartialEq)] LL | x: Error | ^^^^^^^^ the trait `Ord` is not implemented for `Error` | - = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Ord)]` | LL + #[derive(Ord)] diff --git a/tests/ui/derives/derives-span-Ord-enum.stderr b/tests/ui/derives/derives-span-Ord-enum.stderr index 7c75ecb6432..8a92458b51c 100644 --- a/tests/ui/derives/derives-span-Ord-enum.stderr +++ b/tests/ui/derives/derives-span-Ord-enum.stderr @@ -7,7 +7,6 @@ LL | #[derive(Ord,Eq,PartialOrd,PartialEq)] LL | Error | ^^^^^ the trait `Ord` is not implemented for `Error` | - = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Ord)]` | LL + #[derive(Ord)] diff --git a/tests/ui/derives/derives-span-Ord-struct.stderr b/tests/ui/derives/derives-span-Ord-struct.stderr index 429e7e06f5d..ae110d51196 100644 --- a/tests/ui/derives/derives-span-Ord-struct.stderr +++ b/tests/ui/derives/derives-span-Ord-struct.stderr @@ -7,7 +7,6 @@ LL | struct Struct { LL | x: Error | ^^^^^^^^ the trait `Ord` is not implemented for `Error` | - = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Ord)]` | LL + #[derive(Ord)] diff --git a/tests/ui/derives/derives-span-Ord-tuple-struct.stderr b/tests/ui/derives/derives-span-Ord-tuple-struct.stderr index a46133834c6..e2a6d5266b7 100644 --- a/tests/ui/derives/derives-span-Ord-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-Ord-tuple-struct.stderr @@ -7,7 +7,6 @@ LL | struct Struct( LL | Error | ^^^^^ the trait `Ord` is not implemented for `Error` | - = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(Ord)]` | LL + #[derive(Ord)] diff --git a/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr b/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr index e88a523ef4f..09104289c64 100644 --- a/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr +++ b/tests/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr @@ -12,7 +12,6 @@ note: an implementation of `PartialEq` might be missing for `Error` | LL | struct Error; | ^^^^^^^^^^^^ must implement `PartialEq` - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(PartialEq)]` | LL + #[derive(PartialEq)] diff --git a/tests/ui/derives/derives-span-PartialEq-enum.stderr b/tests/ui/derives/derives-span-PartialEq-enum.stderr index 80b225446b4..40dca92ef23 100644 --- a/tests/ui/derives/derives-span-PartialEq-enum.stderr +++ b/tests/ui/derives/derives-span-PartialEq-enum.stderr @@ -12,7 +12,6 @@ note: an implementation of `PartialEq` might be missing for `Error` | LL | struct Error; | ^^^^^^^^^^^^ must implement `PartialEq` - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(PartialEq)]` | LL + #[derive(PartialEq)] diff --git a/tests/ui/derives/derives-span-PartialEq-struct.stderr b/tests/ui/derives/derives-span-PartialEq-struct.stderr index d7fc3da46e0..cfd9fc41d06 100644 --- a/tests/ui/derives/derives-span-PartialEq-struct.stderr +++ b/tests/ui/derives/derives-span-PartialEq-struct.stderr @@ -12,7 +12,6 @@ note: an implementation of `PartialEq` might be missing for `Error` | LL | struct Error; | ^^^^^^^^^^^^ must implement `PartialEq` - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(PartialEq)]` | LL + #[derive(PartialEq)] diff --git a/tests/ui/derives/derives-span-PartialEq-tuple-struct.stderr b/tests/ui/derives/derives-span-PartialEq-tuple-struct.stderr index ea3920f406c..4e35cbb534d 100644 --- a/tests/ui/derives/derives-span-PartialEq-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-PartialEq-tuple-struct.stderr @@ -12,7 +12,6 @@ note: an implementation of `PartialEq` might be missing for `Error` | LL | struct Error; | ^^^^^^^^^^^^ must implement `PartialEq` - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(PartialEq)]` | LL + #[derive(PartialEq)] diff --git a/tests/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr b/tests/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr index 3f83eb56aaf..7fe09d45cc1 100644 --- a/tests/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr +++ b/tests/ui/derives/derives-span-PartialOrd-enum-struct-variant.stderr @@ -8,7 +8,6 @@ LL | x: Error | ^^^^^^^^ no implementation for `Error < Error` and `Error > Error` | = help: the trait `PartialOrd` is not implemented for `Error` - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(PartialOrd)]` | LL + #[derive(PartialOrd)] diff --git a/tests/ui/derives/derives-span-PartialOrd-enum.stderr b/tests/ui/derives/derives-span-PartialOrd-enum.stderr index cf5915173c5..2a14e6e9618 100644 --- a/tests/ui/derives/derives-span-PartialOrd-enum.stderr +++ b/tests/ui/derives/derives-span-PartialOrd-enum.stderr @@ -8,7 +8,6 @@ LL | Error | ^^^^^ no implementation for `Error < Error` and `Error > Error` | = help: the trait `PartialOrd` is not implemented for `Error` - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(PartialOrd)]` | LL + #[derive(PartialOrd)] diff --git a/tests/ui/derives/derives-span-PartialOrd-struct.stderr b/tests/ui/derives/derives-span-PartialOrd-struct.stderr index de21a903b6c..0904e3ace8f 100644 --- a/tests/ui/derives/derives-span-PartialOrd-struct.stderr +++ b/tests/ui/derives/derives-span-PartialOrd-struct.stderr @@ -8,7 +8,6 @@ LL | x: Error | ^^^^^^^^ no implementation for `Error < Error` and `Error > Error` | = help: the trait `PartialOrd` is not implemented for `Error` - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(PartialOrd)]` | LL + #[derive(PartialOrd)] diff --git a/tests/ui/derives/derives-span-PartialOrd-tuple-struct.stderr b/tests/ui/derives/derives-span-PartialOrd-tuple-struct.stderr index 3050aeecc0d..501fea02e8e 100644 --- a/tests/ui/derives/derives-span-PartialOrd-tuple-struct.stderr +++ b/tests/ui/derives/derives-span-PartialOrd-tuple-struct.stderr @@ -8,7 +8,6 @@ LL | Error | ^^^^^ no implementation for `Error < Error` and `Error > Error` | = help: the trait `PartialOrd` is not implemented for `Error` - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Error` with `#[derive(PartialOrd)]` | LL + #[derive(PartialOrd)] diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index c0c2215c04a..befff880280 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -16,7 +16,6 @@ note: required by a bound in `is_copy` | LL | fn is_copy<T: Copy>(_: T) {} | ^^^^ required by this bound in `is_copy` - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider borrowing here | LL | is_copy(B { a: 1, b: &C }); @@ -40,7 +39,6 @@ note: required by a bound in `is_clone` | LL | fn is_clone<T: Clone>(_: T) {} | ^^^^^ required by this bound in `is_clone` - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider borrowing here | LL | is_clone(B { a: 1, b: &C }); @@ -64,7 +62,6 @@ note: required by a bound in `is_copy` | LL | fn is_copy<T: Copy>(_: T) {} | ^^^^ required by this bound in `is_copy` - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider borrowing here | LL | is_copy(B { a: 1, b: &D }); diff --git a/tests/ui/derives/deriving-no-inner-impl-error-message.stderr b/tests/ui/derives/deriving-no-inner-impl-error-message.stderr index ab99ba9fab5..294f700d9de 100644 --- a/tests/ui/derives/deriving-no-inner-impl-error-message.stderr +++ b/tests/ui/derives/deriving-no-inner-impl-error-message.stderr @@ -12,7 +12,6 @@ note: an implementation of `PartialEq` might be missing for `NoCloneOrEq` | LL | struct NoCloneOrEq; | ^^^^^^^^^^^^^^^^^^ must implement `PartialEq` - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `NoCloneOrEq` with `#[derive(PartialEq)]` | LL + #[derive(PartialEq)] @@ -28,7 +27,6 @@ LL | struct C { LL | x: NoCloneOrEq | ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `NoCloneOrEq` | - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `NoCloneOrEq` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr b/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr index 2de4ee4eabd..68c3c8ae9ea 100644 --- a/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr +++ b/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr @@ -7,7 +7,6 @@ LL | struct StructA(String); | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider cloning the value if the performance cost is acceptable | LL | struct StructA(String.clone()); @@ -22,7 +21,6 @@ LL | struct StructA(String); | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | = note: `#[derive(PartialEq)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider cloning the value if the performance cost is acceptable | LL | struct StructA(String.clone()); @@ -37,7 +35,6 @@ LL | struct StructA(String); | ^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait | = note: `#[derive(PartialEq)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider cloning the value if the performance cost is acceptable | LL | struct StructA(String.clone()); @@ -52,7 +49,6 @@ LL | struct StructA(String); | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | = note: `#[derive(PartialOrd)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider cloning the value if the performance cost is acceptable | LL | struct StructA(String.clone()); @@ -67,7 +63,6 @@ LL | struct StructA(String); | ^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait | = note: `#[derive(PartialOrd)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider cloning the value if the performance cost is acceptable | LL | struct StructA(String.clone()); @@ -82,7 +77,6 @@ LL | struct StructA(String); | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | = note: `#[derive(Ord)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour - = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider cloning the value if the performance cost is acceptable | LL | struct StructA(String.clone()); @@ -97,7 +91,6 @@ LL | struct StructA(String); | ^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait | = note: `#[derive(Ord)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour - = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider cloning the value if the performance cost is acceptable | LL | struct StructA(String.clone()); @@ -112,7 +105,6 @@ LL | struct StructA(String); | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | = note: `#[derive(Hash)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour - = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider cloning the value if the performance cost is acceptable | LL | struct StructA(String.clone()); @@ -127,7 +119,6 @@ LL | struct StructA(String); | ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait | = note: `#[derive(Clone)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider cloning the value if the performance cost is acceptable | LL | struct StructA(String.clone()); diff --git a/tests/ui/derives/deriving-with-repr-packed.stderr b/tests/ui/derives/deriving-with-repr-packed.stderr index 321ffb27eeb..5117f8d1112 100644 --- a/tests/ui/derives/deriving-with-repr-packed.stderr +++ b/tests/ui/derives/deriving-with-repr-packed.stderr @@ -16,7 +16,6 @@ LL | struct Y(usize); LL | struct X(Y); | - you could clone this value = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0161]: cannot move a value of type `[u8]` --> $DIR/deriving-with-repr-packed.rs:29:5 @@ -34,7 +33,6 @@ LL | data: [u8], | ^^^^^^^^^^ move occurs because `self.data` has type `[u8]`, which does not implement the `Copy` trait | = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0161]: cannot move a value of type `str` --> $DIR/deriving-with-repr-packed.rs:38:5 @@ -52,7 +50,6 @@ LL | data: str, | ^^^^^^^^^ move occurs because `self.data` has type `str`, which does not implement the `Copy` trait | = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 5 previous errors diff --git a/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.stderr b/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.stderr index f8e1db33f53..b9eb6194f6c 100644 --- a/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.stderr +++ b/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.stderr @@ -5,8 +5,6 @@ LL | #[derive(Copy, Clone)] | ---- first implementation here LL | #[derive(Copy, Clone)] | ^^^^ conflicting implementation for `E` - | - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0119]: conflicting implementations of trait `Clone` for type `E` --> $DIR/duplicate-derive-copy-clone-diagnostics.rs:6:16 @@ -15,8 +13,6 @@ LL | #[derive(Copy, Clone)] | ----- first implementation here LL | #[derive(Copy, Clone)] | ^^^^^ conflicting implementation for `E` - | - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/derives/issue-97343.stderr b/tests/ui/derives/issue-97343.stderr index efb2fb70f5a..27691f57188 100644 --- a/tests/ui/derives/issue-97343.stderr +++ b/tests/ui/derives/issue-97343.stderr @@ -14,7 +14,6 @@ note: type parameter `Irrelevant` defined here | LL | pub struct Irrelevant<Irrelevant> { | ^^^^^^^^^^ - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/deriving/deriving-coerce-pointee-neg.stderr b/tests/ui/deriving/deriving-coerce-pointee-neg.stderr index d3d73132078..6c6e6312875 100644 --- a/tests/ui/deriving/deriving-coerce-pointee-neg.stderr +++ b/tests/ui/deriving/deriving-coerce-pointee-neg.stderr @@ -3,40 +3,30 @@ error[E0802]: `CoercePointee` can only be derived on `struct`s with `#[repr(tran | LL | #[derive(CoercePointee)] | ^^^^^^^^^^^^^ - | - = note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0802]: `CoercePointee` can only be derived on `struct`s with at least one field --> $DIR/deriving-coerce-pointee-neg.rs:15:10 | LL | #[derive(CoercePointee)] | ^^^^^^^^^^^^^ - | - = note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0802]: `CoercePointee` can only be derived on `struct`s with at least one field --> $DIR/deriving-coerce-pointee-neg.rs:22:10 | LL | #[derive(CoercePointee)] | ^^^^^^^^^^^^^ - | - = note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0802]: `CoercePointee` can only be derived on `struct`s that are generic over at least one type --> $DIR/deriving-coerce-pointee-neg.rs:29:10 | LL | #[derive(CoercePointee)] | ^^^^^^^^^^^^^ - | - = note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0802]: exactly one generic type parameter must be marked as `#[pointee]` to derive `CoercePointee` traits --> $DIR/deriving-coerce-pointee-neg.rs:34:10 | LL | #[derive(CoercePointee)] | ^^^^^^^^^^^^^ - | - = note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0802]: only one type parameter can be marked as `#[pointee]` when deriving `CoercePointee` traits --> $DIR/deriving-coerce-pointee-neg.rs:43:39 @@ -126,8 +116,6 @@ LL | #[derive(CoercePointee)] ... LL | inner: std::rc::Rc<(i32, Box<T>)>, | --------------------------------- `Rc<(i32, Box<T>)>` must be a pointer, reference, or smart pointer that is allowed to be unsized - | - = note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0375]: implementing `CoerceUnsized` does not allow multiple fields to be coerced --> $DIR/deriving-coerce-pointee-neg.rs:153:10 @@ -142,7 +130,6 @@ LL | inner1: Box<T>, | ^^^^^^^^^^^^^^ LL | inner2: Box<T>, | ^^^^^^^^^^^^^^ - = note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info) error: for `UsingNonCoercePointeeData<T>` to have a valid implementation of `CoerceUnsized`, it must be possible to coerce the field of type `NotCoercePointeeData<T>` --> $DIR/deriving-coerce-pointee-neg.rs:164:10 @@ -152,8 +139,6 @@ LL | #[derive(CoercePointee)] LL | LL | struct UsingNonCoercePointeeData<T: ?Sized>(NotCoercePointeeData<T>); | ----------------------- `NotCoercePointeeData<T>` must be a pointer, reference, or smart pointer that is allowed to be unsized - | - = note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0690]: transparent struct needs at most one field with non-trivial size or alignment, but has 2 --> $DIR/deriving-coerce-pointee-neg.rs:155:1 diff --git a/tests/ui/deriving/do-not-suggest-calling-fn-in-derive-macro.stderr b/tests/ui/deriving/do-not-suggest-calling-fn-in-derive-macro.stderr index 40464a49c34..af78f645463 100644 --- a/tests/ui/deriving/do-not-suggest-calling-fn-in-derive-macro.stderr +++ b/tests/ui/deriving/do-not-suggest-calling-fn-in-derive-macro.stderr @@ -6,8 +6,6 @@ LL | #[derive(PartialEq)] LL | pub struct Function { LL | callback: Rc<dyn Fn()>, | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/deriving/issue-103157.stderr b/tests/ui/deriving/issue-103157.stderr index 9754b0289c0..51d4d0a8974 100644 --- a/tests/ui/deriving/issue-103157.stderr +++ b/tests/ui/deriving/issue-103157.stderr @@ -20,7 +20,6 @@ LL | Float(Option<f64>), = note: required for `Option<f64>` to implement `Eq` note: required by a bound in `AssertParamIsEq` --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/deriving/multiple-defaults.stderr b/tests/ui/deriving/multiple-defaults.stderr index 05fb6fecffa..a662ed248fe 100644 --- a/tests/ui/deriving/multiple-defaults.stderr +++ b/tests/ui/deriving/multiple-defaults.stderr @@ -11,7 +11,6 @@ LL | B, | - additional default | = note: only one variant can be default - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error: multiple declared defaults --> $DIR/multiple-defaults.rs:18:10 @@ -26,7 +25,6 @@ LL | A, | - additional default | = note: only one variant can be default - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0428]: the name `A` is defined multiple times --> $DIR/multiple-defaults.rs:23:5 diff --git a/tests/ui/diagnostic-width/tabs-trimming.stderr b/tests/ui/diagnostic-width/tabs-trimming.stderr index a896345bd70..e0d1c2d95a9 100644 --- a/tests/ui/diagnostic-width/tabs-trimming.stderr +++ b/tests/ui/diagnostic-width/tabs-trimming.stderr @@ -15,8 +15,6 @@ LL | ... v @ 1 | 2 | 3 => panic!("You gave me too little mon | | | binding initialized here in some conditions | binding declared here but left uninitialized - | - = note: this error originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/dupe-first-attr.rs b/tests/ui/dupe-first-attr.rs deleted file mode 100644 index c254df050c1..00000000000 --- a/tests/ui/dupe-first-attr.rs +++ /dev/null @@ -1,25 +0,0 @@ -//@ run-pass - -// Regression test for a problem with the first mod attribute -// being applied to every mod - - -#[cfg(target_os = "linux")] -mod hello {} - -#[cfg(target_os = "macos")] -mod hello {} - -#[cfg(target_os = "windows")] -mod hello {} - -#[cfg(target_os = "freebsd")] -mod hello {} - -#[cfg(target_os = "dragonfly")] -mod hello {} - -#[cfg(target_os = "android")] -mod hello {} - -fn main() {} diff --git a/tests/ui/duplicate_entry_error.rs b/tests/ui/duplicate_entry_error.rs deleted file mode 100644 index 5a25802c6e7..00000000000 --- a/tests/ui/duplicate_entry_error.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ normalize-stderr: "loaded from .*libstd-.*.rlib" -> "loaded from SYSROOT/libstd-*.rlib" -// note-pattern: first defined in crate `std`. - -// Test for issue #31788 and E0152 - -#![feature(lang_items)] - -extern crate core; - -use core::panic::PanicInfo; - -#[lang = "panic_impl"] -fn panic_impl(info: &PanicInfo) -> ! { -//~^ ERROR: found duplicate lang item `panic_impl` - loop {} -} - -fn main() {} diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr index 87207d607e2..4c4cb45293f 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.new.stderr @@ -4,7 +4,7 @@ error[E0782]: expected a type, found a trait LL | fn id<F>(f: Copy) -> usize { | ^^^^ | - = note: `Copy` it is dyn-incompatible, so it can't be `dyn` + = note: `Copy` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `Copy` | LL - fn id<F>(f: Copy) -> usize { diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr index 6075e313f4e..d3208d07e91 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.new.stderr @@ -4,7 +4,7 @@ error[E0782]: expected a type, found a trait LL | trait A { fn g(b: B) -> B; } | ^ | - = note: `B` it is dyn-incompatible, so it can't be `dyn` + = note: `B` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `B` | LL - trait A { fn g(b: B) -> B; } @@ -32,7 +32,7 @@ error[E0782]: expected a type, found a trait LL | trait B { fn f(a: A) -> A; } | ^ | - = note: `A` it is dyn-incompatible, so it can't be `dyn` + = note: `A` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `A` | LL - trait B { fn f(a: A) -> A; } diff --git a/tests/ui/env-macro/env-escaped-var.stderr b/tests/ui/env-macro/env-escaped-var.stderr index 53a2ead6742..65d53a7fa1f 100644 --- a/tests/ui/env-macro/env-escaped-var.stderr +++ b/tests/ui/env-macro/env-escaped-var.stderr @@ -5,7 +5,6 @@ LL | env!("\t"); | ^^^^^^^^^^ | = help: use `std::env::var("\t")` to read the variable at run time - = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/env-macro/env-not-defined-custom.stderr b/tests/ui/env-macro/env-not-defined-custom.stderr index 70c41bcc52e..638f261e48e 100644 --- a/tests/ui/env-macro/env-not-defined-custom.stderr +++ b/tests/ui/env-macro/env-not-defined-custom.stderr @@ -3,8 +3,6 @@ error: my error message | LL | fn main() { env!("__HOPEFULLY_NOT_DEFINED__", "my error message"); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/env-macro/env-not-defined-default.stderr b/tests/ui/env-macro/env-not-defined-default.stderr index efd7fdb4e53..77ba00e45c1 100644 --- a/tests/ui/env-macro/env-not-defined-default.stderr +++ b/tests/ui/env-macro/env-not-defined-default.stderr @@ -5,7 +5,6 @@ LL | env!("CARGO__HOPEFULLY_NOT_DEFINED__"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: Cargo sets build script variables at run time. Use `std::env::var("CARGO__HOPEFULLY_NOT_DEFINED__")` instead - = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/env-macro/error-recovery-issue-55897.stderr b/tests/ui/env-macro/error-recovery-issue-55897.stderr index f1cacf5420e..3d9ef56c502 100644 --- a/tests/ui/env-macro/error-recovery-issue-55897.stderr +++ b/tests/ui/env-macro/error-recovery-issue-55897.stderr @@ -5,7 +5,6 @@ LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs")); | ^^^^^^^^^^^^^^^^^^^^ | = help: use `std::env::var("NON_EXISTENT")` to read the variable at run time - = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: suffixes on string literals are invalid --> $DIR/error-recovery-issue-55897.rs:15:22 diff --git a/tests/ui/env-macro/name-whitespace-issue-110547.stderr b/tests/ui/env-macro/name-whitespace-issue-110547.stderr index 5f34904d4ae..f29c5dbf8d1 100644 --- a/tests/ui/env-macro/name-whitespace-issue-110547.stderr +++ b/tests/ui/env-macro/name-whitespace-issue-110547.stderr @@ -5,7 +5,6 @@ LL | env!{"\t"}; | ^^^^^^^^^^ | = help: use `std::env::var("\t")` to read the variable at run time - = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: environment variable `\t` not defined at compile time --> $DIR/name-whitespace-issue-110547.rs:5:5 @@ -14,7 +13,6 @@ LL | env!("\t"); | ^^^^^^^^^^ | = help: use `std::env::var("\t")` to read the variable at run time - = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: environment variable `\u{2069}` not defined at compile time --> $DIR/name-whitespace-issue-110547.rs:6:5 @@ -23,7 +21,6 @@ LL | env!("\u{2069}"); | ^^^^^^^^^^^^^^^^ | = help: use `std::env::var("\u{2069}")` to read the variable at run time - = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/error-codes/E0152-duplicate-lang-items.rs b/tests/ui/error-codes/E0152-duplicate-lang-items.rs new file mode 100644 index 00000000000..089810b1ad2 --- /dev/null +++ b/tests/ui/error-codes/E0152-duplicate-lang-items.rs @@ -0,0 +1,20 @@ +//! Validates the correct printing of E0152 in the case of duplicate "lang_item" function +//! definitions. +//! +//! Issue: <https://github.com/rust-lang/rust/issues/31788> + +//@ error-pattern: first defined in crate `std` +//@ normalize-stderr: "loaded from .*libstd-.*.rlib" -> "loaded from SYSROOT/libstd-*.rlib" +#![feature(lang_items)] + +extern crate core; + +use core::panic::PanicInfo; + +#[lang = "panic_impl"] +fn panic_impl(info: &PanicInfo) -> ! { + //~^ ERROR: found duplicate lang item `panic_impl` + loop {} +} + +fn main() {} diff --git a/tests/ui/duplicate_entry_error.stderr b/tests/ui/error-codes/E0152-duplicate-lang-items.stderr index 958e9c7527d..3c3d64322f3 100644 --- a/tests/ui/duplicate_entry_error.stderr +++ b/tests/ui/error-codes/E0152-duplicate-lang-items.stderr @@ -1,5 +1,5 @@ error[E0152]: found duplicate lang item `panic_impl` - --> $DIR/duplicate_entry_error.rs:13:1 + --> $DIR/E0152-duplicate-lang-items.rs:15:1 | LL | / fn panic_impl(info: &PanicInfo) -> ! { LL | | @@ -7,9 +7,9 @@ LL | | loop {} LL | | } | |_^ | - = note: the lang item is first defined in crate `std` (which `duplicate_entry_error` depends on) + = note: the lang item is first defined in crate `std` (which `E0152_duplicate_lang_items` depends on) = note: first definition in `std` loaded from SYSROOT/libstd-*.rlib - = note: second definition in the local crate (`duplicate_entry_error`) + = note: second definition in the local crate (`E0152_duplicate_lang_items`) error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0184.stderr b/tests/ui/error-codes/E0184.stderr index 625c6685a61..1a7df9ac095 100644 --- a/tests/ui/error-codes/E0184.stderr +++ b/tests/ui/error-codes/E0184.stderr @@ -3,8 +3,6 @@ error[E0184]: the trait `Copy` cannot be implemented for this type; the type has | LL | #[derive(Copy)] | ^^^^ `Copy` not allowed on types with destructors - | - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/duplicate-label-E0381-issue-129274.rs b/tests/ui/error-codes/E0381-duplicated-label.rs index b2156e630c8..84a85caa65d 100644 --- a/tests/ui/duplicate-label-E0381-issue-129274.rs +++ b/tests/ui/error-codes/E0381-duplicated-label.rs @@ -1,3 +1,6 @@ +//! Regression test for duplicated label in E0381 error message. +//! +//! Issue: <https://github.com/rust-lang/rust/issues/129274> fn main() { fn test() { loop { diff --git a/tests/ui/duplicate-label-E0381-issue-129274.stderr b/tests/ui/error-codes/E0381-duplicated-label.stderr index 7f8bddb17c5..36e6d966f09 100644 --- a/tests/ui/duplicate-label-E0381-issue-129274.stderr +++ b/tests/ui/error-codes/E0381-duplicated-label.stderr @@ -1,5 +1,5 @@ error[E0381]: used binding `blah` is possibly-uninitialized - --> $DIR/duplicate-label-E0381-issue-129274.rs:8:33 + --> $DIR/E0381-duplicated-label.rs:11:33 | LL | let blah: Option<String>; | ---- binding declared here but left uninitialized diff --git a/tests/ui/exclusive-drop-and-copy.stderr b/tests/ui/exclusive-drop-and-copy.stderr index 546079422a7..340ca89c396 100644 --- a/tests/ui/exclusive-drop-and-copy.stderr +++ b/tests/ui/exclusive-drop-and-copy.stderr @@ -3,16 +3,12 @@ error[E0184]: the trait `Copy` cannot be implemented for this type; the type has | LL | #[derive(Copy, Clone)] | ^^^^ `Copy` not allowed on types with destructors - | - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor --> $DIR/exclusive-drop-and-copy.rs:10:10 | LL | #[derive(Copy, Clone)] | ^^^^ `Copy` not allowed on types with destructors - | - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/explicit-tail-calls/ctfe-tail-call-panic.stderr b/tests/ui/explicit-tail-calls/ctfe-tail-call-panic.stderr index ef71722a0ab..3bdd09e9683 100644 --- a/tests/ui/explicit-tail-calls/ctfe-tail-call-panic.stderr +++ b/tests/ui/explicit-tail-calls/ctfe-tail-call-panic.stderr @@ -9,7 +9,6 @@ note: inside `g` | LL | panic!() | ^^^^^^^^ the failure occurred here - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/extern/issue-28324.stderr b/tests/ui/extern/issue-28324.stderr index 1fccb34fdf3..93eb6ff8174 100644 --- a/tests/ui/extern/issue-28324.stderr +++ b/tests/ui/extern/issue-28324.stderr @@ -2,7 +2,7 @@ error[E0080]: could not evaluate static initializer --> $DIR/issue-28324.rs:5:23 | LL | pub static BAZ: u32 = *&error_message_count; - | ^^^^^^^^^^^^^^^^^^^^^ cannot access extern static (DefId(0:4 ~ issue_28324[8ec4]::{extern#0}::error_message_count)) + | ^^^^^^^^^^^^^^^^^^^^^ cannot access extern static `error_message_count` error[E0133]: use of extern static is unsafe and requires unsafe function or block --> $DIR/issue-28324.rs:5:25 diff --git a/tests/ui/feature-gates/feature-gate-asm_goto.rs b/tests/ui/feature-gates/feature-gate-asm_goto.rs deleted file mode 100644 index beac4590349..00000000000 --- a/tests/ui/feature-gates/feature-gate-asm_goto.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ only-x86_64 - -use std::arch::asm; - -fn main() { - unsafe { - asm!("jmp {}", label {}); - //~^ ERROR label operands for inline assembly are unstable - } -} diff --git a/tests/ui/feature-gates/feature-gate-asm_goto.stderr b/tests/ui/feature-gates/feature-gate-asm_goto.stderr deleted file mode 100644 index 62fd1a320d3..00000000000 --- a/tests/ui/feature-gates/feature-gate-asm_goto.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: label operands for inline assembly are unstable - --> $DIR/feature-gate-asm_goto.rs:7:24 - | -LL | asm!("jmp {}", label {}); - | ^^^^^^^^ - | - = note: see issue #119364 <https://github.com/rust-lang/rust/issues/119364> for more information - = help: add `#![feature(asm_goto)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.rs b/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.rs index 294827f78d2..26b7d5d2fbf 100644 --- a/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.rs +++ b/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.rs @@ -1,7 +1,5 @@ //@ only-x86_64 -#![feature(asm_goto)] - use std::arch::asm; fn main() { diff --git a/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.stderr b/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.stderr index ff7a7d5760a..06e11301565 100644 --- a/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.stderr +++ b/tests/ui/feature-gates/feature-gate-asm_goto_with_outputs.stderr @@ -1,5 +1,5 @@ error[E0658]: using both label and output operands for inline assembly is unstable - --> $DIR/feature-gate-asm_goto_with_outputs.rs:10:52 + --> $DIR/feature-gate-asm_goto_with_outputs.rs:8:52 | LL | asm!("mov {}, 1", "jmp {}", out(reg) _out, label {}); | ^^^^^^^^ diff --git a/tests/ui/feature-gates/feature-gate-concat_idents2.stderr b/tests/ui/feature-gates/feature-gate-concat_idents2.stderr index 2052813ea4a..b42a1d999e4 100644 --- a/tests/ui/feature-gates/feature-gate-concat_idents2.stderr +++ b/tests/ui/feature-gates/feature-gate-concat_idents2.stderr @@ -13,8 +13,6 @@ error[E0425]: cannot find value `ab` in this scope | LL | concat_idents!(a, b); | ^^^^^^^^^^^^^^^^^^^^ not found in this scope - | - = note: this error originates in the macro `concat_idents` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.rs b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.rs new file mode 100644 index 00000000000..0d3af4c5fe0 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.rs @@ -0,0 +1,15 @@ +//@ needs-asm-support +//@ only-x86_64 + +#![feature(naked_functions)] + +use std::arch::naked_asm; + +#[naked] +#[target_feature(enable = "avx2")] +//~^ ERROR: `#[target_feature(/* ... */)]` is currently unstable on `#[naked]` functions +extern "C" fn naked() { + unsafe { naked_asm!("") } +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr new file mode 100644 index 00000000000..b0592d08046 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr @@ -0,0 +1,13 @@ +error[E0658]: `#[target_feature(/* ... */)]` is currently unstable on `#[naked]` functions + --> $DIR/feature-gate-naked_functions_target_feature.rs:9:1 + | +LL | #[target_feature(enable = "avx2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #138568 <https://github.com/rust-lang/rust/issues/138568> for more information + = help: add `#![feature(naked_functions_target_feature)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-print-check-cfg.rs b/tests/ui/feature-gates/feature-gate-print-check-cfg.rs deleted file mode 100644 index 304e0c132e5..00000000000 --- a/tests/ui/feature-gates/feature-gate-print-check-cfg.rs +++ /dev/null @@ -1,3 +0,0 @@ -//@ compile-flags: --print=check-cfg - -fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-print-check-cfg.stderr b/tests/ui/feature-gates/feature-gate-print-check-cfg.stderr deleted file mode 100644 index 62ee44b94a4..00000000000 --- a/tests/ui/feature-gates/feature-gate-print-check-cfg.stderr +++ /dev/null @@ -1,2 +0,0 @@ -error: the `-Z unstable-options` flag must also be passed to enable the check-cfg print option - diff --git a/tests/ui/fmt/format-args-capture-first-literal-is-macro.stderr b/tests/ui/fmt/format-args-capture-first-literal-is-macro.stderr index e399361579f..e9b2e83c288 100644 --- a/tests/ui/fmt/format-args-capture-first-literal-is-macro.stderr +++ b/tests/ui/fmt/format-args-capture-first-literal-is-macro.stderr @@ -24,7 +24,6 @@ LL | format!(concat!("{a}")); | = note: did you intend to capture a variable `a` from the surrounding scope? = note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro - = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/fmt/format-args-capture-from-pm-first-arg-macro.stderr b/tests/ui/fmt/format-args-capture-from-pm-first-arg-macro.stderr index 950dea721e2..e7ed2a76e6a 100644 --- a/tests/ui/fmt/format-args-capture-from-pm-first-arg-macro.stderr +++ b/tests/ui/fmt/format-args-capture-from-pm-first-arg-macro.stderr @@ -6,7 +6,6 @@ LL | format_string_proc_macro::bad_format_args_captures!(); | = note: did you intend to capture a variable `x` from the surrounding scope? = note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro - = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/fmt/format-args-capture-macro-hygiene.stderr b/tests/ui/fmt/format-args-capture-macro-hygiene.stderr index 1b5fbd2af34..47ef581629e 100644 --- a/tests/ui/fmt/format-args-capture-macro-hygiene.stderr +++ b/tests/ui/fmt/format-args-capture-macro-hygiene.stderr @@ -6,7 +6,6 @@ LL | format!(concat!("{foo}")); | = note: did you intend to capture a variable `foo` from the surrounding scope? = note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro - = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) error: there is no argument named `bar` --> $DIR/format-args-capture-macro-hygiene.rs:16:13 @@ -16,7 +15,6 @@ LL | format!(concat!("{ba", "r} {}"), 1); | = note: did you intend to capture a variable `bar` from the surrounding scope? = note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro - = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) error: there is no argument named `foo` --> $DIR/format-args-capture-macro-hygiene.rs:7:13 diff --git a/tests/ui/fmt/format-expanded-string.stderr b/tests/ui/fmt/format-expanded-string.stderr index 26ce7f26958..ab5baaf3789 100644 --- a/tests/ui/fmt/format-expanded-string.stderr +++ b/tests/ui/fmt/format-expanded-string.stderr @@ -5,7 +5,6 @@ LL | format!(concat!("abc}")); | ^^^^^^^^^^^^^^^ unmatched `}` in format string | = note: if you intended to print `}`, you can escape it using `}}` - = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid format string: unmatched `}` found --> $DIR/format-expanded-string.rs:22:34 diff --git a/tests/ui/fmt/ifmt-bad-format-args.stderr b/tests/ui/fmt/ifmt-bad-format-args.stderr index 2db280c5e2a..d458f2bc05b 100644 --- a/tests/ui/fmt/ifmt-bad-format-args.stderr +++ b/tests/ui/fmt/ifmt-bad-format-args.stderr @@ -3,8 +3,6 @@ error: requires at least a format string argument | LL | format_args!(); | ^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info) error: format argument must be a string literal --> $DIR/ifmt-bad-format-args.rs:3:18 diff --git a/tests/ui/fmt/issue-86085.stderr b/tests/ui/fmt/issue-86085.stderr index f325a3ce293..4cc19ec4365 100644 --- a/tests/ui/fmt/issue-86085.stderr +++ b/tests/ui/fmt/issue-86085.stderr @@ -5,7 +5,6 @@ LL | format ! ( concat ! ( r#"lJÆ�.�"# , "r} {}" ) ) ; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unmatched `}` in format string | = note: if you intended to print `}`, you can escape it using `}}` - = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/fmt/issue-91556.stderr b/tests/ui/fmt/issue-91556.stderr index 52917fb8c42..69f3779b93c 100644 --- a/tests/ui/fmt/issue-91556.stderr +++ b/tests/ui/fmt/issue-91556.stderr @@ -5,7 +5,6 @@ LL | let _ = format!(concat!("{0}𝖳𝖾𝗌𝗍{"), i); | ^^^^^^^^^^^^^^^^^^^ expected `}` in format string | = note: if you intended to print `{`, you can escape it using `{{` - = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/fmt/raw-idents.stderr b/tests/ui/fmt/raw-idents.stderr index 2ddc114d286..178340cf57e 100644 --- a/tests/ui/fmt/raw-idents.stderr +++ b/tests/ui/fmt/raw-idents.stderr @@ -27,7 +27,6 @@ LL | println!(concat!("{r#", "type}")); | ^^^^^^^^^^^^^^^^^^^^^^^ raw identifier used here in format string | = note: identifiers in format strings can be keywords and don't need to be prefixed with `r#` - = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid format string: raw identifiers are not supported --> $DIR/raw-idents.rs:11:16 diff --git a/tests/ui/fmt/respanned-literal-issue-106191.stderr b/tests/ui/fmt/respanned-literal-issue-106191.stderr index 17ab29e799b..5c9e538aa0c 100644 --- a/tests/ui/fmt/respanned-literal-issue-106191.stderr +++ b/tests/ui/fmt/respanned-literal-issue-106191.stderr @@ -13,7 +13,6 @@ LL | format_args!(r#concat!("¡ {")); | ^^^^^^^^^^^^^^^^^^^^^^^ expected `}` in format string | = note: if you intended to print `{`, you can escape it using `{{` - = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/fn/trait-fn-generic-mismatch.rs b/tests/ui/fn/trait-fn-generic-mismatch.rs new file mode 100644 index 00000000000..dc8222e967e --- /dev/null +++ b/tests/ui/fn/trait-fn-generic-mismatch.rs @@ -0,0 +1,12 @@ +fn retry() -> impl Sized {} + +struct Core<T>(T); + +impl Core<XXX> { //~ ERROR cannot find type `XXX` in this scope + pub fn spawn(self) {} +} + +fn main() { + let core = Core(1); + core.spawn(retry()); //~ ERROR this method takes 0 arguments but 1 argument was supplied +} diff --git a/tests/ui/fn/trait-fn-generic-mismatch.stderr b/tests/ui/fn/trait-fn-generic-mismatch.stderr new file mode 100644 index 00000000000..8384d74e225 --- /dev/null +++ b/tests/ui/fn/trait-fn-generic-mismatch.stderr @@ -0,0 +1,32 @@ +error[E0412]: cannot find type `XXX` in this scope + --> $DIR/trait-fn-generic-mismatch.rs:5:11 + | +LL | impl Core<XXX> { + | ^^^ not found in this scope + | +help: you might be missing a type parameter + | +LL | impl<XXX> Core<XXX> { + | +++++ + +error[E0061]: this method takes 0 arguments but 1 argument was supplied + --> $DIR/trait-fn-generic-mismatch.rs:11:10 + | +LL | core.spawn(retry()); + | ^^^^^ ------- unexpected argument of type `impl Sized` + | +note: method defined here + --> $DIR/trait-fn-generic-mismatch.rs:6:12 + | +LL | pub fn spawn(self) {} + | ^^^^^ +help: remove the extra argument + | +LL - core.spawn(retry()); +LL + core.spawn(); + | + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0061, E0412. +For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index 291f0ade439..231c0dd89c5 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -41,7 +41,6 @@ LL | trait Foo { ... LL | type C where Self: Clone; | ^ this trait's associated type doesn't have the requirement `Fooy<T>: Copy` - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` with trait `Copy` | LL | impl<T: std::marker::Copy> Foo for Fooy<T> { @@ -66,7 +65,6 @@ LL | trait Foo { ... LL | fn d() where Self: Clone; | ^ this trait's method doesn't have the requirement `Fooy<T>: Copy` - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` with trait `Copy` | LL | impl<T: std::marker::Copy> Foo for Fooy<T> { diff --git a/tests/ui/generic-const-items/def-site-eval.fail.stderr b/tests/ui/generic-const-items/def-site-eval.fail.stderr index 1ba4455c7be..fa07f385522 100644 --- a/tests/ui/generic-const-items/def-site-eval.fail.stderr +++ b/tests/ui/generic-const-items/def-site-eval.fail.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `_::<'_>` failed | LL | const _<'_a>: () = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/generics/post_monomorphization_error_backtrace.stderr b/tests/ui/generics/post_monomorphization_error_backtrace.stderr index 1366d5491f4..96aa04ee359 100644 --- a/tests/ui/generics/post_monomorphization_error_backtrace.stderr +++ b/tests/ui/generics/post_monomorphization_error_backtrace.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `assert_zst::F::<u32>::V` failed | LL | const V: () = assert!(std::mem::size_of::<T>() == 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation panicked: assertion failed: std::mem::size_of::<T>() == 0 - | - = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/post_monomorphization_error_backtrace.rs:14:5 @@ -23,8 +21,6 @@ error[E0080]: evaluation of `assert_zst::F::<i32>::V` failed | LL | const V: () = assert!(std::mem::size_of::<T>() == 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation panicked: assertion failed: std::mem::size_of::<T>() == 0 - | - = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/post_monomorphization_error_backtrace.rs:14:5 diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs index 2f17c0ff508..776bb7278ce 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs @@ -2,8 +2,7 @@ use std::fmt::Debug; fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { - //~^ ERROR cannot resolve opaque type - //~| WARNING elided lifetime has a name + //~^ WARNING elided lifetime has a name |x| x //~^ ERROR expected generic lifetime parameter, found `'_` } diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr index 91550f0e284..209186db4cc 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.stderr @@ -7,24 +7,14 @@ LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { = note: `#[warn(elided_named_lifetimes)]` on by default error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/impl-fn-predefined-lifetimes.rs:7:9 + --> $DIR/impl-fn-predefined-lifetimes.rs:6:9 | LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { | -- this generic parameter must be used with a generic lifetime parameter -... +LL | LL | |x| x | ^ -error[E0720]: cannot resolve opaque type - --> $DIR/impl-fn-predefined-lifetimes.rs:4:35 - | -LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { - | ^^^^^^^^^^^^^^^ recursive opaque type -... -LL | |x| x - | ----- returning here with type `{closure@$DIR/impl-fn-predefined-lifetimes.rs:7:5: 7:8}` - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 1 previous error; 1 warning emitted -Some errors have detailed explanations: E0720, E0792. -For more information about an error, try `rustc --explain E0720`. +For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/issues/issue-86800.rs b/tests/ui/impl-trait/issues/issue-86800.rs index c1176255f24..9e8ea439dde 100644 --- a/tests/ui/impl-trait/issues/issue-86800.rs +++ b/tests/ui/impl-trait/issues/issue-86800.rs @@ -40,7 +40,6 @@ impl Context { f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O>, ) -> TransactionResult<O> { //~^ ERROR expected generic lifetime parameter, found `'_` - //~| ERROR: item does not constrain let mut conn = Connection {}; let mut transaction = TestTransaction { conn: &mut conn }; f(&mut transaction).await diff --git a/tests/ui/impl-trait/issues/issue-86800.stderr b/tests/ui/impl-trait/issues/issue-86800.stderr index 11e23d97d72..80aa5d75c3c 100644 --- a/tests/ui/impl-trait/issues/issue-86800.stderr +++ b/tests/ui/impl-trait/issues/issue-86800.stderr @@ -24,26 +24,6 @@ note: this opaque type is supposed to be constrained LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: item does not constrain `TransactionFuture::{opaque#0}` - --> $DIR/issue-86800.rs:41:31 - | -LL | ) -> TransactionResult<O> { - | _______________________________^ -LL | | -LL | | -LL | | let mut conn = Connection {}; -LL | | let mut transaction = TestTransaction { conn: &mut conn }; -LL | | f(&mut transaction).await -LL | | } - | |_____^ - | - = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]` -note: this opaque type is supposed to be constrained - --> $DIR/issue-86800.rs:21:34 - | -LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0792]: expected generic lifetime parameter, found `'_` --> $DIR/issue-86800.rs:31:5 | @@ -62,13 +42,12 @@ LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionRe LL | ) -> TransactionResult<O> { | _______________________________^ LL | | -LL | | LL | | let mut conn = Connection {}; LL | | let mut transaction = TestTransaction { conn: &mut conn }; LL | | f(&mut transaction).await LL | | } | |_____^ -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/include-macros/mismatched-types.stderr b/tests/ui/include-macros/mismatched-types.stderr index 9bc0e64464e..8d541966a6a 100644 --- a/tests/ui/include-macros/mismatched-types.stderr +++ b/tests/ui/include-macros/mismatched-types.stderr @@ -11,7 +11,6 @@ LL | let b: &[u8] = include_str!("file.txt"); | = note: expected reference `&[u8]` found reference `&'static str` - = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types --> $DIR/mismatched-types.rs:3:19 @@ -23,7 +22,6 @@ LL | let s: &str = include_bytes!("file.txt"); | = note: expected reference `&str` found reference `&'static [u8; 0]` - = note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/include-macros/parent_dir.stderr b/tests/ui/include-macros/parent_dir.stderr index d0a1f4fd3b9..4ee6fe104b0 100644 --- a/tests/ui/include-macros/parent_dir.stderr +++ b/tests/ui/include-macros/parent_dir.stderr @@ -4,7 +4,6 @@ error: couldn't read `$DIR/include-macros/file.txt`: $FILE_NOT_FOUND_MSG LL | let _ = include_str!("include-macros/file.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) help: there is a file with the same name in a different directory | LL - let _ = include_str!("include-macros/file.txt"); @@ -17,7 +16,6 @@ error: couldn't read `$DIR/hello.rs`: $FILE_NOT_FOUND_MSG LL | let _ = include_str!("hello.rs"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) help: there is a file with the same name in a different directory | LL | let _ = include_str!("../hello.rs"); @@ -29,7 +27,6 @@ error: couldn't read `$DIR/../../data.bin`: $FILE_NOT_FOUND_MSG LL | let _ = include_bytes!("../../data.bin"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info) help: there is a file with the same name in a different directory | LL - let _ = include_bytes!("../../data.bin"); @@ -42,7 +39,6 @@ error: couldn't read `$DIR/tests/ui/include-macros/file.txt`: $FILE_NOT_FOUND_MS LL | let _ = include_str!("tests/ui/include-macros/file.txt"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) help: there is a file with the same name in a different directory | LL - let _ = include_str!("tests/ui/include-macros/file.txt"); diff --git a/tests/ui/inline-const/const-expr-generic-err.stderr b/tests/ui/inline-const/const-expr-generic-err.stderr index e67c0b28e02..a40e8bceb36 100644 --- a/tests/ui/inline-const/const-expr-generic-err.stderr +++ b/tests/ui/inline-const/const-expr-generic-err.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `foo::<i32>::{constant#0}` failed | LL | const { assert!(std::mem::size_of::<T>() == 0); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation panicked: assertion failed: std::mem::size_of::<T>() == 0 - | - = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/const-expr-generic-err.rs:4:5 diff --git a/tests/ui/inline-const/required-const.stderr b/tests/ui/inline-const/required-const.stderr index a6c630b5477..2f618e54ed3 100644 --- a/tests/ui/inline-const/required-const.stderr +++ b/tests/ui/inline-const/required-const.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `foo::<i32>::{constant#0}` failed | LL | const { panic!() } | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/required-const.rs:6:9 diff --git a/tests/ui/invalid-compile-flags/print.stderr b/tests/ui/invalid-compile-flags/print.stderr index df0c3977dc8..4ea06a06539 100644 --- a/tests/ui/invalid-compile-flags/print.stderr +++ b/tests/ui/invalid-compile-flags/print.stderr @@ -1,4 +1,5 @@ error: unknown print request: `yyyy` | = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models` + = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information diff --git a/tests/ui/issues/issue-14091-2.stderr b/tests/ui/issues/issue-14091-2.stderr index ac894767059..d573a0917be 100644 --- a/tests/ui/issues/issue-14091-2.stderr +++ b/tests/ui/issues/issue-14091-2.stderr @@ -11,7 +11,6 @@ LL | pub struct BytePos(pub u32); | ^^^^^^^^^^^^^^^^^^ must implement `Not` note: the trait `Not` must be implemented --> $SRC_DIR/core/src/ops/bit.rs:LL:COL - = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-21160.stderr b/tests/ui/issues/issue-21160.stderr index 892a4530ebc..f1145a0a7c1 100644 --- a/tests/ui/issues/issue-21160.stderr +++ b/tests/ui/issues/issue-21160.stderr @@ -6,7 +6,6 @@ LL | #[derive(Hash)] LL | struct Foo(Bar); | ^^^ the trait `Hash` is not implemented for `Bar` | - = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Bar` with `#[derive(Hash)]` | LL + #[derive(Hash)] diff --git a/tests/ui/issues/issue-27340.stderr b/tests/ui/issues/issue-27340.stderr index 61ae660f4cf..d5ff29a618b 100644 --- a/tests/ui/issues/issue-27340.stderr +++ b/tests/ui/issues/issue-27340.stderr @@ -6,8 +6,6 @@ LL | #[derive(Copy, Clone)] LL | LL | struct Bar(Foo); | --- this field does not implement `Copy` - | - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Foo: Clone` is not satisfied --> $DIR/issue-27340.rs:4:12 @@ -20,7 +18,6 @@ LL | struct Bar(Foo); | note: required by a bound in `AssertParamIsClone` --> $SRC_DIR/core/src/clone.rs:LL:COL - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Foo` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/issues/issue-27592.stderr b/tests/ui/issues/issue-27592.stderr index 1205a8b656b..c8649d82d74 100644 --- a/tests/ui/issues/issue-27592.stderr +++ b/tests/ui/issues/issue-27592.stderr @@ -6,16 +6,12 @@ LL | write(|| format_args!("{}", String::from("Hello world"))); | | | | | temporary value created here | returns a value referencing data owned by the current function - | - = note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0515]: cannot return reference to temporary value --> $DIR/issue-27592.rs:16:14 | LL | write(|| format_args!("{}", String::from("Hello world"))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returns a reference to data owned by the current function - | - = note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-28777.rs b/tests/ui/issues/issue-28777.rs deleted file mode 100644 index f67e11e3694..00000000000 --- a/tests/ui/issues/issue-28777.rs +++ /dev/null @@ -1,22 +0,0 @@ -//@ run-pass -#![allow(unused_braces)] -fn main() { - let v1 = { 1 + {2} * {3} }; - let v2 = 1 + {2} * {3} ; - - assert_eq!(7, v1); - assert_eq!(7, v2); - - let v3; - v3 = { 1 + {2} * {3} }; - let v4; - v4 = 1 + {2} * {3}; - assert_eq!(7, v3); - assert_eq!(7, v4); - - let v5 = { 1 + {2} * 3 }; - assert_eq!(7, v5); - - let v9 = { 1 + if 1 > 2 {1} else {2} * {3} }; - assert_eq!(7, v9); -} diff --git a/tests/ui/issues/issue-31260.rs b/tests/ui/issues/issue-31260.rs deleted file mode 100644 index 5e9fffb195c..00000000000 --- a/tests/ui/issues/issue-31260.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ check-pass -#![allow(dead_code)] -pub struct Struct<K: 'static> { - pub field: K, -} - -static STRUCT: Struct<&'static [u8]> = Struct { - field: {&[1]} -}; - -static STRUCT2: Struct<&'static [u8]> = Struct { - field: &[1] -}; - -fn main() {} diff --git a/tests/ui/issues/issue-32950.stderr b/tests/ui/issues/issue-32950.stderr index f6635d982e4..3cdf35af1d8 100644 --- a/tests/ui/issues/issue-32950.stderr +++ b/tests/ui/issues/issue-32950.stderr @@ -9,8 +9,6 @@ error[E0412]: cannot find type `FooBar` in this scope | LL | concat_idents!(Foo, Bar) | ^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope - | - = note: this error originates in the macro `concat_idents` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-34229.stderr b/tests/ui/issues/issue-34229.stderr index e6aa0d25934..2385284de0b 100644 --- a/tests/ui/issues/issue-34229.stderr +++ b/tests/ui/issues/issue-34229.stderr @@ -7,7 +7,6 @@ LL | #[derive(PartialEq, PartialOrd)] struct Nope(Comparable); | in this derive macro expansion | = help: the trait `PartialOrd` is not implemented for `Comparable` - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Comparable` with `#[derive(PartialOrd)]` | LL | #[derive(PartialEq)] #[derive(PartialOrd)] diff --git a/tests/ui/issues/issue-76191.stderr b/tests/ui/issues/issue-76191.stderr index de08fc4ed0d..ac1bdfaa847 100644 --- a/tests/ui/issues/issue-76191.stderr +++ b/tests/ui/issues/issue-76191.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of constant value failed | LL | const RANGE2: RangeInclusive<i32> = panic!(); | ^^^^^^^^ evaluation panicked: explicit panic - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types --> $DIR/issue-76191.rs:14:9 diff --git a/tests/ui/issues/issue-9382.rs b/tests/ui/issues/issue-9382.rs deleted file mode 100644 index 27f9ab57743..00000000000 --- a/tests/ui/issues/issue-9382.rs +++ /dev/null @@ -1,37 +0,0 @@ -//@ run-pass -#![allow(dead_code)] - -// Tests for a previous bug that occurred due to an interaction -// between struct field initialization and the auto-coercion -// from a vector to a slice. The drop glue was being invoked on -// the temporary slice with a wrong type, triggering an LLVM assert. - - -struct Thing1<'a> { - baz: &'a [Box<isize>], - bar: Box<u64>, -} - -struct Thing2<'a> { - baz: &'a [Box<isize>], - bar: u64, -} - -pub fn main() { - let _t1_fixed = Thing1 { - baz: &[], - bar: Box::new(32), - }; - Thing1 { - baz: &Vec::new(), - bar: Box::new(32), - }; - let _t2_fixed = Thing2 { - baz: &[], - bar: 32, - }; - Thing2 { - baz: &Vec::new(), - bar: 32, - }; -} diff --git a/tests/ui/lint/inert-attr-macro.rs b/tests/ui/lint/inert-attr-macro.rs index 90303a1fc3d..5d4133d6c77 100644 --- a/tests/ui/lint/inert-attr-macro.rs +++ b/tests/ui/lint/inert-attr-macro.rs @@ -1,5 +1,6 @@ //@ check-pass +#![feature(cfg_boolean_literals)] #![warn(unused)] macro_rules! foo { @@ -17,4 +18,10 @@ fn main() { // This does work, since the attribute is on a parent // of the macro invocation. #[allow(warnings)] { #[inline] foo!(); } + + // Ok, `cfg` and `cfg_attr` are expanded eagerly and do not warn. + #[cfg(true)] foo!(); + #[cfg(false)] foo!(); + #[cfg_attr(true, cfg(true))] foo!(); + #[cfg_attr(false, nonexistent)] foo!(); } diff --git a/tests/ui/lint/inert-attr-macro.stderr b/tests/ui/lint/inert-attr-macro.stderr index 5ccb4ffe792..b85b0319e71 100644 --- a/tests/ui/lint/inert-attr-macro.stderr +++ b/tests/ui/lint/inert-attr-macro.stderr @@ -1,41 +1,41 @@ warning: unused attribute `inline` - --> $DIR/inert-attr-macro.rs:10:5 + --> $DIR/inert-attr-macro.rs:11:5 | LL | #[inline] foo!(); | ^^^^^^^^^ | note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo` - --> $DIR/inert-attr-macro.rs:10:15 + --> $DIR/inert-attr-macro.rs:11:15 | LL | #[inline] foo!(); | ^^^ note: the lint level is defined here - --> $DIR/inert-attr-macro.rs:3:9 + --> $DIR/inert-attr-macro.rs:4:9 | LL | #![warn(unused)] | ^^^^^^ = note: `#[warn(unused_attributes)]` implied by `#[warn(unused)]` warning: unused attribute `allow` - --> $DIR/inert-attr-macro.rs:14:5 + --> $DIR/inert-attr-macro.rs:15:5 | LL | #[allow(warnings)] #[inline] foo!(); | ^^^^^^^^^^^^^^^^^^ | note: the built-in attribute `allow` will be ignored, since it's applied to the macro invocation `foo` - --> $DIR/inert-attr-macro.rs:14:34 + --> $DIR/inert-attr-macro.rs:15:34 | LL | #[allow(warnings)] #[inline] foo!(); | ^^^ warning: unused attribute `inline` - --> $DIR/inert-attr-macro.rs:14:24 + --> $DIR/inert-attr-macro.rs:15:24 | LL | #[allow(warnings)] #[inline] foo!(); | ^^^^^^^^^ | note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo` - --> $DIR/inert-attr-macro.rs:14:34 + --> $DIR/inert-attr-macro.rs:15:34 | LL | #[allow(warnings)] #[inline] foo!(); | ^^^ diff --git a/tests/ui/lint/linker-warning.stderr b/tests/ui/lint/linker-warning.stderr index 3a2c392fd03..c678562ab54 100644 --- a/tests/ui/lint/linker-warning.stderr +++ b/tests/ui/lint/linker-warning.stderr @@ -16,7 +16,7 @@ warning: unused attribute LL | #![allow(linker_messages)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | - = note: the `linker_warnings` lint can only be controlled at the root of a crate that needs to be linked + = note: the `linker_messages` lint can only be controlled at the root of a crate that needs to be linked warning: 2 warnings emitted diff --git a/tests/ui/lint/test-inner-fn.stderr b/tests/ui/lint/test-inner-fn.stderr index 7a32bc86bf7..bf476a45f77 100644 --- a/tests/ui/lint/test-inner-fn.stderr +++ b/tests/ui/lint/test-inner-fn.stderr @@ -5,15 +5,12 @@ LL | #[test] | ^^^^^^^ | = note: requested on the command line with `-D unnameable-test-items` - = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot test inner items --> $DIR/test-inner-fn.rs:13:9 | LL | #[test] | ^^^^^^^ - | - = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/loops/label-on-block-suggest-move.rs b/tests/ui/loops/label-on-block-suggest-move.rs new file mode 100644 index 00000000000..656034cd0e9 --- /dev/null +++ b/tests/ui/loops/label-on-block-suggest-move.rs @@ -0,0 +1,90 @@ +// see https://github.com/rust-lang/rust/issues/138585 +#![allow(break_with_label_and_loop)] // doesn't work locally + +fn main() { + loop 'a: {} + //~^ ERROR: block label not supported here + //~| HELP: if you meant to label the loop, move this label before the loop + while false 'a: {} + //~^ ERROR: block label not supported here + //~| HELP: if you meant to label the loop, move this label before the loop + for i in [0] 'a: {} + //~^ ERROR: block label not supported here + //~| HELP: if you meant to label the loop, move this label before the loop + 'a: loop { + // first block is parsed as the break expr's value with or without parens + while break 'a 'b: {} 'c: {} + //~^ ERROR: block label not supported here + //~| HELP: if you meant to label the loop, move this label before the loop + while break 'a ('b: {}) 'c: {} + //~^ ERROR: block label not supported here + //~| HELP: if you meant to label the loop, move this label before the loop + + // without the parens, the first block is parsed as the while-loop's body + // (see the 'no errors' section) + // #[allow(break_with_label_and_loop)] (doesn't work locally) + while (break 'a {}) 'c: {} + //~^ ERROR: block label not supported here + //~| HELP: if you meant to label the loop, move this label before the loop + } + + // do not suggest moving the label if there is already a label on the loop + 'a: loop 'b: {} + //~^ ERROR: block label not supported here + //~| HELP: remove this block label + 'a: while false 'b: {} + //~^ ERROR: block label not supported here + //~| HELP: remove this block label + 'a: for i in [0] 'b: {} + //~^ ERROR: block label not supported here + //~| HELP: remove this block label + 'a: loop { + // first block is parsed as the break expr's value with or without parens + 'd: while break 'a 'b: {} 'c: {} + //~^ ERROR: block label not supported here + //~| HELP: remove this block label + 'd: while break 'a ('b: {}) 'c: {} + //~^ ERROR: block label not supported here + //~| HELP: remove this block label + + // without the parens, the first block is parsed as the while-loop's body + // (see the 'no errors' section) + // #[allow(break_with_label_and_loop)] (doesn't work locally) + 'd: while (break 'a {}) 'c: {} + //~^ ERROR: block label not supported here + //~| HELP: remove this block label + } + + // no errors + loop { 'a: {} } + 'a: loop { 'b: {} } + while false { 'a: {} } + 'a: while false { 'b: {} } + for i in [0] { 'a: {} } + 'a: for i in [0] { 'b: {} } + 'a: {} + 'a: { 'b: {} } + 'a: loop { + // first block is parsed as the break expr's value if it is a labeled block + while break 'a 'b: {} {} + 'd: while break 'a 'b: {} {} + while break 'a ('b: {}) {} + 'd: while break 'a ('b: {}) {} + // first block is parsed as the while-loop's body if it has no label + // (the break expr is parsed as having no value), + // so the second block is a normal stmt-block, and the label is allowed + while break 'a {} 'c: {} + while break 'a {} {} + 'd: while break 'a {} 'c: {} + 'd: while break 'a {} {} + } + + // unrelated errors that should not be affected + 'a: 'b: {} + //~^ ERROR: expected `while`, `for`, `loop` or `{` after a label + //~| HELP: consider removing the label + loop { while break 'b: {} {} } + //~^ ERROR: parentheses are required around this expression to avoid confusion with a labeled break expression + //~| HELP: wrap the expression in parentheses + //~| ERROR: `break` or `continue` with no label in the condition of a `while` loop [E0590] +} diff --git a/tests/ui/loops/label-on-block-suggest-move.stderr b/tests/ui/loops/label-on-block-suggest-move.stderr new file mode 100644 index 00000000000..66866703ca6 --- /dev/null +++ b/tests/ui/loops/label-on-block-suggest-move.stderr @@ -0,0 +1,140 @@ +error: block label not supported here + --> $DIR/label-on-block-suggest-move.rs:5:10 + | +LL | loop 'a: {} + | ^^^ not supported here + | +help: if you meant to label the loop, move this label before the loop + | +LL - loop 'a: {} +LL + 'a: loop {} + | + +error: block label not supported here + --> $DIR/label-on-block-suggest-move.rs:8:17 + | +LL | while false 'a: {} + | ^^^ not supported here + | +help: if you meant to label the loop, move this label before the loop + | +LL - while false 'a: {} +LL + 'a: while false {} + | + +error: block label not supported here + --> $DIR/label-on-block-suggest-move.rs:11:18 + | +LL | for i in [0] 'a: {} + | ^^^ not supported here + | +help: if you meant to label the loop, move this label before the loop + | +LL - for i in [0] 'a: {} +LL + 'a: for i in [0] {} + | + +error: block label not supported here + --> $DIR/label-on-block-suggest-move.rs:16:31 + | +LL | while break 'a 'b: {} 'c: {} + | ^^^ not supported here + | +help: if you meant to label the loop, move this label before the loop + | +LL - while break 'a 'b: {} 'c: {} +LL + 'c: while break 'a 'b: {} {} + | + +error: block label not supported here + --> $DIR/label-on-block-suggest-move.rs:19:33 + | +LL | while break 'a ('b: {}) 'c: {} + | ^^^ not supported here + | +help: if you meant to label the loop, move this label before the loop + | +LL - while break 'a ('b: {}) 'c: {} +LL + 'c: while break 'a ('b: {}) {} + | + +error: block label not supported here + --> $DIR/label-on-block-suggest-move.rs:26:29 + | +LL | while (break 'a {}) 'c: {} + | ^^^ not supported here + | +help: if you meant to label the loop, move this label before the loop + | +LL - while (break 'a {}) 'c: {} +LL + 'c: while (break 'a {}) {} + | + +error: block label not supported here + --> $DIR/label-on-block-suggest-move.rs:32:14 + | +LL | 'a: loop 'b: {} + | ^^^ not supported here + +error: block label not supported here + --> $DIR/label-on-block-suggest-move.rs:35:21 + | +LL | 'a: while false 'b: {} + | ^^^ not supported here + +error: block label not supported here + --> $DIR/label-on-block-suggest-move.rs:38:22 + | +LL | 'a: for i in [0] 'b: {} + | ^^^ not supported here + +error: block label not supported here + --> $DIR/label-on-block-suggest-move.rs:43:35 + | +LL | 'd: while break 'a 'b: {} 'c: {} + | ^^^ not supported here + +error: block label not supported here + --> $DIR/label-on-block-suggest-move.rs:46:37 + | +LL | 'd: while break 'a ('b: {}) 'c: {} + | ^^^ not supported here + +error: block label not supported here + --> $DIR/label-on-block-suggest-move.rs:53:33 + | +LL | 'd: while (break 'a {}) 'c: {} + | ^^^ not supported here + +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/label-on-block-suggest-move.rs:83:9 + | +LL | 'a: 'b: {} + | ^^ expected `while`, `for`, `loop` or `{` after a label + | +help: consider removing the label + | +LL - 'a: 'b: {} +LL + 'b: {} + | + +error: parentheses are required around this expression to avoid confusion with a labeled break expression + --> $DIR/label-on-block-suggest-move.rs:86:24 + | +LL | loop { while break 'b: {} {} } + | ^^^^^^ + | +help: wrap the expression in parentheses + | +LL | loop { while break ('b: {}) {} } + | + + + +error[E0590]: `break` or `continue` with no label in the condition of a `while` loop + --> $DIR/label-on-block-suggest-move.rs:86:18 + | +LL | loop { while break 'b: {} {} } + | ^^^^^^^^^^^^ unlabeled `break` in the condition of a `while` loop + +error: aborting due to 15 previous errors + +For more information about this error, try `rustc --explain E0590`. diff --git a/tests/ui/macros/builtin-env-issue-114010.stderr b/tests/ui/macros/builtin-env-issue-114010.stderr index 0da42089cce..2751160e2d4 100644 --- a/tests/ui/macros/builtin-env-issue-114010.stderr +++ b/tests/ui/macros/builtin-env-issue-114010.stderr @@ -5,7 +5,6 @@ LL | env![r#"oopsie"#]; | ^^^^^^^^^^^^^^^^^ | = help: use `std::env::var(r#"oopsie"#)` to read the variable at run time - = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: environment variable `a""a` not defined at compile time --> $DIR/builtin-env-issue-114010.rs:7:1 @@ -14,7 +13,6 @@ LL | env![r#"a""a"#]; | ^^^^^^^^^^^^^^^ | = help: use `std::env::var(r#"a""a"#)` to read the variable at run time - = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/macros/cfg.stderr b/tests/ui/macros/cfg.stderr index 53326914865..ad3f9b188dd 100644 --- a/tests/ui/macros/cfg.stderr +++ b/tests/ui/macros/cfg.stderr @@ -3,8 +3,6 @@ error: macro requires a cfg-pattern as an argument | LL | cfg!(); | ^^^^^^ cfg-pattern required - | - = note: this error originates in the macro `cfg` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0565]: literal in `cfg` predicate value must be a boolean --> $DIR/cfg.rs:3:10 @@ -23,8 +21,6 @@ error: expected 1 cfg-pattern | LL | cfg!(foo, bar); | ^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `cfg` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/tests/ui/macros/duplicate-builtin.rs b/tests/ui/macros/duplicate-builtin.rs deleted file mode 100644 index c75782128f4..00000000000 --- a/tests/ui/macros/duplicate-builtin.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ compile-flags:--crate-type lib -#![feature(decl_macro)] -#![feature(rustc_attrs)] - -#[rustc_builtin_macro] -pub macro test($item:item) { -//~^ NOTE previously defined - /* compiler built-in */ -} - -mod inner { - #[rustc_builtin_macro] - pub macro test($item:item) { - //~^ ERROR attempted to define built-in macro more than once [E0773] - /* compiler built-in */ - } -} diff --git a/tests/ui/macros/duplicate-builtin.stderr b/tests/ui/macros/duplicate-builtin.stderr deleted file mode 100644 index 887a4fbbdc8..00000000000 --- a/tests/ui/macros/duplicate-builtin.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0773]: attempted to define built-in macro more than once - --> $DIR/duplicate-builtin.rs:13:5 - | -LL | / pub macro test($item:item) { -LL | | -LL | | /* compiler built-in */ -LL | | } - | |_____^ - | -note: previously defined here - --> $DIR/duplicate-builtin.rs:6:1 - | -LL | / pub macro test($item:item) { -LL | | -LL | | /* compiler built-in */ -LL | | } - | |_^ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0773`. diff --git a/tests/ui/macros/macros-nonfatal-errors.stderr b/tests/ui/macros/macros-nonfatal-errors.stderr index fd5e41986a8..44194b506a4 100644 --- a/tests/ui/macros/macros-nonfatal-errors.stderr +++ b/tests/ui/macros/macros-nonfatal-errors.stderr @@ -57,7 +57,6 @@ LL | | Bar, LL | | } | |_- this enum needs a unit variant marked with `#[default]` | - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) help: make this unit variant default by placing `#[default]` on it | LL | #[default] Foo, @@ -77,8 +76,6 @@ LL | | Foo(i32), LL | | Bar(i32), LL | | } | |_- this enum needs a unit variant marked with `#[default]` - | - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error: multiple declared defaults --> $DIR/macros-nonfatal-errors.rs:54:10 @@ -96,7 +93,6 @@ LL | Baz, | --- additional default | = note: only one variant can be default - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error: `#[default]` attribute does not accept a value --> $DIR/macros-nonfatal-errors.rs:66:5 @@ -200,7 +196,6 @@ LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: use `std::env::var("RUST_HOPEFULLY_THIS_DOESNT_EXIST")` to read the variable at run time - = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info) error: format argument must be a string literal --> $DIR/macros-nonfatal-errors.rs:114:13 @@ -230,8 +225,6 @@ error: couldn't read `$DIR/i'd be quite surprised if a file with this name exist | LL | include_str!("i'd be quite surprised if a file with this name existed"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `include_str` (in Nightly builds, run with -Z macro-backtrace for more info) error: argument must be a string literal --> $DIR/macros-nonfatal-errors.rs:120:20 @@ -244,8 +237,6 @@ error: couldn't read `$DIR/i'd be quite surprised if a file with this name exist | LL | include_bytes!("i'd be quite surprised if a file with this name existed"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info) error: trace_macros! accepts only `true` or `false` --> $DIR/macros-nonfatal-errors.rs:123:5 diff --git a/tests/ui/macros/not-utf8.stderr b/tests/ui/macros/not-utf8.stderr index be028816e0f..d466d5087d4 100644 --- a/tests/ui/macros/not-utf8.stderr +++ b/tests/ui/macros/not-utf8.stderr @@ -9,7 +9,6 @@ note: byte `193` is not valid utf-8 | LL | �|�␂!5�cc␕␂�Ӻi��WWj�ȥ�'�}�␒�J�ȉ��W�␞O�@����␜w�V���LO����␔[ ␃_�'���SQ�~ذ��ų&��- ��lN~��!@␌ _#���kQ��h�␝�:�␜␇� | ^ - = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/macros/unknown-builtin.rs b/tests/ui/macros/unknown-builtin.rs index 048f5d68d34..aa6e04d3fb8 100644 --- a/tests/ui/macros/unknown-builtin.rs +++ b/tests/ui/macros/unknown-builtin.rs @@ -1,12 +1,11 @@ -//@ error-pattern: attempted to define built-in macro more than once - #![feature(rustc_attrs)] #[rustc_builtin_macro] macro_rules! unknown { () => () } //~ ERROR cannot find a built-in macro with name `unknown` +// Defining another `line` builtin macro should not cause an error. #[rustc_builtin_macro] -macro_rules! line { () => () } //~ NOTE previously defined here +macro_rules! line { () => () } fn main() { line!(); diff --git a/tests/ui/macros/unknown-builtin.stderr b/tests/ui/macros/unknown-builtin.stderr index 22f54e04e54..1a83398891b 100644 --- a/tests/ui/macros/unknown-builtin.stderr +++ b/tests/ui/macros/unknown-builtin.stderr @@ -1,18 +1,8 @@ error: cannot find a built-in macro with name `unknown` - --> $DIR/unknown-builtin.rs:6:1 + --> $DIR/unknown-builtin.rs:4:1 | LL | macro_rules! unknown { () => () } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0773]: attempted to define built-in macro more than once - --> $SRC_DIR/core/src/macros/mod.rs:LL:COL - | -note: previously defined here - --> $DIR/unknown-builtin.rs:9:1 - | -LL | macro_rules! line { () => () } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0773`. diff --git a/tests/ui/macros/unreachable-format-args.edition_2015.stderr b/tests/ui/macros/unreachable-format-args.edition_2015.stderr index 6a133d5e406..9104848a58b 100644 --- a/tests/ui/macros/unreachable-format-args.edition_2015.stderr +++ b/tests/ui/macros/unreachable-format-args.edition_2015.stderr @@ -6,7 +6,6 @@ LL | unreachable!("x is {x} and y is {y}", y = 0); | = note: did you intend to capture a variable `x` from the surrounding scope? = note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro - = note: this error originates in the macro `$crate::concat` which comes from the expansion of the macro `unreachable` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/malformed/malformed-derive-entry.stderr b/tests/ui/malformed/malformed-derive-entry.stderr index 3059d75d718..02036e8d4c9 100644 --- a/tests/ui/malformed/malformed-derive-entry.stderr +++ b/tests/ui/malformed/malformed-derive-entry.stderr @@ -24,7 +24,6 @@ LL | #[derive(Copy(Bad))] | note: required by a bound in `Copy` --> $SRC_DIR/core/src/marker.rs:LL:COL - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Test1` with `#[derive(Clone)]` | LL + #[derive(Clone)] @@ -39,7 +38,6 @@ LL | #[derive(Copy="bad")] | note: required by a bound in `Copy` --> $SRC_DIR/core/src/marker.rs:LL:COL - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Test2` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/match/privately-uninhabited-issue-137999.rs b/tests/ui/match/privately-uninhabited-issue-137999.rs new file mode 100644 index 00000000000..918393a0c6a --- /dev/null +++ b/tests/ui/match/privately-uninhabited-issue-137999.rs @@ -0,0 +1,44 @@ +//@ edition:2024 +//@ check-fail + +mod m { + enum Void {} + + pub struct Internal { + _v: Void, + } + + pub enum Test { + A(u32, u32), + B(Internal), + } +} + +use m::Test; + +pub fn f1(x: &mut Test) { + let r1: &mut u32 = match x { + Test::A(a, _) => a, + _ => todo!(), + }; + + let r2: &mut u32 = match x { //~ ERROR cannot use `*x` because it was mutably borrowed + Test::A(_, b) => b, + _ => todo!(), + }; + + let _ = *r1; + let _ = *r2; +} + +pub fn f2(x: &mut Test) { + let r = &mut *x; + match x { //~ ERROR cannot use `*x` because it was mutably borrowed + Test::A(_, _) => {} + _ => {} + } + + let _ = r; +} + +fn main() {} diff --git a/tests/ui/match/privately-uninhabited-issue-137999.stderr b/tests/ui/match/privately-uninhabited-issue-137999.stderr new file mode 100644 index 00000000000..6f74a75375e --- /dev/null +++ b/tests/ui/match/privately-uninhabited-issue-137999.stderr @@ -0,0 +1,26 @@ +error[E0503]: cannot use `*x` because it was mutably borrowed + --> $DIR/privately-uninhabited-issue-137999.rs:25:30 + | +LL | Test::A(a, _) => a, + | - `x.0` is borrowed here +... +LL | let r2: &mut u32 = match x { + | ^ use of borrowed `x.0` +... +LL | let _ = *r1; + | --- borrow later used here + +error[E0503]: cannot use `*x` because it was mutably borrowed + --> $DIR/privately-uninhabited-issue-137999.rs:36:11 + | +LL | let r = &mut *x; + | ------- `*x` is borrowed here +LL | match x { + | ^ use of borrowed `*x` +... +LL | let _ = r; + | - borrow later used here + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0503`. diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.fixed b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.fixed index 85b1853c23b..922c883f4f7 100644 --- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.fixed +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.fixed @@ -1,16 +1,17 @@ //@ run-rustfix +//@ revisions: current next +//@[next] compile-flags: -Znext-solver #![allow(unused_variables, dead_code)] -use std::collections::BTreeMap; -use std::collections::HashSet; +use std::collections::{BTreeMap, HashSet}; -#[derive(Debug,Eq,PartialEq,Hash)] +#[derive(Debug, Eq, PartialEq, Hash)] #[derive(Clone)] enum Day { Mon, } struct Class { - days: BTreeMap<u32, HashSet<Day>> + days: BTreeMap<u32, HashSet<Day>>, } impl Class { diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.stderr b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr index 6a9d76f7998..301f3c3a458 100644 --- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.stderr +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:18:39 + --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:19:39 | LL | let mut x: HashSet<Day> = v.clone(); | ------------ ^^^^^^^^^ expected `HashSet<Day>`, found `&HashSet<Day>` @@ -9,7 +9,7 @@ LL | let mut x: HashSet<Day> = v.clone(); = note: expected struct `HashSet<_>` found reference `&HashSet<_>` note: `HashSet<Day>` does not implement `Clone`, so `&HashSet<Day>` was cloned instead - --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:18:39 + --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:19:39 | LL | let mut x: HashSet<Day> = v.clone(); | ^ diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.fixed b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.fixed new file mode 100644 index 00000000000..922c883f4f7 --- /dev/null +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.fixed @@ -0,0 +1,31 @@ +//@ run-rustfix +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +#![allow(unused_variables, dead_code)] +use std::collections::{BTreeMap, HashSet}; + +#[derive(Debug, Eq, PartialEq, Hash)] +#[derive(Clone)] +enum Day { + Mon, +} + +struct Class { + days: BTreeMap<u32, HashSet<Day>>, +} + +impl Class { + fn do_stuff(&self) { + for (_, v) in &self.days { + let mut x: HashSet<Day> = v.clone(); //~ ERROR + let y: Vec<Day> = x.drain().collect(); + println!("{:?}", x); + } + } +} + +fn fail() { + let c = Class { days: BTreeMap::new() }; + c.do_stuff(); +} +fn main() {} diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr new file mode 100644 index 00000000000..301f3c3a458 --- /dev/null +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr @@ -0,0 +1,25 @@ +error[E0308]: mismatched types + --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:19:39 + | +LL | let mut x: HashSet<Day> = v.clone(); + | ------------ ^^^^^^^^^ expected `HashSet<Day>`, found `&HashSet<Day>` + | | + | expected due to this + | + = note: expected struct `HashSet<_>` + found reference `&HashSet<_>` +note: `HashSet<Day>` does not implement `Clone`, so `&HashSet<Day>` was cloned instead + --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:19:39 + | +LL | let mut x: HashSet<Day> = v.clone(); + | ^ + = help: `Clone` is not implemented because the trait bound `Day: Clone` is not satisfied +help: consider annotating `Day` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | enum Day { + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.rs b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.rs index 740cda470d9..6f7b55be8bd 100644 --- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.rs +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.rs @@ -1,15 +1,16 @@ //@ run-rustfix +//@ revisions: current next +//@[next] compile-flags: -Znext-solver #![allow(unused_variables, dead_code)] -use std::collections::BTreeMap; -use std::collections::HashSet; +use std::collections::{BTreeMap, HashSet}; -#[derive(Debug,Eq,PartialEq,Hash)] +#[derive(Debug, Eq, PartialEq, Hash)] enum Day { Mon, } struct Class { - days: BTreeMap<u32, HashSet<Day>> + days: BTreeMap<u32, HashSet<Day>>, } impl Class { diff --git a/tests/ui/never_type/fallback-closure-wrap.fallback.stderr b/tests/ui/never_type/fallback-closure-wrap.fallback.stderr index ac99a1fc24c..afb929454c7 100644 --- a/tests/ui/never_type/fallback-closure-wrap.fallback.stderr +++ b/tests/ui/never_type/fallback-closure-wrap.fallback.stderr @@ -9,7 +9,6 @@ LL | panic!("Can't connect to server."); = note: expected unit type `()` found type `!` = note: required for the cast from `Box<{closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47}>` to `Box<dyn FnMut()>` - = note: this error originates in the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/parser/operator-precedence-braces-exprs.rs b/tests/ui/parser/operator-precedence-braces-exprs.rs new file mode 100644 index 00000000000..d6f44ef879c --- /dev/null +++ b/tests/ui/parser/operator-precedence-braces-exprs.rs @@ -0,0 +1,28 @@ +//! Regression test for ensuring that operator precedence is correctly handled in the presence of +//! braces +//! +//! Issue: <https://github.com/rust-lang/rust/issues/28777> + +//@ run-pass + +#[allow(unused_braces)] +fn main() { + let v1 = { 1 + { 2 } * { 3 } }; + let v2 = 1 + { 2 } * { 3 }; + + assert_eq!(7, v1); + assert_eq!(7, v2); + + let v3; + v3 = { 1 + { 2 } * { 3 } }; + let v4; + v4 = 1 + { 2 } * { 3 }; + assert_eq!(7, v3); + assert_eq!(7, v4); + + let v5 = { 1 + { 2 } * 3 }; + assert_eq!(7, v5); + + let v9 = { 1 + if 1 > 2 { 1 } else { 2 } * { 3 } }; + assert_eq!(7, v9); +} diff --git a/tests/ui/pattern/check-struct-pat-fields-stability-issue-138319.rs b/tests/ui/pattern/check-struct-pat-fields-stability-issue-138319.rs new file mode 100644 index 00000000000..b951c6d92ee --- /dev/null +++ b/tests/ui/pattern/check-struct-pat-fields-stability-issue-138319.rs @@ -0,0 +1,12 @@ +//@ check-pass +struct Point { + #[deprecated = "x is deprecated"] + _x: i32, + _y: i32, +} + +fn main() { + let p = Point { _x: 1, _y: 2 }; //~ WARNING use of deprecated field `Point::_x` + // Before fix, it report an warning + let Point { #[expect(deprecated)]_x, .. } = p; +} diff --git a/tests/ui/pattern/check-struct-pat-fields-stability-issue-138319.stderr b/tests/ui/pattern/check-struct-pat-fields-stability-issue-138319.stderr new file mode 100644 index 00000000000..707eb58e547 --- /dev/null +++ b/tests/ui/pattern/check-struct-pat-fields-stability-issue-138319.stderr @@ -0,0 +1,10 @@ +warning: use of deprecated field `Point::_x`: x is deprecated + --> $DIR/check-struct-pat-fields-stability-issue-138319.rs:9:21 + | +LL | let p = Point { _x: 1, _y: 2 }; + | ^^^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/print-request/stability.rs b/tests/ui/print-request/stability.rs new file mode 100644 index 00000000000..b205b055569 --- /dev/null +++ b/tests/ui/print-request/stability.rs @@ -0,0 +1,103 @@ +//! Check that we properly gate unstable print requests (`--print=KIND`) and require the user to +//! specify `-Z unstable-options` to use unstable print requests. + +// We don't care about the exact *stdout* output (i.e. what the print requests actually give back) +// for the purposes of this test. +//@ dont-check-compiler-stdout + +// We want to check for the core error message of the unstable print requests being `-Z +// unstable-options`-gated and not the help because the help can change with addition of a new print +// request, which is not important for the purposes of this test. +//@ dont-check-compiler-stderr + +// ======================= +// Unstable print requests +// ======================= + +//@ revisions: all_target_specs_json +//@[all_target_specs_json] compile-flags: --print=all-target-specs-json +//@[all_target_specs_json] error-pattern: the `-Z unstable-options` flag must also be passed + +//@ revisions: check_cfg +//@[check_cfg] compile-flags: --print=check-cfg +//@[check_cfg] error-pattern: the `-Z unstable-options` flag must also be passed + +//@ revisions: target_spec_json +//@[target_spec_json] compile-flags: --print=target-spec-json +//@[target_spec_json] error-pattern: the `-Z unstable-options` flag must also be passed + +// ======================= +// Stable print requests +// ======================= + +//@ revisions: calling_conventions +//@[calling_conventions] compile-flags: --print=calling-conventions +//@[calling_conventions] check-pass + +//@ revisions: cfg +//@[cfg] compile-flags: --print=cfg +//@[cfg] check-pass + +//@ revisions: code_models +//@[code_models] compile-flags: --print=code-models +//@[code_models] check-pass + +//@ revisions: crate_name +//@[crate_name] compile-flags: --print=crate-name +//@[crate_name] check-pass + +// Note: `--print=deployment_target` is only accepted on Apple targets. +//@ revisions: deployment_target +//@[deployment_target] only-apple +//@[deployment_target] compile-flags: --print=deployment-target +//@[deployment_target] check-pass + +//@ revisions: file_names +//@[file_names] compile-flags: --print=file-names +//@[file_names] check-pass + +//@ revisions: host_tuple +//@[host_tuple] compile-flags: --print=host-tuple +//@[host_tuple] check-pass + +//@ revisions: link_args +//@[link_args] compile-flags: --print=link-args +//@[link_args] check-pass + +//@ revisions: native_static_libs +//@[native_static_libs] compile-flags: --print=native-static-libs +//@[native_static_libs] check-pass + +//@ revisions: relocation_models +//@[relocation_models] compile-flags: --print=relocation-models +//@[relocation_models] check-pass + +//@ revisions: split_debuginfo +//@[split_debuginfo] compile-flags: --print=split-debuginfo +//@[split_debuginfo] check-pass + +//@ revisions: stack_protector_strategies +//@[stack_protector_strategies] compile-flags: --print=stack-protector-strategies +//@[stack_protector_strategies] check-pass + +//@ revisions: target_cpus +//@[target_cpus] compile-flags: --print=target-cpus +//@[target_cpus] check-pass + +//@ revisions: target_features +//@[target_features] compile-flags: --print=target-features +//@[target_features] check-pass + +//@ revisions: target_libdir +//@[target_libdir] compile-flags: --print=target-libdir +//@[target_libdir] check-pass + +//@ revisions: target_list +//@[target_list] compile-flags: --print=target-list +//@[target_list] check-pass + +//@ revisions: tls_models +//@[tls_models] compile-flags: --print=tls-models +//@[tls_models] check-pass + +fn main() {} diff --git a/tests/ui/proc-macro/cfg-attr-trace.rs b/tests/ui/proc-macro/cfg-attr-trace.rs new file mode 100644 index 00000000000..b4927f7a730 --- /dev/null +++ b/tests/ui/proc-macro/cfg-attr-trace.rs @@ -0,0 +1,17 @@ +// Ensure that `cfg_attr_trace` attributes aren't observable by proc-macros. + +//@ check-pass +//@ proc-macro: test-macros.rs + +#![feature(cfg_eval)] + +#[macro_use] +extern crate test_macros; + +#[cfg_eval] +#[test_macros::print_attr] +#[cfg_attr(FALSE, test_macros::print_attr)] +#[cfg_attr(all(), test_macros::print_attr)] +struct S; + +fn main() {} diff --git a/tests/ui/proc-macro/cfg-attr-trace.stdout b/tests/ui/proc-macro/cfg-attr-trace.stdout new file mode 100644 index 00000000000..394c3887fe7 --- /dev/null +++ b/tests/ui/proc-macro/cfg-attr-trace.stdout @@ -0,0 +1,62 @@ +PRINT-ATTR INPUT (DISPLAY): #[test_macros::print_attr] struct S; +PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[test_macros :: print_attr] struct S; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Punct { + ch: '#', + spacing: Alone, + span: #0 bytes(271..272), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "test_macros", + span: #0 bytes(289..300), + }, + Punct { + ch: ':', + spacing: Joint, + span: #0 bytes(300..301), + }, + Punct { + ch: ':', + spacing: Alone, + span: #0 bytes(301..302), + }, + Ident { + ident: "print_attr", + span: #0 bytes(302..312), + }, + ], + span: #0 bytes(272..314), + }, + Ident { + ident: "struct", + span: #0 bytes(315..321), + }, + Ident { + ident: "S", + span: #0 bytes(322..323), + }, + Punct { + ch: ';', + spacing: Alone, + span: #0 bytes(323..324), + }, +] +PRINT-ATTR INPUT (DISPLAY): struct S; +PRINT-ATTR INPUT (DEBUG): TokenStream [ + Ident { + ident: "struct", + span: #0 bytes(315..321), + }, + Ident { + ident: "S", + span: #0 bytes(322..323), + }, + Punct { + ch: ';', + spacing: Alone, + span: #0 bytes(323..324), + }, +] diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index 0fe560afcb5..c12c8d03361 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -7,7 +7,6 @@ LL | #[derive(PartialOrd, AddImpl)] = help: the trait `PartialEq` is not implemented for `PriorityQueue<T>` note: required by a bound in `PartialOrd` --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `PriorityQueue<T>: Eq` is not satisfied --> $DIR/issue-104884-trait-impl-sugg-err.rs:13:22 @@ -32,7 +31,6 @@ LL | #[derive(PartialOrd, AddImpl)] | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro note: required by a bound in `Ord` --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: this error originates in the derive macro `AddImpl` which comes from the expansion of the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `BinaryHeap<PriorityQueueEntry<T>>` with `_` --> $DIR/issue-104884-trait-impl-sugg-err.rs:20:25 @@ -44,7 +42,6 @@ LL | struct PriorityQueue<T>(BinaryHeap<PriorityQueueEntry<T>>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `BinaryHeap<PriorityQueueEntry<T>> < _` and `BinaryHeap<PriorityQueueEntry<T>> > _` | = help: the trait `PartialOrd<_>` is not implemented for `BinaryHeap<PriorityQueueEntry<T>>` - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0599]: no method named `cmp` found for struct `BinaryHeap<PriorityQueueEntry<T>>` in the current scope --> $DIR/issue-104884-trait-impl-sugg-err.rs:13:22 diff --git a/tests/ui/proc-macro/quote/not-quotable.stderr b/tests/ui/proc-macro/quote/not-quotable.stderr index e349b2dce53..62a02638e54 100644 --- a/tests/ui/proc-macro/quote/not-quotable.stderr +++ b/tests/ui/proc-macro/quote/not-quotable.stderr @@ -17,7 +17,6 @@ LL | let _ = quote! { $ip }; Rc<T> bool and 24 others - = note: this error originates in the macro `quote` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/range/range_traits-1.stderr b/tests/ui/range/range_traits-1.stderr index 617afc99530..ab1035778cd 100644 --- a/tests/ui/range/range_traits-1.stderr +++ b/tests/ui/range/range_traits-1.stderr @@ -8,7 +8,6 @@ LL | a: Range<usize>, | ^^^^^^^^^^^^^^^ no implementation for `std::ops::Range<usize> < std::ops::Range<usize>` and `std::ops::Range<usize> > std::ops::Range<usize>` | = help: the trait `PartialOrd` is not implemented for `std::ops::Range<usize>` - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `std::ops::RangeTo<usize>` with `std::ops::RangeTo<usize>` --> $DIR/range_traits-1.rs:8:5 @@ -20,7 +19,6 @@ LL | b: RangeTo<usize>, | ^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeTo<usize> < std::ops::RangeTo<usize>` and `std::ops::RangeTo<usize> > std::ops::RangeTo<usize>` | = help: the trait `PartialOrd` is not implemented for `std::ops::RangeTo<usize>` - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `std::ops::RangeFrom<usize>` with `std::ops::RangeFrom<usize>` --> $DIR/range_traits-1.rs:11:5 @@ -32,7 +30,6 @@ LL | c: RangeFrom<usize>, | ^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeFrom<usize> < std::ops::RangeFrom<usize>` and `std::ops::RangeFrom<usize> > std::ops::RangeFrom<usize>` | = help: the trait `PartialOrd` is not implemented for `std::ops::RangeFrom<usize>` - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `std::ops::RangeFull` with `std::ops::RangeFull` --> $DIR/range_traits-1.rs:14:5 @@ -44,7 +41,6 @@ LL | d: RangeFull, | ^^^^^^^^^^^^ no implementation for `std::ops::RangeFull < std::ops::RangeFull` and `std::ops::RangeFull > std::ops::RangeFull` | = help: the trait `PartialOrd` is not implemented for `std::ops::RangeFull` - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `std::ops::RangeInclusive<usize>` with `std::ops::RangeInclusive<usize>` --> $DIR/range_traits-1.rs:17:5 @@ -56,7 +52,6 @@ LL | e: RangeInclusive<usize>, | ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeInclusive<usize> < std::ops::RangeInclusive<usize>` and `std::ops::RangeInclusive<usize> > std::ops::RangeInclusive<usize>` | = help: the trait `PartialOrd` is not implemented for `std::ops::RangeInclusive<usize>` - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: can't compare `std::ops::RangeToInclusive<usize>` with `std::ops::RangeToInclusive<usize>` --> $DIR/range_traits-1.rs:20:5 @@ -68,7 +63,6 @@ LL | f: RangeToInclusive<usize>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::ops::RangeToInclusive<usize> < std::ops::RangeToInclusive<usize>` and `std::ops::RangeToInclusive<usize> > std::ops::RangeToInclusive<usize>` | = help: the trait `PartialOrd` is not implemented for `std::ops::RangeToInclusive<usize>` - = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `std::ops::Range<usize>: Ord` is not satisfied --> $DIR/range_traits-1.rs:5:5 @@ -78,8 +72,6 @@ LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] LL | struct AllTheRanges { LL | a: Range<usize>, | ^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::Range<usize>` - | - = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `std::ops::RangeTo<usize>: Ord` is not satisfied --> $DIR/range_traits-1.rs:8:5 @@ -89,8 +81,6 @@ LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] ... LL | b: RangeTo<usize>, | ^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeTo<usize>` - | - = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `std::ops::RangeFrom<usize>: Ord` is not satisfied --> $DIR/range_traits-1.rs:11:5 @@ -100,8 +90,6 @@ LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] ... LL | c: RangeFrom<usize>, | ^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeFrom<usize>` - | - = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `std::ops::RangeFull: Ord` is not satisfied --> $DIR/range_traits-1.rs:14:5 @@ -111,8 +99,6 @@ LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] ... LL | d: RangeFull, | ^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeFull` - | - = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `std::ops::RangeInclusive<usize>: Ord` is not satisfied --> $DIR/range_traits-1.rs:17:5 @@ -122,8 +108,6 @@ LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] ... LL | e: RangeInclusive<usize>, | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeInclusive<usize>` - | - = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `std::ops::RangeToInclusive<usize>: Ord` is not satisfied --> $DIR/range_traits-1.rs:20:5 @@ -133,8 +117,6 @@ LL | #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] ... LL | f: RangeToInclusive<usize>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `std::ops::RangeToInclusive<usize>` - | - = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 12 previous errors diff --git a/tests/ui/range/range_traits-2.stderr b/tests/ui/range/range_traits-2.stderr index 04778eecf56..2001c85c434 100644 --- a/tests/ui/range/range_traits-2.stderr +++ b/tests/ui/range/range_traits-2.stderr @@ -5,8 +5,6 @@ LL | #[derive(Copy, Clone)] | ^^^^ LL | struct R(Range<usize>); | ------------ this field does not implement `Copy` - | - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/range/range_traits-3.stderr b/tests/ui/range/range_traits-3.stderr index 094cc146b6c..71210379c79 100644 --- a/tests/ui/range/range_traits-3.stderr +++ b/tests/ui/range/range_traits-3.stderr @@ -5,8 +5,6 @@ LL | #[derive(Copy, Clone)] | ^^^^ LL | struct R(RangeFrom<usize>); | ---------------- this field does not implement `Copy` - | - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/range/range_traits-6.stderr b/tests/ui/range/range_traits-6.stderr index 7c66d1c749c..a58022ef7e4 100644 --- a/tests/ui/range/range_traits-6.stderr +++ b/tests/ui/range/range_traits-6.stderr @@ -5,8 +5,6 @@ LL | #[derive(Copy, Clone)] | ^^^^ LL | struct R(RangeInclusive<usize>); | --------------------- this field does not implement `Copy` - | - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/resolve/multiple_definitions_attribute_merging.stderr b/tests/ui/resolve/multiple_definitions_attribute_merging.stderr index ac6307c7a69..10ce68e506e 100644 --- a/tests/ui/resolve/multiple_definitions_attribute_merging.stderr +++ b/tests/ui/resolve/multiple_definitions_attribute_merging.stderr @@ -15,8 +15,8 @@ LL | #[derive(PartialEq)] LL | #[repr(C)] LL | struct Dealigned<T>(u8, T); | ^ - | - = + + Box<dyn Any> query stack during panic: #0 [mir_built] building MIR for `<impl at $DIR/multiple_definitions_attribute_merging.rs:15:10: 15:19>::eq` diff --git a/tests/ui/resolve/proc_macro_generated_packed.stderr b/tests/ui/resolve/proc_macro_generated_packed.stderr index 8b700595034..47de5be82dd 100644 --- a/tests/ui/resolve/proc_macro_generated_packed.stderr +++ b/tests/ui/resolve/proc_macro_generated_packed.stderr @@ -6,8 +6,8 @@ LL | #[derive(PartialEq)] ... LL | struct Dealigned<T>(u8, T); | ^ - | - = + + Box<dyn Any> query stack during panic: #0 [mir_built] building MIR for `<impl at $DIR/proc_macro_generated_packed.rs:15:10: 15:19>::eq` diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr index 0a703367d96..b89c5e8dda8 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr @@ -9,7 +9,6 @@ LL | fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> { = note: required for `Result<f32, ParseFloatError>` to implement `Termination` note: required by a bound in `assert_test_result` --> $SRC_DIR/test/src/lib.rs:LL:COL - = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr b/tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr index f2942820e28..75718c94b19 100644 --- a/tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr +++ b/tests/ui/rust-2021/ice-return-unsized-can-impl-2.stderr @@ -4,7 +4,7 @@ error[E0782]: expected a type, found a trait LL | fn concrete(b: B) -> B; | ^ | - = note: `B` it is dyn-incompatible, so it can't be `dyn` + = note: `B` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `B` | LL - fn concrete(b: B) -> B; @@ -32,7 +32,7 @@ error[E0782]: expected a type, found a trait LL | fn f(a: A) -> A; | ^ | - = note: `A` it is dyn-incompatible, so it can't be `dyn` + = note: `A` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `A` | LL - fn f(a: A) -> A; diff --git a/tests/ui/rust-2021/ice-return-unsized-can-impl.stderr b/tests/ui/rust-2021/ice-return-unsized-can-impl.stderr index cfee506e29b..284232cf4f4 100644 --- a/tests/ui/rust-2021/ice-return-unsized-can-impl.stderr +++ b/tests/ui/rust-2021/ice-return-unsized-can-impl.stderr @@ -4,7 +4,7 @@ error[E0782]: expected a type, found a trait LL | fn g(new: B) -> B; | ^ | - = note: `B` it is dyn-incompatible, so it can't be `dyn` + = note: `B` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `B` | LL - fn g(new: B) -> B; diff --git a/tests/ui/rust-2021/ice-unsized-fn-params-2.stderr b/tests/ui/rust-2021/ice-unsized-fn-params-2.stderr index 7f837bbe50f..630bbc2b905 100644 --- a/tests/ui/rust-2021/ice-unsized-fn-params-2.stderr +++ b/tests/ui/rust-2021/ice-unsized-fn-params-2.stderr @@ -4,7 +4,7 @@ error[E0782]: expected a type, found a trait LL | fn guard(_s: Copy) -> bool { | ^^^^ | - = note: `Copy` it is dyn-incompatible, so it can't be `dyn` + = note: `Copy` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `Copy` | LL - fn guard(_s: Copy) -> bool { diff --git a/tests/ui/rust-2021/ice-unsized-fn-params.stderr b/tests/ui/rust-2021/ice-unsized-fn-params.stderr index 4d900711ed6..57708031d6b 100644 --- a/tests/ui/rust-2021/ice-unsized-fn-params.stderr +++ b/tests/ui/rust-2021/ice-unsized-fn-params.stderr @@ -4,7 +4,7 @@ error[E0782]: expected a type, found a trait LL | fn g(b: B) -> B; | ^ | - = note: `B` it is dyn-incompatible, so it can't be `dyn` + = note: `B` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `B` | LL - fn g(b: B) -> B; @@ -32,7 +32,7 @@ error[E0782]: expected a type, found a trait LL | fn f(a: A) -> A; | ^ | - = note: `A` it is dyn-incompatible, so it can't be `dyn` + = note: `A` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `A` | LL - fn f(a: A) -> A; diff --git a/tests/ui/rustc-print-info-issue-138612.rs b/tests/ui/rustc-print-info-issue-138612.rs new file mode 100644 index 00000000000..65b595635b1 --- /dev/null +++ b/tests/ui/rustc-print-info-issue-138612.rs @@ -0,0 +1,2 @@ +//@ check-fail +//@ compile-flags: /dev/null --print lints diff --git a/tests/ui/rustc-print-info-issue-138612.stderr b/tests/ui/rustc-print-info-issue-138612.stderr new file mode 100644 index 00000000000..4f7ed821952 --- /dev/null +++ b/tests/ui/rustc-print-info-issue-138612.stderr @@ -0,0 +1,6 @@ +error: unknown print request: `lints` + | + = help: valid print requests are: `all-target-specs-json`, `calling-conventions`, `cfg`, `check-cfg`, `code-models`, `crate-name`, `deployment-target`, `file-names`, `host-tuple`, `link-args`, `native-static-libs`, `relocation-models`, `split-debuginfo`, `stack-protector-strategies`, `sysroot`, `target-cpus`, `target-features`, `target-libdir`, `target-list`, `target-spec-json`, `tls-models` + = help: use `-Whelp` to print a list of lints + = help: for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information + diff --git a/tests/ui/rustdoc/doc-alias-use-item-list-stem.rs b/tests/ui/rustdoc/doc-alias-use-item-list-stem.rs new file mode 100644 index 00000000000..ef310843e21 --- /dev/null +++ b/tests/ui/rustdoc/doc-alias-use-item-list-stem.rs @@ -0,0 +1,11 @@ +// Check that we don't ICE on `#[doc(alias)]`es placed on use items with list stems. +// issue: <https://github.com/rust-lang/rust/issues/138723> +//@ check-pass + +#[doc(alias = "empty")] +pub use {}; + +#[doc(alias = "id")] +pub use {std::convert::identity}; + +fn main() {} diff --git a/tests/ui/simd/array-trait.stderr b/tests/ui/simd/array-trait.stderr index 2d2a11f25ad..299f0ad96ae 100644 --- a/tests/ui/simd/array-trait.stderr +++ b/tests/ui/simd/array-trait.stderr @@ -22,8 +22,6 @@ LL | #[derive(Copy, Clone)] | ----- in this derive macro expansion LL | pub struct T<S: Simd>([S::Lane; S::SIZE]); | ^^^^^^^^^^^^^^^^^^ - | - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/simd/const-err-trumps-simd-err.stderr b/tests/ui/simd/const-err-trumps-simd-err.stderr index e88c277885e..a0f1c664a4f 100644 --- a/tests/ui/simd/const-err-trumps-simd-err.stderr +++ b/tests/ui/simd/const-err-trumps-simd-err.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of `get_elem::<4>::{constant#0}` failed | LL | const { assert!(LANE < 4); } // the error should be here... | ^^^^^^^^^^^^^^^^^ evaluation panicked: assertion failed: LANE < 4 - | - = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) note: erroneous constant encountered --> $DIR/const-err-trumps-simd-err.rs:16:5 diff --git a/tests/ui/span/E0204.stderr b/tests/ui/span/E0204.stderr index 3a0afb541ba..fe375b94781 100644 --- a/tests/ui/span/E0204.stderr +++ b/tests/ui/span/E0204.stderr @@ -15,8 +15,6 @@ LL | #[derive(Copy)] LL | struct Foo2<'a> { LL | ty: &'a mut bool, | ---------------- this field does not implement `Copy` - | - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/E0204.rs:17:15 @@ -35,8 +33,6 @@ LL | #[derive(Copy)] LL | enum EFoo2<'a> { LL | Bar(&'a mut bool), | ------------ this field does not implement `Copy` - | - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/tests/ui/stability-attribute/check-stability-issue-138319.rs b/tests/ui/stability-attribute/check-stability-issue-138319.rs new file mode 100644 index 00000000000..5440e0cad94 --- /dev/null +++ b/tests/ui/stability-attribute/check-stability-issue-138319.rs @@ -0,0 +1,39 @@ +//@ check-pass +fn _foo() { + _Bar { //~ WARNING use of deprecated struct `_Bar`: reason + #[expect(deprecated)] + foo: 0, + }; +} + +#[deprecated = "reason"] +struct _Bar { + foo: u32, +} + +fn _foo2() { + #[expect(deprecated)] + _Bar2 { + foo2: 0, + }; +} + +#[deprecated = "reason"] +struct _Bar2 { + foo2: u32, +} + +fn _foo3() { + _Bar3 { + #[expect(deprecated)] + foo3: 0, + }; +} + +struct _Bar3 { + #[deprecated = "reason"] + foo3: u32, +} + + +fn main() {} diff --git a/tests/ui/stability-attribute/check-stability-issue-138319.stderr b/tests/ui/stability-attribute/check-stability-issue-138319.stderr new file mode 100644 index 00000000000..4a2c3554a1e --- /dev/null +++ b/tests/ui/stability-attribute/check-stability-issue-138319.stderr @@ -0,0 +1,10 @@ +warning: use of deprecated struct `_Bar`: reason + --> $DIR/check-stability-issue-138319.rs:3:5 + | +LL | _Bar { + | ^^^^ + | + = note: `#[warn(deprecated)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/statics/issue-14227.stderr b/tests/ui/statics/issue-14227.stderr index 0aeb973bff3..3551821a3da 100644 --- a/tests/ui/statics/issue-14227.stderr +++ b/tests/ui/statics/issue-14227.stderr @@ -2,7 +2,7 @@ error[E0080]: could not evaluate static initializer --> $DIR/issue-14227.rs:4:21 | LL | static CRASH: u32 = symbol; - | ^^^^^^ cannot access extern static (DefId(0:4 ~ issue_14227[1133]::{extern#0}::symbol)) + | ^^^^^^ cannot access extern static `symbol` error[E0133]: use of extern static is unsafe and requires unsafe function or block --> $DIR/issue-14227.rs:4:21 diff --git a/tests/ui/structs/default-field-values/failures.stderr b/tests/ui/structs/default-field-values/failures.stderr index 50553816462..58f7baee4b2 100644 --- a/tests/ui/structs/default-field-values/failures.stderr +++ b/tests/ui/structs/default-field-values/failures.stderr @@ -21,7 +21,6 @@ LL | pub struct Bar { LL | pub bar: S, | ^^^^^^^^^^ the trait `Default` is not implemented for `S` | - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `S` with `#[derive(Default)]` | LL + #[derive(Default)] diff --git a/tests/ui/structs/default-field-values/invalid-const.stderr b/tests/ui/structs/default-field-values/invalid-const.stderr index 56d20d8d711..030bdbfcc3e 100644 --- a/tests/ui/structs/default-field-values/invalid-const.stderr +++ b/tests/ui/structs/default-field-values/invalid-const.stderr @@ -3,8 +3,6 @@ error[E0080]: evaluation of constant value failed | LL | pub bax: u8 = panic!("asdf"), | ^^^^^^^^^^^^^^ evaluation panicked: asdf - | - = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of `Baz::<C>::bat::{constant#0}` failed --> $DIR/invalid-const.rs:11:19 diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr index eae0b0ae817..eb0355853da 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.stderr +++ b/tests/ui/suggestions/derive-clone-for-eq.stderr @@ -13,7 +13,6 @@ LL | impl<T: Clone, U> PartialEq<U> for Struct<T> | unsatisfied trait bound introduced here note: required by a bound in `Eq` --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` with trait `Clone` | LL | pub struct Struct<T: std::clone::Clone>(T); diff --git a/tests/ui/suggestions/derive-macro-missing-bounds.stderr b/tests/ui/suggestions/derive-macro-missing-bounds.stderr index 37a5f4932ff..68c8204d1e1 100644 --- a/tests/ui/suggestions/derive-macro-missing-bounds.stderr +++ b/tests/ui/suggestions/derive-macro-missing-bounds.stderr @@ -8,7 +8,6 @@ LL | struct Outer<T>(Inner<T>); | = help: the trait `Debug` is not implemented for `a::Inner<T>` = note: add `#[derive(Debug)]` to `a::Inner<T>` or manually `impl Debug for a::Inner<T>` - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `a::Inner<T>` with `#[derive(Debug)]` | LL + #[derive(Debug)] @@ -37,7 +36,6 @@ LL | impl<T: Debug + Trait> Debug for Inner<T> { = note: 1 redundant requirement hidden = note: required for `&c::Inner<T>` to implement `Debug` = note: required for the cast from `&&c::Inner<T>` to `&dyn Debug` - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` with trait `Trait` | LL | struct Outer<T: c::Trait>(Inner<T>); @@ -59,7 +57,6 @@ LL | impl<T> Debug for Inner<T> where T: Debug, T: Trait { = note: 1 redundant requirement hidden = note: required for `&d::Inner<T>` to implement `Debug` = note: required for the cast from `&&d::Inner<T>` to `&dyn Debug` - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` with trait `Trait` | LL | struct Outer<T: d::Trait>(Inner<T>); @@ -81,7 +78,6 @@ LL | impl<T> Debug for Inner<T> where T: Debug + Trait { = note: 1 redundant requirement hidden = note: required for `&e::Inner<T>` to implement `Debug` = note: required for the cast from `&&e::Inner<T>` to `&dyn Debug` - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` with trait `Trait` | LL | struct Outer<T: e::Trait>(Inner<T>); @@ -103,7 +99,6 @@ LL | impl<T: Debug> Debug for Inner<T> where T: Trait { = note: 1 redundant requirement hidden = note: required for `&f::Inner<T>` to implement `Debug` = note: required for the cast from `&&f::Inner<T>` to `&dyn Debug` - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` with trait `Trait` | LL | struct Outer<T: f::Trait>(Inner<T>); diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr index 20aa227d10f..7b0fd979991 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021-without-dyn.stderr @@ -4,7 +4,7 @@ error[E0782]: expected a type, found a trait LL | fn f(a: A) -> A; | ^ | - = note: `A` it is dyn-incompatible, so it can't be `dyn` + = note: `A` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `A` | LL - fn f(a: A) -> A; @@ -32,7 +32,7 @@ error[E0782]: expected a type, found a trait LL | fn f(b: B) -> B; | ^ | - = note: `B` it is dyn-incompatible, so it can't be `dyn` + = note: `B` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `B` | LL - fn f(b: B) -> B; @@ -60,7 +60,7 @@ error[E0782]: expected a type, found a trait LL | fn f(&self, c: C) -> C; | ^ | - = note: `C` it is dyn-incompatible, so it can't be `dyn` + = note: `C` is dyn-incompatible, otherwise a trait object could be used help: use a new generic type parameter, constrained by `C` | LL - fn f(&self, c: C) -> C; diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr index 4408fe0a0a4..a48dd30d008 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -31,7 +31,6 @@ LL | #[derive(Debug, Copy, Clone)] LL | pub struct Vector2<T: Debug + Copy + Clone> { | ---- unsatisfied trait bound introduced in this `derive` macro = note: required for the cast from `&Vector2<K>` to `&dyn Debug` - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting type parameter `K` with trait `Copy` | LL | pub struct AABB<K: Debug + std::marker::Copy> { @@ -51,7 +50,6 @@ note: required by a bound in `Vector2` | LL | pub struct Vector2<T: Debug + Copy + Clone> { | ^^^^ required by this bound in `Vector2` - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting type parameter `K` with trait `Copy` | LL | pub struct AABB<K: Debug + std::marker::Copy> { @@ -73,7 +71,6 @@ LL | #[derive(Debug, Copy, Clone)] | ^^^^^ LL | pub struct Vector2<T: Debug + Copy + Clone> { | ---- unsatisfied trait bound introduced in this `derive` macro - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting type parameter `K` with trait `Copy` | LL | pub struct AABB<K: Debug + std::marker::Copy> { diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr index 1bbf6f66ab2..3f8b6f93e1f 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr @@ -12,7 +12,6 @@ note: the `Copy` impl for `Vector2<K>` requires that `K: Debug` | LL | pub loc: Vector2<K>, | ^^^^^^^^^^ - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting type parameter `K` with trait `Debug` | LL | pub struct AABB<K: Copy + Debug>{ @@ -43,7 +42,6 @@ LL | pub struct AABB<K: Copy>{ LL | pub loc: Vector2<K>, | ^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting type parameter `K` with trait `Debug` | LL | pub struct AABB<K: Copy + std::fmt::Debug>{ @@ -58,7 +56,6 @@ LL | #[derive(Debug, Copy, Clone)] LL | pub size: Vector2<K> | ^^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider further restricting type parameter `K` with trait `Debug` | LL | pub struct AABB<K: Copy + std::fmt::Debug>{ diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 8b5cced4c4a..3766e3e2c7b 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -12,7 +12,6 @@ note: the `Copy` impl for `Vector2<K>` requires that `K: Debug` | LL | pub loc: Vector2<K>, | ^^^^^^^^^^ - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `K` with trait `Debug` | LL | pub struct AABB<K: Debug> { @@ -67,7 +66,6 @@ LL | #[derive(Debug, Copy, Clone)] LL | pub struct Vector2<T: Debug + Copy + Clone> { | ---- unsatisfied trait bound introduced in this `derive` macro = note: required for the cast from `&Vector2<K>` to `&dyn Debug` - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `K` with trait `Copy` | LL | pub struct AABB<K: std::marker::Copy> { @@ -82,7 +80,6 @@ LL | pub struct AABB<K> { LL | pub loc: Vector2<K>, | ^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `K` with trait `Debug` | LL | pub struct AABB<K: std::fmt::Debug> { @@ -102,7 +99,6 @@ note: required by a bound in `Vector2` | LL | pub struct Vector2<T: Debug + Copy + Clone> { | ^^^^ required by this bound in `Vector2` - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `K` with trait `Copy` | LL | pub struct AABB<K: std::marker::Copy> { @@ -117,7 +113,6 @@ LL | #[derive(Debug, Copy, Clone)] LL | pub size: Vector2<K>, | ^^^^^^^^^^^^^^^^^^^^ `K` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `K` with trait `Debug` | LL | pub struct AABB<K: std::fmt::Debug> { @@ -139,7 +134,6 @@ LL | #[derive(Debug, Copy, Clone)] | ^^^^^ LL | pub struct Vector2<T: Debug + Copy + Clone> { | ---- unsatisfied trait bound introduced in this `derive` macro - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `K` with trait `Copy` | LL | pub struct AABB<K: std::marker::Copy> { diff --git a/tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.rs b/tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.rs new file mode 100644 index 00000000000..b7086325d5f --- /dev/null +++ b/tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.rs @@ -0,0 +1,17 @@ +// Verify that the `where` clause suggestion is in the correct place +// Previously, the suggestion to add `where` clause was placed inside the derive +// like `#[derive(Clone where Inner<T>: Clone)]` +// instead of `struct Outer<T>(Inner<T>) where Inner<T>: Clone` + +#![crate_type = "lib"] + +struct Inner<T>(T); +//~^ HELP consider annotating `Inner<T>` with `#[derive(Clone)]` +impl Clone for Inner<()> { + fn clone(&self) -> Self { todo!() } +} + +#[derive(Clone)] +struct Outer<T>(Inner<T>); +//~^ ERROR the trait bound `Inner<T>: Clone` is not satisfied [E0277] +//~| HELP consider introducing a `where` clause diff --git a/tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.stderr b/tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.stderr new file mode 100644 index 00000000000..577b090ce1b --- /dev/null +++ b/tests/ui/suggestions/tuple-struct-where-clause-suggestion-91520.stderr @@ -0,0 +1,21 @@ +error[E0277]: the trait bound `Inner<T>: Clone` is not satisfied + --> $DIR/tuple-struct-where-clause-suggestion-91520.rs:15:17 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct Outer<T>(Inner<T>); + | ^^^^^^^^ the trait `Clone` is not implemented for `Inner<T>` + | +help: consider annotating `Inner<T>` with `#[derive(Clone)]` + | +LL + #[derive(Clone)] +LL | struct Inner<T>(T); + | +help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement + | +LL | struct Outer<T>(Inner<T>) where Inner<T>: Clone; + | +++++++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/test-attrs/custom-test-frameworks/issue-107454.stderr b/tests/ui/test-attrs/custom-test-frameworks/issue-107454.stderr index 6ac79924d80..1b1a59ec582 100644 --- a/tests/ui/test-attrs/custom-test-frameworks/issue-107454.stderr +++ b/tests/ui/test-attrs/custom-test-frameworks/issue-107454.stderr @@ -9,7 +9,6 @@ note: the lint level is defined here | LL | #![deny(unnameable_test_items)] | ^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the attribute macro `test_case` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/test-attrs/issue-12997-2.stderr b/tests/ui/test-attrs/issue-12997-2.stderr index bc84ff413df..1123630a4a1 100644 --- a/tests/ui/test-attrs/issue-12997-2.stderr +++ b/tests/ui/test-attrs/issue-12997-2.stderr @@ -14,7 +14,6 @@ note: function defined here | LL | fn bar(x: isize) { } | ^^^ -------- - = note: this error originates in the attribute macro `bench` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/test-attrs/test-function-signature.stderr b/tests/ui/test-attrs/test-function-signature.stderr index abdb30dc931..c025163c0bd 100644 --- a/tests/ui/test-attrs/test-function-signature.stderr +++ b/tests/ui/test-attrs/test-function-signature.stderr @@ -32,7 +32,6 @@ LL | fn bar() -> i32 { | note: required by a bound in `assert_test_result` --> $SRC_DIR/test/src/lib.rs:LL:COL - = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 5 previous errors diff --git a/tests/ui/tool-attributes/crate-attr.rs b/tests/ui/tool-attributes/crate-attr.rs new file mode 100644 index 00000000000..c6d7974945f --- /dev/null +++ b/tests/ui/tool-attributes/crate-attr.rs @@ -0,0 +1,5 @@ +//@ check-pass +//@ compile-flags: -Z crate-attr=feature(register_tool) -Z crate-attr=register_tool(foo) + +#[allow(foo::bar)] +fn main() {} diff --git a/tests/ui/tool-attributes/multiple-registered.rs b/tests/ui/tool-attributes/multiple-registered.rs new file mode 100644 index 00000000000..4d54c2dcb08 --- /dev/null +++ b/tests/ui/tool-attributes/multiple-registered.rs @@ -0,0 +1,7 @@ +//@ check-pass + +#![feature(register_tool)] +#![register_tool(foo, bar, baz)] + +#[allow(foo::a, bar::b, baz::c)] +fn main() {} diff --git a/tests/ui/tool-attributes/nested-disallowed.rs b/tests/ui/tool-attributes/nested-disallowed.rs new file mode 100644 index 00000000000..8e780427761 --- /dev/null +++ b/tests/ui/tool-attributes/nested-disallowed.rs @@ -0,0 +1,4 @@ +#![feature(register_tool)] +#![register_tool(foo::bar)] //~ ERROR only accepts identifiers + +fn main() {} diff --git a/tests/ui/tool-attributes/nested-disallowed.stderr b/tests/ui/tool-attributes/nested-disallowed.stderr new file mode 100644 index 00000000000..1af73fc2f19 --- /dev/null +++ b/tests/ui/tool-attributes/nested-disallowed.stderr @@ -0,0 +1,8 @@ +error: `register_tool` only accepts identifiers + --> $DIR/nested-disallowed.rs:2:18 + | +LL | #![register_tool(foo::bar)] + | ^^^^^^^^ not an identifier + +error: aborting due to 1 previous error + diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr index fae871a4c85..202210a2e65 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr +++ b/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr @@ -15,7 +15,6 @@ LL | #[derive_const(Default)] | = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr index 64564de2a0c..27f4bcf46ef 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr +++ b/tests/ui/traits/const-traits/const_derives/derive-const-non-const-type.stderr @@ -6,7 +6,6 @@ LL | #[derive_const(Default)] | = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0015]: cannot call non-const associated function `<A as Default>::default` in constant functions --> $DIR/derive-const-non-const-type.rs:11:14 @@ -17,7 +16,6 @@ LL | pub struct S(A); | ^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr index 9ad3b0c1617..8297911a3f3 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr +++ b/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr @@ -27,7 +27,6 @@ LL | #[derive_const(Default, PartialEq)] | = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` --> $DIR/derive-const-use.rs:11:12 @@ -46,7 +45,6 @@ LL | #[derive_const(Default, PartialEq)] | = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0015]: cannot call non-const associated function `<S as Default>::default` in constants --> $DIR/derive-const-use.rs:18:35 @@ -73,7 +71,6 @@ LL | pub struct S((), A); | ^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0015]: cannot call non-const associated function `<A as Default>::default` in constant functions --> $DIR/derive-const-use.rs:16:18 @@ -84,7 +81,6 @@ LL | pub struct S((), A); | ^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0015]: cannot call non-const operator in constant functions --> $DIR/derive-const-use.rs:16:14 @@ -95,7 +91,6 @@ LL | pub struct S((), A); | ^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0015]: cannot call non-const operator in constant functions --> $DIR/derive-const-use.rs:16:18 @@ -106,7 +101,6 @@ LL | pub struct S((), A); | ^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 12 previous errors diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr index 6b1405712ef..d1dbf62d566 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr +++ b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr @@ -6,7 +6,6 @@ LL | #[derive_const(PartialEq)] | = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error: `~const` can only be applied to `#[const_trait]` traits | @@ -22,7 +21,6 @@ LL | pub struct Reverse<T>(T); | ^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0015]: cannot call non-const operator in constant functions --> $DIR/derive-const-with-params.rs:11:5 diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr index 3e0d6d88086..815787c3bfe 100644 --- a/tests/ui/traits/issue-106072.stderr +++ b/tests/ui/traits/issue-106072.stderr @@ -13,8 +13,6 @@ error[E0782]: expected a type, found a trait | LL | #[derive(Clone)] | ^^^^^ - | - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0782]: expected a type, found a trait --> $DIR/issue-106072.rs:1:10 @@ -23,7 +21,6 @@ LL | #[derive(Clone)] | ^^^^^ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/traits/issue-50480.stderr b/tests/ui/traits/issue-50480.stderr index d3c11238ede..ed8c74e9bdd 100644 --- a/tests/ui/traits/issue-50480.stderr +++ b/tests/ui/traits/issue-50480.stderr @@ -79,8 +79,6 @@ LL | struct Foo(N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); | -------- ------ this field does not implement `Copy` | | | this field does not implement `Copy` - | - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0204]: the trait `Copy` cannot be implemented for this type --> $DIR/issue-50480.rs:11:17 @@ -92,8 +90,6 @@ LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); | -------- ------ this field does not implement `Copy` | | | this field does not implement `Copy` - | - = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `i32` is not an iterator --> $DIR/issue-50480.rs:14:33 @@ -118,7 +114,6 @@ LL | #[derive(Clone, Copy)] | ^^^^^ `i32` is not an iterator | = help: the trait `Iterator` is not implemented for `i32` - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `i32` is not an iterator --> $DIR/issue-50480.rs:14:33 @@ -130,7 +125,6 @@ LL | struct Bar<T>(T, N, NotDefined, <i32 as Iterator>::Item, Vec<i32>, String); | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator | = help: the trait `Iterator` is not implemented for `i32` - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 13 previous errors diff --git a/tests/ui/traits/issue-71136.stderr b/tests/ui/traits/issue-71136.stderr index 2c03c6bf08e..cd891c88c9f 100644 --- a/tests/ui/traits/issue-71136.stderr +++ b/tests/ui/traits/issue-71136.stderr @@ -8,7 +8,6 @@ LL | the_foos: Vec<Foo>, | ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Foo` | = note: required for `Vec<Foo>` to implement `Clone` - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `Foo` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/traits/issue-79458.stderr b/tests/ui/traits/issue-79458.stderr index c80efbe9287..9e53ec8cc90 100644 --- a/tests/ui/traits/issue-79458.stderr +++ b/tests/ui/traits/issue-79458.stderr @@ -9,7 +9,6 @@ LL | bar: &'a mut T | = help: the trait `Clone` is implemented for `&T` = note: `Clone` is implemented for `&T`, but not for `&mut T` - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr index da269bbeae4..290b1df1665 100644 --- a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr +++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr @@ -13,7 +13,6 @@ LL | impl<T: Clone, U> PartialEq<U> for Struct<T> | unsatisfied trait bound introduced here note: required by a bound in `Eq` --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` with trait `Clone` | LL | pub struct Struct<T: std::clone::Clone>(T); diff --git a/tests/ui/transmutability/uninhabited.stderr b/tests/ui/transmutability/uninhabited.stderr index 39f8bf19c36..4c5c4107a85 100644 --- a/tests/ui/transmutability/uninhabited.stderr +++ b/tests/ui/transmutability/uninhabited.stderr @@ -3,24 +3,18 @@ error[E0080]: evaluation of constant value failed | LL | assert!(false); | ^^^^^^^^^^^^^^ evaluation panicked: assertion failed: false - | - = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/uninhabited.rs:63:9 | LL | assert!(false); | ^^^^^^^^^^^^^^ evaluation panicked: assertion failed: false - | - = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0080]: evaluation of constant value failed --> $DIR/uninhabited.rs:87:9 | LL | assert!(false); | ^^^^^^^^^^^^^^ evaluation panicked: assertion failed: false - | - = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `()` cannot be safely transmuted into `void::Void` --> $DIR/uninhabited.rs:29:41 diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr index ba97bbf89f8..241eccc5f2b 100644 --- a/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr +++ b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr @@ -19,22 +19,5 @@ note: this opaque type is supposed to be constrained LL | type Bar = impl std::fmt::Display; | ^^^^^^^^^^^^^^^^^^^^^^ -error: item does not constrain `Bar::{opaque#0}` - --> $DIR/const_generic_type.rs:8:31 - | -LL | async fn test<const N: Bar>() { - | _______________________________^ -... | -LL | | let x: u32 = N; -LL | | } - | |_^ - | - = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]` -note: this opaque type is supposed to be constrained - --> $DIR/const_generic_type.rs:5:12 - | -LL | type Bar = impl std::fmt::Display; - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.rs b/tests/ui/type-alias-impl-trait/const_generic_type.rs index 5b093be9231..9b38f1449f8 100644 --- a/tests/ui/type-alias-impl-trait/const_generic_type.rs +++ b/tests/ui/type-alias-impl-trait/const_generic_type.rs @@ -8,7 +8,6 @@ type Bar = impl std::fmt::Display; async fn test<const N: Bar>() { //~^ ERROR: `Bar` is forbidden as the type of a const generic parameter //[no_infer]~^^ ERROR item does not constrain - //[no_infer]~| ERROR item does not constrain #[cfg(infer)] let x: u32 = N; } diff --git a/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.rs b/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.rs new file mode 100644 index 00000000000..a2de3957c0b --- /dev/null +++ b/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.rs @@ -0,0 +1,18 @@ +// We previously didn't taint the borrowck result in this test, +// causing an ICE later on. +#![feature(type_alias_impl_trait)] +trait T {} + +type Alias<'a> = impl T; + +struct S; +impl<'a> T for &'a S {} + +#[define_opaque(Alias)] +fn with_positive(fun: impl Fn(Alias<'_>)) { + //~^ WARN function cannot return without recursing + with_positive(|&n| ()); + //~^ ERROR cannot move out of a shared reference +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.stderr b/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.stderr new file mode 100644 index 00000000000..956ce3e5936 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.stderr @@ -0,0 +1,30 @@ +warning: function cannot return without recursing + --> $DIR/error-tainting-issue-122904.rs:12:1 + | +LL | fn with_positive(fun: impl Fn(Alias<'_>)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | +LL | with_positive(|&n| ()); + | ---------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +error[E0507]: cannot move out of a shared reference + --> $DIR/error-tainting-issue-122904.rs:14:20 + | +LL | with_positive(|&n| ()); + | ^- + | | + | data moved here + | move occurs because `n` has type `S`, which does not implement the `Copy` trait + | +help: consider removing the borrow + | +LL - with_positive(|&n| ()); +LL + with_positive(|n| ()); + | + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs index 7e010918b29..cbd8150d117 100644 --- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs +++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs @@ -22,7 +22,6 @@ where for<'any> F: FnMut(&'any mut ()) -> FutNothing<'any>, { //~^ ERROR: expected generic lifetime parameter, found `'any` - //~| ERROR item does not constrain } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr index 2ca6a199448..2c0be0cbcdc 100644 --- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr +++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr @@ -11,21 +11,6 @@ note: this opaque type is supposed to be constrained LL | type FutNothing<'a> = impl 'a + Future<Output = ()>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: item does not constrain `FutNothing::{opaque#0}` - --> $DIR/hkl_forbidden4.rs:23:1 - | -LL | / { -... | -LL | | } - | |_^ - | - = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]` -note: this opaque type is supposed to be constrained - --> $DIR/hkl_forbidden4.rs:10:23 - | -LL | type FutNothing<'a> = impl 'a + Future<Output = ()>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: concrete type differs from previous defining opaque type use --> $DIR/hkl_forbidden4.rs:12:1 | @@ -54,10 +39,10 @@ LL | type FutNothing<'a> = impl 'a + Future<Output = ()>; | -- this generic parameter must be used with a generic lifetime parameter ... LL | / { -... | +LL | | LL | | } | |_^ -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.rs b/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.rs index 7452000b65d..92c8a8f3216 100644 --- a/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.rs +++ b/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.rs @@ -6,7 +6,7 @@ trait Foo { } impl Foo for () { - type Assoc<'a> = impl Sized; //~ ERROR unconstrained opaque type + type Assoc<'a> = impl Sized; fn bar<'a: 'a>() where Self::Assoc<'a>:, diff --git a/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.stderr b/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.stderr index 1274a8b60de..7ce4517fb1e 100644 --- a/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.stderr +++ b/tests/ui/type-alias-impl-trait/in-assoc-ty-early-bound2.stderr @@ -9,14 +9,6 @@ LL | fn bar<'a: 'a>() LL | let _: Self::Assoc<'a> = x; | ^^^^^^^^^^^^^^^ -error: unconstrained opaque type - --> $DIR/in-assoc-ty-early-bound2.rs:9:22 - | -LL | type Assoc<'a> = impl Sized; - | ^^^^^^^^^^ - | - = note: `Assoc` must be used in combination with a concrete type within the same impl - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/type/pattern_types/derives.stderr b/tests/ui/type/pattern_types/derives.stderr index 9d4baef621b..f59617ebc45 100644 --- a/tests/ui/type/pattern_types/derives.stderr +++ b/tests/ui/type/pattern_types/derives.stderr @@ -6,8 +6,6 @@ LL | #[derive(Clone, Copy, PartialEq)] LL | #[repr(transparent)] LL | struct Nanoseconds(NanoI32); | ^^^^^^^ - | - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/typeck/cyclic_type_ice.stderr b/tests/ui/typeck/cyclic_type_ice.stderr index 4dc02a53c02..645766becbf 100644 --- a/tests/ui/typeck/cyclic_type_ice.stderr +++ b/tests/ui/typeck/cyclic_type_ice.stderr @@ -23,7 +23,7 @@ LL | let f = |_, _| (); help: provide the argument | LL - f(f); -LL + f(/* */, /* */); +LL + f(/* _ */, /* _ */); | error: aborting due to 2 previous errors diff --git a/tests/ui/uninhabited/auxiliary/staged-api.rs b/tests/ui/uninhabited/auxiliary/staged-api.rs new file mode 100644 index 00000000000..342ecf020ea --- /dev/null +++ b/tests/ui/uninhabited/auxiliary/staged-api.rs @@ -0,0 +1,8 @@ +#![feature(staged_api)] +#![stable(feature = "stable", since = "1.0.0")] + +#[stable(feature = "stable", since = "1.0.0")] +pub struct Foo<T> { + #[unstable(feature = "unstable", issue = "none")] + pub field: T, +} diff --git a/tests/ui/uninhabited/uninhabited-pin-field.rs b/tests/ui/uninhabited/uninhabited-pin-field.rs new file mode 100644 index 00000000000..3d0d9a7a4f8 --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-pin-field.rs @@ -0,0 +1,10 @@ +use std::pin::Pin; + +enum Void {} + +fn demo(x: Pin<Void>) { + match x {} + //~^ ERROR non-exhaustive patterns +} + +fn main() {} diff --git a/tests/ui/uninhabited/uninhabited-pin-field.stderr b/tests/ui/uninhabited/uninhabited-pin-field.stderr new file mode 100644 index 00000000000..93254ca9b98 --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-pin-field.stderr @@ -0,0 +1,19 @@ +error[E0004]: non-exhaustive patterns: type `Pin<Void>` is non-empty + --> $DIR/uninhabited-pin-field.rs:6:11 + | +LL | match x {} + | ^ + | +note: `Pin<Void>` defined here + --> $SRC_DIR/core/src/pin.rs:LL:COL + = note: the matched value is of type `Pin<Void>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/uninhabited/uninhabited-unstable-field.current.stderr b/tests/ui/uninhabited/uninhabited-unstable-field.current.stderr new file mode 100644 index 00000000000..9e0feb4c473 --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-unstable-field.current.stderr @@ -0,0 +1,22 @@ +error[E0004]: non-exhaustive patterns: type `Foo<Void>` is non-empty + --> $DIR/uninhabited-unstable-field.rs:13:11 + | +LL | match x {} + | ^ + | +note: `Foo<Void>` defined here + --> $DIR/auxiliary/staged-api.rs:5:1 + | +LL | pub struct Foo<T> { + | ^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `Foo<Void>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/uninhabited/uninhabited-unstable-field.exhaustive.stderr b/tests/ui/uninhabited/uninhabited-unstable-field.exhaustive.stderr new file mode 100644 index 00000000000..9e0feb4c473 --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-unstable-field.exhaustive.stderr @@ -0,0 +1,22 @@ +error[E0004]: non-exhaustive patterns: type `Foo<Void>` is non-empty + --> $DIR/uninhabited-unstable-field.rs:13:11 + | +LL | match x {} + | ^ + | +note: `Foo<Void>` defined here + --> $DIR/auxiliary/staged-api.rs:5:1 + | +LL | pub struct Foo<T> { + | ^^^^^^^^^^^^^^^^^ + = note: the matched value is of type `Foo<Void>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match x { +LL + _ => todo!(), +LL ~ } + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/uninhabited/uninhabited-unstable-field.rs b/tests/ui/uninhabited/uninhabited-unstable-field.rs new file mode 100644 index 00000000000..9b507c518ab --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-unstable-field.rs @@ -0,0 +1,29 @@ +//@ aux-build: staged-api.rs +//@ revisions: current exhaustive + +#![feature(exhaustive_patterns)] + +extern crate staged_api; + +use staged_api::Foo; + +enum Void {} + +fn demo(x: Foo<Void>) { + match x {} + //~^ ERROR non-exhaustive patterns +} + +// Ensure that the pattern is not considered unreachable. +fn demo2(x: Foo<Void>) { + match x { + Foo { .. } => {} + } +} + +// Same as above, but for wildcard. +fn demo3(x: Foo<Void>) { + match x { _ => {} } +} + +fn main() {} diff --git a/tests/ui/union/union-derive-clone.stderr b/tests/ui/union/union-derive-clone.stderr index a2b81f0dba1..679ab6a38e4 100644 --- a/tests/ui/union/union-derive-clone.stderr +++ b/tests/ui/union/union-derive-clone.stderr @@ -6,7 +6,6 @@ LL | #[derive(Clone)] | note: required by a bound in `AssertParamIsCopy` --> $SRC_DIR/core/src/clone.rs:LL:COL - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `U1` with `#[derive(Copy)]` | LL + #[derive(Copy)] diff --git a/tests/ui/union/union-derive-eq.current.stderr b/tests/ui/union/union-derive-eq.current.stderr index 151ceebe1ba..a0339687dad 100644 --- a/tests/ui/union/union-derive-eq.current.stderr +++ b/tests/ui/union/union-derive-eq.current.stderr @@ -9,7 +9,6 @@ LL | a: PartialEqNotEq, | note: required by a bound in `AssertParamIsEq` --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]` | LL + #[derive(Eq)] diff --git a/tests/ui/union/union-derive-eq.next.stderr b/tests/ui/union/union-derive-eq.next.stderr index 151ceebe1ba..a0339687dad 100644 --- a/tests/ui/union/union-derive-eq.next.stderr +++ b/tests/ui/union/union-derive-eq.next.stderr @@ -9,7 +9,6 @@ LL | a: PartialEqNotEq, | note: required by a bound in `AssertParamIsEq` --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]` | LL + #[derive(Eq)] diff --git a/tests/ui/write-fmt-errors.rs b/tests/ui/write-fmt-errors.rs index 1dafb9a784b..b48fa3f11cc 100644 --- a/tests/ui/write-fmt-errors.rs +++ b/tests/ui/write-fmt-errors.rs @@ -4,7 +4,7 @@ #![feature(io_error_uncategorized)] use std::fmt; -use std::io::{self, Error, Write, sink}; +use std::io::{self, Error, Write}; use std::panic::catch_unwind; struct ErrorDisplay; @@ -33,7 +33,7 @@ fn main() { assert!(res.is_err(), "writer error did not propagate"); // Test that the error from the formatter is detected. - let res = catch_unwind(|| write!(sink(), "{} {} {}", 1, ErrorDisplay, "bar")); + let res = catch_unwind(|| write!(vec![], "{} {} {}", 1, ErrorDisplay, "bar")); let err = res.expect_err("formatter error did not lead to panic").downcast::<&str>().unwrap(); assert!( err.contains("formatting trait implementation returned an error"), diff --git a/triagebot.toml b/triagebot.toml index 0096b22da17..7215cd84719 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -47,7 +47,6 @@ add_labels = ["S-waiting-on-review"] [glacier] [ping.icebreakers-llvm] -alias = ["llvm", "llvms"] message = """\ Hey LLVM ICE-breakers! This bug has been identified as a good "LLVM ICE-breaking candidate". In case it's useful, here are some @@ -308,6 +307,23 @@ exclude_labels = [ "T-*", ] +trigger_labels = [ + "D-*", + "A-diagnostics", +] + +[autolabel."A-diagnostics"] + +trigger_labels = [ + "D-*", +] + +[autolabel."A-lints"] + +trigger_labels = [ + "L-*", +] + [autolabel."T-libs"] trigger_files = [ "library/alloc", @@ -421,7 +437,7 @@ trigger_files = [ trigger_files = [ "Cargo.toml", "configure", - "config.example.toml", + "bootstrap.example.toml", "src/bootstrap", "src/build_helper", "src/tools/rust-installer", @@ -948,9 +964,9 @@ This PR modifies `src/bootstrap/defaults`. If appropriate, please update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/utils/change_tracker.rs`. """ -[mentions."config.example.toml"] +[mentions."bootstrap.example.toml"] message = """ -This PR modifies `config.example.toml`. +This PR modifies `bootstrap.example.toml`. If appropriate, please update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/utils/change_tracker.rs`. """ |
